1 #include <test.h>
2
3
4 #include <iteration.c>
5
6
7
test_FindDollarParen(void)8 static void test_FindDollarParen(void)
9 {
10 /* not found */
11 assert_int_equal(FindDollarParen("", 1), 0);
12 assert_int_equal(FindDollarParen(" ", 2), 1);
13 assert_int_equal(FindDollarParen("$", 2), 1);
14 assert_int_equal(FindDollarParen("(", 2), 1);
15 assert_int_equal(FindDollarParen("{", 2), 1);
16 assert_int_equal(FindDollarParen("$ ", 3), 2);
17 assert_int_equal(FindDollarParen("$$", 3), 2);
18 assert_int_equal(FindDollarParen("$[", 3), 2);
19 assert_int_equal(FindDollarParen("($", 3), 2);
20 assert_int_equal(FindDollarParen(" $", 3), 2);
21 assert_int_equal(FindDollarParen(" $[", 4), 3);
22 assert_int_equal(FindDollarParen("$ (", 4), 3);
23 assert_int_equal(FindDollarParen("$ {", 4), 3);
24
25 /* found */
26 assert_int_equal(FindDollarParen("${", 3), 0);
27 assert_int_equal(FindDollarParen("$(", 3), 0);
28 assert_int_equal(FindDollarParen(" $(", 4), 1);
29 assert_int_equal(FindDollarParen(" ${", 4), 1);
30 assert_int_equal(FindDollarParen("$$(", 4), 1);
31 assert_int_equal(FindDollarParen("$${", 4), 1);
32
33 // Detect out of bounds read:
34 // If max is 0, it shouldn't try to deref these invalid pointers:
35 char a = 'a';
36 assert_int_equal(FindDollarParen((char *)0x1, 0), 0);
37 assert_int_equal(FindDollarParen((&a) + 1, 0), 0);
38
39 // Should not read past max bytes:
40 char b[1] = {'b'};
41 assert_int_equal(FindDollarParen(b, 1), 1);
42 char c[8] = {'c', 'c', 'c', 'c', 'c', 'c', 'c', 'c'};
43 assert_int_equal(FindDollarParen(c, 8), 8);
44
45 // We had some problems with FindDollarParen reading outside a buffer
46 // so I added these cryptic but useful tests. Some of them will only
47 // fail if you run tests with ASAN, valgrind or similar.
48 }
49
50
test_IsMangled(void)51 static void test_IsMangled(void)
52 {
53 /* Simply true. */
54 assert_false(IsMangled(""));
55 assert_false(IsMangled("blah"));
56 assert_false(IsMangled("namespace:blah"));
57 assert_false(IsMangled("scope.blah"));
58 assert_false(IsMangled("namespace:scope.blah"));
59
60 /* Simply false. */
61 assert_true(IsMangled("scope#blah"));
62 assert_true(IsMangled("namespace*blah"));
63 assert_true(IsMangled("namespace*scope.blah"));
64 assert_true(IsMangled("namespace:scope#blah"));
65
66 /* Complicated: nested expansions shouldn't affect result */
67 assert_false(IsMangled("$("));
68 assert_false(IsMangled("${"));
69 assert_false(IsMangled("blah$(blue)"));
70 assert_false(IsMangled("blah$(scope.blue)"));
71 assert_false(IsMangled("blah$(scope#blue)"));
72 assert_false(IsMangled("blah$(namespace:blue)"));
73 assert_false(IsMangled("blah$(namespace*blue)"));
74 assert_false(IsMangled("blah$(namespace:scope.blue)"));
75 assert_false(IsMangled("blah$(namespace:scope#blue)"));
76 assert_false(IsMangled("blah$(namespace*scope.blue)"));
77 assert_false(IsMangled("blah$(namespace*scope#blue)"));
78
79 assert_false(IsMangled("scope.blah$(blue)"));
80 assert_false(IsMangled("scope.blah$(scope.blue)"));
81 assert_false(IsMangled("scope.blah$(scope#blue)"));
82 assert_false(IsMangled("scope.blah$(namespace:blue)"));
83 assert_false(IsMangled("scope.blah$(namespace*blue)"));
84 assert_false(IsMangled("scope.blah$(namespace:scope.blue)"));
85 assert_false(IsMangled("scope.blah$(namespace:scope#blue)"));
86 assert_false(IsMangled("scope.blah$(namespace*scope.blue)"));
87 assert_false(IsMangled("scope.blah$(namespace*scope#blue)"));
88
89 assert_true(IsMangled("scope#blah$(blue)"));
90 assert_true(IsMangled("scope#blah$(scope.blue)"));
91 assert_true(IsMangled("scope#blah$(scope#blue)"));
92 assert_true(IsMangled("scope#blah$(namespace:blue)"));
93 assert_true(IsMangled("scope#blah$(namespace*blue)"));
94 assert_true(IsMangled("scope#blah$(namespace:scope.blue)"));
95 assert_true(IsMangled("scope#blah$(namespace:scope#blue)"));
96 assert_true(IsMangled("scope#blah$(namespace*scope.blue)"));
97 assert_true(IsMangled("scope#blah$(namespace*scope#blue)"));
98
99 assert_true(IsMangled("namespace*blah$(blue)"));
100 assert_true(IsMangled("namespace*blah$(scope.blue)"));
101 assert_true(IsMangled("namespace*blah$(scope#blue)"));
102 assert_true(IsMangled("namespace*blah$(namespace:blue)"));
103 assert_true(IsMangled("namespace*blah$(namespace*blue)"));
104 assert_true(IsMangled("namespace*blah$(namespace:scope.blue)"));
105 assert_true(IsMangled("namespace*blah$(namespace:scope#blue)"));
106 assert_true(IsMangled("namespace*blah$(namespace*scope.blue)"));
107 assert_true(IsMangled("namespace*blah$(namespace*scope#blue)"));
108
109 assert_false(IsMangled("$(scope#blah)"));
110 assert_false(IsMangled("$(namespace*blah)"));
111 assert_false(IsMangled("$(namespace*scope#blah)"));
112
113 /* Multiple nested expansions, again, none should matter. */
114 assert_false(IsMangled("blah$(blue$(bleh))"));
115 assert_false(IsMangled("blah$(scope.blue$(scope#bleh))"));
116
117 /* Array indexes shouldn't affect the result either. */
118 assert_false(IsMangled("["));
119 assert_false(IsMangled("blah[$(blue)]"));
120 assert_false(IsMangled("blah$(blue[bleh])"));
121 assert_false(IsMangled("blah[S#i]"));
122 assert_false(IsMangled("blah[S#i][N*i]"));
123 assert_false(IsMangled("blah[S#i][N*i]"));
124
125 assert_true(IsMangled("S#blah[S.blue]"));
126 assert_true(IsMangled("S#blah[N:blue]"));
127 assert_true(IsMangled("S#blah[S#blue]"));
128 assert_true(IsMangled("N*blah[S.blue]"));
129 assert_true(IsMangled("N*blah[N:blue]"));
130 assert_true(IsMangled("N*S.blah[N:blue]"));
131 assert_true(IsMangled("N*S.blah[S.blue]"));
132
133 assert_false(IsMangled("S.blah[S#i][N*i]"));
134 assert_true (IsMangled("S#blah[S#i][N*i]"));
135
136 assert_false(IsMangled("[scope#blah]"));
137 assert_false(IsMangled("[namespace*blah]"));
138 assert_false(IsMangled("[namespace*scope#blah]"));
139
140 /* Complicated: combine nested variables with array expansions. */
141 assert_false(IsMangled("[$("));
142 assert_false(IsMangled("S.blah[$("));
143 assert_false(IsMangled("S.blah[i]$(blah)"));
144 assert_false(IsMangled("S.blah[$(i)]"));
145 assert_false(IsMangled("S.v[$(i)]"));
146 assert_true (IsMangled("S#v[$(i)]"));
147 assert_true (IsMangled("N*v[$(i)]"));
148 assert_false(IsMangled("N:v[$(i)]"));
149 assert_false(IsMangled("N:v[$(N*i)]"));
150 assert_false(IsMangled("N:v[$(S#i)]"));
151 assert_true (IsMangled("N*v[$(S#i)]"));
152 assert_true (IsMangled("S#v[$(S#i)]"));
153 assert_false(IsMangled("v[$(N*S#i)]"));
154 assert_false(IsMangled("v[$(N:S#i)]"));
155 assert_false(IsMangled("v[$(N*S.i)]"));
156 assert_false(IsMangled("S.v[$(N*S#i)]"));
157 assert_true (IsMangled("S#v[$(N*S#i)]"));
158 assert_false(IsMangled("N:v[$(N*S#i)]"));
159 assert_true (IsMangled("N*v[$(N*S#i)]"));
160 }
161
162
Mangle_TestHelper(const char * orig,const char * expected)163 static void Mangle_TestHelper(const char *orig, const char *expected)
164 {
165 printf("Testing MangleVarRefString: %s\n", orig);
166
167 char *s = xstrdup(orig);
168 MangleVarRefString(s, strlen(s));
169 assert_string_equal(s, expected);
170 free(s);
171 }
Mangle_TestHelperWithLength1(const char * orig,size_t orig_len,const char * expected)172 static void Mangle_TestHelperWithLength1(const char *orig, size_t orig_len,
173 const char *expected)
174 {
175 printf("Testing MangleVarRefString: %.*s\n", (int) orig_len, orig);
176
177 char *s = xstrdup(orig);
178 MangleVarRefString(s, orig_len);
179 assert_string_equal(s, expected);
180 free(s);
181 }
182 /* NOTE: this one changes "orig" in-place. */
Mangle_TestHelperWithLength2(char * orig,size_t orig_len,const char * expected,size_t expected_len)183 static void Mangle_TestHelperWithLength2(char *orig, size_t orig_len,
184 const char *expected, size_t expected_len)
185 {
186 printf("Testing MangleVarRefString: %.*s\n", (int) orig_len, orig);
187
188 MangleVarRefString(orig, orig_len);
189 assert_memory_equal(orig, expected, expected_len);
190 }
test_MangleVarRefString(void)191 static void test_MangleVarRefString(void)
192 {
193 Mangle_TestHelper ("", "");
194 Mangle_TestHelperWithLength1 ("a", 0, "a");
195
196 Mangle_TestHelper ("a.b", "a#b");
197 /* Force length to 1, no change should occur. */
198 Mangle_TestHelperWithLength1 ("a.b", 1, "a.b");
199
200 Mangle_TestHelper ("a:b", "a*b");
201 /* Force length to 1, no change should occur. */
202 Mangle_TestHelperWithLength1 ("a:b", 1, "a:b");
203
204 Mangle_TestHelper ("a:b.c", "a*b#c");
205 /* Force length to 1, no change should occur. */
206 Mangle_TestHelperWithLength1 ("a:b.c", 1, "a:b.c");
207
208 /* Never mangle after array indexing */
209 Mangle_TestHelper ("a[b.c]", "a[b.c]");
210
211 /* "this" scope never gets mangled. */
212 Mangle_TestHelper ("this.a", "this.a");
213
214 /* Inner expansions never get mangled. */
215 Mangle_TestHelper ("a_$(s.i)", "a_$(s.i)");
216 Mangle_TestHelper ("a_$(n:i)", "a_$(n:i)");
217
218 /* Only before the inner expansion it gets mangled. */
219 Mangle_TestHelper ("s.a_$(s.i)", "s#a_$(s.i)");
220 Mangle_TestHelper ("n:a_$(n:i)", "n*a_$(n:i)");
221
222 /* Testing non '\0'-terminated char arrays. */
223
224 char A[4] = {'a','b','.','c'};
225 Mangle_TestHelperWithLength2(A, 0, "ab.c", 4);
226 Mangle_TestHelperWithLength2(A, 4, "ab#c", 4);
227 char B[3] = {'a',':','b'};
228 Mangle_TestHelperWithLength2(B, 0, "a:b", 3);
229 Mangle_TestHelperWithLength2(B, 3, "a*b", 3);
230 char C[1] = {'a'};
231 Mangle_TestHelperWithLength2(C, 0, "a", 1);
232 Mangle_TestHelperWithLength2(C, 1, "a", 1);
233 }
234
235
236 /* NOTE: the two variables "i" and "j" are defined as empty slists in the
237 * EvalContext. */
IteratorPrepare_TestHelper(const char * promiser,size_t expected_wheels_num,const char ** expected_wheels)238 static void IteratorPrepare_TestHelper(
239 const char *promiser,
240 size_t expected_wheels_num,
241 const char **expected_wheels)
242 {
243 /* INIT EvalContext and Promise. */
244 EvalContext *evalctx = EvalContextNew();
245 Policy *policy = PolicyNew();
246 Bundle *bundle = PolicyAppendBundle(policy, "ns1", "bundle1", "agent",
247 NULL, NULL);
248 BundleSection *section = BundleAppendSection(bundle, "dummy");
249 Promise *promise = BundleSectionAppendPromise(section, promiser,
250 (Rval) { NULL, RVAL_TYPE_NOPROMISEE },
251 "any", NULL);
252 EvalContextStackPushBundleFrame(evalctx, bundle, NULL, false);
253 EvalContextStackPushBundleSectionFrame(evalctx, section);
254 PromiseIterator *iterctx = PromiseIteratorNew(promise);
255 char *promiser_copy = xstrdup(promiser);
256
257 /* Insert the variables "i" and "j" as empty Rlists in the EvalContext, so
258 * that the iteration engine creates wheels for them. */
259 {
260 VarRef *ref_i = VarRefParseFromBundle("i", bundle);
261 EvalContextVariablePut(evalctx, ref_i,
262 (Rlist *) NULL, CF_DATA_TYPE_STRING_LIST,
263 NULL);
264 VarRefDestroy(ref_i);
265
266 VarRef *ref_j = VarRefParseFromBundle("j", bundle);
267 EvalContextVariablePut(evalctx, ref_j,
268 (Rlist *) NULL, CF_DATA_TYPE_STRING_LIST,
269 NULL);
270 VarRefDestroy(ref_j);
271 }
272
273 /* TEST */
274 printf("Testing PromiseIteratorPrepare: %s\n", promiser);
275 PromiseIteratorPrepare(iterctx, evalctx, promiser_copy);
276
277 /* CHECK */
278 assert_true(iterctx->wheels != NULL);
279
280 size_t wheels_num = SeqLength(iterctx->wheels);
281 assert_int_equal(wheels_num, expected_wheels_num);
282
283 for (size_t i = 0; i < expected_wheels_num; i++)
284 {
285 const Wheel *wheel = SeqAt(iterctx->wheels, i);
286 assert_string_equal(wheel->varname_unexp, expected_wheels[i]);
287 }
288
289 /* CLEANUP */
290 free(promiser_copy);
291 PromiseIteratorDestroy(iterctx);
292 EvalContextStackPopFrame(evalctx);
293 EvalContextStackPopFrame(evalctx);
294 PolicyDestroy(policy);
295 EvalContextDestroy(evalctx);
296 }
test_PromiseIteratorPrepare(void)297 static void test_PromiseIteratorPrepare(void)
298 {
299 IteratorPrepare_TestHelper("", 0, NULL);
300 /* No wheel added for "blah" because this variable does not resolve. */
301 IteratorPrepare_TestHelper("$(blah)", 0, NULL);
302 /* "$(i)" is a valid list, but these syntaxes are not correct. */
303 IteratorPrepare_TestHelper("i", 0, NULL);
304 IteratorPrepare_TestHelper("$i", 0, NULL);
305 IteratorPrepare_TestHelper("$(i", 0, NULL);
306 /* The following however is correct and should add one wheel */
307 IteratorPrepare_TestHelper("$(i)", 1,
308 (const char *[]) {"i"});
309 IteratorPrepare_TestHelper("$(i))", 1,
310 (const char *[]) {"i"});
311 IteratorPrepare_TestHelper("$(i)(", 1,
312 (const char *[]) {"i"});
313 IteratorPrepare_TestHelper("$(i)$(", 1,
314 (const char *[]) {"i"});
315 /* The same variable twice should just add one wheel. */
316 IteratorPrepare_TestHelper("$(i)$(i)", 1,
317 (const char *[]) {"i"});
318 /* "$(ij)" does not resolve. */
319 IteratorPrepare_TestHelper("$(i)$(ij)", 1,
320 (const char *[]) {"i"});
321 /* Both "$(i)" and "$(j)" resolve. */
322 IteratorPrepare_TestHelper("$(i)$(j)", 2,
323 (const char *[]) {"i","j"});
324 IteratorPrepare_TestHelper("$(i))$(j)", 2,
325 (const char *[]) {"i","j"});
326 IteratorPrepare_TestHelper("0$(i)$(j)", 2,
327 (const char *[]) {"i","j"});
328 IteratorPrepare_TestHelper("$(i)1$(j)", 2,
329 (const char *[]) {"i","j"});
330 IteratorPrepare_TestHelper("$(i)$(j)2", 2,
331 (const char *[]) {"i","j"});
332 IteratorPrepare_TestHelper("0$(i)1$(j)", 2,
333 (const char *[]) {"i","j"});
334 IteratorPrepare_TestHelper("0$(i)1$(j)2", 2,
335 (const char *[]) {"i","j"});
336 /* Any variable dependent on other variables should be added as a wheel. */
337 IteratorPrepare_TestHelper("$(A[$(i)][$(j)])", 3,
338 (const char *[]) {"i","j", "A[$(i)][$(j)]"});
339 /* Even if the inner variables don't resolve. */
340 IteratorPrepare_TestHelper("$(A[$(blah)][$(blue)])", 1,
341 (const char *[]) {"A[$(blah)][$(blue)]"});
342 IteratorPrepare_TestHelper("$(A[1][2]) $(A[$(i)][$(j)])", 3,
343 (const char *[]) {"i","j", "A[$(i)][$(j)]"});
344 IteratorPrepare_TestHelper("$(A[$(B[$(i)])][$(j)])", 4,
345 (const char *[]) {"i", "B[$(i)]", "j", "A[$(B[$(i)])][$(j)]"});
346 IteratorPrepare_TestHelper("$(A[$(B[$(i)][$(j)])])", 4,
347 (const char *[]) {"i","j", "B[$(i)][$(j)]", "A[$(B[$(i)][$(j)])]"});
348 }
349
350
351
main()352 int main()
353 {
354 PRINT_TEST_BANNER();
355 const UnitTest tests[] =
356 {
357 unit_test(test_FindDollarParen),
358 unit_test(test_IsMangled),
359 unit_test(test_MangleVarRefString),
360 unit_test(test_PromiseIteratorPrepare),
361 };
362
363 int ret = run_tests(tests);
364
365 return ret;
366 }
367