24#include <boost/test/unit_test.hpp>
65 BOOST_REQUIRE_EQUAL( parsedRules.size(), 1 );
66 auto parsed = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( parsedRules[0] );
71 BOOST_CHECK_CLOSE( parsed->GetMinViaDiameter(), original.
GetMinViaDiameter(), 0.0001 );
72 BOOST_CHECK_CLOSE( parsed->GetMaxViaDiameter(), original.
GetMaxViaDiameter(), 0.0001 );
73 BOOST_CHECK_CLOSE( parsed->GetMinViaHoleSize(), original.
GetMinViaHoleSize(), 0.0001 );
74 BOOST_CHECK_CLOSE( parsed->GetMaxViaHoleSize(), original.
GetMaxViaHoleSize(), 0.0001 );
92 BOOST_REQUIRE_EQUAL( parsedRules.size(), 1 );
93 auto parsed = std::dynamic_pointer_cast<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>( parsedRules[0] );
98 BOOST_CHECK_CLOSE( parsed->GetOptWidth(), original.
GetOptWidth(), 0.0001 );
99 BOOST_CHECK_CLOSE( parsed->GetWidthTolerance(), original.
GetWidthTolerance(), 0.0001 );
104 std::vector<std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>> rules;
106 auto rule1 = std::make_shared<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( 0, 0,
"ViaRule", 0.5, 0.8, 0.2, 0.4 );
107 rule1->SetConstraintCode(
"via_style" );
108 rule1->SetRuleCondition(
"A.NetClass == 'Power'" );
109 rules.push_back( rule1 );
111 auto rule2 = std::make_shared<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>( 0, 0,
"TrackRule", 0.3, 0.1 );
112 rule2->SetConstraintCode(
"track_width" );
113 rule2->SetRuleCondition(
"A.NetClass == 'Signal'" );
114 rules.push_back( rule2 );
116 wxString filename =
"test_rules.dru";
122 wxFFile file( filename );
125 file.ReadAll( &content );
128 BOOST_CHECK( content.Contains(
"(version 1)" ) );
129 BOOST_CHECK( content.Contains(
"(rule ViaRule" ) );
130 BOOST_CHECK( content.Contains(
"(constraint via_diameter" ) );
131 BOOST_CHECK( content.Contains(
"(constraint hole_size" ) );
132 BOOST_CHECK( content.Contains(
"(rule TrackRule" ) );
133 BOOST_CHECK( content.Contains(
"(constraint track_width" ) );
136 wxRemoveFile( filename );
142 std::vector<RULE_TREE_NODE> ruleTreeNodeDatas;
150 auto data = std::make_shared<DRC_RE_BASE_CONSTRAINT_DATA>( 1, 0,
"TestRule" );
151 data->SetConstraintCode(
"clearance" );
154 ruleTreeNodeDatas.push_back( node );
157 std::vector<std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>> rules;
161 if( n.m_nodeType !=
RULE )
164 auto d = std::dynamic_pointer_cast<DRC_RE_BASE_CONSTRAINT_DATA>( n.m_nodeData );
167 rules.push_back( d );
175 auto rule = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( 0, 0, 0.2,
"ClearanceRule" );
176 rule->SetConstraintCode(
"clearance" );
182 wxString ruleText = rule->GenerateRule( ctx );
184 BOOST_CHECK( ruleText.Contains(
"(constraint clearance (min 0.2mm))" ) );
187 auto rule2 = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( 0, 0, 10,
"ViaCountRule" );
188 rule2->SetConstraintCode(
"via_count" );
189 ctx.
ruleName = rule2->GetRuleName();
192 ruleText = rule2->GenerateRule( ctx );
193 BOOST_CHECK( ruleText.Contains(
"(constraint via_count (max 10))" ) );
196 auto rule3 = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( 0, 0, 45,
"AngleRule" );
197 rule3->SetConstraintCode(
"track_angle" );
198 ctx.
ruleName = rule3->GetRuleName();
201 ruleText = rule3->GenerateRule( ctx );
202 BOOST_CHECK( ruleText.Contains(
"(constraint track_angle (min 45deg))" ) );
207 auto rule = std::make_shared<DRC_RE_BOOL_INPUT_CONSTRAINT_DATA>( 0, 0,
true,
"DisallowTestRule" );
208 rule->SetConstraintCode(
"disallow" );
214 wxString ruleText = rule->GenerateRule( ctx );
216 BOOST_CHECK( ruleText.Contains(
"(constraint disallow)" ) );
219 auto rule2 = std::make_shared<DRC_RE_BOOL_INPUT_CONSTRAINT_DATA>( 0, 0,
false,
"NoDisallowTestRule" );
220 rule2->SetConstraintCode(
"disallow" );
221 ctx.
ruleName = rule2->GetRuleName();
224 ruleText = rule2->GenerateRule( ctx );
225 BOOST_CHECK( ruleText.IsEmpty() );
232 "(rule \"Clearance Rule\"\n"
233 "\t(constraint clearance (min 0.2mm))\n"
234 "\t(condition \"A.NetClass == 'Power'\"))\n"
235 "(rule \"Via Style Rule\"\n"
236 "\t(constraint via_diameter (min 0.5mm))\n"
237 "\t(constraint hole_size (min 0.3mm))\n"
238 "\t(condition \"A.NetClass == 'Power'\"))\n";
242 BOOST_REQUIRE_EQUAL( parsedRules.size(), 2 );
245 auto clearanceRule = parsedRules[0];
250 auto numericData = std::dynamic_pointer_cast<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( clearanceRule );
252 BOOST_CHECK_CLOSE( numericData->GetNumericInputValue(), 0.2, 0.0001 );
255 auto viaStyleRule = parsedRules[1];
259 auto viaData = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( viaStyleRule );
261 BOOST_CHECK_CLOSE( viaData->GetMinViaDiameter(), 0.5, 0.0001 );
262 BOOST_CHECK_CLOSE( viaData->GetMinViaHoleSize(), 0.3, 0.0001 );
268 bool parserCalled =
false;
270 [&](
const std::shared_ptr<DRC_RULE>& aRule ) -> std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>
275 auto data = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( 0, 0, aRule->m_Name );
276 data->SetConstraintCode(
"custom_clearance" );
282 wxString ruleText =
"(version 1) (rule \"Test Rule\" (constraint clearance (min 1.0mm)) (condition \"A.Type == 'Pad'\"))";
285 BOOST_CHECK( parserCalled );
286 BOOST_REQUIRE_EQUAL( parsedRules.size(), 1 );
296 BOOST_CHECK(
result.isValid );
297 BOOST_CHECK(
result.errors.empty() );
307 BOOST_CHECK( !
result.isValid );
308 BOOST_CHECK( !
result.errors.empty() );
311 bool foundMinMaxError =
false;
312 for(
const auto& error :
result.errors )
314 if( error.find(
"Minimum Via Diameter cannot be greater than Maximum Via Diameter" ) != std::string::npos )
315 foundMinMaxError =
true;
317 BOOST_CHECK( foundMinMaxError );
327 BOOST_CHECK( !
result.isValid );
328 BOOST_CHECK( !
result.errors.empty() );
331 bool foundNegativeError =
false;
332 for(
const auto& error :
result.errors )
334 if( error.find(
"must be greater than 0" ) != std::string::npos )
335 foundNegativeError =
true;
337 BOOST_CHECK( foundNegativeError );
344 [](
const std::shared_ptr<DRC_RULE>& aRule ) -> std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA> {
345 if( aRule->m_Name ==
"Test" )
346 return std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( 0, 0, aRule->m_Name +
"_1" );
352 [](
const std::shared_ptr<DRC_RULE>& aRule ) -> std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA> {
353 if( aRule->m_Name ==
"Test" )
354 return std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( 0, 0, aRule->m_Name +
"_2" );
358 wxString ruleText =
"(version 1) (rule \"Test\" (constraint clearance (min 1.0mm)))";
361 BOOST_REQUIRE_EQUAL( parsedRules.size(), 1 );
372 BOOST_CHECK(
result.isValid );
373 BOOST_CHECK(
result.errors.empty() );
383 BOOST_CHECK( !result1.
isValid );
384 BOOST_CHECK( !result1.
errors.empty() );
386 bool foundToleranceError =
false;
388 for(
const auto& error : result1.
errors )
390 if( error.find(
"Tolerance is too large" ) != std::string::npos )
391 foundToleranceError =
true;
394 BOOST_CHECK( foundToleranceError );
401 BOOST_CHECK( !result2.
isValid );
403 bool foundNegativeError =
false;
405 for(
const auto& error : result2.
errors )
407 if( error.find(
"Tolerance must be greater than or equal to 0" ) != std::string::npos )
408 foundNegativeError =
true;
411 BOOST_CHECK( foundNegativeError );
422 BOOST_CHECK(
result.isValid );
423 BOOST_CHECK(
result.errors.empty() );
433 BOOST_CHECK( !result1.
isValid );
434 BOOST_CHECK( !result1.
errors.empty() );
436 bool foundWidthError =
false;
437 for(
const auto& error : result1.
errors )
439 if( error.find(
"Width Tolerance must be less than Optimum Width" ) != std::string::npos )
440 foundWidthError =
true;
442 BOOST_CHECK( foundWidthError );
449 BOOST_CHECK( !result2.
isValid );
451 bool foundNegativeError =
false;
452 for(
const auto& error : result2.
errors )
454 if( error.find(
"must be greater than or equal to 0" ) != std::string::npos )
455 foundNegativeError =
true;
457 BOOST_CHECK( foundNegativeError );
467 BOOST_CHECK( result1.
isValid );
468 BOOST_CHECK( result1.
errors.empty() );
475 BOOST_CHECK( result2.
isValid );
476 BOOST_CHECK( result2.
errors.empty() );
483 BOOST_CHECK( result3.
isValid );
484 BOOST_CHECK( result3.
errors.empty() );
494 BOOST_CHECK( !
result.isValid );
495 BOOST_CHECK( !
result.errors.empty() );
497 bool foundLayerError =
false;
498 for(
const auto& error :
result.errors )
500 if( error.find(
"At least one layer must be selected" ) != std::string::npos )
501 foundLayerError =
true;
503 BOOST_CHECK( foundLayerError );
512 BOOST_CHECK(
result.isValid );
513 BOOST_CHECK(
result.errors.empty() );
522 BOOST_CHECK( !
result.isValid );
523 BOOST_CHECK( !
result.errors.empty() );
526 bool foundError =
false;
527 for(
const auto& error :
result.errors )
529 if( error.find(
"must be greater than 0" ) != std::string::npos )
532 BOOST_CHECK( foundError );
541 BOOST_CHECK(
result.isValid );
542 BOOST_CHECK(
result.errors.empty() );
552 BOOST_CHECK( !
result.isValid );
553 BOOST_CHECK( !
result.errors.empty() );
555 bool foundError =
false;
556 for(
const auto& error :
result.errors )
558 if( error.find(
"Width Tolerance must be less than Optimum Width" ) != std::string::npos )
561 BOOST_CHECK( foundError );
571 BOOST_CHECK( result1.
isValid );
572 BOOST_CHECK( result1.
errors.empty() );
579 BOOST_CHECK( result2.
isValid );
580 BOOST_CHECK( result2.
errors.empty() );
587 BOOST_CHECK( result3.
isValid );
588 BOOST_CHECK( result3.
errors.empty() );
595 BOOST_CHECK( result4.
isValid );
596 BOOST_CHECK( result4.
errors.empty() );
606 BOOST_CHECK( !
result.isValid );
607 BOOST_CHECK( !
result.errors.empty() );
609 bool foundOrientationError =
false;
610 for(
const auto& error :
result.errors )
612 if( error.find(
"At least one orientation must be selected" ) != std::string::npos )
613 foundOrientationError =
true;
615 BOOST_CHECK( foundOrientationError );
625 BOOST_CHECK( resultTrue.
isValid );
626 BOOST_CHECK( resultTrue.
errors.empty() );
633 BOOST_CHECK( resultFalse.
isValid );
634 BOOST_CHECK( resultFalse.
errors.empty() );
644 BOOST_CHECK(
result.isValid );
645 BOOST_CHECK(
result.errors.empty() );
655 BOOST_CHECK( !result1.
isValid );
656 BOOST_CHECK( !result1.
errors.empty() );
658 bool foundHeightError =
false;
659 for(
const auto& error : result1.
errors )
661 if( error.find(
"Minimum Text Height must be greater than 0" ) != std::string::npos )
662 foundHeightError =
true;
664 BOOST_CHECK( foundHeightError );
671 BOOST_CHECK( !result2.
isValid );
673 bool foundThicknessError =
false;
674 for(
const auto& error : result2.
errors )
676 if( error.find(
"Minimum Text Thickness must be greater than 0" ) != std::string::npos )
677 foundThicknessError =
true;
679 BOOST_CHECK( foundThicknessError );
686 BOOST_CHECK( !result3.
isValid );
693 data.
SetRuleText(
"(constraint clearance (min 0.2mm))" );
697 BOOST_CHECK(
result.isValid );
698 BOOST_CHECK(
result.errors.empty() );
708 BOOST_CHECK( !
result.isValid );
709 BOOST_CHECK( !
result.errors.empty() );
712 bool foundEmptyError =
false;
713 for(
const auto& error :
result.errors )
715 if( error.find(
"Rule text cannot be empty" ) != std::string::npos )
716 foundEmptyError =
true;
718 BOOST_CHECK( foundEmptyError );
744 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
746 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
756 DRC_RULE rule(
"ViaDiameterOnlyRule" );
763 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
765 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
789 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
791 BOOST_REQUIRE_EQUAL( matches.size(), 2 );
821 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
823 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
832 DRC_RULE rule(
"DiffPairWithUncoupledRule" );
847 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
849 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
860 DRC_RULE rule(
"TrackWidthOnlyRule" );
869 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
871 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
890 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
892 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
909 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
911 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
919 DRC_RULE rule(
"MatchedLengthRule" );
932 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
934 BOOST_REQUIRE_EQUAL( matches.size(), 1 );
937 BOOST_CHECK( matches[0].claimedConstraints.count(
SKEW_CONSTRAINT ) > 0 );
946 std::vector<DRC_PANEL_MATCH> matches = matcher.
MatchRule( rule );
991 "(rule \"Via Test\"\n"
992 " (constraint via_diameter (min 0.5mm) (opt 0.6mm) (max 0.8mm))\n"
993 " (constraint hole_size (min 0.2mm) (opt 0.3mm) (max 0.4mm)))";
996 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
998 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1002 auto viaData = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( entries[0].constraintData );
1005 BOOST_CHECK_CLOSE( viaData->GetMinViaDiameter(), 0.5, 0.0001 );
1006 BOOST_CHECK_CLOSE( viaData->GetMaxViaDiameter(), 0.8, 0.0001 );
1007 BOOST_CHECK_CLOSE( viaData->GetMinViaHoleSize(), 0.2, 0.0001 );
1008 BOOST_CHECK_CLOSE( viaData->GetMaxViaHoleSize(), 0.4, 0.0001 );
1016 "(rule \"Track Test\"\n"
1017 " (constraint track_width (min 0.2mm) (opt 0.25mm) (max 0.3mm)))";
1020 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1022 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1026 auto trackData = std::dynamic_pointer_cast<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>( entries[0].constraintData );
1029 BOOST_CHECK_CLOSE( trackData->GetOptWidth(), 0.25, 0.0001 );
1030 BOOST_CHECK_CLOSE( trackData->GetWidthTolerance(), 0.05, 0.0001 );
1038 "(rule \"Diff Pair Test\"\n"
1039 " (constraint track_width (min 0.2mm) (opt 0.25mm) (max 0.3mm))\n"
1040 " (constraint diff_pair_gap (min 0.1mm) (opt 0.15mm) (max 0.2mm))\n"
1041 " (constraint diff_pair_uncoupled (max 5mm)))";
1044 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1046 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1049 auto dpData = std::dynamic_pointer_cast<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA>( entries[0].constraintData );
1052 BOOST_CHECK_CLOSE( dpData->GetOptWidth(), 0.25, 0.0001 );
1053 BOOST_CHECK_CLOSE( dpData->GetWidthTolerance(), 0.05, 0.0001 );
1054 BOOST_CHECK_CLOSE( dpData->GetOptGap(), 0.15, 0.0001 );
1055 BOOST_CHECK_CLOSE( dpData->GetGapTolerance(), 0.05, 0.0001 );
1056 BOOST_CHECK_CLOSE( dpData->GetMaxUncoupledLength(), 5.0, 0.0001 );
1064 "(rule \"Split Test\"\n"
1065 " (constraint via_diameter (min 0.5mm))\n"
1066 " (constraint hole_size (min 0.2mm))\n"
1067 " (constraint clearance (min 0.15mm)))";
1070 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1072 BOOST_REQUIRE_EQUAL( entries.size(), 2 );
1082 auto numericData = std::dynamic_pointer_cast<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( entries[1].constraintData );
1084 BOOST_CHECK_CLOSE( numericData->GetNumericInputValue(), 0.15, 0.0001 );
1094 "(rule \"clearance_under_fpga\"\n"
1095 " (constraint clearance (min 0.1mm))\n"
1096 " (constraint hole_size (min 0.2mm))\n"
1097 " (constraint via_diameter (min 0.4mm))\n"
1098 " (condition \"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')\"))";
1101 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1104 BOOST_REQUIRE_EQUAL( entries.size(), 2 );
1109 BOOST_CHECK_EQUAL( entries[0].condition,
"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')" );
1114 BOOST_CHECK_EQUAL( entries[1].condition,
"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')" );
1117 auto viaData = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( entries[0].constraintData );
1119 BOOST_CHECK_CLOSE( viaData->GetMinViaDiameter(), 0.4, 0.0001 );
1120 BOOST_CHECK_CLOSE( viaData->GetMinViaHoleSize(), 0.2, 0.0001 );
1123 auto clearanceData = std::dynamic_pointer_cast<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( entries[1].constraintData );
1125 BOOST_CHECK_CLOSE( clearanceData->GetNumericInputValue(), 0.1, 0.0001 );
1133 "(rule \"Text Test\"\n"
1134 " (constraint text_height (min 1mm))\n"
1135 " (constraint text_thickness (min 0.15mm)))";
1138 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1140 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1143 auto textData = std::dynamic_pointer_cast<DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA>( entries[0].constraintData );
1146 BOOST_CHECK_CLOSE( textData->GetMinTextHeight(), 1.0, 0.0001 );
1147 BOOST_CHECK_CLOSE( textData->GetMinTextThickness(), 0.15, 0.0001 );
1155 "(rule \"Length Test\"\n"
1156 " (constraint length (min 10mm) (opt 30mm) (max 50mm)))";
1159 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1161 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1165 auto lengthData = dynamic_pointer_cast<DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA>( entries[0].constraintData );
1167 BOOST_CHECK_CLOSE( lengthData->GetMinimumLength(), 10.0, 0.0001 );
1168 BOOST_CHECK_CLOSE( lengthData->GetOptimumLength(), 30.0, 0.0001 );
1169 BOOST_CHECK_CLOSE( lengthData->GetMaximumLength(), 50.0, 0.0001 );
1177 "(rule \"DP Length Match\"\n"
1178 " (constraint length (min 10mm) (opt 30mm) (max 50mm))\n"
1179 " (constraint skew (max 1mm)))";
1182 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1184 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1189 std::dynamic_pointer_cast<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>( entries[0].constraintData );
1192 BOOST_CHECK_CLOSE( matchedData->GetMinimumLength(), 10.0, 0.0001 );
1193 BOOST_CHECK_CLOSE( matchedData->GetOptimumLength(), 30.0, 0.0001 );
1194 BOOST_CHECK_CLOSE( matchedData->GetMaximumLength(), 50.0, 0.0001 );
1195 BOOST_CHECK_CLOSE( matchedData->GetMaxSkew(), 1.0, 0.0001 );
1203 "(rule \"DP Match RT\"\n"
1204 " (constraint length (min 10mm) (opt 30mm) (max 50mm))\n"
1205 " (constraint skew (max 2.5mm)))";
1208 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1210 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1211 entries[0].wasEdited =
true;
1216 BOOST_CHECK( savedText.Contains(
"length" ) );
1217 BOOST_CHECK( savedText.Contains(
"skew" ) );
1218 BOOST_CHECK( savedText.Contains(
"2.5mm" ) );
1220 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloaded = loader.
LoadFromString( savedText );
1222 BOOST_REQUIRE_EQUAL( reloaded.size(), 1 );
1226 std::dynamic_pointer_cast<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>( reloaded[0].constraintData );
1229 BOOST_CHECK_CLOSE( reloadedData->GetMaxSkew(), 2.5, 0.0001 );
1230 BOOST_CHECK_CLOSE( reloadedData->GetMinimumLength(), 10.0, 0.0001 );
1231 BOOST_CHECK_CLOSE( reloadedData->GetOptimumLength(), 30.0, 0.0001 );
1232 BOOST_CHECK_CLOSE( reloadedData->GetMaximumLength(), 50.0, 0.0001 );
1238 wxString ruleText =
"(version 1)\n"
1239 "(rule \"DP Skew Within\"\n"
1240 " (constraint length (min 10mm) (opt 30mm) (max 50mm))\n"
1241 " (constraint skew (max 1mm) (within_diff_pairs)))";
1244 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1246 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1250 std::dynamic_pointer_cast<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>( entries[0].constraintData );
1253 BOOST_CHECK_CLOSE( matchedData->GetMaxSkew(), 1.0, 0.0001 );
1254 BOOST_CHECK( matchedData->GetWithinDiffPairs() );
1257 entries[0].wasEdited =
true;
1262 BOOST_CHECK( savedText.Contains(
"within_diff_pairs" ) );
1264 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloaded = loader.
LoadFromString( savedText );
1266 BOOST_REQUIRE_EQUAL( reloaded.size(), 1 );
1269 std::dynamic_pointer_cast<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>( reloaded[0].constraintData );
1272 BOOST_CHECK_CLOSE( reloadedData->GetMaxSkew(), 1.0, 0.0001 );
1273 BOOST_CHECK( reloadedData->GetWithinDiffPairs() );
1279 wxString ruleText =
"(version 1)\n"
1280 "(rule \"DP Skew Bus\"\n"
1281 " (constraint length (min 10mm) (opt 30mm) (max 50mm))\n"
1282 " (constraint skew (max 2mm)))";
1285 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1287 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1290 std::dynamic_pointer_cast<DRC_RE_MATCHED_LENGTH_DIFF_PAIR_CONSTRAINT_DATA>( entries[0].constraintData );
1293 BOOST_CHECK( !matchedData->GetWithinDiffPairs() );
1296 entries[0].wasEdited =
true;
1301 BOOST_CHECK( !savedText.Contains(
"within_diff_pairs" ) );
1309 "(rule \"Conditional Test\"\n"
1310 " (condition \"A.NetClass == 'Power'\")\n"
1311 " (constraint clearance (min 0.3mm)))";
1314 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1316 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1319 BOOST_CHECK_EQUAL( entries[0].constraintData->GetRuleCondition(),
"A.NetClass == 'Power'" );
1327 "(rule \"Rule A\"\n"
1328 " (constraint clearance (min 0.2mm)))\n"
1329 "(rule \"Rule B\"\n"
1330 " (constraint track_width (min 0.15mm)))\n"
1331 "(rule \"Rule C\"\n"
1332 " (constraint via_diameter (min 0.5mm))\n"
1333 " (constraint hole_size (min 0.3mm)))";
1336 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1338 BOOST_REQUIRE_EQUAL( entries.size(), 3 );
1355 "(rule \"Empty Rule\")";
1358 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1360 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1368 wxString ruleText =
"not valid rule text at all";
1371 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1381 "(rule \"Edge Clearance\"\n"
1382 " (constraint edge_clearance (min 0.5mm)))\n"
1383 "(rule \"Hole Clearance\"\n"
1384 " (constraint hole_clearance (min 0.3mm)))\n"
1385 "(rule \"Courtyard\"\n"
1386 " (constraint courtyard_clearance (min 0.25mm)))";
1389 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1391 BOOST_REQUIRE_EQUAL( entries.size(), 3 );
1411 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1412 numericData->SetRuleName(
"TestClearance" );
1413 numericData->SetConstraintCode(
"clearance" );
1414 numericData->SetNumericInputValue( 0.2 );
1418 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1421 BOOST_CHECK(
result.Contains(
"(version 1)" ) );
1422 BOOST_CHECK(
result.Contains(
"TestClearance" ) );
1423 BOOST_CHECK(
result.Contains(
"clearance" ) );
1432 entry.
originalRuleText =
"(rule \"Preserved Rule\"\n\t(constraint clearance (min 0.5mm)))";
1435 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1436 numericData->SetRuleName(
"Preserved Rule" );
1437 numericData->SetConstraintCode(
"clearance" );
1438 numericData->SetNumericInputValue( 0.5 );
1442 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1454 entry.
originalRuleText =
"(rule \"EditedRule\"\n\t(constraint clearance (min 0.5mm)))";
1457 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1458 numericData->SetRuleName(
"EditedRule" );
1459 numericData->SetConstraintCode(
"clearance" );
1460 numericData->SetNumericInputValue( 0.3 );
1464 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1468 BOOST_CHECK( !
result.Contains(
"0.5mm" ) );
1469 BOOST_CHECK(
result.Contains(
"EditedRule" ) );
1479 auto viaData = std::make_shared<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>();
1480 viaData->SetRuleName(
"ViaTest" );
1481 viaData->SetMinViaDiameter( 0.5 );
1482 viaData->SetMaxViaDiameter( 0.8 );
1483 viaData->SetMinViaHoleSize( 0.2 );
1484 viaData->SetMaxViaHoleSize( 0.4 );
1489 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1492 BOOST_CHECK(
result.Contains(
"ViaTest" ) );
1493 BOOST_CHECK(
result.Contains(
"via_diameter" ) );
1494 BOOST_CHECK(
result.Contains(
"hole_size" ) );
1500 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries;
1505 auto data1 = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1506 data1->SetRuleName(
"RuleA" );
1507 data1->SetConstraintCode(
"clearance" );
1508 data1->SetNumericInputValue( 0.2 );
1511 entries.push_back( entry1 );
1516 auto data2 = std::make_shared<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>();
1517 data2->SetRuleName(
"RuleB" );
1518 data2->SetOptWidth( 0.2 );
1519 data2->SetWidthTolerance( 0.1 );
1522 entries.push_back( entry2 );
1528 BOOST_CHECK(
result.Contains(
"RuleA" ) );
1529 BOOST_CHECK(
result.Contains(
"RuleB" ) );
1532 size_t posA =
result.Find(
"RuleA" );
1533 size_t posB =
result.Find(
"RuleB" );
1534 BOOST_CHECK( posA < posB );
1542 entry.
ruleName =
"ConditionalRule";
1543 entry.
condition =
"A.NetClass == 'Power'";
1545 auto numericData = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
1546 numericData->SetRuleName(
"ConditionalRule" );
1547 numericData->SetConstraintCode(
"clearance" );
1548 numericData->SetRuleCondition(
"A.NetClass == 'Power'" );
1549 numericData->SetNumericInputValue( 0.3 );
1554 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1557 BOOST_CHECK(
result.Contains(
"ConditionalRule" ) );
1558 BOOST_CHECK(
result.Contains(
"condition" ) );
1559 BOOST_CHECK(
result.Contains(
"Power" ) );
1566 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries;
1569 BOOST_CHECK(
result.Contains(
"(version 1)" ) );
1584 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1588 BOOST_CHECK(
result.Contains(
"(version 1)" ) );
1589 BOOST_CHECK( !
result.Contains(
"Null Data Rule" ) );
1595 wxString originalText =
1597 "(rule \"RoundTripTest\"\n"
1598 " (constraint clearance (min 0.25mm)))";
1601 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( originalText );
1603 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1607 entries[0].wasEdited =
true;
1614 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloadedEntries = loader.
LoadFromString( savedText );
1616 BOOST_REQUIRE_EQUAL( reloadedEntries.size(), 1 );
1628 auto dpData = std::make_shared<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA>();
1629 dpData->SetRuleName(
"DiffPairTest" );
1630 dpData->SetOptWidth( 0.25 );
1631 dpData->SetWidthTolerance( 0.05 );
1632 dpData->SetOptGap( 0.15 );
1633 dpData->SetGapTolerance( 0.05 );
1634 dpData->SetMaxUncoupledLength( 5.0 );
1639 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
1642 BOOST_CHECK(
result.Contains(
"DiffPairTest" ) );
1643 BOOST_CHECK(
result.Contains(
"track_width" ) );
1644 BOOST_CHECK(
result.Contains(
"diff_pair_gap" ) );
1657 "(rule \"PTH to Track Clearance\"\n"
1658 " (constraint hole_clearance (min 1.0mm))\n"
1659 " (condition \"A.Type == 'Pad' && A.Pad_Type == 'Through-hole' && B.Type =='Track'\"))\n"
1660 "(rule \"Max Drill Hole Size Mechanical\"\n"
1661 " (constraint hole (max 2.0mm))\n"
1662 " (condition \"A.Type == 'Pad'\"))";
1665 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1667 BOOST_REQUIRE_GE( entries.size(), 2 );
1672 BOOST_CHECK( !entries[0].condition.IsEmpty() );
1684 "(rule board_edge\n"
1685 " (constraint edge_clearance (min 1mm))\n"
1686 " (condition \"A.memberOf('board_edge')\")\n"
1687 " (severity ignore))";
1690 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1692 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1703 "(rule high_current_netclass\n"
1704 " (constraint connection_width (min 0.16mm))\n"
1705 " (condition \"A.NetClass == 'High_current'\"))\n"
1706 "(rule high_current_area\n"
1707 " (constraint connection_width (min 0.16mm))\n"
1708 " (condition \"A.insideArea('high_current')\"))";
1711 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1713 BOOST_REQUIRE_EQUAL( entries.size(), 2 );
1720 BOOST_CHECK( !entries[0].condition.IsEmpty() );
1721 BOOST_CHECK( !entries[1].condition.IsEmpty() );
1728 wxString originalText =
1730 "(rule ClearanceRule\n"
1731 " (constraint clearance (min 0.2mm))\n"
1732 " (condition \"A.NetClass == 'Power'\"))\n"
1733 "(rule TrackWidthRule\n"
1734 " (constraint track_width (min 0.15mm) (opt 0.2mm) (max 0.3mm)))";
1737 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( originalText );
1739 BOOST_REQUIRE_EQUAL( entries.size(), 2 );
1742 for(
auto& entry : entries )
1743 entry.wasEdited =
true;
1750 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloadedEntries = loader.
LoadFromString( savedText );
1752 BOOST_REQUIRE_EQUAL( reloadedEntries.size(), 2 );
1766 wxString originalText =
1768 "(rule \"Via Style\"\n"
1769 " (constraint via_diameter (min 0.5mm) (opt 0.6mm) (max 0.8mm))\n"
1770 " (constraint hole_size (min 0.2mm) (opt 0.3mm) (max 0.4mm)))";
1773 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( originalText );
1775 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
1778 auto viaData = std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( entries[0].constraintData );
1781 double originalMinDia = viaData->GetMinViaDiameter();
1782 double originalMinHole = viaData->GetMinViaHoleSize();
1785 entries[0].wasEdited =
true;
1790 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloadedEntries = loader.
LoadFromString( savedText );
1792 BOOST_REQUIRE_EQUAL( reloadedEntries.size(), 1 );
1795 auto reloadedViaData =
1796 std::dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( reloadedEntries[0].constraintData );
1799 BOOST_CHECK_CLOSE( reloadedViaData->GetMinViaDiameter(), originalMinDia, 0.0001 );
1800 BOOST_CHECK_CLOSE( reloadedViaData->GetMinViaHoleSize(), originalMinHole, 0.0001 );
1808 "(rule \"Rule A\"\n"
1809 " (constraint clearance (min 0.2mm)))\n"
1810 "(rule \"Rule B\"\n"
1811 " (constraint via_diameter (min 0.5mm))\n"
1812 " (constraint hole_size (min 0.2mm))\n"
1813 " (constraint track_width (min 0.15mm)))\n"
1814 "(rule \"Rule C\"\n"
1815 " (constraint edge_clearance (min 0.3mm)))";
1818 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
1821 BOOST_REQUIRE_GE( entries.size(), 4 );
1824 int ruleACount = 0, ruleBCount = 0, ruleCCount = 0;
1826 for(
const auto& entry : entries )
1828 if( entry.ruleName ==
"Rule A" )
1830 else if( entry.ruleName ==
"Rule B" )
1832 else if( entry.ruleName ==
"Rule C" )
1837 BOOST_CHECK_GE( ruleBCount, 2 );
1841 int lastAIndex = -1, firstBIndex = entries.size(), lastBIndex = -1, firstCIndex = entries.size();
1843 for(
size_t i = 0; i < entries.size(); i++ )
1845 if( entries[i].ruleName ==
"Rule A" )
1847 else if( entries[i].ruleName ==
"Rule B" )
1849 if( (
int)i < firstBIndex )
1854 else if( entries[i].ruleName ==
"Rule C" )
1856 if( (
int)i < firstCIndex )
1861 BOOST_CHECK( lastAIndex < firstBIndex );
1862 BOOST_CHECK( lastBIndex < firstCIndex );
1874 wxString expr =
"A.NetName == 'VCC'";
1877 BOOST_CHECK( !expr.IsEmpty() );
1878 BOOST_CHECK( expr.Contains(
"NetName" ) );
1879 BOOST_CHECK( expr.Contains(
"VCC" ) );
1885 wxString expr =
"A.NetName == 'VCC' && B.NetClass == 'Power'";
1888 BOOST_CHECK( expr.Contains(
"&&" ) );
1889 BOOST_CHECK( expr.Contains(
"NetName" ) );
1890 BOOST_CHECK( expr.Contains(
"NetClass" ) );
1896 wxString expr =
"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')";
1899 BOOST_CHECK( expr.Contains(
"||" ) );
1900 BOOST_CHECK( expr.Contains(
"intersectsArea" ) );
1906 wxString expr =
"A.NetClass == 'Power' && !A.intersectsArea('NoRouting')";
1909 BOOST_CHECK( expr.Contains(
"&&" ) );
1910 BOOST_CHECK( expr.Contains(
"!" ) );
1916 wxString expr =
"A.intersectsArea('underFPGA') || A.intersectsArea('underDDR')";
1919 BOOST_CHECK( expr.Contains(
"||" ) );
1920 BOOST_CHECK( expr.Contains(
"underFPGA" ) );
1921 BOOST_CHECK( expr.Contains(
"underDDR" ) );
1927 while( ( pos = expr.find(
"||", pos ) ) != wxString::npos )
1950 for(
KICAD_T type : excludedTypes )
1957 BOOST_CHECK(
true );
1961 BOOST_FAIL(
"Excluded type not handled in filter" );
1966 for(
KICAD_T type : includedTypes )
1973 BOOST_FAIL(
"Included type incorrectly matched by filter" );
1977 BOOST_CHECK(
true );
1990 entry.
condition =
"A.NetClass == 'Power'";
1994 auto data = std::make_shared<DRC_RE_SILK_TO_SOLDERMASK_CLEARANCE_CONSTRAINT_DATA>();
1995 data->SetRuleName(
"SilkMaskTest" );
1996 data->SetConstraintCode(
"silk_clearance" );
1997 data->SetRuleCondition(
"A.NetClass == 'Power'" );
1998 data->SetNumericInputValue( 0.15 );
2002 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
2006 BOOST_CHECK(
result.Contains(
"L == 'F.Mask'" ) );
2007 BOOST_CHECK(
result.Contains(
"Power" ) );
2008 BOOST_CHECK( !
result.Contains(
"(layer" ) );
2013 while( ( pos =
result.find(
"(condition", pos ) ) != wxString::npos )
2031 auto data = std::make_shared<DRC_RE_SILK_TO_SOLDERMASK_CLEARANCE_CONSTRAINT_DATA>();
2032 data->SetRuleName(
"SilkMaskSimple" );
2033 data->SetConstraintCode(
"silk_clearance" );
2034 data->SetNumericInputValue( 0.1 );
2038 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
2041 BOOST_CHECK(
result.Contains(
"L == 'B.Mask'" ) );
2042 BOOST_CHECK(
result.Contains(
"(condition" ) );
2043 BOOST_CHECK( !
result.Contains(
"(layer" ) );
2055 auto data = std::make_shared<DRC_RE_SILK_TO_SILK_CLEARANCE_CONSTRAINT_DATA>();
2056 data->SetRuleName(
"SilkSilkBoth" );
2057 data->SetConstraintCode(
"silk_clearance" );
2058 data->SetNumericInputValue( 0.2 );
2062 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
2065 BOOST_CHECK(
result.Contains(
"L == 'F.SilkS' || L == 'B.SilkS'" ) );
2066 BOOST_CHECK(
result.Contains(
"(condition" ) );
2067 BOOST_CHECK( !
result.Contains(
"(layer" ) );
2079 auto data = std::make_shared<DRC_RE_SILK_TO_SILK_CLEARANCE_CONSTRAINT_DATA>();
2080 data->SetRuleName(
"SilkSilkFront" );
2081 data->SetConstraintCode(
"silk_clearance" );
2082 data->SetNumericInputValue( 0.2 );
2086 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
2089 BOOST_CHECK(
result.Contains(
"L == 'F.SilkS'" ) );
2090 BOOST_CHECK( !
result.Contains(
"B.SilkS" ) );
2091 BOOST_CHECK(
result.Contains(
"(condition" ) );
2092 BOOST_CHECK( !
result.Contains(
"(layer" ) );
2101 entry.
condition =
"A.NetClass == 'Signal'";
2105 auto data = std::make_shared<DRC_RE_SILK_TO_SILK_CLEARANCE_CONSTRAINT_DATA>();
2106 data->SetRuleName(
"SilkSilkCond" );
2107 data->SetConstraintCode(
"silk_clearance" );
2108 data->SetRuleCondition(
"A.NetClass == 'Signal'" );
2109 data->SetNumericInputValue( 0.2 );
2113 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = { entry };
2116 BOOST_CHECK(
result.Contains(
"L == 'F.SilkS'" ) );
2117 BOOST_CHECK(
result.Contains(
"Signal" ) );
2122 while( ( pos =
result.find(
"(condition", pos ) ) != wxString::npos )
2135 BOOST_CHECK( result1.
isValid );
2136 BOOST_CHECK( result1.
errors.empty() );
2141 BOOST_CHECK( result2.
isValid );
2142 BOOST_CHECK( result2.
errors.empty() );
2150 BOOST_CHECK( !
result.isValid );
2151 BOOST_CHECK( !
result.errors.empty() );
2153 bool foundError =
false;
2154 for(
const auto& error :
result.errors )
2156 if( error.find(
"At least one via type must be selected" ) != std::string::npos )
2159 BOOST_CHECK( foundError );
2171 BOOST_REQUIRE_EQUAL( clauses.size(), 1 );
2172 BOOST_CHECK( clauses[0].Contains(
"disallow via" ) );
2173 BOOST_CHECK( !clauses[0].Contains(
"through_via" ) );
2178 BOOST_REQUIRE_EQUAL( clauses.size(), 1 );
2179 BOOST_CHECK( clauses[0].Contains(
"micro_via" ) );
2180 BOOST_CHECK( !clauses[0].Contains(
"through_via" ) );
2181 BOOST_CHECK( !clauses[0].Contains(
"blind_via" ) );
2182 BOOST_CHECK( !clauses[0].Contains(
"buried_via" ) );
2187 BOOST_REQUIRE_EQUAL( clauses.size(), 1 );
2188 BOOST_CHECK( clauses[0].Contains(
"through_via" ) );
2189 BOOST_CHECK( clauses[0].Contains(
"blind_via" ) );
2190 BOOST_CHECK( !clauses[0].Contains(
"micro_via" ) );
2191 BOOST_CHECK( !clauses[0].Contains(
"buried_via" ) );
2196 BOOST_CHECK( clauses.empty() );
2202 wxString originalText =
"(version 1)\n"
2203 "(rule \"ViasUnderSmdTest\"\n"
2204 " (constraint disallow micro_via)\n"
2205 " (condition \"A.Pad_Type == 'SMD' && A.insideArea('BGA*')\"))";
2208 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( originalText );
2210 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2213 auto viaData = std::dynamic_pointer_cast<DRC_RE_VIAS_UNDER_SMD_CONSTRAINT_DATA>( entries[0].constraintData );
2217 BOOST_CHECK( !viaData->GetDisallowThroughVias() );
2218 BOOST_CHECK( viaData->GetDisallowMicroVias() );
2219 BOOST_CHECK( !viaData->GetDisallowBlindVias() );
2220 BOOST_CHECK( !viaData->GetDisallowBuriedVias() );
2223 entries[0].wasEdited =
true;
2228 BOOST_CHECK( savedText.Contains(
"micro_via" ) );
2229 BOOST_CHECK( !savedText.Contains(
"through_via" ) );
2230 BOOST_CHECK( !savedText.Contains(
"blind_via" ) );
2231 BOOST_CHECK( !savedText.Contains(
"buried_via" ) );
2234 std::vector<DRC_RE_LOADED_PANEL_ENTRY> reloadedEntries = loader.
LoadFromString( savedText );
2235 BOOST_REQUIRE_EQUAL( reloadedEntries.size(), 1 );
2238 std::dynamic_pointer_cast<DRC_RE_VIAS_UNDER_SMD_CONSTRAINT_DATA>( reloadedEntries[0].constraintData );
2241 BOOST_CHECK( !reloadedData->GetDisallowThroughVias() );
2242 BOOST_CHECK( reloadedData->GetDisallowMicroVias() );
2243 BOOST_CHECK( !reloadedData->GetDisallowBlindVias() );
2244 BOOST_CHECK( !reloadedData->GetDisallowBuriedVias() );
2247 wxString blanketText =
"(version 1)\n"
2248 "(rule \"BlanketVia\"\n"
2249 " (constraint disallow via)\n"
2250 " (condition \"A.Pad_Type == 'SMD' && A.insideArea('BGA*')\"))";
2253 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2255 auto blanketData = std::dynamic_pointer_cast<DRC_RE_VIAS_UNDER_SMD_CONSTRAINT_DATA>( entries[0].constraintData );
2258 BOOST_CHECK( blanketData->GetDisallowThroughVias() );
2259 BOOST_CHECK( blanketData->GetDisallowMicroVias() );
2260 BOOST_CHECK( blanketData->GetDisallowBlindVias() );
2261 BOOST_CHECK( blanketData->GetDisallowBuriedVias() );
2264 wxString multiText =
"(version 1)\n"
2265 "(rule \"TwoVias\"\n"
2266 " (constraint disallow through_via blind_via)\n"
2267 " (condition \"A.Pad_Type == 'SMD' && A.insideArea('BGA*')\"))";
2270 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2272 auto multiData = std::dynamic_pointer_cast<DRC_RE_VIAS_UNDER_SMD_CONSTRAINT_DATA>( entries[0].constraintData );
2275 BOOST_CHECK( multiData->GetDisallowThroughVias() );
2276 BOOST_CHECK( !multiData->GetDisallowMicroVias() );
2277 BOOST_CHECK( multiData->GetDisallowBlindVias() );
2278 BOOST_CHECK( !multiData->GetDisallowBuriedVias() );
2280 entries[0].wasEdited =
true;
2283 BOOST_CHECK( savedText.Contains(
"through_via" ) );
2284 BOOST_CHECK( savedText.Contains(
"blind_via" ) );
2285 BOOST_CHECK( !savedText.Contains(
"micro_via" ) );
2286 BOOST_CHECK( !savedText.Contains(
"buried_via" ) );
2292 wxString ruleText =
"(version 1)\n"
2293 "(rule \"Angled\"\n"
2294 " (constraint assertion \"A.Orientation == 46 deg\")\n"
2298 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
2300 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2303 auto customData = std::dynamic_pointer_cast<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( entries[0].constraintData );
2305 BOOST_CHECK( customData->GetRuleText().Contains( wxS(
"46 deg" ) ) );
2306 BOOST_CHECK( !customData->GetRuleText().Contains( wxS(
"Angled" ) ) );
2309 wxString ruleTextUnquoted =
"(version 1)\n"
2311 " (constraint assertion \"A.Orientation == 46 deg\")\n"
2316 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2319 auto customDataUnquoted =
2320 std::dynamic_pointer_cast<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( entries[0].constraintData );
2322 BOOST_CHECK( customDataUnquoted->GetRuleText().Contains( wxS(
"46 deg" ) ) );
2323 BOOST_CHECK( !customDataUnquoted->GetRuleText().Contains( wxS(
"Angled" ) ) );
2328 wxString ruleText =
"(version 1)\n"
2329 "(rule \"Standard\"\n"
2330 " (constraint assertion \"A.Orientation == 0 deg || A.Orientation == 90 deg\")\n"
2334 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
2336 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2340 std::dynamic_pointer_cast<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA>( entries[0].constraintData );
2342 BOOST_CHECK( orientData->GetIsZeroDegreesAllowed() );
2343 BOOST_CHECK( orientData->GetIsNinetyDegreesAllowed() );
2344 BOOST_CHECK( !orientData->GetIsOneEightyDegreesAllowed() );
2345 BOOST_CHECK( !orientData->GetIsAllDegreesAllowed() );
2348 wxString singleLine =
"(version 1) (rule \"SingleLine\" (constraint assertion \"A.Orientation == 0 deg || "
2349 "A.Orientation == 90 deg\"))";
2353 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2356 auto singleLineData =
2357 std::dynamic_pointer_cast<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA>( entries[0].constraintData );
2359 BOOST_CHECK( singleLineData->GetIsZeroDegreesAllowed() );
2360 BOOST_CHECK( singleLineData->GetIsNinetyDegreesAllowed() );
2361 BOOST_CHECK( !singleLineData->GetIsOneEightyDegreesAllowed() );
2362 BOOST_CHECK( !singleLineData->GetIsAllDegreesAllowed() );
2367 wxString ruleText =
"(version 1)\n"
2368 "(rule \"AllAngles\"\n"
2369 " (constraint assertion \"A.Orientation == 0 deg || A.Orientation == 90 deg || "
2370 "A.Orientation == 180 deg || A.Orientation == 270 deg\")\n"
2374 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
2376 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2380 std::dynamic_pointer_cast<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA>( entries[0].constraintData );
2382 BOOST_CHECK( orientData->GetIsAllDegreesAllowed() );
2383 BOOST_CHECK( orientData->GetIsZeroDegreesAllowed() );
2384 BOOST_CHECK( orientData->GetIsNinetyDegreesAllowed() );
2385 BOOST_CHECK( orientData->GetIsOneEightyDegreesAllowed() );
2386 BOOST_CHECK( orientData->GetIsTwoSeventyDegreesAllowed() );
2391 wxString ruleText =
"(version 1)\n"
2392 "(rule \"InnerLayers\"\n"
2393 " (constraint assertion \"A.Layer == 'F.Cu' || A.Layer == 'In1.Cu'\")\n"
2397 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
2399 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2402 auto customData = std::dynamic_pointer_cast<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( entries[0].constraintData );
2404 BOOST_CHECK( customData->GetRuleText().Contains( wxS(
"In1.Cu" ) ) );
2409 wxString ruleText =
"(version 1)\n"
2410 "(rule \"StandardLayers\"\n"
2411 " (constraint assertion \"A.Layer == 'F.Cu' || A.Layer == 'B.Cu'\")\n"
2415 std::vector<DRC_RE_LOADED_PANEL_ENTRY> entries = loader.
LoadFromString( ruleText );
2417 BOOST_REQUIRE_EQUAL( entries.size(), 1 );
2420 auto layerData = std::dynamic_pointer_cast<DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA>( entries[0].constraintData );
2422 BOOST_CHECK( layerData->GetTopLayerEnabled() );
2423 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)