20#include <boost/test/unit_test.hpp>
27#include <system_error>
42#include <wx/filename.h>
54 explicit TEMP_FILE(
const wxString& aPrefix ) :
55 m_path( std::string( wxFileName::CreateTempFileName( aPrefix ).ToUTF8() ) )
62 std::filesystem::remove( m_path, ec );
65 const std::filesystem::path& Path()
const {
return m_path; }
66 std::string Str()
const {
return m_path.string(); }
67 wxString WxStr()
const {
return wxString( m_path.string() ); }
70 std::filesystem::path m_path;
74std::string slurp(
const std::filesystem::path& aPath )
76 std::ifstream in( aPath );
83std::unique_ptr<BOARD> loadTestBoard()
85 const std::filesystem::path boardPath =
94int countTraces(
BOARD* aBoard )
108void importSession(
BOARD* aBoard,
const wxString& aSesPath )
111 toolMgr.
SetEnvironment( aBoard,
nullptr,
nullptr,
nullptr,
nullptr );
116 commit.Push( wxT(
"Import Specctra Session" ),
SKIP_UNDO );
124 toolMgr.
SetEnvironment( aBoard,
nullptr,
nullptr,
nullptr,
nullptr );
129 commit.Push( wxT(
"Import Specctra Session" ),
SKIP_UNDO );
145 std::unique_ptr<BOARD> board = loadTestBoard();
148 board->Footprints().front()->SetValue( wxT(
"2x20 pin 0.1\" female header" ) );
150 TEMP_FILE out( wxT(
"kicad_specctra_24946_" ) );
153 const std::string dsn = slurp( out.Path() );
156 BOOST_CHECK( dsn.find(
"0.1\" female" ) == std::string::npos );
157 BOOST_CHECK( dsn.find(
"0.1'' female" ) != std::string::npos );
167 std::unique_ptr<BOARD> board = loadTestBoard();
169 BOOST_REQUIRE_GE( board->Footprints().size(), 5u );
171 board->Footprints()[0]->SetReference( wxEmptyString );
172 board->Footprints()[1]->SetReference( wxEmptyString );
173 board->Footprints()[2]->SetReference( wxT(
"U1" ) );
174 board->Footprints()[3]->SetReference( wxT(
"U1" ) );
175 board->Footprints()[4]->SetReference( wxT(
"u1" ) );
177 TEMP_FILE out( wxT(
"kicad_specctra_24947_" ) );
180 const std::string dsn = slurp( out.Path() );
183 BOOST_CHECK( dsn.find(
"(place REF**_1 " ) != std::string::npos );
184 BOOST_CHECK( dsn.find(
"(place U1 " ) != std::string::npos );
185 BOOST_CHECK( dsn.find(
"(place U1_1 " ) != std::string::npos );
186 BOOST_CHECK( dsn.find(
"(place u1_2 " ) != std::string::npos );
195 std::unique_ptr<BOARD> board = loadTestBoard();
197 TEMP_FILE ses( wxT(
"kicad_specctra_allegro_poly_" ) );
199 const std::string validLayer = std::string( board->GetLayerName(
F_Cu ).ToUTF8() );
201 std::ofstream out( ses.Path() );
202 out <<
"(session test.ses\n"
203 <<
" (base_design test.dsn)\n"
205 <<
" (resolution um 10)\n"
206 <<
" (library_out )\n"
208 <<
" (net \"/ALLPST\"\n"
209 <<
" (wire (path \"" << validLayer <<
"\" 1600 0 0 1000 0)\n"
210 <<
" (type route))\n"
211 <<
" (wire (poly \"" << validLayer <<
"\" 0 0 0 1000 0 1000 1000 0 1000 0 0)\n"
212 <<
" (type normal))\n"
219 BOOST_REQUIRE_NO_THROW( importSession( board.get(), ses.Str() ) );
231 std::unique_ptr<BOARD> board = loadTestBoard();
233 TEMP_FILE ses( wxT(
"kicad_specctra_24948_" ) );
237 const std::string validLayer = std::string( board->GetLayerName(
F_Cu ).ToUTF8() );
239 std::ofstream out( ses.Path() );
240 out <<
"(session test.ses\n"
241 <<
" (base_design test.dsn)\n"
243 <<
" (resolution um 10)\n"
244 <<
" (component test\n"
245 <<
" (place Nonexistent_Ref 0 0 front 0)\n"
249 <<
" (resolution um 10)\n"
250 <<
" (library_out )\n"
252 <<
" (net \"/ALLPST\"\n"
253 <<
" (wire (path \"" << validLayer <<
"\" 1600 0 0 1000 0))\n"
254 <<
" (wire (path Bogus_Missing_Layer 1600 0 0 1000 1000))\n"
263 wxLog::SetTimestamp( wxEmptyString );
266 BOOST_REQUIRE_NO_THROW( importSession( board.get(), ses.Str() ) );
280 std::unique_ptr<BOARD> board = loadTestBoard();
282 TEMP_FILE out( wxT(
"kicad_specctra_parseable_" ) );
289 BOOST_CHECK( db.
GetPCB() !=
nullptr );
293 BOOST_FAIL( ioe.
What().ToStdString() );
301 std::unique_ptr<BOARD> board = loadTestBoard();
305 TEMP_FILE out( wxT(
"kicad_specctra_content_" ) );
308 const std::string dsn = slurp( out.Path() );
311 BOOST_CHECK( dsn.find(
"(unit um" ) != std::string::npos );
314 bool netHeaderFound =
false;
316 for(
const NETINFO_ITEM* net : board->GetNetInfo().NetsByNetcode() | std::views::values )
318 if( net->GetNetname().IsEmpty() )
321 if( dsn.find(
"(net \"" + std::string( net->GetNetname().ToUTF8() ) +
"\"" ) != std::string::npos )
322 netHeaderFound =
true;
325 BOOST_CHECK( netHeaderFound );
333 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
336 TEMP_FILE out( wxT(
"kicad_specctra_reporter_" ) );
339 BOOST_CHECK(
reporter.GetMessages().Contains( wxT(
"Board outline is malformed" ) ) );
General utilities for PCB file IO for QA programs.
Information pertinent to a Pcbnew printed circuit board.
const TRACKS & Tracks() const
A DSN data tree, usually coming from a DSN file.
void LoadPCB(const wxString &aFilename)
A recursive descent parser for a SPECCTRA DSN "design" file.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Handle the data for a net.
A wrapper for reporting to a wxString object.
This source file implements export and import capabilities to the specctra dsn file format.
void ExportBoardToSpecctraFile(BOARD *aBoard, const wxString &aFullFilename, REPORTER *aReporter=nullptr)
Helper method to export board to DSN file.
bool ImportSpecctraSession(BOARD *aBoard, const wxString &fullFileName, COMMIT &aCommit, REPORTER *aReporter=nullptr, int *aSkippedCount=nullptr)
Helper method to import SES file to a board.
std::string GetPcbnewTestDataDir()
Utility which returns a path to the data directory where the test board files are stored.
std::unique_ptr< BOARD > RequireBoardFromPcbnewQAData(const std::filesystem::path &aFilename)
Require a board from the path relative to the pcbnew QA data directory.
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
IbisParser parser & reporter
BOOST_AUTO_TEST_CASE(SpecctraExportQuoteInField)
BOOST_CHECK_EQUAL(result, "25.4")
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)