2 * Copyright (c) 2013, Olivier MATZ <zer0@droids-corp.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the University of California, Berkeley nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <cfzy_expr.h>
34 #include "test_expr.h"
37 #define CANNOT_PARSE -1
38 #define CANNOT_CONVERT_TO_STR -2
39 #define IN_AND_OUT_DIFFERS -3
40 #define CANNOT_EVAL -4
41 #define CANNOT_GET_VARS -5
43 /* all variables starting with "A" are evaluated to 1, the other are
44 * evaluated to 0. The variable names "unknown" returns an error
45 * (variable not found). */
46 static int getvalue(const char *varname, void *arg)
50 if (!strcmp(varname, "unknown"))
53 if (varname[0] == 'A')
58 static int test_one_expr(const char *in)
61 struct cfzy_expr *exp;
64 /* valid expression */
65 exp = cfzy_expr_parse(in);
69 cfzy_expr_graph_dump("test.graph", exp);
70 ret = cfzy_expr_to_str(exp, out, sizeof(out));
73 return CANNOT_CONVERT_TO_STR;
76 if (strncmp(in, out, sizeof(out))) {
78 return IN_AND_OUT_DIFFERS;
81 ret = cfzy_expr_eval(exp, getvalue, NULL);
91 static void print_error(const char *in, int err)
93 printf("Unexpected return value when parsing: <%s>\n", in);
97 printf("Test returned %d, but should not\n", err);
100 printf("Cannot parse expression\n");
102 case CANNOT_CONVERT_TO_STR:
103 printf("Cannot convert expression to string\n");
105 case IN_AND_OUT_DIFFERS:
106 printf("Input and output expressions differ\n");
109 printf("Cannot evaluate expression\n");
111 case CANNOT_GET_VARS:
112 printf("Cannot get variable list\n");
115 printf("Invalid error %d\n", err);
120 /* must be called with an expression containing only A and B as vars */
121 static int test_vars(const char *in)
123 struct cfzy_expr *exp;
124 struct cfzy_list_elt *e;
125 struct cfzy_list_head *list;
126 int ret = 0, count = 0;
128 /* valid expression */
129 exp = cfzy_expr_parse(in);
133 list = cfzy_expr_get_vars(exp);
136 return CANNOT_GET_VARS;
139 /* list must contain 2 elements: A and B */
140 TAILQ_FOREACH(e, list, next) {
142 if (!strcmp(e->ptr, "A"))
144 if (!strcmp(e->ptr, "B"))
146 ret = CANNOT_GET_VARS;
149 ret = CANNOT_GET_VARS;
151 cfzy_list_free(list, free);
162 err = test_one_expr(in);
164 print_error(in, err);
168 in = "(true || false) && false";
169 err = test_one_expr(in);
171 print_error(in, err);
175 in = "true || (false && false)";
176 err = test_one_expr(in);
178 print_error(in, err);
182 /* && has priority */
183 in = "true || false && false";
184 err = test_one_expr(in);
186 print_error(in, err);
190 /* && has priority */
191 in = "false || true && false && true || true && false";
192 err = test_one_expr(in);
194 print_error(in, err);
198 /* '==' has priority */
199 in = "false == true && false";
200 err = test_one_expr(in);
202 print_error(in, err);
207 err = test_one_expr(in);
209 print_error(in, err);
214 err = test_one_expr(in);
216 print_error(in, err);
220 in = "true && (true)";
221 err = test_one_expr(in);
223 print_error(in, err);
227 in = "(!(A1 && !(B1 || A2 && B2 || A_aa)) || "
228 "(x && !(D && !A) && !(D || E))) == true";
229 err = test_one_expr(in);
231 print_error(in, err);
235 /* invalid expression */
237 err = test_one_expr(in);
238 if (err != CANNOT_PARSE) {
239 print_error(in, err);
243 /* invalid expression */
245 err = test_one_expr(in);
246 if (err != CANNOT_PARSE) {
247 print_error(in, err);
251 /* invalid expression */
253 err = test_one_expr(in);
254 if (err != CANNOT_PARSE) {
255 print_error(in, err);
259 /* invalid expression */
261 err = test_one_expr(in);
262 if (err != CANNOT_PARSE) {
263 print_error(in, err);
267 /* invalid expression */
269 err = test_one_expr(in);
270 if (err != CANNOT_PARSE) {
271 print_error(in, err);
274 /* invalid expression */
276 err = test_one_expr(in);
277 if (err != CANNOT_PARSE) {
278 print_error(in, err);
282 /* invalid expression */
284 err = test_one_expr(in);
285 if (err != CANNOT_PARSE) {
286 print_error(in, err);
290 /* invalid expression */
291 in = "A && B || C D";
292 err = test_one_expr(in);
293 if (err != CANNOT_PARSE) {
294 print_error(in, err);
298 /* invalid expression */
300 err = test_one_expr(in);
301 if (err != CANNOT_PARSE) {
302 print_error(in, err);
306 /* invalid expression */
308 err = test_one_expr(in);
309 if (err != CANNOT_PARSE) {
310 print_error(in, err);
314 /* invalid expression */
316 err = test_one_expr(in);
317 if (err != CANNOT_PARSE) {
318 print_error(in, err);
322 /* invalid expression */
324 err = test_one_expr(in);
325 if (err != CANNOT_PARSE) {
326 print_error(in, err);
330 /* invalid expression */
332 err = test_one_expr(in);
333 if (err != CANNOT_PARSE) {
334 print_error(in, err);
338 /* invalid expression, variable must start with a letter */
340 err = test_one_expr(in);
341 if (err != CANNOT_PARSE) {
342 print_error(in, err);
346 /* invalid expression, variable must start with a letter and
347 * numbers are not allowed (at least today) */
349 err = test_one_expr(in);
350 if (err != CANNOT_PARSE) {
351 print_error(in, err);
355 /* valid expression, but unknown variable */
357 err = test_one_expr(in);
358 if (err != CANNOT_EVAL) {
359 print_error(in, err);
363 /* valid expression, but won't display like this because
364 * spaces are stripped */
365 in = " true||(false && \n false)";
366 err = test_one_expr(in);
367 if (err != IN_AND_OUT_DIFFERS) {
368 print_error(in, err);
372 err = test_vars("A && B || true && A == !B");
374 print_error(in, err);