KiCad PCB EDA Suite
test_libeval_compiler.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <wx/wx.h>
25
27
28#include <layer_ids.h>
30#include <drc/drc_rule.h>
31#include <pcbnew/board.h>
32#include <pcbnew/pcb_track.h>
33
34BOOST_AUTO_TEST_SUITE( Libeval_Compiler )
35
37{
38 wxString expression;
41};
42
44
45const static std::vector<EXPR_TO_TEST> simpleExpressions = {
46 { "10mm + 20 mm", false, VAL( 30e6 ) },
47 { "3*(7+8)", false, VAL( 3 * ( 7 + 8 ) ) },
48 { "3*7+8", false, VAL( 3 * 7 + 8 ) },
49 { "(3*7)+8", false, VAL( 3 * 7 + 8 ) },
50 { "10mm + 20)", true, VAL( 0 ) },
51
52 { "1", false, VAL(1) },
53 { "1.5", false, VAL(1.5) },
54 { "1,5", false, VAL(1.5) },
55 { "1mm", false, VAL(1e6) },
56 // Any White-space is OK
57 { " 1 + 2 ", false, VAL(3) },
58 // Decimals are OK in expressions
59 { "1.5 + 0.2 + 0.1", false, VAL(1.8) },
60 // Negatives are OK
61 { "3 - 10", false, VAL(-7) },
62 // Lots of operands
63 { "1 + 2 + 10 + 1000.05", false, VAL(1013.05) },
64 // Operator precedence
65 { "1 + 2 - 4 * 20 / 2", false, VAL(-37) },
66 // Parens
67 { "(1)", false, VAL(1) },
68 // Parens affect precedence
69 { "-(1 + (2 - 4)) * 20.8 / 2", false, VAL(10.4) },
70 // Unary addition is a sign, not a leading operator
71 { "+2 - 1", false, VAL(1) }
72};
73
74
75const static std::vector<EXPR_TO_TEST> introspectionExpressions = {
76 { "A.type == 'Pad' && B.type == 'Pad' && (A.existsOnLayer('F.Cu'))", false, VAL( 0.0 ) },
77 { "A.Width > B.Width", false, VAL( 0.0 ) },
78 { "A.Width + B.Width", false, VAL( pcbIUScale.MilsToIU(10) + pcbIUScale.MilsToIU(20) ) },
79 { "A.Netclass", false, VAL( "HV" ) },
80 { "(A.Netclass == 'HV') && (B.netclass == 'otherClass') && (B.netclass != 'F.Cu')", false,
81 VAL( 1.0 ) },
82 { "A.Netclass + 1.0", false, VAL( 1.0 ) },
83 { "A.type == 'Track' && B.type == 'Track' && A.layer == 'F.Cu'", false, VAL( 1.0 ) },
84 { "(A.type == 'Track') && (B.type == 'Track') && (A.layer == 'F.Cu')", false, VAL( 1.0 ) },
85 { "A.type == 'Via' && A.isMicroVia()", false, VAL(0.0) }
86};
87
88
89static bool testEvalExpr( const wxString& expr, const LIBEVAL::VALUE& expectedResult,
90 bool expectError = false, BOARD_ITEM* itemA = nullptr,
91 BOARD_ITEM* itemB = nullptr )
92{
93 PCB_EXPR_COMPILER compiler( new PCB_UNIT_RESOLVER() );
94 PCB_EXPR_UCODE ucode;
97 bool ok = true;
98
99 context.SetItems( itemA, itemB );
100
101
102 BOOST_TEST_MESSAGE( "Expr: '" << expr.c_str() << "'" );
103
104 bool error = !compiler.Compile( expr, &ucode, &preflightContext );
105
106 BOOST_CHECK_EQUAL( error, expectError );
107
108 if( error != expectError )
109 {
110 BOOST_TEST_MESSAGE( "Result: FAIL: " << compiler.GetError().message.c_str() <<
111 " (code pos: " << compiler.GetError().srcPos << ")" );
112
113 return false;
114 }
115
116 if( error )
117 return true;
118
119 LIBEVAL::VALUE result;
120
121 if( ok )
122 {
123 result = *ucode.Run( &context );
124 ok = ( result.EqualTo( &context, &expectedResult ) );
125 }
126
127 if( expectedResult.GetType() == LIBEVAL::VT_NUMERIC )
128 {
129 BOOST_CHECK_EQUAL( result.AsDouble(), expectedResult.AsDouble() );
130 }
131 else
132 {
133 BOOST_CHECK_EQUAL( result.AsString(), expectedResult.AsString() );
134 }
135
136 return ok;
137}
138
139
140BOOST_AUTO_TEST_CASE( SimpleExpressions )
141{
142 for( const auto& expr : simpleExpressions )
143 {
144 testEvalExpr( expr.expression, expr.expectedResult, expr.expectError );
145 }
146}
147
148
149BOOST_AUTO_TEST_CASE( IntrospectedProperties )
150{
152 propMgr.Rebuild();
153
154 BOARD brd;
155
156 NETINFO_LIST& netInfo = brd.GetNetInfo();
157
158 std::shared_ptr<NETCLASS> netclass1( new NETCLASS( "HV" ) );
159 std::shared_ptr<NETCLASS> netclass2( new NETCLASS( "otherClass" ) );
160
161 auto net1info = new NETINFO_ITEM( &brd, "net1", 1 );
162 auto net2info = new NETINFO_ITEM( &brd, "net2", 2 );
163
164 net1info->SetNetClass( netclass1 );
165 net2info->SetNetClass( netclass2 );
166
167 PCB_TRACK trackA( &brd );
168 PCB_TRACK trackB( &brd );
169
170 trackA.SetNet( net1info );
171 trackB.SetNet( net2info );
172
173 trackB.SetLayer( F_Cu );
174
175 trackA.SetWidth( pcbIUScale.MilsToIU( 10 ) );
176 trackB.SetWidth( pcbIUScale.MilsToIU( 20 ) );
177
178 for( const auto& expr : introspectionExpressions )
179 {
180 testEvalExpr( expr.expression, expr.expectedResult, expr.expectError, &trackA, &trackB );
181 }
182}
183
184BOOST_AUTO_TEST_SUITE_END()
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:58
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:214
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:765
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
virtual bool EqualTo(CONTEXT *aCtx, const VALUE *b) const
A collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:47
Handle the data for a net.
Definition: netinfo.h:66
Container for NETINFO_ITEM elements, which are the nets.
Definition: netinfo.h:324
void SetItems(BOARD_ITEM *a, BOARD_ITEM *b=nullptr)
void SetWidth(int aWidth)
Definition: pcb_track.h:105
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:67
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:69
void Rebuild()
Rebuild the list of all registered properties.
@ NULL_CONSTRAINT
Definition: drc_rule.h:45
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
@ F_Cu
Definition: layer_ids.h:64
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
LIBEVAL::VALUE expectedResult
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)
LIBEVAL::VALUE VAL
static const std::vector< EXPR_TO_TEST > introspectionExpressions
BOOST_AUTO_TEST_CASE(SimpleExpressions)