20#include <boost/test/unit_test.hpp>
61 BOOST_REQUIRE_EQUAL( parsedRules.size(), 1 );
62 auto parsed = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( parsedRules[0] );
67 BOOST_CHECK_CLOSE( parsed->GetMinViaDiameter(), original.
GetMinViaDiameter(), 0.0001 );
68 BOOST_CHECK_CLOSE( parsed->GetMaxViaDiameter(), original.
GetMaxViaDiameter(), 0.0001 );
69 BOOST_CHECK_CLOSE( parsed->GetMinViaHoleSize(), original.
GetMinViaHoleSize(), 0.0001 );
70 BOOST_CHECK_CLOSE( parsed->GetMaxViaHoleSize(), original.
GetMaxViaHoleSize(), 0.0001 );
88 BOOST_REQUIRE_EQUAL( parsedRules.size(), 1 );
89 auto parsed = std::dynamic_pointer_cast<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>( parsedRules[0] );
94 BOOST_CHECK_CLOSE( parsed->GetOptWidth(), original.
GetOptWidth(), 0.0001 );
95 BOOST_CHECK_CLOSE( parsed->GetWidthTolerance(), original.
GetWidthTolerance(), 0.0001 );
100 std::vector<std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>> rules;
102 auto rule1 = std::make_shared<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( 0, 0,
"ViaRule", 0.5, 0.8, 0.2, 0.4 );
103 rule1->SetConstraintCode(
"via_style" );
104 rule1->SetRuleCondition(
"A.NetClass == 'Power'" );
105 rules.push_back( rule1 );
107 auto rule2 = std::make_shared<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>( 0, 0,
"TrackRule", 0.3, 0.1 );
108 rule2->SetConstraintCode(
"track_width" );
109 rule2->SetRuleCondition(
"A.NetClass == 'Signal'" );
110 rules.push_back( rule2 );
112 wxString filename =
"test_rules.dru";
118 wxFFile file( filename );
121 file.ReadAll( &content );
124 BOOST_CHECK( content.Contains(
"(version 2)" ) );
125 BOOST_CHECK( content.Contains(
"(rule ViaRule" ) );
126 BOOST_CHECK( content.Contains(
"(constraint via_diameter" ) );
127 BOOST_CHECK( content.Contains(
"(constraint hole_size" ) );
128 BOOST_CHECK( content.Contains(
"(rule TrackRule" ) );
129 BOOST_CHECK( content.Contains(
"(constraint track_width" ) );
132 wxRemoveFile( filename );
138 std::vector<RULE_TREE_NODE> ruleTreeNodeDatas;
146 auto data = std::make_shared<DRC_RE_BASE_CONSTRAINT_DATA>( 1, 0,
"TestRule" );
147 data->SetConstraintCode(
"clearance" );
150 ruleTreeNodeDatas.push_back( node );
153 std::vector<std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>> rules;
157 if( n.m_nodeType !=
RULE )
160 auto d = std::dynamic_pointer_cast<DRC_RE_BASE_CONSTRAINT_DATA>( n.m_nodeData );
163 rules.push_back( d );
171 auto rule = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( 0, 0, 0.2,
"ClearanceRule" );
172 rule->SetConstraintCode(
"clearance" );
178 wxString ruleText = rule->GenerateRule( ctx );
180 BOOST_CHECK( ruleText.Contains(
"(constraint clearance (min 0.2mm))" ) );
183 auto rule2 = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( 0, 0, 10,
"ViaCountRule" );
184 rule2->SetConstraintCode(
"via_count" );
185 ctx.
ruleName = rule2->GetRuleName();
188 ruleText = rule2->GenerateRule( ctx );
189 BOOST_CHECK( ruleText.Contains(
"(constraint via_count (max 10))" ) );
192 auto rule3 = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( 0, 0, 45,
"AngleRule" );
193 rule3->SetConstraintCode(
"track_angle" );
194 ctx.
ruleName = rule3->GetRuleName();
197 ruleText = rule3->GenerateRule( ctx );
198 BOOST_CHECK( ruleText.Contains(
"(constraint track_angle (min 45deg))" ) );
203 auto rule = std::make_shared<DRC_RE_BOOL_INPUT_CONSTRAINT_DATA>( 0, 0,
true,
"DisallowTestRule" );
204 rule->SetConstraintCode(
"disallow" );
210 wxString ruleText = rule->GenerateRule( ctx );
212 BOOST_CHECK( ruleText.Contains(
"(constraint disallow)" ) );
215 auto rule2 = std::make_shared<DRC_RE_BOOL_INPUT_CONSTRAINT_DATA>( 0, 0,
false,
"NoDisallowTestRule" );
216 rule2->SetConstraintCode(
"disallow" );
217 ctx.
ruleName = rule2->GetRuleName();
220 ruleText = rule2->GenerateRule( ctx );
221 BOOST_CHECK( ruleText.IsEmpty() );
228 "(rule \"Clearance Rule\"\n"
229 "\t(constraint clearance (min 0.2mm))\n"
230 "\t(condition \"A.NetClass == 'Power'\"))\n"
231 "(rule \"Via Style Rule\"\n"
232 "\t(constraint via_diameter (min 0.5mm))\n"
233 "\t(constraint hole_size (min 0.3mm))\n"
234 "\t(condition \"A.NetClass == 'Power'\"))\n";
238 BOOST_REQUIRE_EQUAL( parsedRules.size(), 2 );
241 auto clearanceRule = parsedRules[0];
246 auto numericData = std::dynamic_pointer_cast<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( clearanceRule );
248 BOOST_CHECK_CLOSE( numericData->GetNumericInputValue(), 0.2, 0.0001 );
251 auto viaStyleRule = parsedRules[1];
255 auto viaData = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( viaStyleRule );
257 BOOST_CHECK_CLOSE( viaData->GetMinViaDiameter(), 0.5, 0.0001 );
258 BOOST_CHECK_CLOSE( viaData->GetMinViaHoleSize(), 0.3, 0.0001 );
264 bool parserCalled =
false;
266 [&](
const std::shared_ptr<DRC_RULE>& aRule ) -> std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>
271 auto data = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( 0, 0, aRule->m_Name );
272 data->SetConstraintCode(
"custom_clearance" );
278 wxString ruleText =
"(version 1) (rule \"Test Rule\" (constraint clearance (min 1.0mm)) (condition \"A.Type == 'Pad'\"))";
281 BOOST_CHECK( parserCalled );
282 BOOST_REQUIRE_EQUAL( parsedRules.size(), 1 );
292 BOOST_CHECK(
result.isValid );
293 BOOST_CHECK(
result.errors.empty() );
303 BOOST_CHECK( !
result.isValid );
304 BOOST_CHECK( !
result.errors.empty() );
307 bool foundMinMaxError =
false;
308 for(
const auto& error :
result.errors )
310 if( error.find(
"Minimum Via Diameter cannot be greater than Maximum Via Diameter" ) != std::string::npos )
311 foundMinMaxError =
true;
313 BOOST_CHECK( foundMinMaxError );
323 BOOST_CHECK( !
result.isValid );
324 BOOST_CHECK( !
result.errors.empty() );
327 bool foundNegativeError =
false;
328 for(
const auto& error :
result.errors )
330 if( error.find(
"must be greater than 0" ) != std::string::npos )
331 foundNegativeError =
true;
333 BOOST_CHECK( foundNegativeError );
340 [](
const std::shared_ptr<DRC_RULE>& aRule ) -> std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA> {
341 if( aRule->m_Name ==
"Test" )
342 return std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( 0, 0, aRule->m_Name +
"_1" );
348 [](
const std::shared_ptr<DRC_RULE>& aRule ) -> std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA> {
349 if( aRule->m_Name ==
"Test" )
350 return std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( 0, 0, aRule->m_Name +
"_2" );
354 wxString ruleText =
"(version 1) (rule \"Test\" (constraint clearance (min 1.0mm)))";
357 BOOST_REQUIRE_EQUAL( parsedRules.size(), 1 );
368 BOOST_CHECK(
result.isValid );
369 BOOST_CHECK(
result.errors.empty() );
379 BOOST_CHECK( !result1.
isValid );
380 BOOST_CHECK( !result1.
errors.empty() );
382 bool foundToleranceError =
false;
384 for(
const auto& error : result1.
errors )
386 if( error.find(
"Tolerance is too large" ) != std::string::npos )
387 foundToleranceError =
true;
390 BOOST_CHECK( foundToleranceError );
397 BOOST_CHECK( !result2.
isValid );
399 bool foundNegativeError =
false;
401 for(
const auto& error : result2.
errors )
403 if( error.find(
"Tolerance must be greater than or equal to 0" ) != std::string::npos )
404 foundNegativeError =
true;
407 BOOST_CHECK( foundNegativeError );
418 BOOST_CHECK(
result.isValid );
419 BOOST_CHECK(
result.errors.empty() );
429 BOOST_CHECK( !result1.
isValid );
430 BOOST_CHECK( !result1.
errors.empty() );
432 bool foundWidthError =
false;
433 for(
const auto& error : result1.
errors )
435 if( error.find(
"Width Tolerance must be less than Optimum Width" ) != std::string::npos )
436 foundWidthError =
true;
438 BOOST_CHECK( foundWidthError );
445 BOOST_CHECK( !result2.
isValid );
447 bool foundNegativeError =
false;
448 for(
const auto& error : result2.
errors )
450 if( error.find(
"must be greater than or equal to 0" ) != std::string::npos )
451 foundNegativeError =
true;
453 BOOST_CHECK( foundNegativeError );
463 BOOST_CHECK( result1.
isValid );
464 BOOST_CHECK( result1.
errors.empty() );
471 BOOST_CHECK( result2.
isValid );
472 BOOST_CHECK( result2.
errors.empty() );
479 BOOST_CHECK( result3.
isValid );
480 BOOST_CHECK( result3.
errors.empty() );
490 BOOST_CHECK( !
result.isValid );
491 BOOST_CHECK( !
result.errors.empty() );
493 bool foundLayerError =
false;
494 for(
const auto& error :
result.errors )
496 if( error.find(
"At least one layer must be selected" ) != std::string::npos )
497 foundLayerError =
true;
499 BOOST_CHECK( foundLayerError );
508 BOOST_CHECK(
result.isValid );
509 BOOST_CHECK(
result.errors.empty() );
518 BOOST_CHECK( !
result.isValid );
519 BOOST_CHECK( !
result.errors.empty() );
522 bool foundError =
false;
523 for(
const auto& error :
result.errors )
525 if( error.find(
"must be greater than 0" ) != std::string::npos )
528 BOOST_CHECK( foundError );
537 BOOST_CHECK(
result.isValid );
538 BOOST_CHECK(
result.errors.empty() );
548 BOOST_CHECK( !
result.isValid );
549 BOOST_CHECK( !
result.errors.empty() );
551 bool foundError =
false;
552 for(
const auto& error :
result.errors )
554 if( error.find(
"Width Tolerance must be less than Optimum Width" ) != std::string::npos )
557 BOOST_CHECK( foundError );
567 BOOST_CHECK( result1.
isValid );
568 BOOST_CHECK( result1.
errors.empty() );
575 BOOST_CHECK( result2.
isValid );
576 BOOST_CHECK( result2.
errors.empty() );
583 BOOST_CHECK( result3.
isValid );
584 BOOST_CHECK( result3.
errors.empty() );
591 BOOST_CHECK( result4.
isValid );
592 BOOST_CHECK( result4.
errors.empty() );
602 BOOST_CHECK( !
result.isValid );
603 BOOST_CHECK( !
result.errors.empty() );
605 bool foundOrientationError =
false;
606 for(
const auto& error :
result.errors )
608 if( error.find(
"At least one orientation must be selected" ) != std::string::npos )
609 foundOrientationError =
true;
611 BOOST_CHECK( foundOrientationError );
621 BOOST_CHECK( resultTrue.
isValid );
622 BOOST_CHECK( resultTrue.
errors.empty() );
629 BOOST_CHECK( resultFalse.
isValid );
630 BOOST_CHECK( resultFalse.
errors.empty() );
640 BOOST_CHECK(
result.isValid );
641 BOOST_CHECK(
result.errors.empty() );
651 BOOST_CHECK( !result1.
isValid );
652 BOOST_CHECK( !result1.
errors.empty() );
654 bool foundHeightError =
false;
655 for(
const auto& error : result1.
errors )
657 if( error.find(
"Minimum Text Height must be greater than 0" ) != std::string::npos )
658 foundHeightError =
true;
660 BOOST_CHECK( foundHeightError );
667 BOOST_CHECK( !result2.
isValid );
669 bool foundThicknessError =
false;
670 for(
const auto& error : result2.
errors )
672 if( error.find(
"Minimum Text Thickness must be greater than 0" ) != std::string::npos )
673 foundThicknessError =
true;
675 BOOST_CHECK( foundThicknessError );
682 BOOST_CHECK( !result3.
isValid );
689 data.
SetRuleText(
"(constraint clearance (min 0.2mm))" );
693 BOOST_CHECK(
result.isValid );
694 BOOST_CHECK(
result.errors.empty() );
704 BOOST_CHECK( !
result.isValid );
705 BOOST_CHECK( !
result.errors.empty() );
708 bool foundEmptyError =
false;
709 for(
const auto& error :
result.errors )
711 if( error.find(
"Rule text cannot be empty" ) != std::string::npos )
712 foundEmptyError =
true;
714 BOOST_CHECK( foundEmptyError );
740 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
742 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
752 DRC_RULE rule(
"ViaDiameterOnlyRule" );
759 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
761 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
785 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
787 BOOST_REQUIRE_EQUAL( matches.size(), 2 );
817 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
819 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
828 DRC_RULE rule(
"DiffPairWithUncoupledRule" );
843 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
845 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
856 DRC_RULE rule(
"TrackWidthOnlyRule" );
865 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
867 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
886 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
888 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
905 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
907 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
915 DRC_RULE rule(
"MatchedLengthRule" );
928 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
930 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
933 BOOST_CHECK( matches[0].claimedConstraints.count(
SKEW_CONSTRAINT ) > 0 );
942 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
987 "(rule \"Via Test\"\n"
988 " (constraint via_diameter (min 0.5mm) (opt 0.6mm) (max 0.8mm))\n"
989 " (constraint hole_size (min 0.2mm) (opt 0.3mm) (max 0.4mm)))";
992 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
994 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
998 auto viaData = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( entries[0].constraintData );
1001 BOOST_CHECK_CLOSE( viaData->GetMinViaDiameter(), 0.5, 0.0001 );
1002 BOOST_CHECK_CLOSE( viaData->GetMaxViaDiameter(), 0.8, 0.0001 );
1003 BOOST_CHECK_CLOSE( viaData->GetMinViaHoleSize(), 0.2, 0.0001 );
1004 BOOST_CHECK_CLOSE( viaData->GetMaxViaHoleSize(), 0.4, 0.0001 );
1012 "(rule \"Track Test\"\n"
1013 " (constraint track_width (min 0.2mm) (opt 0.25mm) (max 0.3mm)))";
1016 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1018 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1022 auto trackData = std::dynamic_pointer_cast<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>( entries[0].constraintData );
1025 BOOST_CHECK_CLOSE( trackData->GetOptWidth(), 0.25, 0.0001 );
1026 BOOST_CHECK_CLOSE( trackData->GetWidthTolerance(), 0.05, 0.0001 );
1034 "(rule \"Diff Pair Test\"\n"
1035 " (constraint track_width (min 0.2mm) (opt 0.25mm) (max 0.3mm))\n"
1036 " (constraint diff_pair_gap (min 0.1mm) (opt 0.15mm) (max 0.2mm))\n"
1037 " (constraint diff_pair_uncoupled (max 5mm)))";
1040 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1042 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1045 auto dpData = std::dynamic_pointer_cast<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA>( entries[0].constraintData );
1048 BOOST_CHECK_CLOSE( dpData->GetOptWidth(), 0.25, 0.0001 );
1049 BOOST_CHECK_CLOSE( dpData->GetWidthTolerance(), 0.05, 0.0001 );
1050 BOOST_CHECK_CLOSE( dpData->GetOptGap(), 0.15, 0.0001 );
1051 BOOST_CHECK_CLOSE( dpData->GetGapTolerance(), 0.05, 0.0001 );
1052 BOOST_CHECK_CLOSE( dpData->GetMaxUncoupledLength(), 5.0, 0.0001 );
1060 "(rule \"Split Test\"\n"
1061 " (constraint via_diameter (min 0.5mm))\n"
1062 " (constraint hole_size (min 0.2mm))\n"
1063 " (constraint clearance (min 0.15mm)))";
1066 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1068 BOOST_REQUIRE_EQUAL( entries.size(), 2 );
1078 auto numericData = std::dynamic_pointer_cast<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( entries[1].constraintData );
1080 BOOST_CHECK_CLOSE( numericData->GetNumericInputValue(), 0.15, 0.0001 );
1090 "(rule \"clearance_under_fpga\"\n"
1091 " (constraint clearance (min 0.1mm))\n"
1092 " (constraint hole_size (min 0.2mm))\n"
1093 " (constraint via_diameter (min 0.4mm))\n"
1094 " (condition \"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')\"))";
1097 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1100 BOOST_REQUIRE_EQUAL( entries.size(), 2 );
1105 BOOST_CHECK_EQUAL( entries[0].condition,
"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')" );
1110 BOOST_CHECK_EQUAL( entries[1].condition,
"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')" );
1113 auto viaData = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( entries[0].constraintData );
1115 BOOST_CHECK_CLOSE( viaData->GetMinViaDiameter(), 0.4, 0.0001 );
1116 BOOST_CHECK_CLOSE( viaData->GetMinViaHoleSize(), 0.2, 0.0001 );
1119 auto clearanceData = std::dynamic_pointer_cast<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( entries[1].constraintData );
1121 BOOST_CHECK_CLOSE( clearanceData->GetNumericInputValue(), 0.1, 0.0001 );
1129 "(rule \"Text Test\"\n"
1130 " (constraint text_height (min 1mm))\n"
1131 " (constraint text_thickness (min 0.15mm)))";
1134 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1136 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1139 auto textData = std::dynamic_pointer_cast<DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA>( entries[0].constraintData );
1142 BOOST_CHECK_CLOSE( textData->GetMinTextHeight(), 1.0, 0.0001 );
1143 BOOST_CHECK_CLOSE( textData->GetMinTextThickness(), 0.15, 0.0001 );
1151 "(rule \"Length Test\"\n"
1152 " (constraint length (min 10mm) (opt 30mm) (max 50mm)))";
1155 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1157 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1161 auto lengthData = dynamic_pointer_cast<DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA>( entries[0].constraintData );
1163 BOOST_CHECK_CLOSE( lengthData->GetMinimumLength(), 10.0, 0.0001 );
1164 BOOST_CHECK_CLOSE( lengthData->GetOptimumLength(), 30.0, 0.0001 );
1165 BOOST_CHECK_CLOSE( lengthData->GetMaximumLength(), 50.0, 0.0001 );
1173 "(rule \"DP Length Match\"\n"
1174 " (constraint length (min 10mm) (opt 30mm) (max 50mm))\n"
1175 " (constraint skew (max 1mm)))";
1178 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1180 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1185 std::dynamic_pointer_cast<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>( entries[0].constraintData );
1188 BOOST_CHECK_CLOSE( matchedData->GetMinimumLength(), 10.0, 0.0001 );
1189 BOOST_CHECK_CLOSE( matchedData->GetOptimumLength(), 30.0, 0.0001 );
1190 BOOST_CHECK_CLOSE( matchedData->GetMaximumLength(), 50.0, 0.0001 );
1191 BOOST_CHECK_CLOSE( matchedData->GetMaxSkew(), 1.0, 0.0001 );
1199 "(rule \"DP Match RT\"\n"
1200 " (constraint length (min 10mm) (opt 30mm) (max 50mm))\n"
1201 " (constraint skew (max 2.5mm)))";
1204 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1206 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1207 entries[0].wasEdited =
true;
1212 BOOST_CHECK( savedText.Contains(
"length" ) );
1213 BOOST_CHECK( savedText.Contains(
"skew" ) );
1214 BOOST_CHECK( savedText.Contains(
"2.5mm" ) );
1216 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloaded = loader.
LoadFromString( savedText );
1218 BOOST_REQUIRE_EQUAL( reloaded.size(), 1 );
1222 std::dynamic_pointer_cast<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>( reloaded[0].constraintData );
1225 BOOST_CHECK_CLOSE( reloadedData->GetMaxSkew(), 2.5, 0.0001 );
1226 BOOST_CHECK_CLOSE( reloadedData->GetMinimumLength(), 10.0, 0.0001 );
1227 BOOST_CHECK_CLOSE( reloadedData->GetOptimumLength(), 30.0, 0.0001 );
1228 BOOST_CHECK_CLOSE( reloadedData->GetMaximumLength(), 50.0, 0.0001 );
1234 wxString ruleText =
"(version 1)\n"
1235 "(rule \"DP Skew Within\"\n"
1236 " (constraint length (min 10mm) (opt 30mm) (max 50mm))\n"
1237 " (constraint skew (max 1mm) (within_diff_pairs)))";
1240 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1242 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1246 std::dynamic_pointer_cast<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>( entries[0].constraintData );
1249 BOOST_CHECK_CLOSE( matchedData->GetMaxSkew(), 1.0, 0.0001 );
1250 BOOST_CHECK( matchedData->GetWithinDiffPairs() );
1253 entries[0].wasEdited =
true;
1258 BOOST_CHECK( savedText.Contains(
"within_diff_pairs" ) );
1260 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloaded = loader.
LoadFromString( savedText );
1262 BOOST_REQUIRE_EQUAL( reloaded.size(), 1 );
1265 std::dynamic_pointer_cast<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>( reloaded[0].constraintData );
1268 BOOST_CHECK_CLOSE( reloadedData->GetMaxSkew(), 1.0, 0.0001 );
1269 BOOST_CHECK( reloadedData->GetWithinDiffPairs() );
1275 wxString ruleText =
"(version 1)\n"
1276 "(rule \"DP Skew Bus\"\n"
1277 " (constraint length (min 10mm) (opt 30mm) (max 50mm))\n"
1278 " (constraint skew (max 2mm)))";
1281 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1283 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1286 std::dynamic_pointer_cast<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>( entries[0].constraintData );
1289 BOOST_CHECK( !matchedData->GetWithinDiffPairs() );
1292 entries[0].wasEdited =
true;
1297 BOOST_CHECK( !savedText.Contains(
"within_diff_pairs" ) );
1305 "(rule \"Conditional Test\"\n"
1306 " (condition \"A.NetClass == 'Power'\")\n"
1307 " (constraint clearance (min 0.3mm)))";
1310 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1312 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1315 BOOST_CHECK_EQUAL( entries[0].constraintData->GetRuleCondition(),
"A.NetClass == 'Power'" );
1323 "(rule \"Rule A\"\n"
1324 " (constraint clearance (min 0.2mm)))\n"
1325 "(rule \"Rule B\"\n"
1326 " (constraint track_width (min 0.15mm)))\n"
1327 "(rule \"Rule C\"\n"
1328 " (constraint via_diameter (min 0.5mm))\n"
1329 " (constraint hole_size (min 0.3mm)))";
1332 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1334 BOOST_REQUIRE_EQUAL( entries.size(), 3 );
1351 "(rule \"Empty Rule\")";
1354 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1356 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1364 wxString ruleText =
"not valid rule text at all";
1367 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1377 "(rule \"Edge Clearance\"\n"
1378 " (constraint edge_clearance (min 0.5mm)))\n"
1379 "(rule \"Hole Clearance\"\n"
1380 " (constraint hole_clearance (min 0.3mm)))\n"
1381 "(rule \"Courtyard\"\n"
1382 " (constraint courtyard_clearance (min 0.25mm)))";
1385 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1387 BOOST_REQUIRE_EQUAL( entries.size(), 3 );
1407 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1408 numericData->SetRuleName(
"TestClearance" );
1409 numericData->SetConstraintCode(
"clearance" );
1410 numericData->SetNumericInputValue( 0.2 );
1414 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1417 BOOST_CHECK(
result.Contains(
"(version 2)" ) );
1418 BOOST_CHECK(
result.Contains(
"TestClearance" ) );
1419 BOOST_CHECK(
result.Contains(
"clearance" ) );
1428 entry.
originalRuleText =
"(rule \"Preserved Rule\"\n\t(constraint clearance (min 0.5mm)))";
1431 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1432 numericData->SetRuleName(
"Preserved Rule" );
1433 numericData->SetConstraintCode(
"clearance" );
1434 numericData->SetNumericInputValue( 0.5 );
1438 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1450 entry.
originalRuleText =
"(rule \"EditedRule\"\n\t(constraint clearance (min 0.5mm)))";
1453 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1454 numericData->SetRuleName(
"EditedRule" );
1455 numericData->SetConstraintCode(
"clearance" );
1456 numericData->SetNumericInputValue( 0.3 );
1460 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1464 BOOST_CHECK( !
result.Contains(
"0.5mm" ) );
1465 BOOST_CHECK(
result.Contains(
"EditedRule" ) );
1475 auto viaData = std::make_shared<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>();
1476 viaData->SetRuleName(
"ViaTest" );
1477 viaData->SetMinViaDiameter( 0.5 );
1478 viaData->SetMaxViaDiameter( 0.8 );
1479 viaData->SetMinViaHoleSize( 0.2 );
1480 viaData->SetMaxViaHoleSize( 0.4 );
1485 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1488 BOOST_CHECK(
result.Contains(
"ViaTest" ) );
1489 BOOST_CHECK(
result.Contains(
"via_diameter" ) );
1490 BOOST_CHECK(
result.Contains(
"hole_size" ) );
1496 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries;
1501 auto data1 = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1502 data1->SetRuleName(
"RuleA" );
1503 data1->SetConstraintCode(
"clearance" );
1504 data1->SetNumericInputValue( 0.2 );
1507 entries.push_back( entry1 );
1512 auto data2 = std::make_shared<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>();
1513 data2->SetRuleName(
"RuleB" );
1514 data2->SetOptWidth( 0.2 );
1515 data2->SetWidthTolerance( 0.1 );
1518 entries.push_back( entry2 );
1524 BOOST_CHECK(
result.Contains(
"RuleA" ) );
1525 BOOST_CHECK(
result.Contains(
"RuleB" ) );
1528 size_t posA =
result.Find(
"RuleA" );
1529 size_t posB =
result.Find(
"RuleB" );
1530 BOOST_CHECK( posA < posB );
1538 entry.
ruleName =
"ConditionalRule";
1539 entry.
condition =
"A.NetClass == 'Power'";
1541 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1542 numericData->SetRuleName(
"ConditionalRule" );
1543 numericData->SetConstraintCode(
"clearance" );
1544 numericData->SetRuleCondition(
"A.NetClass == 'Power'" );
1545 numericData->SetNumericInputValue( 0.3 );
1550 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1553 BOOST_CHECK(
result.Contains(
"ConditionalRule" ) );
1554 BOOST_CHECK(
result.Contains(
"condition" ) );
1555 BOOST_CHECK(
result.Contains(
"Power" ) );
1562 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries;
1565 BOOST_CHECK(
result.Contains(
"(version 2)" ) );
1580 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1584 BOOST_CHECK(
result.Contains(
"(version 2)" ) );
1585 BOOST_CHECK( !
result.Contains(
"Null Data Rule" ) );
1591 wxString originalText =
1593 "(rule \"RoundTripTest\"\n"
1594 " (constraint clearance (min 0.25mm)))";
1597 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( originalText );
1599 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1603 entries[0].wasEdited =
true;
1610 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloadedEntries = loader.
LoadFromString( savedText );
1612 BOOST_REQUIRE_EQUAL( reloadedEntries.size(), 1 );
1622 const wxString originalName = wxS(
"Annular width: LEDs" );
1629 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1630 numericData->SetRuleName( originalName );
1631 numericData->SetConstraintCode(
"annular_width" );
1632 numericData->SetNumericInputValue( 0.085 );
1636 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1640 BOOST_CHECK(
result.Contains( wxS(
"\"Annular width: LEDs\"" ) ) );
1641 BOOST_CHECK( !
result.Contains( wxS(
"Annular_width__LEDs" ) ) );
1647 BOOST_REQUIRE_EQUAL( reloaded.size(), 1 );
1657 entry.
ruleName = wxS(
"My_Bare_Rule-1.0" );
1660 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1661 numericData->SetRuleName( entry.
ruleName );
1662 numericData->SetConstraintCode(
"clearance" );
1663 numericData->SetNumericInputValue( 0.2 );
1667 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1670 BOOST_CHECK(
result.Contains( wxS(
"(rule My_Bare_Rule-1.0\n" ) ) );
1671 BOOST_CHECK( !
result.Contains( wxS(
"\"My_Bare_Rule-1.0\"" ) ) );
1681 entry.
ruleName = wxS(
"3.3V_Power" );
1684 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1685 numericData->SetRuleName( entry.
ruleName );
1686 numericData->SetConstraintCode(
"clearance" );
1687 numericData->SetNumericInputValue( 0.2 );
1691 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1694 BOOST_CHECK(
result.Contains( wxS(
"\"3.3V_Power\"" ) ) );
1698 BOOST_REQUIRE_EQUAL( reloaded.size(), 1 );
1710 auto dpData = std::make_shared<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA>();
1711 dpData->SetRuleName(
"DiffPairTest" );
1712 dpData->SetOptWidth( 0.25 );
1713 dpData->SetWidthTolerance( 0.05 );
1714 dpData->SetOptGap( 0.15 );
1715 dpData->SetGapTolerance( 0.05 );
1716 dpData->SetMaxUncoupledLength( 5.0 );
1721 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1724 BOOST_CHECK(
result.Contains(
"DiffPairTest" ) );
1725 BOOST_CHECK(
result.Contains(
"track_width" ) );
1726 BOOST_CHECK(
result.Contains(
"diff_pair_gap" ) );
1739 "(rule \"PTH to Track Clearance\"\n"
1740 " (constraint hole_clearance (min 1.0mm))\n"
1741 " (condition \"A.Type == 'Pad' && A.Pad_Type == 'Through-hole' && B.Type =='Track'\"))\n"
1742 "(rule \"Max Drill Hole Size Mechanical\"\n"
1743 " (constraint hole (max 2.0mm))\n"
1744 " (condition \"A.Type == 'Pad'\"))";
1747 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1749 BOOST_REQUIRE_GE( entries.size(), 2 );
1754 BOOST_CHECK( !entries[0].condition.IsEmpty() );
1766 "(rule board_edge\n"
1767 " (constraint edge_clearance (min 1mm))\n"
1768 " (condition \"A.memberOf('board_edge')\")\n"
1769 " (severity ignore))";
1772 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1774 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1785 "(rule high_current_netclass\n"
1786 " (constraint connection_width (min 0.16mm))\n"
1787 " (condition \"A.NetClass == 'High_current'\"))\n"
1788 "(rule high_current_area\n"
1789 " (constraint connection_width (min 0.16mm))\n"
1790 " (condition \"A.insideArea('high_current')\"))";
1793 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1795 BOOST_REQUIRE_EQUAL( entries.size(), 2 );
1802 BOOST_CHECK( !entries[0].condition.IsEmpty() );
1803 BOOST_CHECK( !entries[1].condition.IsEmpty() );
1810 wxString originalText =
1812 "(rule ClearanceRule\n"
1813 " (constraint clearance (min 0.2mm))\n"
1814 " (condition \"A.NetClass == 'Power'\"))\n"
1815 "(rule TrackWidthRule\n"
1816 " (constraint track_width (min 0.15mm) (opt 0.2mm) (max 0.3mm)))";
1819 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( originalText );
1821 BOOST_REQUIRE_EQUAL( entries.size(), 2 );
1824 for(
auto& entry : entries )
1825 entry.wasEdited =
true;
1832 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloadedEntries = loader.
LoadFromString( savedText );
1834 BOOST_REQUIRE_EQUAL( reloadedEntries.size(), 2 );
1848 wxString originalText =
1850 "(rule \"Via Style\"\n"
1851 " (constraint via_diameter (min 0.5mm) (opt 0.6mm) (max 0.8mm))\n"
1852 " (constraint hole_size (min 0.2mm) (opt 0.3mm) (max 0.4mm)))";
1855 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( originalText );
1857 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1860 auto viaData = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( entries[0].constraintData );
1863 double originalMinDia = viaData->GetMinViaDiameter();
1864 double originalMinHole = viaData->GetMinViaHoleSize();
1867 entries[0].wasEdited =
true;
1872 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloadedEntries = loader.
LoadFromString( savedText );
1874 BOOST_REQUIRE_EQUAL( reloadedEntries.size(), 1 );
1877 auto reloadedViaData =
1878 std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( reloadedEntries[0].constraintData );
1881 BOOST_CHECK_CLOSE( reloadedViaData->GetMinViaDiameter(), originalMinDia, 0.0001 );
1882 BOOST_CHECK_CLOSE( reloadedViaData->GetMinViaHoleSize(), originalMinHole, 0.0001 );
1890 "(rule \"Rule A\"\n"
1891 " (constraint clearance (min 0.2mm)))\n"
1892 "(rule \"Rule B\"\n"
1893 " (constraint via_diameter (min 0.5mm))\n"
1894 " (constraint hole_size (min 0.2mm))\n"
1895 " (constraint track_width (min 0.15mm)))\n"
1896 "(rule \"Rule C\"\n"
1897 " (constraint edge_clearance (min 0.3mm)))";
1900 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1903 BOOST_REQUIRE_GE( entries.size(), 4 );
1906 int ruleACount = 0, ruleBCount = 0, ruleCCount = 0;
1908 for(
const auto& entry : entries )
1910 if( entry.ruleName ==
"Rule A" )
1912 else if( entry.ruleName ==
"Rule B" )
1914 else if( entry.ruleName ==
"Rule C" )
1919 BOOST_CHECK_GE( ruleBCount, 2 );
1923 int lastAIndex = -1, firstBIndex = entries.size(), lastBIndex = -1, firstCIndex = entries.size();
1925 for(
size_t i = 0; i < entries.size(); i++ )
1927 if( entries[i].ruleName ==
"Rule A" )
1929 else if( entries[i].ruleName ==
"Rule B" )
1931 if( (
int)i < firstBIndex )
1936 else if( entries[i].ruleName ==
"Rule C" )
1938 if( (
int)i < firstCIndex )
1943 BOOST_CHECK( lastAIndex < firstBIndex );
1944 BOOST_CHECK( lastBIndex < firstCIndex );
1956 wxString expr =
"A.NetName == 'VCC'";
1959 BOOST_CHECK( !expr.IsEmpty() );
1960 BOOST_CHECK( expr.Contains(
"NetName" ) );
1961 BOOST_CHECK( expr.Contains(
"VCC" ) );
1967 wxString expr =
"A.NetName == 'VCC' && B.NetClass == 'Power'";
1970 BOOST_CHECK( expr.Contains(
"&&" ) );
1971 BOOST_CHECK( expr.Contains(
"NetName" ) );
1972 BOOST_CHECK( expr.Contains(
"NetClass" ) );
1978 wxString expr =
"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')";
1981 BOOST_CHECK( expr.Contains(
"||" ) );
1982 BOOST_CHECK( expr.Contains(
"intersectsArea" ) );
1988 wxString expr =
"A.NetClass == 'Power' && !A.intersectsArea('NoRouting')";
1991 BOOST_CHECK( expr.Contains(
"&&" ) );
1992 BOOST_CHECK( expr.Contains(
"!" ) );
1998 wxString expr =
"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')";
2001 BOOST_CHECK( expr.Contains(
"||" ) );
2002 BOOST_CHECK( expr.Contains(
"underFPGA" ) );
2003 BOOST_CHECK( expr.Contains(
"underDDR" ) );
2009 while( ( pos = expr.find(
"||", pos ) ) != wxString::npos )
2032 for(
KICAD_T type : excludedTypes )
2039 BOOST_CHECK(
true );
2043 BOOST_FAIL(
"Excluded type not handled in filter" );
2048 for(
KICAD_T type : includedTypes )
2055 BOOST_FAIL(
"Included type incorrectly matched by filter" );
2059 BOOST_CHECK(
true );
2072 entry.
condition =
"A.NetClass == 'Power'";
2076 auto data = std::make_shared<DRC_RE_SILK_TO_SOLDERMASK_CLEARANCE_CONSTRAINT_DATA>();
2077 data->SetRuleName(
"SilkMaskTest" );
2078 data->SetConstraintCode(
"silk_clearance" );
2079 data->SetRuleCondition(
"A.NetClass == 'Power'" );
2080 data->SetNumericInputValue( 0.15 );
2084 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
2088 BOOST_CHECK(
result.Contains(
"L == 'F.Mask'" ) );
2089 BOOST_CHECK(
result.Contains(
"Power" ) );
2090 BOOST_CHECK( !
result.Contains(
"(layer" ) );
2095 while( ( pos =
result.find(
"(condition", pos ) ) != wxString::npos )
2113 auto data = std::make_shared<DRC_RE_SILK_TO_SOLDERMASK_CLEARANCE_CONSTRAINT_DATA>();
2114 data->SetRuleName(
"SilkMaskSimple" );
2115 data->SetConstraintCode(
"silk_clearance" );
2116 data->SetNumericInputValue( 0.1 );
2120 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
2123 BOOST_CHECK(
result.Contains(
"L == 'B.Mask'" ) );
2124 BOOST_CHECK(
result.Contains(
"(condition" ) );
2125 BOOST_CHECK( !
result.Contains(
"(layer" ) );
2137 auto data = std::make_shared<DRC_RE_SILK_TO_SILK_CLEARANCE_CONSTRAINT_DATA>();
2138 data->SetRuleName(
"SilkSilkBoth" );
2139 data->SetConstraintCode(
"silk_clearance" );
2140 data->SetNumericInputValue( 0.2 );
2144 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
2147 BOOST_CHECK(
result.Contains(
"L == 'F.SilkS' || L == 'B.SilkS'" ) );
2148 BOOST_CHECK(
result.Contains(
"(condition" ) );
2149 BOOST_CHECK( !
result.Contains(
"(layer" ) );
2161 auto data = std::make_shared<DRC_RE_SILK_TO_SILK_CLEARANCE_CONSTRAINT_DATA>();
2162 data->SetRuleName(
"SilkSilkFront" );
2163 data->SetConstraintCode(
"silk_clearance" );
2164 data->SetNumericInputValue( 0.2 );
2168 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
2171 BOOST_CHECK(
result.Contains(
"L == 'F.SilkS'" ) );
2172 BOOST_CHECK( !
result.Contains(
"B.SilkS" ) );
2173 BOOST_CHECK(
result.Contains(
"(condition" ) );
2174 BOOST_CHECK( !
result.Contains(
"(layer" ) );
2183 entry.
condition =
"A.NetClass == 'Signal'";
2187 auto data = std::make_shared<DRC_RE_SILK_TO_SILK_CLEARANCE_CONSTRAINT_DATA>();
2188 data->SetRuleName(
"SilkSilkCond" );
2189 data->SetConstraintCode(
"silk_clearance" );
2190 data->SetRuleCondition(
"A.NetClass == 'Signal'" );
2191 data->SetNumericInputValue( 0.2 );
2195 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
2198 BOOST_CHECK(
result.Contains(
"L == 'F.SilkS'" ) );
2199 BOOST_CHECK(
result.Contains(
"Signal" ) );
2204 while( ( pos =
result.find(
"(condition", pos ) ) != wxString::npos )
2217 BOOST_CHECK( result1.
isValid );
2218 BOOST_CHECK( result1.
errors.empty() );
2223 BOOST_CHECK( result2.
isValid );
2224 BOOST_CHECK( result2.
errors.empty() );
2232 BOOST_CHECK( !
result.isValid );
2233 BOOST_CHECK( !
result.errors.empty() );
2235 bool foundError =
false;
2236 for(
const auto& error :
result.errors )
2238 if( error.find(
"At least one via type must be selected" ) != std::string::npos )
2241 BOOST_CHECK( foundError );
2253 BOOST_REQUIRE_EQUAL( clauses.size(), 1 );
2254 BOOST_CHECK( clauses[0].Contains(
"disallow via" ) );
2255 BOOST_CHECK( !clauses[0].Contains(
"through_via" ) );
2260 BOOST_REQUIRE_EQUAL( clauses.size(), 1 );
2261 BOOST_CHECK( clauses[0].Contains(
"micro_via" ) );
2262 BOOST_CHECK( !clauses[0].Contains(
"through_via" ) );
2263 BOOST_CHECK( !clauses[0].Contains(
"blind_via" ) );
2264 BOOST_CHECK( !clauses[0].Contains(
"buried_via" ) );
2269 BOOST_REQUIRE_EQUAL( clauses.size(), 1 );
2270 BOOST_CHECK( clauses[0].Contains(
"through_via" ) );
2271 BOOST_CHECK( clauses[0].Contains(
"blind_via" ) );
2272 BOOST_CHECK( !clauses[0].Contains(
"micro_via" ) );
2273 BOOST_CHECK( !clauses[0].Contains(
"buried_via" ) );
2278 BOOST_CHECK( clauses.empty() );
2284 wxString originalText =
"(version 1)\n"
2285 "(rule \"ViasUnderSmdTest\"\n"
2286 " (constraint disallow micro_via)\n"
2287 " (condition \"A.Pad_Type == 'SMD' && A.insideArea('BGA*')\"))";
2290 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( originalText );
2292 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2295 auto viaData = std::dynamic_pointer_cast<DRC_RE_VIAS_UNDER_SMD_CONSTRAINT_DATA>( entries[0].constraintData );
2299 BOOST_CHECK( !viaData->GetDisallowThroughVias() );
2300 BOOST_CHECK( viaData->GetDisallowMicroVias() );
2301 BOOST_CHECK( !viaData->GetDisallowBlindVias() );
2302 BOOST_CHECK( !viaData->GetDisallowBuriedVias() );
2305 entries[0].wasEdited =
true;
2310 BOOST_CHECK( savedText.Contains(
"micro_via" ) );
2311 BOOST_CHECK( !savedText.Contains(
"through_via" ) );
2312 BOOST_CHECK( !savedText.Contains(
"blind_via" ) );
2313 BOOST_CHECK( !savedText.Contains(
"buried_via" ) );
2316 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloadedEntries = loader.
LoadFromString( savedText );
2317 BOOST_REQUIRE_EQUAL( reloadedEntries.size(), 1 );
2320 std::dynamic_pointer_cast<DRC_RE_VIAS_UNDER_SMD_CONSTRAINT_DATA>( reloadedEntries[0].constraintData );
2323 BOOST_CHECK( !reloadedData->GetDisallowThroughVias() );
2324 BOOST_CHECK( reloadedData->GetDisallowMicroVias() );
2325 BOOST_CHECK( !reloadedData->GetDisallowBlindVias() );
2326 BOOST_CHECK( !reloadedData->GetDisallowBuriedVias() );
2329 wxString blanketText =
"(version 1)\n"
2330 "(rule \"BlanketVia\"\n"
2331 " (constraint disallow via)\n"
2332 " (condition \"A.Pad_Type == 'SMD' && A.insideArea('BGA*')\"))";
2335 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2337 auto blanketData = std::dynamic_pointer_cast<DRC_RE_VIAS_UNDER_SMD_CONSTRAINT_DATA>( entries[0].constraintData );
2340 BOOST_CHECK( blanketData->GetDisallowThroughVias() );
2341 BOOST_CHECK( blanketData->GetDisallowMicroVias() );
2342 BOOST_CHECK( blanketData->GetDisallowBlindVias() );
2343 BOOST_CHECK( blanketData->GetDisallowBuriedVias() );
2346 wxString multiText =
"(version 1)\n"
2347 "(rule \"TwoVias\"\n"
2348 " (constraint disallow through_via blind_via)\n"
2349 " (condition \"A.Pad_Type == 'SMD' && A.insideArea('BGA*')\"))";
2352 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2354 auto multiData = std::dynamic_pointer_cast<DRC_RE_VIAS_UNDER_SMD_CONSTRAINT_DATA>( entries[0].constraintData );
2357 BOOST_CHECK( multiData->GetDisallowThroughVias() );
2358 BOOST_CHECK( !multiData->GetDisallowMicroVias() );
2359 BOOST_CHECK( multiData->GetDisallowBlindVias() );
2360 BOOST_CHECK( !multiData->GetDisallowBuriedVias() );
2362 entries[0].wasEdited =
true;
2365 BOOST_CHECK( savedText.Contains(
"through_via" ) );
2366 BOOST_CHECK( savedText.Contains(
"blind_via" ) );
2367 BOOST_CHECK( !savedText.Contains(
"micro_via" ) );
2368 BOOST_CHECK( !savedText.Contains(
"buried_via" ) );
2374 wxString ruleText =
"(version 1)\n"
2375 "(rule \"Angled\"\n"
2376 " (constraint assertion \"A.Orientation == 46 deg\")\n"
2380 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
2382 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2385 auto customData = std::dynamic_pointer_cast<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( entries[0].constraintData );
2387 BOOST_CHECK( customData->GetRuleText().Contains( wxS(
"46 deg" ) ) );
2388 BOOST_CHECK( !customData->GetRuleText().Contains( wxS(
"Angled" ) ) );
2391 wxString ruleTextUnquoted =
"(version 1)\n"
2393 " (constraint assertion \"A.Orientation == 46 deg\")\n"
2398 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2401 auto customDataUnquoted =
2402 std::dynamic_pointer_cast<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( entries[0].constraintData );
2404 BOOST_CHECK( customDataUnquoted->GetRuleText().Contains( wxS(
"46 deg" ) ) );
2405 BOOST_CHECK( !customDataUnquoted->GetRuleText().Contains( wxS(
"Angled" ) ) );
2410 wxString ruleText =
"(version 1)\n"
2411 "(rule \"Standard\"\n"
2412 " (constraint assertion \"A.Orientation == 0 deg || A.Orientation == 90 deg\")\n"
2416 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
2418 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2422 std::dynamic_pointer_cast<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA>( entries[0].constraintData );
2424 BOOST_CHECK( orientData->GetIsZeroDegreesAllowed() );
2425 BOOST_CHECK( orientData->GetIsNinetyDegreesAllowed() );
2426 BOOST_CHECK( !orientData->GetIsOneEightyDegreesAllowed() );
2427 BOOST_CHECK( !orientData->GetIsAllDegreesAllowed() );
2430 wxString singleLine =
"(version 1) (rule \"SingleLine\" (constraint assertion \"A.Orientation == 0 deg || "
2431 "A.Orientation == 90 deg\"))";
2435 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2438 auto singleLineData =
2439 std::dynamic_pointer_cast<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA>( entries[0].constraintData );
2441 BOOST_CHECK( singleLineData->GetIsZeroDegreesAllowed() );
2442 BOOST_CHECK( singleLineData->GetIsNinetyDegreesAllowed() );
2443 BOOST_CHECK( !singleLineData->GetIsOneEightyDegreesAllowed() );
2444 BOOST_CHECK( !singleLineData->GetIsAllDegreesAllowed() );
2449 wxString ruleText =
"(version 1)\n"
2450 "(rule \"AllAngles\"\n"
2451 " (constraint assertion \"A.Orientation == 0 deg || A.Orientation == 90 deg || "
2452 "A.Orientation == 180 deg || A.Orientation == 270 deg\")\n"
2456 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
2458 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2462 std::dynamic_pointer_cast<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA>( entries[0].constraintData );
2464 BOOST_CHECK( orientData->GetIsAllDegreesAllowed() );
2465 BOOST_CHECK( orientData->GetIsZeroDegreesAllowed() );
2466 BOOST_CHECK( orientData->GetIsNinetyDegreesAllowed() );
2467 BOOST_CHECK( orientData->GetIsOneEightyDegreesAllowed() );
2468 BOOST_CHECK( orientData->GetIsTwoSeventyDegreesAllowed() );
2473 wxString ruleText =
"(version 1)\n"
2474 "(rule \"InnerLayers\"\n"
2475 " (constraint assertion \"A.Layer == 'F.Cu' || A.Layer == 'In1.Cu'\")\n"
2479 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
2481 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2484 auto customData = std::dynamic_pointer_cast<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( entries[0].constraintData );
2486 BOOST_CHECK( customData->GetRuleText().Contains( wxS(
"In1.Cu" ) ) );
2491 wxString ruleText =
"(version 1)\n"
2492 "(rule \"StandardLayers\"\n"
2493 " (constraint assertion \"A.Layer == 'F.Cu' || A.Layer == 'B.Cu'\")\n"
2497 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
2499 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2502 auto layerData = std::dynamic_pointer_cast<DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA>( entries[0].constraintData );
2504 BOOST_CHECK( layerData->GetTopLayerEnabled() );
2505 BOOST_CHECK( layerData->GetBottomLayerEnabled() );
MINOPTMAX< int > & Value()
Maps DRC rule constraints to appropriate editor panels.
DRC_RULE_EDITOR_CONSTRAINT_NAME GetPanelForConstraint(DRC_CONSTRAINT_T aConstraintType)
Get the panel type for a single constraint.
bool CanPanelLoad(DRC_RULE_EDITOR_CONSTRAINT_NAME aPanel, const std::set< DRC_CONSTRAINT_T > &aConstraints)
Check if a specific panel type can load a set of constraints.
std::vector< DRC_PANEL_MATCH > MatchRule(const DRC_RULE &aRule)
Match a DRC rule to one or more panel types.
VALIDATION_RESULT Validate() const override
Validates the constraint data.
VALIDATION_RESULT Validate() const override
Validates the constraint data.
wxString GetConstraintCode() const
void SetConstraintCode(const wxString &aCode)
wxString GetRuleCondition()
void SetRuleCondition(const wxString &aRuleCondition)
Simple constraint data object used by custom rules.
void SetRuleText(const wxString &aText)
VALIDATION_RESULT Validate() const override
Validates the constraint data.
VALIDATION_RESULT Validate() const override
Validates the constraint data.
VALIDATION_RESULT Validate() const override
Validates the constraint data.
VALIDATION_RESULT Validate() const override
Validates the constraint data.
double GetWidthTolerance()
wxString GenerateRule(const RULE_GENERATION_CONTEXT &aContext) override
VALIDATION_RESULT Validate() const override
Validates the constraint data.
VALIDATION_RESULT Validate() const override
Validates the constraint data.
std::vector< wxString > GetConstraintClauses(const RULE_GENERATION_CONTEXT &aContext) const override
Returns just the constraint clauses without the rule wrapper.
double GetMaxViaDiameter()
double GetMinViaHoleSize()
double GetMinViaDiameter()
double GetMaxViaHoleSize()
VALIDATION_RESULT Validate() const override
Validates the constraint data.
wxString GenerateRule(const RULE_GENERATION_CONTEXT &aContext) override
static bool SaveRules(const wxString &aFilename, const std::vector< std::shared_ptr< DRC_RE_BASE_CONSTRAINT_DATA > > &aRules, const BOARD *aBoard)
static void RegisterRuleConverter(RuleConverter aConverter)
static std::vector< std::shared_ptr< DRC_RE_BASE_CONSTRAINT_DATA > > ParseRules(const wxString &aRules)
Loads DRC rules from .kicad_dru files and converts them to panel entries.
std::vector< DRC_RE_LOADED_PANEL_ENTRY > LoadFromString(const wxString &aRulesText)
Load rules from a text string.
Saves DRC panel entries back to .kicad_dru files.
wxString GenerateRulesText(const std::vector< DRC_RE_LOADED_PANEL_ENTRY > &aEntries, const BOARD *aBoard=nullptr)
Generate rule text from panel entries.
void AddConstraint(DRC_CONSTRAINT &aConstraint)
LSET is a set of PCB_LAYER_IDs.
wxString GetRuleName()
Get the name of the rule.
@ VIA_DIAMETER_CONSTRAINT
@ DIFF_PAIR_GAP_CONSTRAINT
@ SILK_CLEARANCE_CONSTRAINT
@ EDGE_CLEARANCE_CONSTRAINT
@ TEXT_THICKNESS_CONSTRAINT
@ MAX_UNCOUPLED_CONSTRAINT
@ HOLE_CLEARANCE_CONSTRAINT
@ HOLE_TO_HOLE_CONSTRAINT
@ SILK_TO_SOLDERMASK_CLEARANCE
@ MINIMUM_CONNECTION_WIDTH
@ MINIMUM_TEXT_HEIGHT_AND_THICKNESS
@ COPPER_TO_HOLE_CLEARANCE
@ MATCHED_LENGTH_DIFF_PAIR
@ COPPER_TO_EDGE_CLEARANCE
Represents a rule loaded from a .kicad_dru file and mapped to a panel.
wxString originalRuleText
std::shared_ptr< DRC_RE_BASE_CONSTRAINT_DATA > constraintData
DRC_RULE_EDITOR_CONSTRAINT_NAME panelType
wxString conditionExpression
Structure representing a node in a rule tree, collection of this used for building the rule tree.
std::shared_ptr< RULE_EDITOR_DATA_BASE > m_nodeData
Result of a validation operation.
std::vector< wxString > errors
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_CASE(RoundTripViaStyle)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_GENERATOR_T
class PCB_GENERATOR, generator on a layer
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
@ PCB_ZONE_T
class ZONE, a copper pour area
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_NETINFO_T
class NETINFO_ITEM, a description of a net
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)