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