21#include <boost/test/unit_test.hpp>
53static const char* DRU_HEADER =
"(version 1)\n";
56std::string makeChainBudgetRule(
const wxString& aName,
const wxString& aMinMM,
57 const wxString& aMaxMM )
59 return wxString::Format(
"%s(rule \"%s\"\n"
60 " (condition \"A.NetClass == 'Default'\")\n"
61 " (constraint net_chain_length (min %smm) (max %smm))\n"
63 DRU_HEADER, aName, aMinMM, aMaxMM )
71size_t runChainLengthDrc(
const std::string& aBoardText,
const std::string& aRuleText,
72 const std::string& aTmpSubdir )
74 namespace fs = std::filesystem;
76 fs::path tmpDir = fs::temp_directory_path() / aTmpSubdir;
77 fs::create_directories( tmpDir );
79 fs::path pcbPath = tmpDir /
"chain_bridge.kicad_pcb";
80 fs::path druPath = tmpDir /
"chain_bridge.kicad_dru";
83 std::ofstream pcbOut( pcbPath );
88 std::ofstream druOut( druPath );
93 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
94 plugin.
LoadBoard( pcbPath.string(), board.get() );
95 board->BuildConnectivity();
99 if( net && net->GetNetname().StartsWith( wxS(
"/NET_" ) ) )
100 net->SetNetChain( wxS(
"SIG" ) );
105 auto drcEngine = std::make_shared<DRC_ENGINE>( board.get(), &bds );
106 wxFileName ruleFile( druPath.string() );
107 drcEngine->InitEngine( ruleFile );
118 size_t lengthViolations = 0;
120 drcEngine->SetViolationHandler(
121 [&](
const std::shared_ptr<DRC_ITEM>& aItem,
const VECTOR2I&,
int,
131 fs::remove( pcbPath, ec );
132 fs::remove( druPath, ec );
134 return lengthViolations;
148 static const char* boardText = R
"KICAD(
152 (generator_version "9.99")
160 (segment (start 0 0) (end 10 0) (width 0.2) (layer "F.Cu") (net 1))
161 (segment (start 15 0) (end 25 0) (width 0.2) (layer "F.Cu") (net 2))
162 (footprint "TestFP:FB_3PAD" (layer "F.Cu") (at 12.5 0)
163 (property "Reference" "FB1")
164 (pad "1" smd rect (at -2.5 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
165 (pad "2" smd rect (at 0 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
166 (pad "3" smd rect (at 2.5 0) (size 0.5 0.5) (layers "F.Cu") (net 2 "/NET_B"))
173 runChainLengthDrc( boardText, makeChainBudgetRule(
"Pass",
"0",
"26" ),
174 "kicad_drc_chain_bridging_3pad_pass" );
181 runChainLengthDrc( boardText, makeChainBudgetRule(
"Fail",
"0",
"22" ),
182 "kicad_drc_chain_bridging_3pad_fail" );
193 static const char* boardText = R
"KICAD(
197 (generator_version "9.99")
206 (segment (start 0 0) (end 10 0) (width 0.2) (layer "F.Cu") (net 1))
207 (segment (start 15 0) (end 25 0) (width 0.2) (layer "F.Cu") (net 2))
208 (segment (start 30 0) (end 40 0) (width 0.2) (layer "F.Cu") (net 3))
209 (footprint "TestFP:XFMR_3PAD" (layer "F.Cu") (at 12.5 0)
210 (property "Reference" "T1")
211 (pad "1" smd rect (at -2.5 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
212 (pad "2" smd rect (at 0 0) (size 0.5 0.5) (layers "F.Cu") (net 2 "/NET_B"))
213 (pad "3" smd rect (at 2.5 0) (size 0.5 0.5) (layers "F.Cu") (net 3 "/NET_C"))
220 runChainLengthDrc( boardText, makeChainBudgetRule(
"Pass",
"0",
"36" ),
221 "kicad_drc_chain_bridging_3net_pass" );
228 runChainLengthDrc( boardText, makeChainBudgetRule(
"Fail",
"0",
"32" ),
229 "kicad_drc_chain_bridging_3net_fail" );
240 static const char* boardText = R
"KICAD(
244 (generator_version "9.99")
252 (segment (start 0 0) (end 10 0) (width 0.2) (layer "F.Cu") (net 1))
253 (segment (start 16 0) (end 26 0) (width 0.2) (layer "F.Cu") (net 2))
254 (footprint "TestFP:DUAL_4PAD" (layer "F.Cu") (at 13 0)
255 (property "Reference" "U1")
256 (pad "1" smd rect (at -3 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
257 (pad "2" smd rect (at -1 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
258 (pad "3" smd rect (at 1 0) (size 0.5 0.5) (layers "F.Cu") (net 2 "/NET_B"))
259 (pad "4" smd rect (at 3 0) (size 0.5 0.5) (layers "F.Cu") (net 2 "/NET_B"))
266 runChainLengthDrc( boardText, makeChainBudgetRule(
"Pass",
"0",
"27" ),
267 "kicad_drc_chain_bridging_4pad_pass" );
273 runChainLengthDrc( boardText, makeChainBudgetRule(
"Fail",
"0",
"24" ),
274 "kicad_drc_chain_bridging_4pad_fail" );
283 static const char* boardText = R
"KICAD(
287 (generator_version "9.99")
295 (segment (start 0 0) (end 10 0) (width 0.2) (layer "F.Cu") (net 1))
296 (segment (start 20 0) (end 30 0) (width 0.2) (layer "F.Cu") (net 2))
297 (footprint "TestFP:STAR_3PAD" (layer "F.Cu") (at 5 5)
298 (property "Reference" "U2")
299 (pad "1" smd rect (at -2 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
300 (pad "2" smd rect (at 0 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
301 (pad "3" smd rect (at 2 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
308 runChainLengthDrc( boardText, makeChainBudgetRule(
"Pass",
"0",
"21" ),
309 "kicad_drc_chain_bridging_singlenet_pass" );
310 BOOST_CHECK_MESSAGE( pass == 0,
"Single-net 3-pad footprint must not contribute bridging; "
311 "got " << pass <<
" violations under 21 mm budget" );
Container for design settings for a BOARD object.
std::map< int, SEVERITY > m_DRCSeverities
std::shared_ptr< DRC_ENGINE > m_DRCEngine
Handle the data for a net.
A #PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
@ DRCE_LIB_FOOTPRINT_ISSUES
@ DRCE_DRILL_OUT_OF_RANGE
@ DRCE_LENGTH_OUT_OF_RANGE
@ DRCE_LIB_FOOTPRINT_MISMATCH
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_CASE(ThreePadTwoNetFootprintContributesMaxPairwiseSpan)
BOOST_AUTO_TEST_SUITE_END()
BOOST_CHECK_MESSAGE(totalMismatches==0, std::to_string(totalMismatches)+" board(s) with strategy disagreements")
VECTOR2< int32_t > VECTOR2I