22#include <boost/test/data/test_case.hpp>
65 {
"10mm + 20 mm",
false,
VAL( 30e6 ) },
66 {
"3*(7+8)",
false,
VAL( 3 * ( 7 + 8 ) ) },
67 {
"3*7+8",
false,
VAL( 3 * 7 + 8 ) },
68 {
"(3*7)+8",
false,
VAL( 3 * 7 + 8 ) },
69 {
"10mm + 20)",
true,
VAL( 0 ) },
71 {
"1",
false,
VAL(1) },
72 {
"1.5",
false,
VAL(1.5) },
73 {
"1,5",
false,
VAL(1.5) },
74 {
"1mm",
false,
VAL(1e6) },
76 {
" 1 + 2 ",
false,
VAL(3) },
78 {
"1.5 + 0.2 + 0.1",
false,
VAL(1.8) },
80 {
"3 - 10",
false,
VAL(-7) },
82 {
"1 + 2 + 10 + 1000.05",
false,
VAL(1013.05) },
84 {
"1 + 2 - 4 * 20 / 2",
false,
VAL(-37) },
86 {
"(1)",
false,
VAL(1) },
88 {
"-(1 + (2 - 4)) * 20.8 / 2",
false,
VAL(10.4) },
90 {
"+2 - 1",
false,
VAL(1) },
93 {
"(2 || 0) == 1",
false,
VAL(1) },
94 {
"(7 || 0) + 5",
false,
VAL(6) }
99 {
"A.type == 'Pad' && B.type == 'Pad' && (A.existsOnLayer('F.Cu'))",
false,
VAL( 0.0 ) },
100 {
"A.Width > B.Width",
false,
VAL( 0.0 ) },
102 {
"A.Netclass",
false,
VAL(
"HV_LINE" ) },
103 {
"A.Net_Class == 'HV_LINE'",
false,
VAL( 1.0 ) },
104 {
"(A.Netclass == 'HV_LINE') && (B.netclass == 'otherClass') && (B.netclass != 'F.Cu')",
false,
VAL( 1.0 ) },
105 {
"A.Netclass + 1.0",
false,
VAL( 1.0 ) },
106 {
"A.hasNetclass('HV_LINE')",
false,
VAL( 1.0 ) },
107 {
"A.hasNetclass('HV_*')",
false,
VAL( 1.0 ) },
108 {
"A.existsOnLayer(B.Layer)",
false,
VAL( 1.0 ) },
109 {
"A.type == 'Track' && B.type == 'Track' && A.layer == 'F.Cu'",
false,
VAL( 1.0 ) },
110 {
"(A.type == 'Track') && (B.type == 'Track') && (A.layer == 'F.Cu')",
false,
VAL( 1.0 ) },
111 {
"A.type == 'Via' && A.isMicroVia()",
false,
VAL(0.0) }
129 bool error = !compiler.
Compile( expr, &ucode, &preflightContext );
133 if( error != expectError )
149 ok = (
result->EqualTo( &context, &expectedResult ) );
171 compiler.
Compile( aExpr, &ucode, &preflight );
173 BOOST_CHECK_MESSAGE( compiler.
IsErrorPending(),
"Expected a compile error for: " << aExpr.mb_str() );
183 compiler.
Compile( aExpr, &ucode, &preflight );
185 BOOST_CHECK_MESSAGE( !compiler.
IsErrorPending(),
"Expected expression to compile: " << aExpr.mb_str() );
191 testEvalExpr( expr.expression, expr.expectedResult, expr.expectError );
204 std::shared_ptr<NETCLASS> netclass1(
new NETCLASS(
"HV_LINE" ) );
205 std::shared_ptr<NETCLASS> netclass2(
new NETCLASS(
"otherClass" ) );
216 trackA.
SetNet( net1info );
217 trackB.
SetNet( net2info );
226 testEvalExpr( expr.expression, expr.expectedResult, expr.expectError, &trackA, &trackB );
245 testEvalExpr( wxT(
"A.Hatch_Orientation == 45deg" ),
VAL( 1.0 ),
false, &zone );
246 testEvalExpr( wxT(
"A.Minimum_Island_Area == 123456789" ),
VAL( 1.0 ),
false, &zone );
251 testEvalExpr( wxT(
"A.Ellipse_Rotation == 30deg" ),
VAL( 1.0 ),
false, &ellipse );
256 testEvalExpr( wxT(
"A.Solderpaste_Margin_Ratio_Override == 0.125" ),
VAL( 1.0 ),
false, &footprint );
260 testEvalExpr( wxT(
"A.Solderpaste_Margin_Ratio_Override == null" ),
VAL( 1.0 ),
false, &footprint );
280 testEvalExpr( wxT(
"A.Origin_X != A.End_X" ),
VAL( 1.0 ),
false, &track );
281 testEvalExpr( wxT(
"A.origin_y != A.End_Y" ),
VAL( 1.0 ),
false, &track );
297 [&](
const COLOR4D& aColor,
const wxString& aExpectedCss )
299 table.SetBorderColor( aColor );
302 wxString expression = wxT(
"A.Border_Color == '" ) + aExpectedCss + wxT(
"'" );
306 checkColor(
COLOR4D( 0.25, 0.5, 0.75, 0.5 ), wxT(
"rgba(64, 128, 191, 0.502)" ) );
308 checkColor(
COLOR4D( wxString( wxT(
"red" ) ) ), wxT(
"rgb(255, 0, 0)" ) );
318 std::set<std::pair<TYPE_ID, PROPERTY_BASE*>> seen;
319 std::map<wxString, std::set<LIBEVAL::VAR_TYPE_T>> fieldTypes;
328 if( !seen.emplace( cls.type, prop ).second )
334 "Unsupported expression property: class=" << cls.name.mb_str()
335 <<
", property=" << prop->
Name().mb_str()
336 <<
", type_hash=" << prop->
TypeHash() );
345 auto shapeTypes = fieldTypes.find( wxT(
"Shape" ) );
348 fieldTypes.erase( shapeTypes );
350 for(
const auto& [field, types] : fieldTypes )
352 BOOST_CHECK_MESSAGE( types.size() == 1,
"Incompatible expression types for property: " << field.mb_str() );
387 netSettings->SetNetChainClass( wxT(
"ChainHS" ), wxT(
"HighSpeed" ) );
393 netUnclassified->
SetNetChain( wxT(
"ChainOrphan" ) );
400 trackUnclassified.
SetNet( netUnclassified );
401 trackClassified.
SetNet( netClassified );
402 trackNoChain.
SetNet( netNoChain );
406 testEvalExpr( wxT(
"A.inNetChainClass('*')" ),
VAL( 0.0 ),
false, &trackUnclassified, &trackUnclassified );
407 testEvalExpr( wxT(
"A.inNetChainClass('HighSpeed')" ),
VAL( 0.0 ),
false, &trackUnclassified, &trackUnclassified );
410 testEvalExpr( wxT(
"A.inNetChainClass('*')" ),
VAL( 0.0 ),
false, &trackNoChain, &trackNoChain );
413 testEvalExpr( wxT(
"A.inNetChainClass('*')" ),
VAL( 1.0 ),
false, &trackClassified, &trackClassified );
414 testEvalExpr( wxT(
"A.inNetChainClass('HighSpeed')" ),
VAL( 1.0 ),
false, &trackClassified, &trackClassified );
415 testEvalExpr( wxT(
"A.inNetChainClass('High*')" ),
VAL( 1.0 ),
false, &trackClassified, &trackClassified );
416 testEvalExpr( wxT(
"A.inNetChainClass('LowSpeed')" ),
VAL( 0.0 ),
false, &trackClassified, &trackClassified );
432 via->SetPosition( aPos );
433 via->SetLayerPair( aTop, aBottom );
458 testEvalExpr( wxT(
"A.isStackedVia()" ),
VAL( 1.0 ),
false, upperHop, upperHop );
459 testEvalExpr( wxT(
"A.isStackedVia()" ),
VAL( 1.0 ),
false, lowerHop, lowerHop );
462 testEvalExpr( wxT(
"A.isStackedVia()" ),
VAL( 0.0 ),
false, lone, lone );
465 testEvalExpr( wxT(
"A.isStackedVia()" ),
VAL( 0.0 ),
false, through, through );
468 testEvalExpr( wxT(
"A.isMicroVia() && !A.isStackedVia()" ),
VAL( 1.0 ),
false, lone, lone );
474 testEvalExpr( wxT(
"A.isStackedVia()" ),
VAL( 1.0 ),
false, lone, lone );
475 testEvalExpr( wxT(
"A.isStackedVia()" ),
VAL( 1.0 ),
false, landing, landing );
491 text->SetText( wxT(
"J1" ) );
551 testEvalExpr( wxT(
"A.Do_not_Populate == 0" ),
VAL( 1.0 ),
false, &fp, &fp );
555 testEvalExpr( wxT(
"A.Do_not_Populate == 1" ),
VAL( 1.0 ),
false, &fp, &fp );
571 variant->
SetFieldValue( wxT(
"Value" ), wxT(
"VariantVal" ) );
576 testEvalExpr( wxT(
"A.Do_not_Populate == 1" ),
VAL( 1.0 ),
false, &fp, &fp );
577 testEvalExpr( wxT(
"A.getField('Value') == 'VariantVal'" ),
VAL( 1.0 ),
false, &fp, &fp );
582 testEvalExpr( wxT(
"A.Do_not_Populate == 0" ),
VAL( 1.0 ),
false, &fp, &fp );
583 testEvalExpr( wxT(
"A.getField('Value') == 'BaseVal'" ),
VAL( 1.0 ),
false, &fp, &fp );
591 std::vector<PROPERTY_ROW_DATA> rows;
597 wxS(
"A.getField('Value') == 'X'" ) );
606 wxS(
"A.getField('My Field') == 'X'" ) );
629 compiler.
Compile( wxT(
"L.Layer == '*.Paste'" ), &ucode, &preflight );
637 paste.SetItems( &track, &track );
669 for(
const wxString& expression : {
670 wxString(
"A.intersectsFrontCourtyard(B.Parent)" ),
671 wxString(
"A.intersectsCourtyard(B.Parent.Reference)" ),
672 wxString(
"A.intersectsFrontCourtyard(B.Parent.getField('Reference'))" ) } )
685 context.
SetItems( &graphic, &targetChild );
688 context.
SetItems( &graphic, &otherChild );
691 context.
SetItems( &graphic, &targetChild );
705 expectCompileError( wxS(
"A.intersectsFrontCourtyard(B.Parent.unknownFunction())" ) );
713 for(
const wxString& constraint : {
714 wxString(
"assertion \"A.Type == 'Graphic'\"" ),
715 wxString(
"hole_size (min 0.2mm)" ), wxString(
"text_height (min 1mm)" ),
716 wxString(
"text_thickness (min 0.1mm)" ),
717 wxString(
"track_segment_length (min 1mm)" ), wxString(
"annular_width (min 0.1mm)" ),
718 wxString(
"solder_mask_expansion (opt 0mm)" ),
719 wxString(
"solder_paste_abs_margin (opt 0mm)" ),
720 wxString(
"solder_paste_rel_margin (opt 0mm)" ), wxString(
"disallow track" ),
721 wxString(
"via_diameter (min 0.5mm)" ), wxString(
"length (max 100mm)" ),
722 wxString(
"net_chain_length (max 100mm)" ), wxString(
"stub_length (max 1mm)" ),
723 wxString(
"return_path (layer 'B.Cu')" ), wxString(
"skew (max 1mm)" ),
724 wxString(
"via_count (max 2)" ),
725 wxString(
"via_dangling (max 0)" ), wxString(
"bridged_mask (min 0)" ),
726 wxString(
"microvia_stack_depth (max 2)" ), wxString(
"microvia_aspect_ratio (max 1)" ) } )
728 for(
bool conditionFirst : {
true,
false } )
732 wxString condition = wxS(
"(condition \"B.Type == 'Graphic'\")" );
733 wxString body = wxString::Format( wxS(
"(constraint %s)" ), constraint );
734 wxString
source = wxS(
"(version 1)\n(rule test\n" )
735 + ( conditionFirst ? condition + wxS(
"\n" ) + body
736 : body + wxS(
"\n" ) + condition ) + wxS(
"\n)" );
737 std::vector<std::shared_ptr<DRC_RULE>> rules;
739 wxString controlSource =
source;
740 controlSource.Replace( wxS(
"B.Type" ), wxS(
"A.Type" ) );
741 DRC_RULES_PARSER controlParser( controlSource, wxS(
"single item control" ) );
743 BOOST_REQUIRE_MESSAGE( !
reporter.GetMessages().Contains( wxS(
"ERROR:" ) ),
reporter.GetMessages() );
748 BOOST_CHECK_MESSAGE(
reporter.GetMessages().Contains( wxS(
"Item 'B'" ) ),
755 return error.What().Contains( wxS(
"Item 'B' is not available" ) )
756 && error.lineNumber == ( conditionFirst ? 3 : 4 );
768 for(
const wxString& body : {
769 wxString(
"(condition \"A.intersectsFrontCourtyard(B.Parent)\")"
770 "(constraint assertion \"A.Type == 'Graphic'\")" ),
771 wxString(
"(condition \"AB.isCoupledDiffPair()\")(constraint hole_size (min 0.2mm))" ),
772 wxString(
"(constraint assertion \"B.Type == 'Graphic'\")" ),
773 wxString(
"(constraint assertion \"A.intersectsFrontCourtyard(B.Parent.getField('Reference'))\")" ),
774 wxString(
"(condition \"B.Type == 'Graphic'\")(constraint clearance (min 0.2mm))"
775 "(constraint hole_size (min 0.2mm))" ),
776 wxString(
"(condition \"AB.isCoupledDiffPair() && B.Type == 'Track'\")"
777 "(constraint length (max 100mm))" ) } )
781 std::vector<std::shared_ptr<DRC_RULE>> rules;
782 DRC_RULES_PARSER parser( wxS(
"(version 1)(rule test " ) + body + wxS(
")" ), wxS(
"preflight" ) );
786 return error.What().Contains( wxS(
"Item 'B' is not available" ) );
791 for(
const wxString& body : {
792 wxString(
"(condition \"A.Reference == 'B.Width'\")(constraint hole_size (min 0.2mm))" ),
793 wxString(
"(constraint assertion \"A.Type == 'Graphic'\")" ),
794 wxString(
"(condition \"A.intersectsFrontCourtyard(B.Parent)\")"
795 "(constraint physical_clearance (min 100mm))" ),
796 wxString(
"(condition \"AB.isCoupledDiffPair()\")(constraint diff_pair_gap (min 0.2mm))" ),
797 wxString(
"(condition \"AB.isCoupledDiffPair()\")(constraint track_width (min 0.2mm))" ),
798 wxString(
"(condition \"AB.isCoupledDiffPair()\")(constraint diff_pair_uncoupled (max 1mm))" ),
799 wxString(
"(condition \"AB.isCoupledDiffPair()\")(constraint length (max 100mm))" ),
800 wxString(
"(condition \"AB.isCoupledDiffPair()\")(constraint net_chain_length (max 100mm))" ),
801 wxString(
"(condition \"AB.isCoupledDiffPair()\")(constraint skew (max 1mm))" ),
802 wxString(
"(condition \"B.Type == 'Track'\")(constraint track_width (min 0.2mm))" ),
803 wxString(
"(condition \"B.Type == 'Track'\")(constraint track_angle (min 45))" ),
804 wxString(
"(condition \"B.Type == 'Zone'\")(constraint thermal_relief_gap (min 0.2mm))" ) } )
808 std::vector<std::shared_ptr<DRC_RULE>> rules;
810 DRC_RULES_PARSER parser( wxS(
"(version 1)(rule test " ) + body + wxS(
")" ), wxS(
"preflight" ) );
812 BOOST_CHECK_MESSAGE( !
reporter.GetMessages().Contains( wxS(
"ERROR:" ) ),
reporter.GetMessages() );
820 auto requiresPairItems =
821 [](
const wxString& aExpr )
831 BOOST_CHECK( !requiresPairItems( wxT(
"A.Width == 1mm" ) ) );
832 BOOST_CHECK( requiresPairItems( wxT(
"B.Width == 1mm" ) ) );
833 BOOST_CHECK( requiresPairItems( wxT(
"AB.isCoupledDiffPair()" ) ) );
834 BOOST_CHECK( !requiresPairItems( wxT(
"A.Reference == 'B.Width'" ) ) );
constexpr EDA_IU_SCALE pcbIUScale
Construction utilities for PCB tests.
virtual void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
std::shared_ptr< NET_SETTINGS > m_NetSettings
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Information pertinent to a Pcbnew printed circuit board.
const NETINFO_LIST & GetNetInfo() const
void SetCurrentVariant(const wxString &aVariant)
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
void AddVariant(const wxString &aVariantName)
void IncrementTimeStamp()
void SetCopperLayerCount(int aCount)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
void Parse(std::vector< std::shared_ptr< DRC_RULE > > &aRules, REPORTER *aReporter)
A color representation with 4 components: red, green, blue, alpha.
wxString ToCSSString() const
bool IsErrorPending() const
const ERROR_STATUS & GetError() const
bool Compile(const wxString &aString, UCODE *aCode, CONTEXT *aPreflightContext)
VALUE * Run(CONTEXT *ctx)
virtual const wxString & AsString() const
virtual double AsDouble() const
VAR_TYPE_T GetType() const
A collection of nets and the parameters used to route or test these nets.
Handle the data for a net.
void SetNetChain(const wxString &aNetChain)
void SetNetClass(const std::shared_ptr< NETCLASS > &aNetClass)
Container for NETINFO_ITEM elements, which are the nets.
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
void SetItems(BOARD_ITEM *a, BOARD_ITEM *b=nullptr)
bool RequiresPairItems() const
static PCBEXPR_PROPERTY_KIND ClassifyProperty(const PROPERTY_BASE *aProperty)
static LIBEVAL::VAR_TYPE_T ExpressionType(PCBEXPR_PROPERTY_KIND aKind)
void SetWidth(int aWidth) override
void SetEnd(const VECTOR2I &aEnd) override
void SetEllipseRotation(const EDA_ANGLE &aA) override
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetStart(const VECTOR2I &aStart) override
void SetEnd(const VECTOR2I &aEnd)
void SetStart(const VECTOR2I &aStart)
virtual void SetWidth(int aWidth)
void SetDrill(int aDrill)
void SetPosition(const VECTOR2I &aPoint) override
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
For a via m_layer contains the top layer, the other layer is in m_bottomLayer/.
void SetViaType(VIATYPE aViaType)
void SetWidth(int aWidth) override
virtual size_t TypeHash() const =0
Return type-id of the property type.
const wxString & Name() const
CLASSES_INFO GetAllClasses()
static PROPERTY_MANAGER & Instance()
void Rebuild()
Rebuild the list of all registered properties.
bool IsOfType(TYPE_ID aDerived, TYPE_ID aBase) const
Return true if aDerived is inherited from aBase.
A wrapper for reporting to a wxString object.
Handle a list of polygons defining a copper zone.
void SetHatchOrientation(const EDA_ANGLE &aStep)
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetIsRuleArea(bool aEnable)
void SetAssignedPriority(unsigned aPriority)
void SetMinIslandArea(long long int aArea)
wxString normalizeQueryFieldAliases(const wxString &aExpression, const std::vector< PROPERTY_ROW_DATA > &aRows)
PCB_LAYER_ID
A quick note on layer IDs:
void DrawRect(FOOTPRINT &aFootprint, const VECTOR2I &aPos, const VECTOR2I &aSize, int aRadius, int aWidth, PCB_LAYER_ID aLayer)
Draw a rectangle on a footprint.
#define TYPE_HASH(x)
Macro to generate unique identifier for a type.
friend std::ostream & operator<<(std::ostream &os, const EXPR_TO_TEST &expr)
LIBEVAL::VALUE expectedResult
A filename or source description, a problem input line, a line number, a byte offset,...
PROPERTY_MATCH_MODE matchMode
BOOST_DATA_TEST_CASE(ConvertToKicadUnit, boost::unit_test::data::make(altium_to_kicad_unit), input_value, expected_result)
Test conversation from Altium internal units into KiCad internal units.
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
IbisParser parser & reporter
static void expectCompileError(const wxString &aExpr)
static void expectCompileSuccess(const wxString &aExpr)
static const std::vector< EXPR_TO_TEST > simpleExpressions
static bool testEvalExpr(const wxString &expr, const LIBEVAL::VALUE &expectedResult, bool expectError=false, BOARD_ITEM *itemA=nullptr, BOARD_ITEM *itemB=nullptr)
static const std::vector< EXPR_TO_TEST > introspectionExpressions
BOOST_AUTO_TEST_CASE(IntrospectedProperties)
BOOST_TEST_CONTEXT("Test Clearance")
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
wxString result
Test unit parsing edge cases and error handling.
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I