1 #include <stdarg.h>
2 #include <stddef.h>
3 #include <setjmp.h>
4 #include <cmocka.h>
5 #include <stdlib.h>
6 
7 #include "tools/parser.h"
8 
9 void
parse_null_returns_null(void ** state)10 parse_null_returns_null(void** state)
11 {
12     char* inp = NULL;
13     gboolean result = TRUE;
14     gchar** args = parse_args(inp, 1, 2, &result);
15 
16     assert_false(result);
17     assert_null(args);
18     g_strfreev(args);
19 }
20 
21 void
parse_empty_returns_null(void ** state)22 parse_empty_returns_null(void** state)
23 {
24     char* inp = "";
25     gboolean result = TRUE;
26     gchar** args = parse_args(inp, 1, 2, &result);
27 
28     assert_false(result);
29     assert_null(args);
30     g_strfreev(args);
31 }
32 
33 void
parse_space_returns_null(void ** state)34 parse_space_returns_null(void** state)
35 {
36     char* inp = "   ";
37     gboolean result = TRUE;
38     gchar** args = parse_args(inp, 1, 2, &result);
39 
40     assert_false(result);
41     assert_null(args);
42     g_strfreev(args);
43 }
44 
45 void
parse_cmd_no_args_returns_null(void ** state)46 parse_cmd_no_args_returns_null(void** state)
47 {
48     char* inp = "/cmd";
49     gboolean result = TRUE;
50     gchar** args = parse_args(inp, 1, 2, &result);
51 
52     assert_false(result);
53     assert_null(args);
54     g_strfreev(args);
55 }
56 
57 void
parse_cmd_with_space_returns_null(void ** state)58 parse_cmd_with_space_returns_null(void** state)
59 {
60     char* inp = "/cmd   ";
61     gboolean result = TRUE;
62     gchar** args = parse_args(inp, 1, 2, &result);
63 
64     assert_false(result);
65     assert_null(args);
66     g_strfreev(args);
67 }
68 
69 void
parse_cmd_with_too_few_returns_null(void ** state)70 parse_cmd_with_too_few_returns_null(void** state)
71 {
72     char* inp = "/cmd arg1";
73     gboolean result = TRUE;
74     gchar** args = parse_args(inp, 2, 3, &result);
75 
76     assert_false(result);
77     assert_null(args);
78     g_strfreev(args);
79 }
80 
81 void
parse_cmd_with_too_many_returns_null(void ** state)82 parse_cmd_with_too_many_returns_null(void** state)
83 {
84     char* inp = "/cmd arg1 arg2 arg3 arg4";
85     gboolean result = TRUE;
86     gchar** args = parse_args(inp, 1, 3, &result);
87 
88     assert_false(result);
89     assert_null(args);
90     g_strfreev(args);
91 }
92 
93 void
parse_cmd_one_arg(void ** state)94 parse_cmd_one_arg(void** state)
95 {
96     char* inp = "/cmd arg1";
97     gboolean result = FALSE;
98     gchar** args = parse_args(inp, 1, 2, &result);
99 
100     assert_true(result);
101     assert_int_equal(1, g_strv_length(args));
102     assert_string_equal("arg1", args[0]);
103     g_strfreev(args);
104 }
105 
106 void
parse_cmd_two_args(void ** state)107 parse_cmd_two_args(void** state)
108 {
109     char* inp = "/cmd arg1 arg2";
110     gboolean result = FALSE;
111     gchar** args = parse_args(inp, 1, 2, &result);
112 
113     assert_true(result);
114     assert_int_equal(2, g_strv_length(args));
115     assert_string_equal("arg1", args[0]);
116     assert_string_equal("arg2", args[1]);
117     g_strfreev(args);
118 }
119 
120 void
parse_cmd_three_args(void ** state)121 parse_cmd_three_args(void** state)
122 {
123     char* inp = "/cmd arg1 arg2 arg3";
124     gboolean result = FALSE;
125     gchar** args = parse_args(inp, 3, 3, &result);
126 
127     assert_true(result);
128     assert_int_equal(3, g_strv_length(args));
129     assert_string_equal("arg1", args[0]);
130     assert_string_equal("arg2", args[1]);
131     assert_string_equal("arg3", args[2]);
132     g_strfreev(args);
133 }
134 
135 void
parse_cmd_three_args_with_spaces(void ** state)136 parse_cmd_three_args_with_spaces(void** state)
137 {
138     char* inp = "  /cmd    arg1  arg2     arg3 ";
139     gboolean result = FALSE;
140     gchar** args = parse_args(inp, 3, 3, &result);
141 
142     assert_true(result);
143     assert_int_equal(3, g_strv_length(args));
144     assert_string_equal("arg1", args[0]);
145     assert_string_equal("arg2", args[1]);
146     assert_string_equal("arg3", args[2]);
147     g_strfreev(args);
148 }
149 
150 void
parse_cmd_with_freetext(void ** state)151 parse_cmd_with_freetext(void** state)
152 {
153     char* inp = "/cmd this is some free text";
154     gboolean result = FALSE;
155     gchar** args = parse_args_with_freetext(inp, 1, 1, &result);
156 
157     assert_true(result);
158     assert_int_equal(1, g_strv_length(args));
159     assert_string_equal("this is some free text", args[0]);
160     g_strfreev(args);
161 }
162 
163 void
parse_cmd_one_arg_with_freetext(void ** state)164 parse_cmd_one_arg_with_freetext(void** state)
165 {
166     char* inp = "/cmd arg1 this is some free text";
167     gboolean result = FALSE;
168     gchar** args = parse_args_with_freetext(inp, 1, 2, &result);
169 
170     assert_true(result);
171     assert_int_equal(2, g_strv_length(args));
172     assert_string_equal("arg1", args[0]);
173     assert_string_equal("this is some free text", args[1]);
174     g_strfreev(args);
175 }
176 
177 void
parse_cmd_two_args_with_freetext(void ** state)178 parse_cmd_two_args_with_freetext(void** state)
179 {
180     char* inp = "/cmd arg1 arg2 this is some free text";
181     gboolean result = FALSE;
182     gchar** args = parse_args_with_freetext(inp, 1, 3, &result);
183 
184     assert_true(result);
185     assert_int_equal(3, g_strv_length(args));
186     assert_string_equal("arg1", args[0]);
187     assert_string_equal("arg2", args[1]);
188     assert_string_equal("this is some free text", args[2]);
189     g_strfreev(args);
190 }
191 
192 void
parse_cmd_min_zero(void ** state)193 parse_cmd_min_zero(void** state)
194 {
195     char* inp = "/cmd";
196     gboolean result = FALSE;
197     gchar** args = parse_args(inp, 0, 2, &result);
198 
199     assert_true(result);
200     assert_int_equal(0, g_strv_length(args));
201     assert_null(args[0]);
202     g_strfreev(args);
203 }
204 
205 void
parse_cmd_min_zero_with_freetext(void ** state)206 parse_cmd_min_zero_with_freetext(void** state)
207 {
208     char* inp = "/cmd";
209     gboolean result = FALSE;
210     gchar** args = parse_args_with_freetext(inp, 0, 2, &result);
211 
212     assert_true(result);
213     assert_int_equal(0, g_strv_length(args));
214     assert_null(args[0]);
215     g_strfreev(args);
216 }
217 
218 void
parse_cmd_with_quoted(void ** state)219 parse_cmd_with_quoted(void** state)
220 {
221     char* inp = "/cmd \"arg1\" arg2";
222     gboolean result = FALSE;
223     gchar** args = parse_args(inp, 2, 2, &result);
224 
225     assert_true(result);
226     assert_int_equal(2, g_strv_length(args));
227     assert_string_equal("arg1", args[0]);
228     assert_string_equal("arg2", args[1]);
229     g_strfreev(args);
230 }
231 
232 void
parse_cmd_with_quoted_and_space(void ** state)233 parse_cmd_with_quoted_and_space(void** state)
234 {
235     char* inp = "/cmd \"the arg1\" arg2";
236     gboolean result = FALSE;
237     gchar** args = parse_args(inp, 2, 2, &result);
238 
239     assert_true(result);
240     assert_int_equal(2, g_strv_length(args));
241     assert_string_equal("the arg1", args[0]);
242     assert_string_equal("arg2", args[1]);
243     g_strfreev(args);
244 }
245 
246 void
parse_cmd_with_quoted_and_many_spaces(void ** state)247 parse_cmd_with_quoted_and_many_spaces(void** state)
248 {
249     char* inp = "/cmd \"the arg1 is here\" arg2";
250     gboolean result = FALSE;
251     gchar** args = parse_args(inp, 2, 2, &result);
252 
253     assert_true(result);
254     assert_int_equal(2, g_strv_length(args));
255     assert_string_equal("the arg1 is here", args[0]);
256     assert_string_equal("arg2", args[1]);
257     g_strfreev(args);
258 }
259 
260 void
parse_cmd_with_many_quoted_and_many_spaces(void ** state)261 parse_cmd_with_many_quoted_and_many_spaces(void** state)
262 {
263     char* inp = "/cmd \"the arg1 is here\" \"and arg2 is right here\"";
264     gboolean result = FALSE;
265     gchar** args = parse_args(inp, 2, 2, &result);
266 
267     assert_true(result);
268     assert_int_equal(2, g_strv_length(args));
269     assert_string_equal("the arg1 is here", args[0]);
270     assert_string_equal("and arg2 is right here", args[1]);
271     g_strfreev(args);
272 }
273 
274 void
parse_cmd_freetext_with_quoted(void ** state)275 parse_cmd_freetext_with_quoted(void** state)
276 {
277     char* inp = "/cmd \"arg1\" arg2 hello there whats up";
278     gboolean result = FALSE;
279     gchar** args = parse_args_with_freetext(inp, 3, 3, &result);
280 
281     assert_true(result);
282     assert_int_equal(3, g_strv_length(args));
283     assert_string_equal("arg1", args[0]);
284     assert_string_equal("arg2", args[1]);
285     assert_string_equal("hello there whats up", args[2]);
286     g_strfreev(args);
287 }
288 
289 void
parse_cmd_freetext_with_quoted_and_space(void ** state)290 parse_cmd_freetext_with_quoted_and_space(void** state)
291 {
292     char* inp = "/cmd \"the arg1\" arg2 another bit of freetext";
293     gboolean result = FALSE;
294     gchar** args = parse_args_with_freetext(inp, 3, 3, &result);
295 
296     assert_true(result);
297     assert_int_equal(3, g_strv_length(args));
298     assert_string_equal("the arg1", args[0]);
299     assert_string_equal("arg2", args[1]);
300     assert_string_equal("another bit of freetext", args[2]);
301     g_strfreev(args);
302 }
303 
304 void
parse_cmd_freetext_with_quoted_and_many_spaces(void ** state)305 parse_cmd_freetext_with_quoted_and_many_spaces(void** state)
306 {
307     char* inp = "/cmd \"the arg1 is here\" arg2 some more freetext";
308     gboolean result = FALSE;
309     gchar** args = parse_args_with_freetext(inp, 3, 3, &result);
310 
311     assert_true(result);
312     assert_int_equal(3, g_strv_length(args));
313     assert_string_equal("the arg1 is here", args[0]);
314     assert_string_equal("arg2", args[1]);
315     assert_string_equal("some more freetext", args[2]);
316     g_strfreev(args);
317 }
318 
319 void
parse_cmd_freetext_with_many_quoted_and_many_spaces(void ** state)320 parse_cmd_freetext_with_many_quoted_and_many_spaces(void** state)
321 {
322     char* inp = "/cmd \"the arg1 is here\" \"and arg2 is right here\" and heres the free text";
323     gboolean result = FALSE;
324     gchar** args = parse_args_with_freetext(inp, 3, 3, &result);
325 
326     assert_true(result);
327     assert_int_equal(3, g_strv_length(args));
328     assert_string_equal("the arg1 is here", args[0]);
329     assert_string_equal("and arg2 is right here", args[1]);
330     assert_string_equal("and heres the free text", args[2]);
331     g_strfreev(args);
332 }
333 
334 void
parse_cmd_with_quoted_freetext(void ** state)335 parse_cmd_with_quoted_freetext(void** state)
336 {
337     char* inp = "/cmd arg1 here is \"some\" quoted freetext";
338     gboolean result = FALSE;
339     gchar** args = parse_args_with_freetext(inp, 1, 2, &result);
340 
341     assert_true(result);
342     assert_int_equal(2, g_strv_length(args));
343     assert_string_equal("arg1", args[0]);
344     assert_string_equal("here is \"some\" quoted freetext", args[1]);
345     g_strfreev(args);
346 }
347 
348 void
parse_cmd_with_third_arg_quoted_0_min_3_max(void ** state)349 parse_cmd_with_third_arg_quoted_0_min_3_max(void** state)
350 {
351     char* inp = "/group add friends \"The User\"";
352     gboolean result = FALSE;
353     gchar** args = parse_args_with_freetext(inp, 0, 3, &result);
354 
355     assert_true(result);
356     assert_int_equal(3, g_strv_length(args));
357     assert_string_equal("add", args[0]);
358     assert_string_equal("friends", args[1]);
359     assert_string_equal("The User", args[2]);
360 
361     g_strfreev(args);
362 }
363 
364 void
parse_cmd_with_second_arg_quoted_0_min_3_max(void ** state)365 parse_cmd_with_second_arg_quoted_0_min_3_max(void** state)
366 {
367     char* inp = "/group add \"The Group\" friend";
368     gboolean result = FALSE;
369     gchar** args = parse_args_with_freetext(inp, 0, 3, &result);
370 
371     assert_true(result);
372     assert_int_equal(3, g_strv_length(args));
373     assert_string_equal("add", args[0]);
374     assert_string_equal("The Group", args[1]);
375     assert_string_equal("friend", args[2]);
376 
377     g_strfreev(args);
378 }
379 
380 void
parse_cmd_with_second_and_third_arg_quoted_0_min_3_max(void ** state)381 parse_cmd_with_second_and_third_arg_quoted_0_min_3_max(void** state)
382 {
383     char* inp = "/group add \"The Group\" \"The User\"";
384     gboolean result = FALSE;
385     gchar** args = parse_args_with_freetext(inp, 0, 3, &result);
386 
387     assert_true(result);
388     assert_int_equal(3, g_strv_length(args));
389     assert_string_equal("add", args[0]);
390     assert_string_equal("The Group", args[1]);
391     assert_string_equal("The User", args[2]);
392 
393     g_strfreev(args);
394 }
395 
396 void
count_one_token(void ** state)397 count_one_token(void** state)
398 {
399     char* inp = "one";
400     int result = count_tokens(inp);
401 
402     assert_int_equal(1, result);
403 }
404 
405 void
count_one_token_quoted_no_whitespace(void ** state)406 count_one_token_quoted_no_whitespace(void** state)
407 {
408     char* inp = "\"one\"";
409     int result = count_tokens(inp);
410 
411     assert_int_equal(1, result);
412 }
413 
414 void
count_one_token_quoted_with_whitespace(void ** state)415 count_one_token_quoted_with_whitespace(void** state)
416 {
417     char* inp = "\"one two\"";
418     int result = count_tokens(inp);
419 
420     assert_int_equal(1, result);
421 }
422 
423 void
count_two_tokens(void ** state)424 count_two_tokens(void** state)
425 {
426     char* inp = "one two";
427     int result = count_tokens(inp);
428 
429     assert_int_equal(2, result);
430 }
431 
432 void
count_two_tokens_first_quoted(void ** state)433 count_two_tokens_first_quoted(void** state)
434 {
435     char* inp = "\"one and\" two";
436     int result = count_tokens(inp);
437 
438     assert_int_equal(2, result);
439 }
440 
441 void
count_two_tokens_second_quoted(void ** state)442 count_two_tokens_second_quoted(void** state)
443 {
444     char* inp = "one \"two and\"";
445     int result = count_tokens(inp);
446 
447     assert_int_equal(2, result);
448 }
449 
450 void
count_two_tokens_both_quoted(void ** state)451 count_two_tokens_both_quoted(void** state)
452 {
453     char* inp = "\"one and then\" \"two and\"";
454     int result = count_tokens(inp);
455 
456     assert_int_equal(2, result);
457 }
458 
459 void
get_first_of_one(void ** state)460 get_first_of_one(void** state)
461 {
462     char* inp = "one";
463     char* result = get_start(inp, 2);
464 
465     assert_string_equal("one", result);
466     free(result);
467 }
468 
469 void
get_first_of_two(void ** state)470 get_first_of_two(void** state)
471 {
472     char* inp = "one two";
473     char* result = get_start(inp, 2);
474 
475     assert_string_equal("one ", result);
476     free(result);
477 }
478 
479 void
get_first_two_of_three(void ** state)480 get_first_two_of_three(void** state)
481 {
482     char* inp = "one two three";
483     char* result = get_start(inp, 3);
484 
485     assert_string_equal("one two ", result);
486     free(result);
487 }
488 
489 void
get_first_two_of_three_first_quoted(void ** state)490 get_first_two_of_three_first_quoted(void** state)
491 {
492     char* inp = "\"one\" two three";
493     char* result = get_start(inp, 3);
494 
495     assert_string_equal("\"one\" two ", result);
496     free(result);
497 }
498 
499 void
get_first_two_of_three_second_quoted(void ** state)500 get_first_two_of_three_second_quoted(void** state)
501 {
502     char* inp = "one \"two\" three";
503     char* result = get_start(inp, 3);
504 
505     assert_string_equal("one \"two\" ", result);
506     free(result);
507 }
508 
509 void
get_first_two_of_three_first_and_second_quoted(void ** state)510 get_first_two_of_three_first_and_second_quoted(void** state)
511 {
512     char* inp = "\"one\" \"two\" three";
513     char* result = get_start(inp, 3);
514 
515     assert_string_equal("\"one\" \"two\" ", result);
516     free(result);
517 }
518 
519 void
parse_options_when_none_returns_empty_hasmap(void ** state)520 parse_options_when_none_returns_empty_hasmap(void** state)
521 {
522     gchar* args[] = { "cmd1", "cmd2", NULL };
523     gchar* keys[] = { "opt1", NULL };
524 
525     gboolean res = FALSE;
526 
527     GHashTable* options = parse_options(&args[2], keys, &res);
528 
529     assert_true(options != NULL);
530     assert_int_equal(0, g_hash_table_size(options));
531     assert_true(res);
532 
533     options_destroy(options);
534 }
535 
536 void
parse_options_when_opt1_no_val_sets_error(void ** state)537 parse_options_when_opt1_no_val_sets_error(void** state)
538 {
539     gchar* args[] = { "cmd1", "cmd2", "opt1", NULL };
540     gchar* keys[] = { "opt1", NULL };
541 
542     gboolean res = TRUE;
543 
544     GHashTable* options = parse_options(&args[2], keys, &res);
545 
546     assert_null(options);
547     assert_false(res);
548 
549     options_destroy(options);
550 }
551 
552 void
parse_options_when_one_returns_map(void ** state)553 parse_options_when_one_returns_map(void** state)
554 {
555     gchar* args[] = { "cmd1", "cmd2", "opt1", "val1", NULL };
556     gchar* keys[] = { "opt1", NULL };
557 
558     gboolean res = FALSE;
559 
560     GHashTable* options = parse_options(&args[2], keys, &res);
561 
562     assert_int_equal(1, g_hash_table_size(options));
563     assert_true(g_hash_table_contains(options, "opt1"));
564     assert_string_equal("val1", g_hash_table_lookup(options, "opt1"));
565     assert_true(res);
566 
567     options_destroy(options);
568 }
569 
570 void
parse_options_when_opt2_no_val_sets_error(void ** state)571 parse_options_when_opt2_no_val_sets_error(void** state)
572 {
573     gchar* args[] = { "cmd1", "cmd2", "opt1", "val1", "opt2", NULL };
574     gchar* keys[] = { "opt1", "opt2", NULL };
575 
576     gboolean res = TRUE;
577 
578     GHashTable* options = parse_options(&args[2], keys, &res);
579 
580     assert_null(options);
581     assert_false(res);
582 
583     options_destroy(options);
584 }
585 
586 void
parse_options_when_two_returns_map(void ** state)587 parse_options_when_two_returns_map(void** state)
588 {
589     gchar* args[] = { "cmd1", "cmd2", "opt1", "val1", "opt2", "val2", NULL };
590     gchar* keys[] = { "opt1", "opt2", NULL };
591 
592     gboolean res = FALSE;
593 
594     GHashTable* options = parse_options(&args[2], keys, &res);
595 
596     assert_int_equal(2, g_hash_table_size(options));
597     assert_true(g_hash_table_contains(options, "opt1"));
598     assert_true(g_hash_table_contains(options, "opt2"));
599     assert_string_equal("val1", g_hash_table_lookup(options, "opt1"));
600     assert_string_equal("val2", g_hash_table_lookup(options, "opt2"));
601     assert_true(res);
602 
603     options_destroy(options);
604 }
605 
606 void
parse_options_when_opt3_no_val_sets_error(void ** state)607 parse_options_when_opt3_no_val_sets_error(void** state)
608 {
609     gchar* args[] = { "cmd1", "cmd2", "opt1", "val1", "opt2", "val2", "opt3", NULL };
610     gchar* keys[] = { "opt1", "opt2", "opt3", NULL };
611 
612     gboolean res = TRUE;
613 
614     GHashTable* options = parse_options(&args[2], keys, &res);
615 
616     assert_null(options);
617     assert_false(res);
618 
619     options_destroy(options);
620 }
621 
622 void
parse_options_when_three_returns_map(void ** state)623 parse_options_when_three_returns_map(void** state)
624 {
625     gchar* args[] = { "cmd1", "cmd2", "opt1", "val1", "opt2", "val2", "opt3", "val3", NULL };
626     gchar* keys[] = { "opt1", "opt2", "opt3", NULL };
627 
628     gboolean res = FALSE;
629 
630     GHashTable* options = parse_options(&args[2], keys, &res);
631 
632     assert_int_equal(3, g_hash_table_size(options));
633     assert_true(g_hash_table_contains(options, "opt1"));
634     assert_true(g_hash_table_contains(options, "opt2"));
635     assert_true(g_hash_table_contains(options, "opt3"));
636     assert_string_equal("val1", g_hash_table_lookup(options, "opt1"));
637     assert_string_equal("val2", g_hash_table_lookup(options, "opt2"));
638     assert_string_equal("val3", g_hash_table_lookup(options, "opt3"));
639     assert_true(res);
640 
641     options_destroy(options);
642 }
643 
644 void
parse_options_when_unknown_opt_sets_error(void ** state)645 parse_options_when_unknown_opt_sets_error(void** state)
646 {
647     gchar* args[] = { "cmd1", "cmd2", "opt1", "val1", "oops", "val2", "opt3", "val3", NULL };
648     gchar* keys[] = { "opt1", "opt2", "opt3", NULL };
649 
650     gboolean res = TRUE;
651 
652     GHashTable* options = parse_options(&args[2], keys, &res);
653 
654     assert_null(options);
655     assert_false(res);
656 
657     options_destroy(options);
658 }
659 
660 void
parse_options_with_duplicated_option_sets_error(void ** state)661 parse_options_with_duplicated_option_sets_error(void** state)
662 {
663     gchar* args[] = { "cmd1", "cmd2", "opt1", "val1", "opt2", "val2", "opt1", "val3", NULL };
664     gchar* keys[] = { "opt1", "opt2", "opt3", NULL };
665 
666     gboolean res = TRUE;
667 
668     GHashTable* options = parse_options(&args[2], keys, &res);
669 
670     assert_null(options);
671     assert_false(res);
672 
673     options_destroy(options);
674 }
675