• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2017 Cyril Hrubis <chrubis@suse.cz>
4  */
5 
6 /*
7  * Basic unit test for the bolean expression parser and evaluator.
8  */
9 
10 #include <string.h>
11 #include <stdio.h>
12 #include "tst_test.h"
13 #include "tst_bool_expr.h"
14 
15 static int a, b, c;
16 
map(struct tst_expr_tok * var)17 static int map(struct tst_expr_tok *var)
18 {
19 	if (!strncmp(var->tok, "A", var->tok_len))
20 		return a;
21 
22 	if (!strncmp(var->tok, "B", var->tok_len))
23 		return b;
24 
25 	if (!strncmp(var->tok, "C", var->tok_len))
26 		return c;
27 
28 	if (!strncmp(var->tok, "True", var->tok_len))
29 		return 1;
30 
31 	if (!strncmp(var->tok, "False", var->tok_len))
32 		return 0;
33 
34 	return -1;
35 }
36 
parse_fail(const char * expr)37 static void parse_fail(const char *expr)
38 {
39 	struct tst_expr *res;
40 
41 	tst_res(TINFO, "Parsing '%s'", expr);
42 
43 	res = tst_bool_expr_parse(expr);
44 
45 	if (res) {
46 		printf("In RPN: ");
47 		tst_bool_expr_print(stdout, res);
48 		printf("\n");
49 		tst_bool_expr_free(res);
50 		tst_res(TFAIL, "Expression was parsed");
51 	} else {
52 		tst_res(TPASS, "Parser returned an error");
53 	}
54 }
55 
do_eval_test(const char * expr_str,int set_a,int set_b,int set_c,int exp_res)56 static void do_eval_test(const char *expr_str, int set_a, int set_b, int set_c, int exp_res)
57 {
58 	struct tst_expr *expr;
59 	int res;
60 
61 	a = set_a;
62 	b = set_b;
63 	c = set_c;
64 
65 	tst_res(TINFO, "'%s' A=%i B=%i C=%i == %i", expr_str, a, b, c, exp_res);
66 
67 	expr = tst_bool_expr_parse(expr_str);
68 
69 	if (!expr) {
70 		tst_res(TFAIL, "Parser returned error");
71 		return;
72 	}
73 
74 	printf("In RPN: ");
75 	tst_bool_expr_print(stdout, expr);
76 	printf("\n");
77 
78 	res = tst_bool_expr_eval(expr, map);
79 
80 	if (res == exp_res)
81 		tst_res(TPASS, "Got %i", res);
82 	else
83 		tst_res(TFAIL, "Got %i", res);
84 
85 	tst_bool_expr_free(expr);
86 }
87 
do_test(void)88 static void do_test(void)
89 {
90 	do_eval_test("(A | B) & !!C", 0, 0, 0, 0);
91 	do_eval_test("(A | B) & !!C", 1, 0, 1, 1);
92 	do_eval_test("!A & B", 1, 0, 0, 0);
93 	do_eval_test("!A & B", 0, 1, 0, 1);
94 	do_eval_test("A & !B", 1, 0, 0, 1);
95 	do_eval_test("!!A & !!B", 0, 1, 0, 0);
96 	do_eval_test("!!A & !!B", 1, 1, 0, 1);
97 	do_eval_test("!(A & B) & C", 1, 1, 0, 0);
98 	do_eval_test("A & (B | C)", 1, 1, 0, 1);
99 	do_eval_test("A & B | C", 1, 1, 0, 1);
100 	do_eval_test("((((A)))&(B))", 1, 1, 0, 1);
101 	do_eval_test("   A  \t", 0, 0, 0, 0);
102 	do_eval_test("False & A", 1, 0, 0, 0);
103 	do_eval_test("! Undefined", 0, 0, 0, -1);
104 
105 	do_eval_test("\"(none)\"", 0, 0, 0, -1);
106 	do_eval_test("\"(none)\" & \" \"", 0, 0, 0, -1);
107 
108 	parse_fail("A!");
109 	parse_fail("A &");
110 	parse_fail("A B");
111 	parse_fail("A ) B");
112 	parse_fail("A ( B");
113 	parse_fail("A ( B )");
114 	parse_fail("A |");
115 	parse_fail("A ! B");
116 	parse_fail("A! & B");
117 	parse_fail("A & | B");
118 	parse_fail("A & (B |)");
119 	parse_fail("A & ( | B)");
120 	parse_fail("A & B &");
121 	parse_fail("((A )");
122 	parse_fail("& A");
123 	parse_fail("! &");
124 	parse_fail(")");
125 	parse_fail("| A");
126 	parse_fail("");
127 }
128 
129 static struct tst_test test = {
130 	.test_all = do_test,
131 };
132