1 #include <test.h>
2
3 #include <stdlib.h>
4
5 #include <rlist.h>
6 #include <string_lib.h>
7
8 #include <assoc.h>
9 #include <eval_context.h>
10
11 /* Stubs */
12
FatalError(ARG_UNUSED char * s,...)13 void FatalError(ARG_UNUSED char *s, ...)
14 {
15 mock_assert(0, "0", __FILE__, __LINE__);
16 abort();
17 }
18
test_length(void)19 static void test_length(void)
20 {
21 Rlist *list = NULL;
22
23 assert_int_equal(RlistLen(list), 0);
24
25 RlistPrepend(&list, "stuff", RVAL_TYPE_SCALAR);
26 assert_int_equal(RlistLen(list), 1);
27
28 RlistPrepend(&list, "more-stuff", RVAL_TYPE_SCALAR);
29 assert_int_equal(RlistLen(list), 2);
30
31 RlistDestroy(list);
32 }
33
test_prepend_scalar_idempotent(void)34 static void test_prepend_scalar_idempotent(void)
35 {
36 Rlist *list = NULL;
37
38 RlistPrependScalarIdemp(&list, "stuff");
39 RlistPrependScalarIdemp(&list, "stuff");
40
41 assert_string_equal(RlistScalarValue(list), "stuff");
42 assert_int_equal(RlistLen(list), 1);
43
44 RlistDestroy(list);
45 }
46
test_copy(void)47 static void test_copy(void)
48 {
49 Rlist *list = NULL, *copy = NULL;
50
51 RlistPrepend(&list, "stuff", RVAL_TYPE_SCALAR);
52 RlistPrepend(&list, "more-stuff", RVAL_TYPE_SCALAR);
53
54 copy = RlistCopy(list);
55
56 assert_string_equal(RlistScalarValue(list), RlistScalarValue(copy));
57 assert_string_equal(RlistScalarValue(list->next), RlistScalarValue(copy->next));
58
59 RlistDestroy(list);
60 RlistDestroy(copy);
61 }
62
test_rval_to_scalar(void)63 static void test_rval_to_scalar(void)
64 {
65 Rval rval = { "abc", RVAL_TYPE_SCALAR };
66 assert_string_equal("abc", RvalScalarValue(rval));
67 }
68
test_rval_to_scalar2(void)69 static void test_rval_to_scalar2(void)
70 {
71 Rval rval = { NULL, RVAL_TYPE_FNCALL };
72 expect_assert_failure(RvalScalarValue(rval));
73 }
74
test_rval_to_list(void)75 static void test_rval_to_list(void)
76 {
77 Rval rval = { NULL, RVAL_TYPE_SCALAR };
78 expect_assert_failure(RvalRlistValue(rval));
79 }
80
test_rval_to_list2(void)81 static void test_rval_to_list2(void)
82 {
83 Rval rval = { NULL, RVAL_TYPE_LIST };
84 assert_false(RvalRlistValue(rval));
85 }
86
test_rval_to_fncall(void)87 static void test_rval_to_fncall(void)
88 {
89 Rval rval = { NULL, RVAL_TYPE_SCALAR };
90 expect_assert_failure(RvalFnCallValue(rval));
91 }
92
test_rval_to_fncall2(void)93 static void test_rval_to_fncall2(void)
94 {
95 Rval rval = { NULL, RVAL_TYPE_FNCALL };
96 assert_false(RvalFnCallValue(rval));
97 }
98
test_last(void)99 static void test_last(void)
100 {
101 Rlist *l = NULL;
102 assert_true(RlistLast(l) == NULL);
103 RlistAppendScalar(&l, "a");
104 assert_string_equal("a", RlistScalarValue(RlistLast(l)));
105 RlistAppendScalar(&l, "b");
106 assert_string_equal("b", RlistScalarValue(RlistLast(l)));
107 RlistDestroy(l);
108 }
109
is_even(void * item,void * data)110 static bool is_even(void *item, void *data)
111 {
112 // What does this function do?
113 long d = StringToLongDefaultOnError(data, 0);
114 long i = StringToLongExitOnError(item);
115 return i % 2 == d;
116 }
117
test_filter(void)118 static void test_filter(void)
119 {
120 Rlist *list = NULL;
121 for (int i = 0; i < 10; i++)
122 {
123 char *item = StringFromLong(i);
124 RlistAppend(&list, item, RVAL_TYPE_SCALAR);
125 free(item);
126 }
127
128 assert_int_equal(10, RlistLen(list));
129 int mod_by = 0;
130 RlistFilter(&list, is_even, &mod_by, free);
131 assert_int_equal(5, RlistLen(list));
132
133 int i = 0;
134 for (Rlist *rp = list; rp; rp = rp->next)
135 {
136 int k = StringToLongExitOnError(rp->val.item);
137 assert_int_equal(i, k);
138
139 i += 2;
140 }
141
142 RlistDestroy(list);
143 }
144
test_filter_everything(void)145 static void test_filter_everything(void)
146 {
147 Rlist *list = NULL;
148 for (int i = 1; i < 10; i += 2)
149 {
150 char *item = StringFromLong(i);
151 RlistAppend(&list, item, RVAL_TYPE_SCALAR);
152 free(item);
153 }
154
155 assert_int_equal(5, RlistLen(list));
156 int mod_by = 0;
157 RlistFilter(&list, is_even, &mod_by, free);
158 assert_int_equal(0, RlistLen(list));
159
160 assert_true(list == NULL);
161 }
162
test_reverse(void)163 static void test_reverse(void)
164 {
165 Rlist *list = RlistFromSplitString("a,b,c", ',');
166
167 RlistReverse(&list);
168 assert_int_equal(3, RlistLen(list));
169 assert_string_equal("c", RlistScalarValue(list));
170 assert_string_equal("b", RlistScalarValue(list->next));
171 assert_string_equal("a", RlistScalarValue(list->next->next));
172
173 RlistDestroy(list);
174 }
175
test_split_escaped(void)176 static void test_split_escaped(void)
177 {
178 Rlist *list = RlistFromSplitString("a\\,b\\c\\,d,w\\,x\\,y\\,z", ',');
179 assert_int_equal(2, RlistLen(list));
180 assert_string_equal("a,b\\c,d", RlistScalarValue(list));
181 assert_string_equal("w,x,y,z", RlistScalarValue(list->next));
182
183 RlistDestroy(list);
184 }
185
test_split_lines(void)186 static void test_split_lines(void)
187 {
188 Rlist *list = RlistFromStringSplitLines(NULL, true);
189 assert_true(list == NULL);
190 list = RlistFromStringSplitLines(NULL, false);
191 assert_true(list == NULL);
192
193 list = RlistFromStringSplitLines("hello\nworld!\nCheers!\n", true);
194 assert_int_equal(3, RlistLen(list));
195 assert_string_equal("hello", RlistScalarValue(list));
196 assert_string_equal("world!", RlistScalarValue(list->next));
197 assert_string_equal("Cheers!", RlistScalarValue(list->next->next));
198 /* no empty string here as the last item */
199 RlistDestroy(list);
200
201 /* one extra blank line */
202 list = RlistFromStringSplitLines("hello\nworld!\nCheers!\n\n", true);
203 assert_int_equal(4, RlistLen(list));
204 assert_string_equal("hello", RlistScalarValue(list));
205 assert_string_equal("world!", RlistScalarValue(list->next));
206 assert_string_equal("Cheers!", RlistScalarValue(list->next->next));
207 assert_string_equal("", RlistScalarValue(list->next->next->next));
208 RlistDestroy(list);
209
210 list = RlistFromStringSplitLines("hello\r\nworld!\r\nCheers!\r\n", true);
211 assert_int_equal(3, RlistLen(list));
212 assert_string_equal("hello", RlistScalarValue(list));
213 assert_string_equal("world!", RlistScalarValue(list->next));
214 assert_string_equal("Cheers!", RlistScalarValue(list->next->next));
215 /* no empty string here as the last item */
216 RlistDestroy(list);
217
218 /* one extra blank line */
219 list = RlistFromStringSplitLines("hello\r\nworld!\r\nCheers!\r\n\r\n", true);
220 assert_int_equal(4, RlistLen(list));
221 assert_string_equal("hello", RlistScalarValue(list));
222 assert_string_equal("world!", RlistScalarValue(list->next));
223 assert_string_equal("Cheers!", RlistScalarValue(list->next->next));
224 assert_string_equal("", RlistScalarValue(list->next->next->next));
225 RlistDestroy(list);
226
227 /* UNIX-like newlines only */
228 list = RlistFromStringSplitLines("hello\r\nworld!\r\nCheers!\r\n\r\n", false);
229 assert_int_equal(4, RlistLen(list));
230 assert_string_equal("hello\r", RlistScalarValue(list));
231 assert_string_equal("world!\r", RlistScalarValue(list->next));
232 assert_string_equal("Cheers!\r", RlistScalarValue(list->next->next));
233 assert_string_equal("\r", RlistScalarValue(list->next->next->next));
234 RlistDestroy(list);
235 }
236
test_split_long(void)237 static void test_split_long(void)
238 {
239 char buf[CF_MAXVARSIZE * 2], *tail = buf + CF_MAXVARSIZE;
240 memset(buf, '$', sizeof(buf) - 1);
241 buf[sizeof(buf) - 1] = '\0';
242 buf[CF_MAXVARSIZE - 1] = ',';
243
244 Rlist *list = RlistFromSplitString(buf, ',');
245 assert_int_equal(2, RlistLen(list));
246
247 assert_string_equal(tail, RlistScalarValue(list));
248 assert_string_equal(tail, RlistScalarValue(list->next));
249
250 RlistDestroy(list);
251 }
252
test_split_long_escaped(void)253 static void test_split_long_escaped(void)
254 {
255 char buf[CF_MAXVARSIZE * 2 + 2], *tail = buf + CF_MAXVARSIZE + 1;
256 memset(buf, '$', sizeof(buf) - 1);
257 buf[sizeof(buf) - 1] = '\0';
258 buf[CF_MAXVARSIZE] = ',';
259 memcpy(buf + CF_MAXVARSIZE / 2, "\\,", 2);
260 memcpy(tail + CF_MAXVARSIZE / 2, "\\,", 2);
261
262 Rlist *list = RlistFromSplitString(buf, ',');
263 assert_int_equal(2, RlistLen(list));
264
265 tail[CF_MAXVARSIZE / 2] = '$'; /* blot out the back-slash */
266 assert_string_equal(tail + 1, RlistScalarValue(list));
267 assert_string_equal(tail + 1, RlistScalarValue(list->next));
268
269 RlistDestroy(list);
270 }
271 /***************************************************************************/
272 static struct ParseRoulette
273 {
274 int nfields;
275 char *str;
276 } PR[] =
277 {
278 /*Simple */
279 {
280 1, "{\"a\"}"},
281 {
282 2, "{\"a\",\"b\"}"},
283 {
284 3, "{\"a\",\"b\",\"c\"}"},
285 /*Simple empty */
286 {
287 1, "{\"\"}"},
288 {
289 2, "{\"\",\"\"}"},
290 {
291 3, "{\"\",\"\",\"\"}"},
292 /*Simple mixed kind of quotations */
293 {
294 1, "{\"'\"}"},
295 {
296 1, "{'\"'}"},
297 {
298 1, "{\",\"}"},
299 {
300 1, "{','}"},
301 {
302 1, "{\"\\\\\"}"},
303 {
304 1, "{'\\\\'}"},
305 {
306 1, "{\"}\"}"},
307 {
308 1, "{'}'}"},
309 {
310 1, "{\"{\"}"},
311 {
312 1, "{'{'}"},
313 {
314 1, "{\"'\"}"},
315 {
316 1, "{'\"'}"},
317 {
318 1, "{'\\\",'}"}, /* [",] */
319 {
320 1, "{\"\\',\"}"}, /* [",] */
321
322 {
323 1, "{',\\\"'}"}, /* [,"] */
324 {
325 1, "{\",\\'\"}"}, /* [,"] */
326
327 {
328 1, "{\",,\"}"}, /* [\\] */
329 {
330 1, "{',,'}"}, /* [\\] */
331
332 {
333 1, "{\"\\\\\\\\\"}"}, /* [\\] */
334 {
335 1, "{'\\\\\\\\'}"}, /* [\\] */
336
337 {
338 1, "{'\\\\\\\"'}"}, /* [\"] */
339 {
340 1, "{\"\\\\\\'\"}"}, /* [\"] */
341
342 {
343 1, "{'\\\"\\\\'}"}, /* ["\] */
344 {
345 1, "{\"\\'\\\\\"}"}, /* ["\] */
346
347 /*Very long */
348 {
349 1, "{\"AaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaA\"}"},
350 {
351 1, "{'AaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaA'}"},
352
353 {
354 2, "{\"Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa''aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaA\" , \"Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\\\\bbbbbbbbbbbbbbbbbbbbbbbb\\\\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb''bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbB\" }"},
355 {
356 2, "{'Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaA' , 'Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\\\\bbbbbbbbbbbbbbbbbbbbbbbb\\\\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\\\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbB' }"},
357 {
358 2, "{\"Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa''aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaA\" , 'Bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\\\\bbbbbbbbbbbbbbbbbbbbbbbb\\\\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\\\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbB' }"},
359
360 /*Inner space (inside elements) */
361 {
362 1, "{\" \"}"},
363 {
364 1, "{\" \"}"},
365 {
366 1, "{\" \"}"},
367 {
368 1, "{\"\t\"}"},
369 /*Outer space (outside elements) */
370 {
371 1, " {\"\"} "},
372 {
373 1, " {\"a\"} "},
374 {
375 2, " {\"a\",\"b\"} "},
376 {
377 1, "{ \"a\" }"},
378 {
379 2, "{ \"a\",\"b\" }"},
380 {
381 2, "{ \"a\" ,\"b\" }"},
382 {
383 2, "{ \"a\", \"b\" }"},
384 {
385 2, "{ \"a\", \"b\"} "},
386 /*Normal */
387 {
388 4, " { \" ab,c,d\\\\ \" , ' e,f\\\"g ' ,\"hi\\\\jk\", \"l''m \" } "},
389 {
390 21, " { 'A\\\"\\\\ ', \" \\\\\", \"}B\", \"\\\\\\\\\" , \" \\\\C\\'\" , \"\\',\" , ',\\\"D' , \" ,, \", \"E\\\\\\\\F\", \"\", \"{\", \" G '\" , \"\\\\\\'\", ' \\\" H \\\\ ', \", ,\" , \"I\", \" \", \"\\' J \", '\\\",', \",\\'\", \",\" } "},
391 {
392 3, "{ \" aaa \", \" bbbb \" , \" cc \" } "},
393 {
394 3, " { \" a'a \", \" b''b \" , \" c'c \" } "},
395 {
396 3, " { ' a\"a ', ' b\"\"b ' , ' c\"c ' } "},
397 {
398 3, " { ' a\"a ', \" b''b \" , ' c\"c ' } "},
399 {
400 3, " { ' a,\"a } { ', \" } b','b \" , ' {, c\"c } ' } "},
401 {
402 -1, (char *)NULL}
403 };
404
405 static char *PFR[] = {
406 /* trim left failure */
407 "",
408 " ",
409 "a",
410 "\"",
411 "'",
412 "\"\"",
413 "''",
414 "'\"",
415 "\"'",
416 /* trim right failure */
417 "{",
418 "{ ",
419 "{a",
420 "{\"",
421 "{'",
422 "{\"\"",
423 "{''",
424 "{\"'",
425 /* parse failure */
426 /* un-even number of quotation marks */
427 "{\"\"\"}",
428 "{\"\",\"}",
429 "{\"\"\"\"}",
430 "{\"\"\"\"\"}",
431 "{\"\",\"\"\"}",
432 "{\"\"\"\",\"}",
433 "{\"\",\"\",\"}",
434 "{'''}",
435 "{'','}",
436 "{''''}",
437 "{'''''}",
438 "{'','''}",
439 "{'''','}",
440 "{\"}",
441 "{'}",
442 "{'','','}",
443 "{\"\"'}",
444 "{\"\",'}",
445 "{\"'\"'}",
446 "{\"\"'\"\"}",
447 "{\"\",'\"\"}",
448 "{'\"\"\",\"}",
449 "{'',\"\",'}",
450
451 /* Misplaced commas*/
452 "{\"a\",}",
453 "{,\"a\"}",
454 "{,,\"a\"}",
455 "{\"a\",,\"b\"}",
456 "{'a',}",
457 "{,'a'}",
458 "{,,'a'}",
459 "{'a',,'b'}",
460 "{\"a\",,'b'}",
461 "{'a',,\"b\"}",
462 " {,}",
463 " {,,}",
464 " {,,,}",
465 " {,\"\"}",
466 " {\"\",}",
467 " {,\"\",}",
468 " {\"\",,}",
469 " {\"\",,,}",
470 " {,,\"\",,}",
471 " {\"\",\"\",}",
472 " {\"\",\"\",,}",
473 " { \"\" , \"\" , , }",
474 " {,''}",
475 " {'',}",
476 " {,'',}",
477 " {'',,}",
478 " {'',,,}",
479 " {,,'',,}",
480 " {'','',}",
481 " {'','',,}",
482 " { '' , '' , , }",
483 " {'',\"\",}",
484 " {\"\",'',,}",
485 " { '' , \"\" , , }",
486 " { \"\" , '' , , }",
487
488 /*Ignore space's oddities */
489 "\" {\"\"}",
490 "{ {\"\"}",
491 "{\"\"}\"",
492 "{\"\"}\\",
493 "{\"\"} } ",
494 "a{\"\"}",
495 " a {\"\"}",
496 "{a\"\"}",
497 "{ a \"\"}",
498 "{\"\"}a",
499 "{\"\"} a ",
500 "{\"\"a}",
501 "{\"\" a }",
502 "a{\"\"}b",
503 "{a\"\"b}",
504 "a{\"\"b}",
505 "{a\"\"}b",
506 "{\"\"a\"\"}",
507 "{\"\",\"\"a\"\"}",
508 "' {''}",
509 "{ {''}",
510 "{''}'",
511 "{''}\\",
512 "{''} } ",
513 "a{''}",
514 " a {''}",
515 "{a''}",
516 "{ a ''}",
517 "{''}a",
518 "{''} a ",
519 "{''a}",
520 "{'' a }",
521 "a{''}b",
522 "{a''b}",
523 "a{''b}",
524 "{a''}b",
525 "{''a''}",
526 "{'',''a''}",
527 "{''a\"\"}",
528 "{\"\"a''}",
529 "{\"\",''a''}",
530 "{'',\"\"a''}",
531 "{'',''a\"\"}",
532 "{\"\",''a\"\"}",
533 /* Bad type of quotation inside an element */
534 "{'aa'aa'}",
535 "{\"aa\"aa\"}",
536 "{'aa\"''}",
537 "{'aa\"\"''}",
538 "{\"aa'\"\"}",
539 "{\"aa''\"\"}",
540 "{'aa\"'', 'aa\"\"'',\"aa'\"\"}",
541 "{\"aa\"aa\", 'aa\"'', 'aa\"\"''}",
542 "{ \"aa\"aa\" ,'aa\"\"'',\"aa''\"\" }",
543 NULL
544 };
545
546
test_new_parser_success()547 static void test_new_parser_success()
548 {
549 Rlist *list = NULL;
550 int i = 0;
551 while (PR[i].nfields != -1)
552 {
553 list = RlistParseString(PR[i].str);
554 assert_int_equal(PR[i].nfields, RlistLen(list));
555 if (list != NULL)
556 {
557 RlistDestroy(list);
558 }
559 i++;
560 }
561 }
562
test_new_parser_failure()563 static void test_new_parser_failure()
564 {
565 int i = 0;
566 Rlist *list = NULL;
567 while (PFR[i] != NULL)
568 {
569 list = RlistParseString(PFR[i]);
570 assert_true(RlistLast(list) == NULL);
571 if(list) RlistDestroy(list);
572 i++;
573 }
574 }
575
test_regex_split()576 static void test_regex_split()
577 {
578 Rlist *list = RlistFromRegexSplitNoOverflow("one-->two-->three", "-+>", 3);
579
580 assert_int_equal(3, RlistLen(list));
581
582 assert_string_equal(RlistScalarValue(list), "one");
583 assert_string_equal(RlistScalarValue(list->next), "two");
584 assert_string_equal(RlistScalarValue(list->next->next), "three");
585
586 RlistDestroy(list);
587 }
588
test_regex_split_too_few_chunks()589 static void test_regex_split_too_few_chunks()
590 {
591 Rlist *list = RlistFromRegexSplitNoOverflow("one:two:three", ":", 2);
592
593 assert_int_equal(2, RlistLen(list));
594
595 assert_string_equal(RlistScalarValue(list), "one");
596 assert_string_equal(RlistScalarValue(list->next), "two:three");
597
598 RlistDestroy(list);
599 }
600
test_regex_split_too_many_chunks()601 static void test_regex_split_too_many_chunks()
602 {
603 Rlist *list = RlistFromRegexSplitNoOverflow("one:two:three:", ":", 10);
604
605 assert_int_equal(4, RlistLen(list));
606
607 assert_string_equal(RlistScalarValue(list), "one");
608 assert_string_equal(RlistScalarValue(list->next), "two");
609 assert_string_equal(RlistScalarValue(list->next->next), "three");
610 assert_string_equal(RlistScalarValue(list->next->next->next), "");
611
612 RlistDestroy(list);
613 }
614
test_regex_split_empty_chunks()615 static void test_regex_split_empty_chunks()
616 {
617 Rlist *list = RlistFromRegexSplitNoOverflow(":one:two:three:", ":", 5);
618
619 assert_int_equal(5, RlistLen(list));
620
621 assert_string_equal(RlistScalarValue(list), "");
622 assert_string_equal(RlistScalarValue(list->next), "one");
623 assert_string_equal(RlistScalarValue(list->next->next), "two");
624 assert_string_equal(RlistScalarValue(list->next->next->next), "three");
625 assert_string_equal(RlistScalarValue(list->next->next->next->next), "");
626
627 RlistDestroy(list);
628 }
629
test_regex_split_no_match()630 static void test_regex_split_no_match()
631 {
632 Rlist *list = RlistFromRegexSplitNoOverflow(":one:two:three:", "/", 2);
633
634 assert_int_equal(1, RlistLen(list));
635 assert_string_equal(RlistScalarValue(list), ":one:two:three:");
636
637 RlistDestroy(list);
638 }
639
test_regex_split_adjacent_separators()640 static void test_regex_split_adjacent_separators()
641 {
642 Rlist *list = RlistFromRegexSplitNoOverflow(":one::two::three:", ":", 3);
643
644 assert_int_equal(3, RlistLen(list));
645
646 assert_string_equal(RlistScalarValue(list), "");
647 assert_string_equal(RlistScalarValue(list->next), "one");
648 assert_string_equal(RlistScalarValue(list->next->next), ":two::three:");
649
650 RlistDestroy(list);
651
652
653 list = RlistFromRegexSplitNoOverflow(":one::two:::three:", ":", 4);
654
655 assert_int_equal(4, RlistLen(list));
656
657 assert_string_equal(RlistScalarValue(list), "");
658 assert_string_equal(RlistScalarValue(list->next), "one");
659 assert_string_equal(RlistScalarValue(list->next->next), "");
660 assert_string_equal(RlistScalarValue(list->next->next->next), "two:::three:");
661
662 RlistDestroy(list);
663
664
665 list = RlistFromRegexSplitNoOverflow(":one::two:::three:", ":", 7);
666
667 assert_int_equal(7, RlistLen(list));
668
669 assert_string_equal(RlistScalarValue(list), "");
670 assert_string_equal(RlistScalarValue(list->next), "one");
671 assert_string_equal(RlistScalarValue(list->next->next), "");
672 assert_string_equal(RlistScalarValue(list->next->next->next), "two");
673 assert_string_equal(RlistScalarValue(list->next->next->next->next), "");
674 assert_string_equal(RlistScalarValue(list->next->next->next->next->next), "");
675 assert_string_equal(RlistScalarValue(list->next->next->next->next->next->next), "three:");
676
677 RlistDestroy(list);
678 }
679
test_regex_split_real_regex()680 static void test_regex_split_real_regex()
681 {
682 //whole string is matched by regex in below example
683 Rlist *list = RlistFromRegexSplitNoOverflow("one-two-three", ".+", 3);
684
685 assert_int_equal(2, RlistLen(list));
686 assert_string_equal(RlistScalarValue(list), "");
687 assert_string_equal(RlistScalarValue(list->next), "");
688
689 RlistDestroy(list);
690
691
692 list = RlistFromRegexSplitNoOverflow("one>>>two<<<three<><>four", "[<>]+", 4);
693
694 assert_int_equal(4, RlistLen(list));
695 assert_string_equal(RlistScalarValue(list), "one");
696 assert_string_equal(RlistScalarValue(list->next), "two");
697 assert_string_equal(RlistScalarValue(list->next->next), "three");
698 assert_string_equal(RlistScalarValue(list->next->next->next), "four");
699
700 RlistDestroy(list);
701 }
702
test_regex_split_overlapping_delimiters()703 static void test_regex_split_overlapping_delimiters()
704 {
705 Rlist *list = RlistFromRegexSplitNoOverflow("-one---two---three", "--", 3);
706
707 assert_int_equal(3, RlistLen(list));
708
709 assert_string_equal(RlistScalarValue(list), "-one");
710 assert_string_equal(RlistScalarValue(list->next), "-two");
711 assert_string_equal(RlistScalarValue(list->next->next), "-three");
712
713 RlistDestroy(list);
714 }
715
main()716 int main()
717 {
718 PRINT_TEST_BANNER();
719 const UnitTest tests[] =
720 {
721 unit_test(test_prepend_scalar_idempotent),
722 unit_test(test_length),
723 unit_test(test_copy),
724 unit_test(test_rval_to_scalar),
725 unit_test(test_rval_to_scalar2),
726 unit_test(test_rval_to_list),
727 unit_test(test_rval_to_list2),
728 unit_test(test_rval_to_fncall),
729 unit_test(test_rval_to_fncall2),
730 unit_test(test_last),
731 unit_test(test_filter),
732 unit_test(test_filter_everything),
733 unit_test(test_reverse),
734 unit_test(test_split_escaped),
735 unit_test(test_split_lines),
736 unit_test(test_split_long),
737 unit_test(test_split_long_escaped),
738 unit_test(test_new_parser_success),
739 unit_test(test_new_parser_failure),
740 unit_test(test_regex_split),
741 unit_test(test_regex_split_too_few_chunks),
742 unit_test(test_regex_split_too_many_chunks),
743 unit_test(test_regex_split_empty_chunks),
744 unit_test(test_regex_split_no_match),
745 unit_test(test_regex_split_adjacent_separators),
746 unit_test(test_regex_split_real_regex),
747 unit_test(test_regex_split_overlapping_delimiters)
748 };
749
750 return run_tests(tests);
751 }
752
753 /* ===== Stub out functionality we don't really use. ===== */
754
755 /* Silence all "unused parameter" warnings. */
756 #pragma GCC diagnostic ignored "-Wunused-parameter"
757
758
759
760 char CONTEXTID[32];
761
__ProgrammingError(const char * file,int lineno,const char * format,...)762 void __ProgrammingError(const char *file, int lineno, const char *format, ...)
763 {
764 mock_assert(0, "0", __FILE__, __LINE__);
765 }
766
FullTextMatch(const char * regptr,const char * cmpptr)767 bool FullTextMatch(const char *regptr, const char *cmpptr)
768 {
769 fail();
770 }
771
EvalContextVariableGet(const EvalContext * ctx,const VarRef * lval,DataType * type_out)772 const void *EvalContextVariableGet(const EvalContext *ctx, const VarRef *lval, DataType *type_out)
773 {
774 fail();
775 }
776
777 pthread_mutex_t *cft_lock;
__ThreadLock(pthread_mutex_t * name)778 int __ThreadLock(pthread_mutex_t *name)
779 {
780 return true;
781 }
782
__ThreadUnlock(pthread_mutex_t * name)783 int __ThreadUnlock(pthread_mutex_t *name)
784 {
785 return true;
786 }
787
IsNakedVar(const char * str,char vtype)788 int IsNakedVar(const char *str, char vtype)
789 {
790 fail();
791 }
792
FnCallPrint(Writer * writer,const FnCall * fp)793 void FnCallPrint(Writer *writer, const FnCall *fp)
794 {
795 fail();
796 }
797
GetNaked(char * s1,const char * s2)798 void GetNaked(char *s1, const char *s2)
799 {
800 fail();
801 }
802
803 /*
804 void Log(LogLevel level, const char *fmt, ...)
805 {
806 fail();
807 }
808 */
809
ScopeGetVariable(const char * scope,const char * lval,Rval * returnv)810 DataType ScopeGetVariable(const char *scope, const char *lval, Rval *returnv)
811 {
812 fail();
813 }
814
DeleteAssoc(CfAssoc * ap)815 void DeleteAssoc(CfAssoc *ap)
816 {
817 fail();
818 }
819
CopyAssoc(CfAssoc * old)820 CfAssoc *CopyAssoc(CfAssoc *old)
821 {
822 fail();
823 }
824
FnCallCopy(const FnCall * f)825 FnCall *FnCallCopy(const FnCall *f)
826 {
827 fail();
828 }
829
FnCallDestroy(FnCall * fp)830 void FnCallDestroy(FnCall *fp)
831 {
832 fail();
833 }
834
SubStrnCopyChr(char * to,const char * from,int len,char sep)835 int SubStrnCopyChr(char *to, const char *from, int len, char sep)
836 {
837 fail();
838 }
839
BlockTextMatch(const char * regexp,const char * teststring,int * s,int * e)840 int BlockTextMatch(const char *regexp, const char *teststring, int *s, int *e)
841 {
842 fail();
843 }
844
FnCallToJson(const FnCall * fp)845 JsonElement *FnCallToJson(const FnCall *fp)
846 {
847 fail();
848 }
849
JsonObjectCreate(size_t initialCapacity)850 JsonElement *JsonObjectCreate(size_t initialCapacity)
851 {
852 fail();
853 }
854
JsonObjectAppendArray(JsonElement * object,const char * key,JsonElement * array)855 void JsonObjectAppendArray(JsonElement *object, const char *key, JsonElement *array)
856 {
857 fail();
858 }
859
JsonObjectAppendString(JsonElement * obj,const char * key,const char * value)860 void JsonObjectAppendString(JsonElement *obj, const char *key, const char *value)
861 {
862 fail();
863 }
864
JsonArrayCreate(size_t initialCapacity)865 JsonElement *JsonArrayCreate(size_t initialCapacity)
866 {
867 fail();
868 }
869
JsonArrayAppendString(JsonElement * array,const char * value)870 void JsonArrayAppendString(JsonElement *array, const char *value)
871 {
872 fail();
873 }
874
JsonArrayAppendArray(JsonElement * array,JsonElement * childArray)875 void JsonArrayAppendArray(JsonElement *array, JsonElement *childArray)
876 {
877 fail();
878 }
879
JsonArrayAppendObject(JsonElement * array,JsonElement * object)880 void JsonArrayAppendObject(JsonElement *array, JsonElement *object)
881 {
882 fail();
883 }
884
JsonStringCreate(const char * value)885 JsonElement *JsonStringCreate(const char *value)
886 {
887 fail();
888 }
889