20#include <boost/test/unit_test.hpp>
52static const char* DRU_HEADER =
"(version 1)\n";
55std::string makeChainBudgetRule(
const wxString& aName,
const wxString& aMinMM,
56 const wxString& aMaxMM )
58 return wxString::Format(
"%s(rule \"%s\"\n"
59 " (condition \"A.NetClass == 'Default'\")\n"
60 " (constraint net_chain_length (min %smm) (max %smm))\n"
62 DRU_HEADER, aName, aMinMM, aMaxMM )
70size_t runChainLengthDrc(
const std::string& aBoardText,
const std::string& aRuleText,
71 const std::string& aTmpSubdir )
73 namespace fs = std::filesystem;
75 fs::path tmpDir = fs::temp_directory_path() / aTmpSubdir;
76 fs::create_directories( tmpDir );
78 fs::path pcbPath = tmpDir /
"chain_bridge.kicad_pcb";
79 fs::path druPath = tmpDir /
"chain_bridge.kicad_dru";
82 std::ofstream pcbOut( pcbPath );
87 std::ofstream druOut( druPath );
92 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
93 plugin.
LoadBoard( pcbPath.string(), board.get() );
94 board->BuildConnectivity();
98 if( net && net->GetNetname().StartsWith( wxS(
"/NET_" ) ) )
99 net->SetNetChain( wxS(
"SIG" ) );
104 auto drcEngine = std::make_shared<DRC_ENGINE>( board.get(), &bds );
105 wxFileName ruleFile( druPath.string() );
106 drcEngine->InitEngine( ruleFile );
117 size_t lengthViolations = 0;
119 drcEngine->SetViolationHandler(
120 [&](
const std::shared_ptr<DRC_ITEM>& aItem,
const VECTOR2I&,
int,
130 fs::remove( pcbPath, ec );
131 fs::remove( druPath, ec );
133 return lengthViolations;
147 static const char* boardText = R
"KICAD(
151 (generator_version "9.99")
159 (segment (start 0 0) (end 10 0) (width 0.2) (layer "F.Cu") (net 1))
160 (segment (start 15 0) (end 25 0) (width 0.2) (layer "F.Cu") (net 2))
161 (footprint "TestFP:FB_3PAD" (layer "F.Cu") (at 12.5 0)
162 (property "Reference" "FB1")
163 (pad "1" smd rect (at -2.5 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
164 (pad "2" smd rect (at 0 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
165 (pad "3" smd rect (at 2.5 0) (size 0.5 0.5) (layers "F.Cu") (net 2 "/NET_B"))
172 runChainLengthDrc( boardText, makeChainBudgetRule(
"Pass",
"0",
"26" ),
173 "kicad_drc_chain_bridging_3pad_pass" );
180 runChainLengthDrc( boardText, makeChainBudgetRule(
"Fail",
"0",
"22" ),
181 "kicad_drc_chain_bridging_3pad_fail" );
192 static const char* boardText = R
"KICAD(
196 (generator_version "9.99")
205 (segment (start 0 0) (end 10 0) (width 0.2) (layer "F.Cu") (net 1))
206 (segment (start 15 0) (end 25 0) (width 0.2) (layer "F.Cu") (net 2))
207 (segment (start 30 0) (end 40 0) (width 0.2) (layer "F.Cu") (net 3))
208 (footprint "TestFP:XFMR_3PAD" (layer "F.Cu") (at 12.5 0)
209 (property "Reference" "T1")
210 (pad "1" smd rect (at -2.5 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
211 (pad "2" smd rect (at 0 0) (size 0.5 0.5) (layers "F.Cu") (net 2 "/NET_B"))
212 (pad "3" smd rect (at 2.5 0) (size 0.5 0.5) (layers "F.Cu") (net 3 "/NET_C"))
219 runChainLengthDrc( boardText, makeChainBudgetRule(
"Pass",
"0",
"36" ),
220 "kicad_drc_chain_bridging_3net_pass" );
227 runChainLengthDrc( boardText, makeChainBudgetRule(
"Fail",
"0",
"32" ),
228 "kicad_drc_chain_bridging_3net_fail" );
239 static const char* boardText = R
"KICAD(
243 (generator_version "9.99")
251 (segment (start 0 0) (end 10 0) (width 0.2) (layer "F.Cu") (net 1))
252 (segment (start 16 0) (end 26 0) (width 0.2) (layer "F.Cu") (net 2))
253 (footprint "TestFP:DUAL_4PAD" (layer "F.Cu") (at 13 0)
254 (property "Reference" "U1")
255 (pad "1" smd rect (at -3 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
256 (pad "2" smd rect (at -1 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
257 (pad "3" smd rect (at 1 0) (size 0.5 0.5) (layers "F.Cu") (net 2 "/NET_B"))
258 (pad "4" smd rect (at 3 0) (size 0.5 0.5) (layers "F.Cu") (net 2 "/NET_B"))
265 runChainLengthDrc( boardText, makeChainBudgetRule(
"Pass",
"0",
"27" ),
266 "kicad_drc_chain_bridging_4pad_pass" );
272 runChainLengthDrc( boardText, makeChainBudgetRule(
"Fail",
"0",
"24" ),
273 "kicad_drc_chain_bridging_4pad_fail" );
282 static const char* boardText = R
"KICAD(
286 (generator_version "9.99")
294 (segment (start 0 0) (end 10 0) (width 0.2) (layer "F.Cu") (net 1))
295 (segment (start 20 0) (end 30 0) (width 0.2) (layer "F.Cu") (net 2))
296 (footprint "TestFP:STAR_3PAD" (layer "F.Cu") (at 5 5)
297 (property "Reference" "U2")
298 (pad "1" smd rect (at -2 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
299 (pad "2" smd rect (at 0 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
300 (pad "3" smd rect (at 2 0) (size 0.5 0.5) (layers "F.Cu") (net 1 "/NET_A"))
307 runChainLengthDrc( boardText, makeChainBudgetRule(
"Pass",
"0",
"21" ),
308 "kicad_drc_chain_bridging_singlenet_pass" );
309 BOOST_CHECK_MESSAGE( pass == 0,
"Single-net 3-pad footprint must not contribute bridging; "
310 "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