47#include <wx/filename.h>
72 BOOST_CHECK( m_plugin.CanReadBoard( GetTestDataDir() +
"keyboard.dip" ) );
73 BOOST_CHECK( m_plugin.CanReadBoard( GetTestDataDir() +
"156bus_narrow.dip" ) );
74 BOOST_CHECK( m_plugin.CanReadBoard( GetTestDataDir() +
"z80_board.dip" ) );
75 BOOST_CHECK( m_plugin.CanReadBoard( GetTestDataDir() +
"logic_probe.dip" ) );
76 BOOST_CHECK( m_plugin.CanReadBoard( GetTestDataDir() +
"project4.dip" ) );
78 wxString tempBase = wxFileName::CreateTempFileName( wxS(
"kicad_diptrace_legacy_" ) );
79 wxRemoveFile( tempBase );
80 wxString legacyPath = tempBase + wxS(
".dip" );
83 const uint8_t legacyHeader[] = {
84 0x0B,
'D',
'T',
'B',
'O',
'A',
'R',
'D',
'2',
'.',
'2',
'1'
87 wxFFile file( legacyPath, wxS(
"wb" ) );
89 BOOST_REQUIRE_EQUAL( file.Write( legacyHeader,
sizeof( legacyHeader ) ),
90 sizeof( legacyHeader ) );
93 BOOST_CHECK( m_plugin.CanReadBoard( legacyPath ) );
94 wxRemoveFile( legacyPath );
100 const std::string sourcePath = GetTestDataDir() +
"z80_board.dip";
101 wxString tempBase = wxFileName::CreateTempFileName( wxS(
"kicad_diptrace_bad_pcb_comp_" ) );
102 wxRemoveFile( tempBase );
103 wxString tempPath = tempBase + wxS(
".dip" );
108 static constexpr wxFileOffset FIRST_COMPONENT_FLAGS_OFFSET = 0x491;
109 const uint8_t invalidFlags[] = { 0xFF, 0x00, 0x00, 0x00 };
111 wxFFile file( tempPath, wxS(
"r+b" ) );
114 BOOST_REQUIRE_EQUAL( file.Write( invalidFlags,
sizeof( invalidFlags ) ),
115 sizeof( invalidFlags ) );
118 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
120 BOOST_CHECK_THROW( m_plugin.LoadBoard( tempPath.ToStdString(), board.get() ),
IO_ERROR );
122 wxRemoveFile( tempPath );
128 const std::string sourcePath = GetTestDataDir() +
"z80_board.dip";
129 wxString tempBase = wxFileName::CreateTempFileName( wxS(
"kicad_diptrace_bad_route_chain_" ) );
130 wxRemoveFile( tempBase );
131 wxString tempPath = tempBase + wxS(
".dip" );
136 static constexpr wxFileOffset FIRST_ROUTE_CHAIN_NODE_COUNT_OFFSET = 0x1CEA7;
137 const uint8_t invalidNodeCount[] = { 0x0F, 0x69, 0x51 };
139 wxFFile file( tempPath, wxS(
"r+b" ) );
141 BOOST_REQUIRE( file.Seek( FIRST_ROUTE_CHAIN_NODE_COUNT_OFFSET ) );
142 BOOST_REQUIRE_EQUAL( file.Write( invalidNodeCount,
sizeof( invalidNodeCount ) ),
143 sizeof( invalidNodeCount ) );
146 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
148 BOOST_CHECK_THROW( m_plugin.LoadBoard( tempPath.ToStdString(), board.get() ),
IO_ERROR );
150 wxRemoveFile( tempPath );
156 const std::string sourcePath = GetTestDataDir() +
"z80_board.dip";
157 wxString tempBase = wxFileName::CreateTempFileName( wxS(
"kicad_diptrace_bad_net_name_" ) );
158 wxRemoveFile( tempBase );
159 wxString tempPath = tempBase + wxS(
".dip" );
164 static constexpr wxFileOffset FIRST_NET_NAME_LENGTH_OFFSET = 0x1CE2D;
165 const uint8_t invalidNameLength[] = { 0x01, 0xF5 };
167 wxFFile file( tempPath, wxS(
"r+b" ) );
170 BOOST_REQUIRE_EQUAL( file.Write( invalidNameLength,
sizeof( invalidNameLength ) ),
171 sizeof( invalidNameLength ) );
174 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
176 BOOST_CHECK_THROW( m_plugin.LoadBoard( tempPath.ToStdString(), board.get() ),
IO_ERROR );
178 wxRemoveFile( tempPath );
184 const std::string sourcePath = GetTestDataDir() +
"z80_board.dip";
185 wxString tempBase = wxFileName::CreateTempFileName( wxS(
"kicad_diptrace_bad_zone_width_" ) );
186 wxRemoveFile( tempBase );
187 wxString tempPath = tempBase + wxS(
".dip" );
192 static constexpr wxFileOffset FIRST_ZONE_MIN_WIDTH_OFFSET = 0x382CB;
193 const uint8_t zeroMinWidth[] = { 0x3B, 0x9A, 0xCA, 0x00 };
195 wxFFile file( tempPath, wxS(
"r+b" ) );
198 BOOST_REQUIRE_EQUAL( file.Write( zeroMinWidth,
sizeof( zeroMinWidth ) ),
199 sizeof( zeroMinWidth ) );
202 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
204 BOOST_CHECK_THROW( m_plugin.LoadBoard( tempPath.ToStdString(), board.get() ),
IO_ERROR );
206 wxRemoveFile( tempPath );
217 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
219 m_plugin.LoadBoard( GetTestDataDir() +
"keyboard.dip", board.get() );
224 BOOST_CHECK_GT( board->Footprints().size(), 50 );
227 BOOST_CHECK_GT( board->GetNetCount(), 20 );
246 const std::vector<std::string> files = {
247 "keyboard.dip",
"156bus_narrow.dip",
"logic_probe.dip",
"project4.dip",
"z80_board.dip"
250 for(
const std::string&
name : files )
252 const std::string
path = GetTestDataDir() +
name;
253 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
254 board->SetFileName( wxString::FromUTF8(
path ) );
266 name +
": mount hole located by scan ("
269 name +
": shape located by scan ("
272 name +
": component located by scan ("
275 name +
": section located by scan ("
280 name +
": object/section located by byte-pattern scan (total="
297 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
299 m_plugin.LoadBoard( GetTestDataDir() +
"156bus_narrow.dip", board.get() );
302 BOOST_CHECK_GT( board->Footprints().size(), 0 );
305 bool hasOutline =
false;
307 for(
BOARD_ITEM* drawing : board->Drawings() )
316 BOOST_CHECK( hasOutline );
326 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
328 m_plugin.LoadBoard( GetTestDataDir() +
"project4.dip", board.get() );
331 BOOST_CHECK_GT( board->Footprints().size(), 0 );
340 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
342 m_plugin.LoadBoard( GetTestDataDir() +
"logic_probe.dip", board.get() );
345 BOOST_CHECK_GT( board->Footprints().size(), 0 );
355 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
357 m_plugin.LoadBoard( GetTestDataDir() +
"z80_board.dip", board.get() );
362 BOOST_CHECK_GT( board->Footprints().size(), 10 );
368 for(
const FOOTPRINT* fp : board->Footprints() )
370 if( !fp->GetReference().IsEmpty() )
373 totalPads +=
static_cast<int>( fp->Pads().size() );
376 BOOST_CHECK_GT( refsFound, 10 );
377 BOOST_CHECK_GT( totalPads, 0 );
380 BOOST_CHECK_GT( board->GetNetCount(), 20 );
389 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
391 m_plugin.LoadBoard( GetTestDataDir() +
"project4.dip", board.get() );
397 for(
const FOOTPRINT* fp : board->Footprints() )
398 totalPads +=
static_cast<int>( fp->Pads().size() );
401 BOOST_CHECK_GT( totalPads, 0 );
410 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
412 m_plugin.LoadBoard( GetTestDataDir() +
"keyboard.dip", board.get() );
418 for(
const FOOTPRINT* fp : board->Footprints() )
419 totalPads +=
static_cast<int>( fp->Pads().size() );
421 BOOST_CHECK_GT( totalPads, 0 );
433 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
435 m_plugin.LoadBoard( GetTestDataDir() +
"keyboard.dip", board.get() );
439 int totalGraphics = 0;
441 for(
const FOOTPRINT* fp : board->Footprints() )
443 for(
const BOARD_ITEM* item : fp->GraphicalItems() )
452 BOOST_CHECK_GT( totalGraphics, 100 );
462 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
464 m_plugin.LoadBoard( GetTestDataDir() +
"logic_probe.dip", board.get() );
468 int totalGraphics = 0;
470 for(
const FOOTPRINT* fp : board->Footprints() )
472 for(
const BOARD_ITEM* item : fp->GraphicalItems() )
479 BOOST_CHECK_GT( totalGraphics, 50 );
489 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
491 m_plugin.LoadBoard( GetTestDataDir() +
"z80_board.dip", board.get() );
495 int totalGraphics = 0;
497 for(
const FOOTPRINT* fp : board->Footprints() )
499 for(
const BOARD_ITEM* item : fp->GraphicalItems() )
508 BOOST_CHECK_GT( totalGraphics, 10 );
519 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
521 m_plugin.LoadBoard( GetTestDataDir() +
"logic_probe.dip", board.get() );
528 for(
const FOOTPRINT* fp : board->Footprints() )
530 VECTOR2I refPos = fp->Reference().GetPosition();
531 VECTOR2I valPos = fp->Value().GetPosition();
534 if( refPos.
y != fpPos.
y )
537 if( valPos.
y != fpPos.
y )
543 BOOST_CHECK_GT( nonZeroRefY, 30 );
544 BOOST_CHECK_GT( nonZeroValY, 3 );
553 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
555 m_plugin.LoadBoard( GetTestDataDir() +
"z80_board.dip", board.get() );
562 for(
const FOOTPRINT* fp : board->Footprints() )
564 VECTOR2I refPos = fp->Reference().GetPosition();
565 VECTOR2I valPos = fp->Value().GetPosition();
568 if( refPos.
y != fpPos.
y )
571 if( valPos.
y != fpPos.
y )
575 BOOST_CHECK_GT( nonZeroRefY, 1 );
576 BOOST_CHECK_GT( nonZeroValY, 1 );
585 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
587 m_plugin.LoadBoard( GetTestDataDir() +
"keyboard.dip", board.get() );
593 for(
const FOOTPRINT* fp : board->Footprints() )
595 VECTOR2I refPos = fp->Reference().GetPosition();
598 if( refPos.
y != fpPos.
y )
602 BOOST_CHECK_GT( nonZeroRefY, 30 );
611 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
613 m_plugin.LoadBoard( GetTestDataDir() +
"project4.dip", board.get() );
619 for(
const FOOTPRINT* fp : board->Footprints() )
621 VECTOR2I valPos = fp->Value().GetPosition();
624 if( valPos.
y != fpPos.
y )
629 BOOST_CHECK_GT( nonZeroValY, 5 );
639 std::vector<std::string> files = {
"logic_probe.dip",
"keyboard.dip" };
641 int totalSegments = 0;
642 int totalCircles = 0;
645 for(
const std::string& file : files )
647 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
649 m_plugin.LoadBoard( GetTestDataDir() + file, board.get() );
657 for(
const FOOTPRINT* fp : board->Footprints() )
659 for(
const BOARD_ITEM* item : fp->GraphicalItems() )
677 <<
" CIRCLE=" << circles <<
" ARC=" << arcs );
679 BOOST_CHECK_GT( segments + circles + arcs, 0 );
681 totalSegments += segments;
682 totalCircles += circles;
687 BOOST_CHECK_GT( totalSegments, 200 );
688 BOOST_CHECK_GT( totalCircles + totalArcs, 0 );
699 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
701 m_plugin.LoadBoard( GetTestDataDir() +
"z80_board.dip", board.get() );
707 for(
const FOOTPRINT* fp : board->Footprints() )
709 for(
const PAD*
pad : fp->Pads() )
716 BOOST_CHECK_GT( customPads, 0 );
726 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
728 m_plugin.LoadBoard( GetTestDataDir() +
"z80_board.dip", board.get() );
734 for(
const FOOTPRINT* fp : board->Footprints() )
736 for(
const PAD*
pad : fp->Pads() )
744 BOOST_CHECK_GT( rectPads, 0 );
754 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
756 m_plugin.LoadBoard( GetTestDataDir() +
"keyboard.dip", board.get() );
764 for(
const FOOTPRINT* fp : board->Footprints() )
766 for(
const PAD*
pad : fp->Pads() )
779 <<
" OVAL=" << ovalPads <<
" RECT=" << rectPads );
782 BOOST_CHECK_GT( circlePads, 0 );
792 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
794 m_plugin.LoadBoard( GetTestDataDir() +
"logic_probe.dip", board.get() );
801 BOOST_CHECK_GE( board->GetCopperLayerCount(), 2 );
805 BOOST_CHECK_GT( defNc->GetTrackWidth(), 0 );
806 BOOST_CHECK_GT( defNc->GetClearance(), 0 );
809 BOOST_CHECK_GT( defNc->GetViaDiameter(), 0 );
810 BOOST_CHECK_GT( defNc->GetViaDrill(), 0 );
819 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
821 m_plugin.LoadBoard( GetTestDataDir() +
"z80_board.dip", board.get() );
832 BOOST_CHECK_GT( defNc->GetTrackWidth(), 0 );
General utilities for PCB file IO for QA programs.
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Parses a DipTrace .dip binary board file and populates a KiCad BOARD.
int ScanLocatorUseCount() const
Number of objects or sections that were located by byte-pattern scanning rather than a deterministic ...
int ComponentLocatorScans() const
int PadLocatorScans() const
int MountHoleLocatorScans() const
int SectionLocatorScans() const
void Parse()
Parse the file and populate the board. Throws IO_ERROR on failure.
int ShapeLocatorScans() const
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Parser for DipTrace binary .dip board files.
std::string GetPcbnewTestDataDir()
Utility which returns a path to the data directory where the test board files are stored.
Pcbnew PCB_IO for DipTrace binary .dip board files.
std::string GetTestDataDir()
DIPTRACE_PCB_IMPORT_FIXTURE()
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_CASE(CanReadBoard)
Test that CanReadBoard correctly identifies DipTrace .dip files by their magic header bytes (0x07 "DT...
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_CHECK_MESSAGE(totalMismatches==0, std::to_string(totalMismatches)+" board(s) with strategy disagreements")
BOOST_TEST_MESSAGE("\n=== Real-World Polygon PIP Benchmark ===\n"<< formatTable(table))
BOOST_CHECK_EQUAL(result, "25.4")
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
VECTOR2< int32_t > VECTOR2I