1 /* $Id: test_expr.cpp 567764 2018-07-24 12:05:33Z ivanov $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Sergey Sikorskiy, Mikhail Zakharov
27 *
28 * File Description:
29 * Unit tests for expresiion parsing and evaluation.
30 *
31 * ===========================================================================
32 */
33
34
35 #include <ncbi_pch.hpp>
36
37 #include <corelib/ncbifile.hpp>
38 #include <corelib/expr.hpp>
39 #include <corelib/test_boost.hpp>
40
41 //#include <corelib/ncbifile.hpp>
42
43 #include <common/test_assert.h> /* This header must go last */
44
45
46 USING_NCBI_SCOPE;
47
48
49 ////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(ParseInt)50 BOOST_AUTO_TEST_CASE(ParseInt)
51 {
52 CExprParser parser;
53
54 // Int ...
55 parser.Parse("1");
56 BOOST_CHECK_EQUAL(CExprValue::eINT, parser.GetResult().GetType());
57 BOOST_CHECK_EQUAL(1, parser.GetResult().GetInt());
58
59 parser.Parse("1 + 1");
60 BOOST_CHECK_EQUAL(CExprValue::eINT, parser.GetResult().GetType());
61 BOOST_CHECK_EQUAL(2, parser.GetResult().GetInt());
62
63 parser.Parse("abc + def");
64
65 parser.Parse("1 + 2 * 3");
66 BOOST_CHECK_EQUAL(CExprValue::eINT, parser.GetResult().GetType());
67 BOOST_CHECK_EQUAL(7, parser.GetResult().GetInt());
68
69 parser.Parse("(1 + 2) * 3");
70 BOOST_CHECK_EQUAL(CExprValue::eINT, parser.GetResult().GetType());
71 BOOST_CHECK_EQUAL(9, parser.GetResult().GetInt());
72 }
73
74
75 ////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(ParseDouble)76 BOOST_AUTO_TEST_CASE(ParseDouble)
77 {
78 CExprParser parser;
79
80 // Double ...
81 parser.Parse("1.0");
82 BOOST_CHECK_EQUAL(CExprValue::eFLOAT, parser.GetResult().GetType());
83 BOOST_CHECK_EQUAL(1.0, parser.GetResult().GetDouble());
84
85 parser.Parse("pi");
86 BOOST_CHECK_EQUAL(CExprValue::eFLOAT, parser.GetResult().GetType());
87 BOOST_CHECK_EQUAL(3.1415926535897932385E0, parser.GetResult().GetDouble());
88
89 parser.Parse("e");
90 BOOST_CHECK_EQUAL(CExprValue::eFLOAT, parser.GetResult().GetType());
91 BOOST_CHECK_EQUAL(2.7182818284590452354E0, parser.GetResult().GetDouble());
92
93 parser.Parse("abs(-1)");
94 BOOST_CHECK_EQUAL(CExprValue::eFLOAT, parser.GetResult().GetType());
95 BOOST_CHECK_EQUAL(1.0, parser.GetResult().GetDouble());
96 }
97
98
99 ////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(ParseBool)100 BOOST_AUTO_TEST_CASE(ParseBool)
101 {
102 CExprParser parser;
103
104 // Boolean ...
105 parser.Parse("true");
106 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
107 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
108
109 parser.Parse("false");
110 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
111 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());
112
113 parser.Parse("true && true");
114 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
115 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
116
117 parser.Parse("true && false");
118 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
119 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());
120
121 parser.Parse("false && true");
122 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
123 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());
124
125 parser.Parse("false && false");
126 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
127 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());
128
129 parser.Parse("true || true");
130 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
131 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
132
133 parser.Parse("true || false");
134 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
135 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
136
137 parser.Parse("false || true");
138 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
139 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
140
141 parser.Parse("false || false");
142 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
143 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());
144
145 parser.Parse("true || true && true");
146 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
147 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
148
149 parser.Parse("false || true && true");
150 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
151 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
152
153 parser.Parse("(false || true) && true");
154 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
155 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
156
157 parser.Parse("true || false && true");
158 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
159 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
160
161 parser.Parse("(true || false) && true");
162 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
163 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
164
165 parser.Parse("true || true && false");
166 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
167 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
168
169 parser.Parse("true && true || true");
170 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
171 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
172
173 parser.Parse("false && (true || true)");
174 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
175 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());
176
177 parser.Parse("false && true || true");
178 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
179 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
180
181 parser.Parse("true && false || true");
182 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
183 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
184
185 parser.Parse("true && true || false");
186 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
187 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
188
189 parser.Parse("false && true || false");
190 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
191 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());
192
193 parser.Parse("false && (true || false)");
194 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
195 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());
196
197 parser.Parse("2 > 1");
198 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
199 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
200
201 parser.Parse("1 > 2");
202 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
203 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());
204
205 parser.Parse("1 != 2");
206 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
207 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
208
209 parser.Parse("true != false");
210 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
211 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
212
213 parser.Parse("1 == 1");
214 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
215 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
216
217 parser.Parse("false == false");
218 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
219 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
220
221 parser.Parse("true == true");
222 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
223 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
224
225 parser.Parse("true ^ true");
226 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
227 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());
228
229 parser.Parse("false ^ false");
230 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
231 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());
232
233 parser.Parse("true ^ false");
234 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
235 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
236
237 parser.Parse("false ^ true");
238 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
239 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
240
241 }
242
243 ////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE(AddSymbol)244 BOOST_AUTO_TEST_CASE(AddSymbol)
245 {
246 CExprParser parser;
247
248 parser.AddSymbol("1", Int8(1));
249 parser.AddSymbol("2", double(2.0));
250 parser.AddSymbol("3", false);
251
252 // request for member 'invalid_data_type' in '* value', which is of
253 // non-class type 'const char'
254 // parser.AddSymbol("4", (const char*)4);
255 // Call is ambiguous
256 // parser.AddSymbol("5", 0);
257 // Call is ambiguous
258 // parser.AddSymbol("5", 1);
259 // 'void*' is not a pointer-to-object type
260 // parser.AddSymbol("4", (void*)0);
261 }
262
263 ////////////////////////////////////////////////////////////////////////////////
264 /// Test string 2 bool function: checks if given directory exists
DirectoryExists(const string & DirectoryName)265 bool DirectoryExists(const string& DirectoryName)
266 {
267 CDir Directory(DirectoryName);
268
269 return Directory.Exists();
270 }
271
272 /// Boost test case checks parsing of string literals
BOOST_AUTO_TEST_CASE(ParseString)273 BOOST_AUTO_TEST_CASE(ParseString)
274 {
275 CExprParser parser;
276
277 // String literal
278 parser.Parse("\"abc\"");
279 BOOST_CHECK_EQUAL(CExprValue::eSTRING, parser.GetResult().GetType());
280 BOOST_CHECK_EQUAL("abc", parser.GetResult().GetString());
281
282 // String literal concatenation by "+"
283 parser.Parse("\"abc\"+\"def\"");
284 BOOST_CHECK_EQUAL(CExprValue::eSTRING, parser.GetResult().GetType());
285 BOOST_CHECK_EQUAL("abcdef", parser.GetResult().GetString());
286
287 // All other operations on strings throw
288 BOOST_CHECK_THROW(parser.Parse("\"abc\"-\"def\""), CExprParserException);
289 BOOST_CHECK_THROW(parser.Parse("\"abc\"*\"def\""), CExprParserException);
290 BOOST_CHECK_THROW(parser.Parse("\"abc\"/\"def\""), CExprParserException);
291 BOOST_CHECK_THROW(parser.Parse("\"abc\"\\\"def\""), CExprParserException);
292 BOOST_CHECK_THROW(parser.Parse("\"abc\"&&\"def\""), CExprParserException);
293 BOOST_CHECK_THROW(parser.Parse("\"abc\"||\"def\""), CExprParserException);
294 BOOST_CHECK_THROW(parser.Parse("\"abc\"^^\"def\""), CExprParserException);
295 BOOST_CHECK_THROW(parser.Parse("!\"abc\""), CExprParserException);
296 BOOST_CHECK_THROW(parser.Parse("-\"abc\""), CExprParserException);
297 BOOST_CHECK_THROW(parser.Parse("~\"abc\""), CExprParserException);
298 BOOST_CHECK_THROW(parser.Parse("\"abc\"%\"def\""), CExprParserException);
299 BOOST_CHECK_THROW(parser.Parse("\"abc\"<\"def\""), CExprParserException);
300 BOOST_CHECK_THROW(parser.Parse("\"abc\">\"def\""), CExprParserException);
301 BOOST_CHECK_THROW(parser.Parse("\"abc\"&\"def\""), CExprParserException);
302 BOOST_CHECK_THROW(parser.Parse("\"abc\"|\"def\""), CExprParserException);
303 BOOST_CHECK_THROW(parser.Parse("\"abc\"^\"def\""), CExprParserException);
304 BOOST_CHECK_THROW(parser.Parse("\"abc\"**\"def\""), CExprParserException);
305
306 // String to Bool function call
307 parser.AddSymbol("dir", DirectoryExists);
308
309 #ifndef NCBI_OS_MSWIN
310 parser.Parse("dir(\"/var/log\")");
311 #else
312 parser.Parse("dir(\"c:\\\")");
313 #endif
314 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
315 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
316
317 parser.Parse("dir(\"/var/NotExistingDirectory\")");
318 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
319 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());
320
321 // String ==/!= check
322 string Dummy("SomeDummyString");
323
324 parser.AddSymbol("var1", Dummy);
325 parser.Parse("var1 == \"SomeDammyString\"");
326 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
327 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());
328
329 parser.Parse("var1 == \"SomeDummyString\"");
330 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
331 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
332
333 parser.Parse("var1 != \"SomeDammyString\"");
334 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
335 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
336
337 parser.Parse("var1 != \"SomeDummyString\"");
338 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
339 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());}
340
341 /// Test special no-division mode
BOOST_AUTO_TEST_CASE(NoDivisionMode)342 BOOST_AUTO_TEST_CASE(NoDivisionMode)
343 {
344 // Switch NoDivision mode
345 CExprParser parser(CExprParser::fLogicalOnly);
346
347 // Int
348 parser.AddSymbol("/var/log", 2);
349 parser.Parse("/var/log");
350 BOOST_CHECK_EQUAL(CExprValue::eINT, parser.GetResult().GetType());
351 BOOST_CHECK_EQUAL(2, parser.GetResult().GetInt());
352
353 // Boolean
354 parser.AddSymbol("/var/log1", true);
355 parser.Parse("/var/log1");
356 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
357 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
358
359 // Check that dot is actually disabled and allowed as variable name
360 parser.AddSymbol("0.1.0/main/Group1/Test1/0.0.2", true);
361 parser.Parse("0.1.0/main/Group1/Test1/0.0.2");
362 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
363 BOOST_CHECK_EQUAL(true, parser.GetResult().GetBool());
364
365 // Check that dot is actually disabled and allowed as variable name
366 parser.AddSymbol("0.1.0/main/Group1/Test1/0.0.2", true);
367 parser.Parse("false || 0.1.0/main/Group2/Test1/0.0.2");
368 BOOST_CHECK_EQUAL(CExprValue::eBOOL, parser.GetResult().GetType());
369 BOOST_CHECK_EQUAL(false, parser.GetResult().GetBool());
370 }
371
372