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 15static int a, b, c; 16 17static 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 37static 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 56static 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 88static 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 129static struct tst_test test = { 130 .test_all = do_test, 131}; 132