1 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <gtest/gtest.h>
6
7 #include "cras_expr.h"
8
9 namespace {
10
TEST(ExprTest,UnparsibleExpression)11 TEST(ExprTest, UnparsibleExpression) {
12 struct cras_expr_expression* expr;
13
14 /* un-parsable input */
15 expr = cras_expr_expression_parse("#");
16 EXPECT_EQ(NULL, expr);
17
18 expr = cras_expr_expression_parse(NULL);
19 EXPECT_EQ(NULL, expr);
20
21 cras_expr_expression_free(expr);
22 }
23
TEST(ExprTest,LiteralExpression)24 TEST(ExprTest, LiteralExpression) {
25 struct cras_expr_expression* expr;
26 struct cras_expr_value value = CRAS_EXPR_VALUE_INIT;
27 struct cras_expr_env env = CRAS_EXPR_ENV_INIT;
28 int integer = 0;
29
30 /* parse integer literal */
31 expr = cras_expr_expression_parse(" -2");
32 EXPECT_EQ(EXPR_TYPE_LITERAL, expr->type);
33 EXPECT_EQ(CRAS_EXPR_VALUE_TYPE_INT, expr->u.literal.type);
34 EXPECT_EQ(-2, expr->u.literal.u.integer);
35
36 /* evaluate integer literal */
37 cras_expr_expression_eval(expr, &env, &value);
38 EXPECT_EQ(CRAS_EXPR_VALUE_TYPE_INT, value.type);
39 EXPECT_EQ(-2, value.u.integer);
40
41 EXPECT_EQ(0, cras_expr_expression_eval_int(expr, &env, &integer));
42 EXPECT_EQ(-2, integer);
43 cras_expr_expression_free(expr);
44
45 /* parse string literal */
46 expr = cras_expr_expression_parse("\"hello\" ");
47 EXPECT_EQ(EXPR_TYPE_LITERAL, expr->type);
48 EXPECT_EQ(CRAS_EXPR_VALUE_TYPE_STRING, expr->u.literal.type);
49 EXPECT_STREQ("hello", expr->u.literal.u.string);
50
51 /* evaluate string literal */
52 cras_expr_expression_eval(expr, &env, &value);
53 ASSERT_EQ(CRAS_EXPR_VALUE_TYPE_STRING, value.type);
54 EXPECT_STREQ("hello", value.u.string);
55
56 cras_expr_value_free(&value);
57 cras_expr_expression_free(expr);
58 cras_expr_env_free(&env);
59 }
60
TEST(ExprTest,Variable)61 TEST(ExprTest, Variable) {
62 struct cras_expr_expression* expr;
63 struct cras_expr_value value = CRAS_EXPR_VALUE_INIT;
64 struct cras_expr_env env = CRAS_EXPR_ENV_INIT;
65 int integer = 0;
66
67 /* parse variable */
68 expr = cras_expr_expression_parse("a");
69 ASSERT_EQ(EXPR_TYPE_VARIABLE, expr->type);
70 EXPECT_STREQ("a", expr->u.variable);
71
72 /* evaluate variable (undefined now) */
73 cras_expr_expression_eval(expr, &env, &value);
74 EXPECT_EQ(CRAS_EXPR_VALUE_TYPE_NONE, value.type);
75
76 /* undefined variable */
77 EXPECT_EQ(-1, cras_expr_expression_eval_int(expr, &env, &integer));
78
79 /* now define a variable with integer value 2 */
80 cras_expr_env_set_variable_integer(&env, "a", 2);
81
82 /* re-evaluate the variable */
83 EXPECT_EQ(0, cras_expr_expression_eval_int(expr, &env, &integer));
84 EXPECT_EQ(2, integer);
85
86 cras_expr_value_free(&value);
87 cras_expr_expression_free(expr);
88 cras_expr_env_free(&env);
89 }
90
TEST(ExprTest,Compound)91 TEST(ExprTest, Compound) {
92 struct cras_expr_expression *expr, *expr1, *expr2;
93 struct cras_expr_value value = CRAS_EXPR_VALUE_INIT;
94 struct cras_expr_env env = CRAS_EXPR_ENV_INIT;
95
96 /* parse empty compound expression */
97 expr = cras_expr_expression_parse("()");
98 ASSERT_EQ(EXPR_TYPE_COMPOUND, expr->type);
99 EXPECT_EQ(0, ARRAY_COUNT(&expr->u.children));
100
101 /* evaluate empty compound expression */
102 cras_expr_expression_eval(expr, &env, &value);
103 EXPECT_EQ(CRAS_EXPR_VALUE_TYPE_NONE, value.type);
104 cras_expr_expression_free(expr);
105
106 /* parse non-empty compound expression */
107 expr = cras_expr_expression_parse("(foo bar)");
108 ASSERT_EQ(EXPR_TYPE_COMPOUND, expr->type);
109 EXPECT_EQ(2, ARRAY_COUNT(&expr->u.children));
110
111 /* evaluate non-empty compound expression */
112 cras_expr_expression_eval(expr, &env, &value);
113 EXPECT_EQ(CRAS_EXPR_VALUE_TYPE_NONE, value.type);
114 cras_expr_expression_free(expr);
115
116 /* parse nested compound expression */
117 expr = cras_expr_expression_parse("((foo 3)bar )");
118 ASSERT_EQ(EXPR_TYPE_COMPOUND, expr->type);
119 ASSERT_EQ(2, ARRAY_COUNT(&expr->u.children));
120
121 expr1 = *ARRAY_ELEMENT(&expr->u.children, 0);
122 ASSERT_EQ(EXPR_TYPE_COMPOUND, expr1->type);
123 ASSERT_EQ(2, ARRAY_COUNT(&expr1->u.children));
124
125 expr2 = *ARRAY_ELEMENT(&expr1->u.children, 1);
126 ASSERT_EQ(EXPR_TYPE_LITERAL, expr2->type);
127 EXPECT_EQ(CRAS_EXPR_VALUE_TYPE_INT, expr2->u.literal.type);
128 EXPECT_EQ(3, expr2->u.literal.u.integer);
129
130 /* evaluate nested compound expression */
131 cras_expr_expression_eval(expr, &env, &value);
132 EXPECT_EQ(CRAS_EXPR_VALUE_TYPE_NONE, value.type);
133 cras_expr_expression_free(expr);
134
135 cras_expr_value_free(&value);
136 cras_expr_env_free(&env);
137 }
138
TEST(ExprTest,Environment)139 TEST(ExprTest, Environment) {
140 struct cras_expr_expression* expr;
141 struct cras_expr_value value = CRAS_EXPR_VALUE_INIT;
142 struct cras_expr_env env1 = CRAS_EXPR_ENV_INIT;
143 struct cras_expr_env env2 = CRAS_EXPR_ENV_INIT;
144 int integer = 0;
145 char boolean = 0;
146
147 /* parse variable */
148 expr = cras_expr_expression_parse("baz");
149
150 /* put baz=4 into env1 */
151 cras_expr_env_set_variable_integer(&env1, "baz", 4);
152
153 /* evaluate expr against env1 and env2 */
154 EXPECT_EQ(0, cras_expr_expression_eval_int(expr, &env1, &integer));
155 EXPECT_EQ(4, integer);
156 EXPECT_EQ(-1, cras_expr_expression_eval_int(expr, &env2, &integer));
157
158 /* put baz=5 into env2 */
159 cras_expr_env_set_variable_integer(&env2, "baz", 5);
160
161 /* evaluate again */
162 EXPECT_EQ(0, cras_expr_expression_eval_int(expr, &env1, &integer));
163 EXPECT_EQ(4, integer);
164 EXPECT_EQ(0, cras_expr_expression_eval_int(expr, &env2, &integer));
165 EXPECT_EQ(5, integer);
166
167 /* an integer is not a boolean */
168 EXPECT_EQ(-1, cras_expr_expression_eval_boolean(expr, &env2, &boolean));
169
170 cras_expr_value_free(&value);
171 cras_expr_expression_free(expr);
172 cras_expr_env_free(&env1);
173 cras_expr_env_free(&env2);
174 }
175
expect_int(int expected,const char * str,struct cras_expr_env * env)176 static void expect_int(int expected,
177 const char* str,
178 struct cras_expr_env* env) {
179 struct cras_expr_expression* expr;
180 struct cras_expr_value value = CRAS_EXPR_VALUE_INIT;
181
182 expr = cras_expr_expression_parse(str);
183 cras_expr_expression_eval(expr, env, &value);
184 EXPECT_EQ(CRAS_EXPR_VALUE_TYPE_INT, value.type);
185 EXPECT_EQ(expected, value.u.integer);
186 cras_expr_expression_free(expr);
187 }
188
expect_boolean(char expected,const char * str,struct cras_expr_env * env)189 static void expect_boolean(char expected,
190 const char* str,
191 struct cras_expr_env* env) {
192 struct cras_expr_expression* expr;
193 struct cras_expr_value value = CRAS_EXPR_VALUE_INIT;
194
195 expr = cras_expr_expression_parse(str);
196 cras_expr_expression_eval(expr, env, &value);
197 EXPECT_EQ(CRAS_EXPR_VALUE_TYPE_BOOLEAN, value.type);
198 EXPECT_EQ(expected, value.u.boolean);
199 cras_expr_expression_free(expr);
200 }
201
TEST(ExprTest,Builtin)202 TEST(ExprTest, Builtin) {
203 struct cras_expr_expression* expr;
204 struct cras_expr_value value = CRAS_EXPR_VALUE_INIT;
205 struct cras_expr_env env = CRAS_EXPR_ENV_INIT;
206
207 cras_expr_env_install_builtins(&env);
208
209 /* parse variable */
210 expr = cras_expr_expression_parse("or");
211 cras_expr_expression_eval(expr, &env, &value);
212 EXPECT_EQ(CRAS_EXPR_VALUE_TYPE_FUNCTION, value.type);
213 cras_expr_expression_free(expr);
214
215 /* test builtin functions */
216 expect_boolean(1, "(and)", &env);
217 expect_boolean(1, "(and #t)", &env);
218 expect_boolean(1, "(and #t #t)", &env);
219 expect_int(3, "(and 1 2 3)", &env);
220 expect_boolean(0, "(and #f 4)", &env);
221 expect_boolean(0, "(or)", &env);
222 expect_boolean(1, "(or #t)", &env);
223 expect_boolean(0, "(or #f #f)", &env);
224 expect_int(2, "(or #f #f 2)", &env);
225 expect_int(3, "(or #f (or 3))", &env);
226 expect_boolean(0, "(equal? \"hello\" 3)", &env);
227 expect_boolean(1, "(equal? \"hello\" \"hello\")", &env);
228
229 /* a more complex example a="hello" b="world"*/
230 expr = cras_expr_expression_parse("(or (equal? \"test\" a) b)");
231 cras_expr_env_set_variable_string(&env, "a", "hello");
232 cras_expr_env_set_variable_string(&env, "b", "world");
233
234 cras_expr_expression_eval(expr, &env, &value);
235 EXPECT_EQ(CRAS_EXPR_VALUE_TYPE_STRING, value.type);
236 EXPECT_STREQ("world", value.u.string);
237 cras_expr_expression_free(expr);
238
239 cras_expr_value_free(&value);
240 cras_expr_env_free(&env);
241 }
242
243 } // namespace
244
main(int argc,char ** argv)245 int main(int argc, char** argv) {
246 ::testing::InitGoogleTest(&argc, argv);
247 return RUN_ALL_TESTS();
248 }
249