KiCad PCB EDA Suite
test_drc_courtyard_overlap.cpp File Reference

Go to the source code of this file.

Classes

struct  RECT_DEFINITION
 Simple definition of a rectangle, can be rounded. More...
 
struct  COURTYARD_TEST_FP
 
struct  COURTYARD_COLLISION
 
struct  COURTYARD_OVERLAP_TEST_CASE
 A complete courtyard overlap test case: a name, the board footprint list and the expected collisions. More...
 
struct  COURTYARD_TEST_FIXTURE
 

Functions

std::ostream & operator<< (std::ostream &os, const COURTYARD_COLLISION &aColl)
 
void AddRectCourtyard (FOOTPRINT &aFootprint, const RECT_DEFINITION &aRect)
 Add a rectangular courtyard outline to a footprint. More...
 
std::unique_ptr< FOOTPRINTMakeCourtyardTestFP (BOARD &aBoard, const COURTYARD_TEST_FP &aFPDef)
 Construct a FOOTPRINT to use in a courtyard test from a COURTYARD_TEST_FP definition. More...
 
std::unique_ptr< BOARDMakeBoard (const std::vector< COURTYARD_TEST_FP > &aFPDefs)
 Make a board for courtyard testing. More...
 
static bool CollisionMatchesExpected (BOARD &aBoard, const PCB_MARKER &aMarker, const COURTYARD_COLLISION &aCollision)
 Check if a PCB_MARKER is described by a particular COURTYARD_COLLISION object. More...
 
static void CheckCollisionsMatchExpected (BOARD &aBoard, const std::vector< std::unique_ptr< PCB_MARKER >> &aMarkers, const std::vector< COURTYARD_COLLISION > &aExpCollisions)
 Check that the produced markers match the expected. More...
 
static void DoCourtyardOverlapTest (const COURTYARD_OVERLAP_TEST_CASE &aCase, const KI_TEST::BOARD_DUMPER &aDumper)
 Run a single courtyard overlap testcase. More...
 
 BOOST_AUTO_TEST_CASE (OverlapCases)
 

Variables

static std::vector< COURTYARD_OVERLAP_TEST_CASEcourtyard_cases
 

Function Documentation

◆ AddRectCourtyard()

void AddRectCourtyard ( FOOTPRINT aFootprint,
const RECT_DEFINITION aRect 
)

Add a rectangular courtyard outline to a footprint.

Definition at line 97 of file test_drc_courtyard_overlap.cpp.

98 {
99  const PCB_LAYER_ID layer = aRect.m_front ? F_CrtYd : B_CrtYd;
100 
101  const int width = Millimeter2iu( 0.1 );
102 
103  KI_TEST::DrawRect( aFootprint, aRect.m_centre, aRect.m_size, aRect.m_corner_rad, width, layer );
104 }
void DrawRect(FOOTPRINT &aFootprint, const VECTOR2I &aPos, const VECTOR2I &aSize, int aRadius, int aWidth, PCB_LAYER_ID aLayer)
Draw a rectangle on a footprint.
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
static constexpr int Millimeter2iu(double mm)

References B_CrtYd, KI_TEST::DrawRect(), F_CrtYd, RECT_DEFINITION::m_centre, RECT_DEFINITION::m_corner_rad, RECT_DEFINITION::m_front, RECT_DEFINITION::m_size, and Millimeter2iu().

Referenced by MakeCourtyardTestFP().

◆ BOOST_AUTO_TEST_CASE()

BOOST_AUTO_TEST_CASE ( OverlapCases  )

Definition at line 479 of file test_drc_courtyard_overlap.cpp.

480 {
481  for( const auto& c : courtyard_cases )
482  {
483  BOOST_TEST_CONTEXT( c.m_case_name )
484  {
485  DoCourtyardOverlapTest( c, m_dumper );
486  }
487  }
488 }
static std::vector< COURTYARD_OVERLAP_TEST_CASE > courtyard_cases
#define BOOST_TEST_CONTEXT(A)
static void DoCourtyardOverlapTest(const COURTYARD_OVERLAP_TEST_CASE &aCase, const KI_TEST::BOARD_DUMPER &aDumper)
Run a single courtyard overlap testcase.

References BOOST_TEST_CONTEXT, courtyard_cases, and DoCourtyardOverlapTest().

◆ CheckCollisionsMatchExpected()

static void CheckCollisionsMatchExpected ( BOARD aBoard,
const std::vector< std::unique_ptr< PCB_MARKER >> &  aMarkers,
const std::vector< COURTYARD_COLLISION > &  aExpCollisions 
)
static

Check that the produced markers match the expected.

This does NOT check ordering, as that is not part of the contract of the DRC function.

Parameters
aMarkerslist of markers produced by the DRC
aCollisionslist of expected collisions

Definition at line 418 of file test_drc_courtyard_overlap.cpp.

421 {
422  for( const auto& marker : aMarkers )
423  {
424  BOOST_CHECK_PREDICATE(
426  }
427 
428  KI_TEST::CheckUnorderedMatches( aExpCollisions, aMarkers,
429  [&]( const COURTYARD_COLLISION& aColl, const std::unique_ptr<PCB_MARKER>& aMarker )
430  {
431  return CollisionMatchesExpected( aBoard, *aMarker, aColl );
432  } );
433 }
static bool CollisionMatchesExpected(BOARD &aBoard, const PCB_MARKER &aMarker, const COURTYARD_COLLISION &aCollision)
Check if a PCB_MARKER is described by a particular COURTYARD_COLLISION object.
void CheckUnorderedMatches(const EXP_CONT &aExpected, const FOUND_CONT &aFound, MATCH_PRED aMatchPredicate)
Check that a container of "found" objects matches a container of "expected" objects.
bool IsDrcMarkerOfType(const PCB_MARKER &aMarker, int aErrorCode)
Predicate for testing the type of a DRC marker.

References KI_TEST::CheckUnorderedMatches(), CollisionMatchesExpected(), DRCE_OVERLAPPING_FOOTPRINTS, and KI_TEST::IsDrcMarkerOfType().

Referenced by DoCourtyardOverlapTest().

◆ CollisionMatchesExpected()

static bool CollisionMatchesExpected ( BOARD aBoard,
const PCB_MARKER aMarker,
const COURTYARD_COLLISION aCollision 
)
static

Check if a PCB_MARKER is described by a particular COURTYARD_COLLISION object.

Definition at line 388 of file test_drc_courtyard_overlap.cpp.

390 {
391  auto reporter = std::static_pointer_cast<DRC_ITEM>( aMarker.GetRCItem() );
392 
393  const FOOTPRINT* item_a = dynamic_cast<FOOTPRINT*>( aBoard.GetItem( reporter->GetMainItemID() ) );
394  const FOOTPRINT* item_b = dynamic_cast<FOOTPRINT*>( aBoard.GetItem( reporter->GetAuxItemID() ) );
395 
396  // can't find the items!
397  if( !item_a || !item_b )
398  return false;
399 
400  const bool ref_match_aa_bb = ( item_a->GetReference() == aCollision.m_refdes_a )
401  && ( item_b->GetReference() == aCollision.m_refdes_b );
402 
403  const bool ref_match_ab_ba = ( item_a->GetReference() == aCollision.m_refdes_b )
404  && ( item_b->GetReference() == aCollision.m_refdes_a );
405 
406  // Doesn't matter which way around it is, but both have to match somehow
407  return ref_match_aa_bb || ref_match_ab_ba;
408 }
BOARD_ITEM * GetItem(const KIID &aID) const
Definition: board.cpp:845
const wxString & GetReference() const
Definition: footprint.h:466
std::shared_ptr< RC_ITEM > GetRCItem() const
Definition: marker_base.h:101

References BOARD::GetItem(), MARKER_BASE::GetRCItem(), FOOTPRINT::GetReference(), COURTYARD_COLLISION::m_refdes_a, and COURTYARD_COLLISION::m_refdes_b.

Referenced by CheckCollisionsMatchExpected().

◆ DoCourtyardOverlapTest()

static void DoCourtyardOverlapTest ( const COURTYARD_OVERLAP_TEST_CASE aCase,
const KI_TEST::BOARD_DUMPER aDumper 
)
static

Run a single courtyard overlap testcase.

Parameters
aCaseThe testcase to run.

Definition at line 440 of file test_drc_courtyard_overlap.cpp.

442 {
443  auto board = MakeBoard( aCase.m_fpDefs );
444 
445  // Dump if env var set
446  aDumper.DumpBoardToFile( *board, aCase.m_case_name );
447 
448  BOARD_DESIGN_SETTINGS& bds = board->GetDesignSettings();
449 
451 
452  // we might not always have courtyards - that's a separate test
454 
455  // list of markers to collect
456  std::vector<std::unique_ptr<PCB_MARKER>> markers;
457 
458  DRC_ENGINE drcEngine( board.get(), &board->GetDesignSettings() );
459 
460  drcEngine.InitEngine( wxFileName() );
461 
462  drcEngine.SetViolationHandler(
463  [&]( const std::shared_ptr<DRC_ITEM>& aItem, wxPoint aPos )
464  {
465  if( aItem->GetErrorCode() == DRCE_OVERLAPPING_FOOTPRINTS
466  || aItem->GetErrorCode() == DRCE_MALFORMED_COURTYARD
467  || aItem->GetErrorCode() == DRCE_MISSING_COURTYARD )
468  {
469  markers.push_back( std::make_unique<PCB_MARKER>( aItem, aPos ) );
470  }
471  } );
472 
473  drcEngine.RunTests( EDA_UNITS::MILLIMETRES, true, false );
474 
475  CheckCollisionsMatchExpected( *board, markers, aCase.m_collisions );
476 }
std::unique_ptr< BOARD > MakeBoard(const std::vector< COURTYARD_TEST_FP > &aFPDefs)
Make a board for courtyard testing.
Design Rule Checker object that performs all the DRC tests.
Definition: drc_engine.h:81
std::vector< COURTYARD_COLLISION > m_collisions
static void CheckCollisionsMatchExpected(BOARD &aBoard, const std::vector< std::unique_ptr< PCB_MARKER >> &aMarkers, const std::vector< COURTYARD_COLLISION > &aExpCollisions)
Check that the produced markers match the expected.
void DumpBoardToFile(BOARD &aBoard, const std::string &aName) const
std::vector< COURTYARD_TEST_FP > m_fpDefs
std::map< int, SEVERITY > m_DRCSeverities
void InitEngine(const wxFileName &aRulePath)
Initialize the DRC engine.
Definition: drc_engine.cpp:620
Container for design settings for a BOARD object.

References CheckCollisionsMatchExpected(), DRCE_MALFORMED_COURTYARD, DRCE_MISSING_COURTYARD, DRCE_OVERLAPPING_FOOTPRINTS, KI_TEST::BOARD_DUMPER::DumpBoardToFile(), DRC_ENGINE::InitEngine(), COURTYARD_OVERLAP_TEST_CASE::m_case_name, COURTYARD_OVERLAP_TEST_CASE::m_collisions, BOARD_DESIGN_SETTINGS::m_DRCSeverities, COURTYARD_OVERLAP_TEST_CASE::m_fpDefs, MakeBoard(), MILLIMETRES, RPT_SEVERITY_ERROR, and RPT_SEVERITY_IGNORE.

Referenced by BOOST_AUTO_TEST_CASE().

◆ MakeBoard()

std::unique_ptr<BOARD> MakeBoard ( const std::vector< COURTYARD_TEST_FP > &  aFPDefs)

Make a board for courtyard testing.

Parameters
aFPDefsthe list of footprint definitions to add to the board

Definition at line 130 of file test_drc_courtyard_overlap.cpp.

131 {
132  std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
133 
134  for( const COURTYARD_TEST_FP& fpDef : aFPDefs )
135  {
136  std::unique_ptr<FOOTPRINT> footprint = MakeCourtyardTestFP( *board, fpDef );
137 
138  board->Add( footprint.release() );
139  }
140 
141  return board;
142 }
std::unique_ptr< FOOTPRINT > MakeCourtyardTestFP(BOARD &aBoard, const COURTYARD_TEST_FP &aFPDef)
Construct a FOOTPRINT to use in a courtyard test from a COURTYARD_TEST_FP definition.

References MakeCourtyardTestFP().

Referenced by DoCourtyardOverlapTest().

◆ MakeCourtyardTestFP()

std::unique_ptr<FOOTPRINT> MakeCourtyardTestFP ( BOARD aBoard,
const COURTYARD_TEST_FP aFPDef 
)

Construct a FOOTPRINT to use in a courtyard test from a COURTYARD_TEST_FP definition.

Definition at line 110 of file test_drc_courtyard_overlap.cpp.

111 {
112  std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>( &aBoard );
113 
114  for( const RECT_DEFINITION& rect : aFPDef.m_rects )
115  AddRectCourtyard( *footprint, rect );
116 
117  footprint->SetReference( aFPDef.m_refdes );
118 
119  // This has to go after adding the courtyards, or all the poly sets are empty when DRC'd
120  footprint->SetPosition( (wxPoint) aFPDef.m_pos );
121 
122  return footprint;
123 }
Simple definition of a rectangle, can be rounded.
std::vector< RECT_DEFINITION > m_rects
void AddRectCourtyard(FOOTPRINT &aFootprint, const RECT_DEFINITION &aRect)
Add a rectangular courtyard outline to a footprint.

References AddRectCourtyard(), COURTYARD_TEST_FP::m_pos, COURTYARD_TEST_FP::m_rects, and COURTYARD_TEST_FP::m_refdes.

Referenced by MakeBoard().

◆ operator<<()

std::ostream& operator<< ( std::ostream &  os,
const COURTYARD_COLLISION aColl 
)

Definition at line 75 of file test_drc_courtyard_overlap.cpp.

76 {
77  os << "COURTYARD_COLLISION[ " << aColl.m_refdes_a << " -> " << aColl.m_refdes_b << "]";
78  return os;
79 }

References COURTYARD_COLLISION::m_refdes_a, and COURTYARD_COLLISION::m_refdes_b.

Variable Documentation

◆ courtyard_cases

std::vector<COURTYARD_OVERLAP_TEST_CASE> courtyard_cases
static

Definition at line 154 of file test_drc_courtyard_overlap.cpp.

Referenced by BOOST_AUTO_TEST_CASE().