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