1 /*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2018 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 /**
25 * @file test_numeric_evaluator.cpp
26 * Test suite for #NUMERIC_EVALUATOR
27 */
28
29 #include <qa_utils/wx_utils/unit_test_utils.h>
30
31 #include <libeval/numeric_evaluator.h>
32
33 struct NUM_EVAL_FIXTURE
34 {
NUM_EVAL_FIXTURENUM_EVAL_FIXTURE35 NUM_EVAL_FIXTURE() : m_eval( EDA_UNITS::MILLIMETRES )
36 {
37 }
38
39 NUMERIC_EVALUATOR m_eval;
40 };
41
42
43 /**
44 * Declares the struct as the Boost test fixture.
45 */
46 BOOST_FIXTURE_TEST_SUITE( NumericEvaluator, NUM_EVAL_FIXTURE )
47
48
49 /**
50 * Struct representing a test case for #NUMERIC_EVALUATOR
51 */
52 struct EVAL_CASE
53 {
54 wxString input;
55 wxString exp_result;
56 };
57
58
59 /**
60 * Basic class ops: set one up, trivial input, tear it down
61 */
BOOST_AUTO_TEST_CASE(Basic)62 BOOST_AUTO_TEST_CASE( Basic )
63 {
64 m_eval.Process( "1" );
65 BOOST_CHECK_EQUAL( m_eval.Result(), "1" );
66 }
67
68 /**
69 * Check that getting/setting vars works
70 */
BOOST_AUTO_TEST_CASE(SetVar)71 BOOST_AUTO_TEST_CASE( SetVar )
72 {
73 m_eval.SetVar( "MoL", 42 );
74
75 m_eval.Process( "1 + MoL" );
76 BOOST_CHECK_EQUAL( m_eval.GetVar( "MoL" ), 42 );
77 BOOST_CHECK_EQUAL( m_eval.Result(), "43" );
78
79 m_eval.SetVar( "MoL", 422 );
80
81 // have to process again to re-evaluate
82 m_eval.Process( "1 + MoL" );
83 BOOST_CHECK_EQUAL( m_eval.Result(), "423" );
84
85 // Can remove one var
86 m_eval.SetVar( "pi", 3.14 );
87 BOOST_CHECK_EQUAL( m_eval.GetVar( "pi" ), 3.14 );
88 m_eval.RemoveVar( "pi" );
89 BOOST_CHECK_EQUAL( m_eval.GetVar( "pi" ), 0.0 );
90
91 // Other is still there
92 BOOST_CHECK_EQUAL( m_eval.GetVar( "MoL" ), 422 );
93
94 // Add another one back
95 m_eval.SetVar( "piish", 3.1 );
96
97 // String clear doesn't clear vars
98 m_eval.Clear();
99 m_eval.Process( "1 + MoL + piish" );
100 BOOST_CHECK_EQUAL( m_eval.Result(), "426.1" );
101
102 // Clear both
103 m_eval.ClearVar();
104 BOOST_CHECK_EQUAL( m_eval.GetVar( "MoL" ), 0.0 );
105 BOOST_CHECK_EQUAL( m_eval.GetVar( "piish" ), 0.0 );
106 }
107
108 /**
109 * A list of valid test strings and the expected results
110 */
111 static const std::vector<EVAL_CASE> eval_cases_valid = {
112 // Empty case
113 { "", "0" },
114 // Trivial eval
115 { "1", "1" },
116 // Decimal separators
117 { "1.5", "1.5" },
118 { "1,5", "1.5" },
119 // Semicolon is valid, but the result is NaN
120 { "1;", "NaN" },
121 // With own unit
122 { "1mm", "1" },
123 // Unit that's not the evaluator's unit
124 { "1in", "25.4" },
125 // Unit with white-space
126 { "1 in", "25.4" },
127 // Unit-less arithmetic
128 { "1+2", "3" },
129 // Multiple units
130 { "1 + 10mm + 1\" + 1.5in + 500mil", "87.2" },
131 // Any White-space is OK
132 { " 1 + 2 ", "3" },
133 // Decimals are OK in expressions
134 { "1.5 + 0.2 + .1", "1.8" },
135 // Negatives are OK
136 { "3 - 10", "-7" },
137 // Lots of operands
138 { "1 + 2 + 10 + 1000.05", "1013.05" },
139 // Operator precedence
140 { "1 + 2 - 4 * 20 / 2", "-37" },
141 // Parens
142 { "(1)", "1" },
143 // Parens affect precedence
144 { "-(1 + (2 - 4)) * 20.8 / 2", "10.4" },
145 // Unary addition is a sign, not a leading operator
146 { "+2 - 1", "1" },
147 // Unknown vars are 0.0
148 { "1 + unknown", "1" },
149 // Set var in-string
150 { "x = 1; 1 + x", "2" },
151 // Multiple set vars
152 { "x = 1; y = 2; 10 + x - y", "9" },
153 };
154
155
156 /**
157 * Run through a set of test strings, clearing in between
158 */
BOOST_AUTO_TEST_CASE(Results)159 BOOST_AUTO_TEST_CASE( Results )
160 {
161 for( const auto& c : eval_cases_valid )
162 {
163 BOOST_TEST_CONTEXT( c.input + " -> " + c.exp_result )
164 {
165 // Clear for new string input
166 m_eval.Clear();
167
168 m_eval.Process( c.input );
169
170 // These are all valid
171 BOOST_CHECK_EQUAL( m_eval.IsValid(), true );
172 BOOST_CHECK_EQUAL( m_eval.Result(), c.exp_result );
173
174 // Does original text still match?
175 BOOST_CHECK_EQUAL( m_eval.OriginalText(), c.input );
176 }
177 }
178 }
179
180 struct EVAL_INVALID_CASE
181 {
182 wxString input;
183 };
184
185 /**
186 * A list of invalid test strings
187 */
188 static const std::vector<EVAL_INVALID_CASE> eval_cases_invalid = {
189 // Trailing operator
190 { "1+" },
191 // Leading operator
192 { "*2 + 1" },
193 // No operator
194 { "1 2" },
195 { "(1)(2)" },
196 // Unknown operator
197 { "1 $ 2" },
198 // Mismatched parens
199 { "(1 + 2" },
200 { "1 + 2)" },
201 // random text
202 { "sdfsdf sdfsd" },
203 // Div by 0
204 { "1 / 0" },
205 { "1 / unknown" },
206 // Semicolons can't be empty or redundant
207 { ";" },
208 { ";1" },
209 { ";1;" },
210 };
211
212 /**
213 * Run through a set of invalid test strings, clearing in between
214 */
BOOST_AUTO_TEST_CASE(ResultsInvalid)215 BOOST_AUTO_TEST_CASE( ResultsInvalid )
216 {
217 for( const auto& c : eval_cases_invalid )
218 {
219 BOOST_TEST_CONTEXT( c.input )
220 {
221 // Clear for new string input
222 m_eval.Clear();
223
224 m_eval.Process( c.input );
225
226 // These are all valid
227 BOOST_CHECK_EQUAL( m_eval.IsValid(), false );
228
229 // Does original text still match?
230 BOOST_CHECK_EQUAL( m_eval.OriginalText(), c.input );
231 }
232 }
233 }
234
235 BOOST_AUTO_TEST_SUITE_END()
236