f9f8f4991bb7e1eee484067f9ecc0879a9ff5a6a
[argpar.git] / tests / test_argpar.c
1 /*
2 * Copyright (c) 2019-2021 Philippe Proulx <pproulx@efficios.com>
3 * Copyright (c) 2020-2021 Simon Marchi <simon.marchi@efficios.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; under version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include <assert.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdbool.h>
23 #include <glib.h>
24
25 #include "tap/tap.h"
26 #include "argpar/argpar.h"
27
28 /*
29 * Formats `item` and appends the resulting string to `res_str` to
30 * incrementally build an expected command line string.
31 *
32 * This function:
33 *
34 * * Prefers the `--long-opt=arg` style over the `-s arg` style.
35 *
36 * * Uses the `arg<A,B>` form for non-option arguments, where `A` is the
37 * original argument index and `B` is the non-option argument index.
38 */
39 static
40 void append_to_res_str(GString * const res_str,
41 const struct argpar_item * const item)
42 {
43 if (res_str->len > 0) {
44 g_string_append_c(res_str, ' ');
45 }
46
47 switch (argpar_item_type(item)) {
48 case ARGPAR_ITEM_TYPE_OPT:
49 {
50 const struct argpar_opt_descr * const descr =
51 argpar_item_opt_descr(item);
52 const char * const arg = argpar_item_opt_arg(item);
53
54 if (descr->long_name) {
55 g_string_append_printf(res_str, "--%s",
56 descr->long_name);
57
58 if (arg) {
59 g_string_append_printf(res_str, "=%s", arg);
60 }
61 } else if (descr->short_name) {
62 g_string_append_printf(res_str, "-%c",
63 descr->short_name);
64
65 if (arg) {
66 g_string_append_printf(res_str, " %s", arg);
67 }
68 }
69
70 break;
71 }
72 case ARGPAR_ITEM_TYPE_NON_OPT:
73 {
74 const char * const arg = argpar_item_non_opt_arg(item);
75 const unsigned int orig_index =
76 argpar_item_non_opt_orig_index(item);
77 const unsigned int non_opt_index =
78 argpar_item_non_opt_non_opt_index(item);
79
80 g_string_append_printf(res_str, "%s<%u,%u>", arg, orig_index,
81 non_opt_index);
82 break;
83 }
84 default:
85 abort();
86 }
87 }
88
89 /*
90 * Parses `cmdline` with argpar_parse() using the option descriptors
91 * `descrs`, and ensures that the resulting effective command line is
92 * `expected_cmd_line` and that the number of ingested original
93 * arguments is `expected_ingested_orig_args`.
94 *
95 * This function splits `cmdline` on spaces to create an original
96 * argument array.
97 *
98 * This function builds the resulting command line from parsing items
99 * by space-separating each formatted item (see append_to_res_str()).
100 */
101 static
102 void test_succeed_argpar_parse(const char * const cmdline,
103 const char * const expected_cmd_line,
104 const struct argpar_opt_descr * const descrs,
105 const unsigned int expected_ingested_orig_args)
106 {
107 struct argpar_parse_ret parse_ret;
108 GString * const res_str = g_string_new(NULL);
109 gchar ** const argv = g_strsplit(cmdline, " ", 0);
110 unsigned int i;
111
112 assert(argv);
113 assert(res_str);
114 parse_ret = argpar_parse(g_strv_length(argv),
115 (const char * const *) argv, descrs, false);
116 ok(parse_ret.items,
117 "argpar_parse() succeeds for command line `%s`", cmdline);
118 ok(!parse_ret.error,
119 "argpar_parse() doesn't set an error for command line `%s`",
120 cmdline);
121 ok(parse_ret.ingested_orig_args == expected_ingested_orig_args,
122 "argpar_parse() returns the correct number of ingested "
123 "original arguments for command line `%s`", cmdline);
124
125 if (parse_ret.ingested_orig_args != expected_ingested_orig_args) {
126 diag("Expected: %u Got: %u", expected_ingested_orig_args,
127 parse_ret.ingested_orig_args);
128 }
129
130 if (!parse_ret.items) {
131 fail("argpar_parse() returns the expected parsing items "
132 "for command line `%s`", cmdline);
133 goto end;
134 }
135
136 for (i = 0; i < parse_ret.items->n_items; i++) {
137 append_to_res_str(res_str, parse_ret.items->items[i]);
138 }
139
140 ok(strcmp(expected_cmd_line, res_str->str) == 0,
141 "argpar_parse() returns the expected parsed arguments "
142 "for command line `%s`", cmdline);
143
144 if (strcmp(expected_cmd_line, res_str->str) != 0) {
145 diag("Expected: `%s`", expected_cmd_line);
146 diag("Got: `%s`", res_str->str);
147 }
148
149 end:
150 argpar_parse_ret_fini(&parse_ret);
151 g_string_free(res_str, TRUE);
152 g_strfreev(argv);
153 }
154
155 /*
156 * Parses `cmdline` with the iterator API using the option descriptors
157 * `descrs`, and ensures that the resulting effective command line is
158 * `expected_cmd_line` and that the number of ingested original
159 * arguments is `expected_ingested_orig_args`.
160 *
161 * This function splits `cmdline` on spaces to create an original
162 * argument array.
163 *
164 * This function builds the resulting command line from parsing items
165 * by space-separating each formatted item (see append_to_res_str()).
166 */
167 static
168 void test_succeed_argpar_iter(const char * const cmdline,
169 const char * const expected_cmd_line,
170 const struct argpar_opt_descr * const descrs,
171 const unsigned int expected_ingested_orig_args)
172 {
173 struct argpar_iter *iter = NULL;
174 const struct argpar_item *item = NULL;
175 char *error = NULL;
176 GString * const res_str = g_string_new(NULL);
177 gchar ** const argv = g_strsplit(cmdline, " ", 0);
178 unsigned int i, actual_ingested_orig_args;
179
180 assert(argv);
181 assert(res_str);
182 iter = argpar_iter_create(g_strv_length(argv),
183 (const char * const *) argv, descrs);
184 assert(iter);
185
186 for (i = 0; ; i++) {
187 enum argpar_iter_next_status status;
188
189 ARGPAR_ITEM_DESTROY_AND_RESET(item);
190 status = argpar_iter_next(iter, &item, &error);
191
192 ok(status == ARGPAR_ITER_NEXT_STATUS_OK ||
193 status == ARGPAR_ITER_NEXT_STATUS_END ||
194 status == ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
195 "argpar_iter_next() returns the expected status "
196 "(%d) for command line `%s` (call %u)",
197 status, cmdline, i + 1);
198
199 if (status == ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
200 ok(error,
201 "argpar_iter_next() sets an error for "
202 "status `ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT` "
203 "and command line `%s` (call %u)",
204 cmdline, i + 1);
205 } else {
206 ok(!error,
207 "argpar_iter_next() doesn't set an error "
208 "for other status than "
209 "`ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT` "
210 "and command line `%s` (call %u)",
211 cmdline, i + 1);
212 }
213
214 if (status == ARGPAR_ITER_NEXT_STATUS_END ||
215 status == ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
216 ok(!item,
217 "argpar_iter_next() doesn't set an item "
218 "for status `ARGPAR_ITER_NEXT_STATUS_END` "
219 "or `ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT` "
220 "and command line `%s` (call %u)",
221 cmdline, i + 1);
222 break;
223 }
224
225 append_to_res_str(res_str, item);
226 }
227
228 actual_ingested_orig_args = argpar_iter_get_ingested_orig_args(iter);
229 ok(actual_ingested_orig_args == expected_ingested_orig_args,
230 "argpar_iter_get_ingested_orig_args() returns the expected "
231 "number of ingested original arguments for command line `%s`",
232 cmdline);
233
234 if (actual_ingested_orig_args != expected_ingested_orig_args) {
235 diag("Expected: %u Got: %u", expected_ingested_orig_args,
236 actual_ingested_orig_args);
237 }
238
239 ok(strcmp(expected_cmd_line, res_str->str) == 0,
240 "argpar_iter_next() returns the expected parsing items "
241 "for command line `%s`", cmdline);
242
243 if (strcmp(expected_cmd_line, res_str->str) != 0) {
244 diag("Expected: `%s`", expected_cmd_line);
245 diag("Got: `%s`", res_str->str);
246 }
247
248 argpar_item_destroy(item);
249 argpar_iter_destroy(iter);
250 g_string_free(res_str, TRUE);
251 g_strfreev(argv);
252 free(error);
253 }
254
255 /*
256 * Calls test_succeed_argpar_parse() and test_succeed_argpar_iter()
257 * with the provided parameters.
258 */
259 static
260 void test_succeed(const char * const cmdline,
261 const char * const expected_cmd_line,
262 const struct argpar_opt_descr * const descrs,
263 const unsigned int expected_ingested_orig_args)
264 {
265 test_succeed_argpar_parse(cmdline, expected_cmd_line, descrs,
266 expected_ingested_orig_args);
267 test_succeed_argpar_iter(cmdline, expected_cmd_line, descrs,
268 expected_ingested_orig_args);
269 }
270
271 static
272 void succeed_tests(void)
273 {
274 /* No arguments */
275 {
276 const struct argpar_opt_descr descrs[] = {
277 ARGPAR_OPT_DESCR_SENTINEL
278 };
279
280 test_succeed(
281 "",
282 "",
283 descrs, 0);
284 }
285
286 /* Single long option */
287 {
288 const struct argpar_opt_descr descrs[] = {
289 { 0, '\0', "salut", false },
290 ARGPAR_OPT_DESCR_SENTINEL
291 };
292
293 test_succeed(
294 "--salut",
295 "--salut",
296 descrs, 1);
297 }
298
299 /* Single short option */
300 {
301 const struct argpar_opt_descr descrs[] = {
302 { 0, 'f', NULL, false },
303 ARGPAR_OPT_DESCR_SENTINEL
304 };
305
306 test_succeed(
307 "-f",
308 "-f",
309 descrs, 1);
310 }
311
312 /* Short and long option (aliases) */
313 {
314 const struct argpar_opt_descr descrs[] = {
315 { 0, 'f', "flaw", false },
316 ARGPAR_OPT_DESCR_SENTINEL
317 };
318
319 test_succeed(
320 "-f --flaw",
321 "--flaw --flaw",
322 descrs, 2);
323 }
324
325 /* Long option with argument (space form) */
326 {
327 const struct argpar_opt_descr descrs[] = {
328 { 0, '\0', "tooth", true },
329 ARGPAR_OPT_DESCR_SENTINEL
330 };
331
332 test_succeed(
333 "--tooth 67",
334 "--tooth=67",
335 descrs, 2);
336 }
337
338 /* Long option with argument (equal form) */
339 {
340 const struct argpar_opt_descr descrs[] = {
341 { 0, '\0', "polish", true },
342 ARGPAR_OPT_DESCR_SENTINEL
343 };
344
345 test_succeed(
346 "--polish=brick",
347 "--polish=brick",
348 descrs, 1);
349 }
350
351 /* Short option with argument (space form) */
352 {
353 const struct argpar_opt_descr descrs[] = {
354 { 0, 'c', NULL, true },
355 ARGPAR_OPT_DESCR_SENTINEL
356 };
357
358 test_succeed(
359 "-c chilly",
360 "-c chilly",
361 descrs, 2);
362 }
363
364 /* Short option with argument (glued form) */
365 {
366 const struct argpar_opt_descr descrs[] = {
367 { 0, 'c', NULL, true },
368 ARGPAR_OPT_DESCR_SENTINEL
369 };
370
371 test_succeed(
372 "-cchilly",
373 "-c chilly",
374 descrs, 1);
375 }
376
377 /* Short and long option (aliases) with argument (all forms) */
378 {
379 const struct argpar_opt_descr descrs[] = {
380 { 0, 'd', "dry", true },
381 ARGPAR_OPT_DESCR_SENTINEL
382 };
383
384 test_succeed(
385 "--dry=rate -dthing --dry street --dry=shape",
386 "--dry=rate --dry=thing --dry=street --dry=shape",
387 descrs, 5);
388 }
389
390 /* Many short options, last one with argument (glued form) */
391 {
392 const struct argpar_opt_descr descrs[] = {
393 { 0, 'd', NULL, false },
394 { 0, 'e', NULL, false },
395 { 0, 'f', NULL, true },
396 ARGPAR_OPT_DESCR_SENTINEL
397 };
398
399 test_succeed(
400 "-defmeow",
401 "-d -e -f meow",
402 descrs, 1);
403 }
404
405 /* Many options */
406 {
407 const struct argpar_opt_descr descrs[] = {
408 { 0, 'd', NULL, false },
409 { 0, 'e', "east", true },
410 { 0, '\0', "mind", false },
411 ARGPAR_OPT_DESCR_SENTINEL
412 };
413
414 test_succeed(
415 "-d --mind -destart --mind --east cough -d --east=itch",
416 "-d --mind -d --east=start --mind --east=cough -d --east=itch",
417 descrs, 8);
418 }
419
420 /* Single non-option argument */
421 {
422 const struct argpar_opt_descr descrs[] = {
423 ARGPAR_OPT_DESCR_SENTINEL
424 };
425
426 test_succeed(
427 "kilojoule",
428 "kilojoule<0,0>",
429 descrs, 1);
430 }
431
432 /* Two non-option arguments */
433 {
434 const struct argpar_opt_descr descrs[] = {
435 ARGPAR_OPT_DESCR_SENTINEL
436 };
437
438 test_succeed(
439 "kilojoule mitaine",
440 "kilojoule<0,0> mitaine<1,1>",
441 descrs, 2);
442 }
443
444 /* Single non-option argument mixed with options */
445 {
446 const struct argpar_opt_descr descrs[] = {
447 { 0, 'd', NULL, false },
448 { 0, '\0', "squeeze", true },
449 ARGPAR_OPT_DESCR_SENTINEL
450 };
451
452 test_succeed(
453 "-d sprout yes --squeeze little bag -d",
454 "-d sprout<1,0> yes<2,1> --squeeze=little bag<5,2> -d",
455 descrs, 7);
456 }
457
458 /* Unknown short option (space form) */
459 {
460 const struct argpar_opt_descr descrs[] = {
461 { 0, 'd', NULL, true },
462 ARGPAR_OPT_DESCR_SENTINEL
463 };
464
465 test_succeed(
466 "-d salut -e -d meow",
467 "-d salut",
468 descrs, 2);
469 }
470
471 /* Unknown short option (glued form) */
472 {
473 const struct argpar_opt_descr descrs[] = {
474 { 0, 'd', NULL, true },
475 ARGPAR_OPT_DESCR_SENTINEL
476 };
477
478 test_succeed(
479 "-dsalut -e -d meow",
480 "-d salut",
481 descrs, 1);
482 }
483
484 /* Unknown long option (space form) */
485 {
486 const struct argpar_opt_descr descrs[] = {
487 { 0, '\0', "sink", true },
488 ARGPAR_OPT_DESCR_SENTINEL
489 };
490
491 test_succeed(
492 "--sink party --food --sink impulse",
493 "--sink=party",
494 descrs, 2);
495 }
496
497 /* Unknown long option (equal form) */
498 {
499 const struct argpar_opt_descr descrs[] = {
500 { 0, '\0', "sink", true },
501 ARGPAR_OPT_DESCR_SENTINEL
502 };
503
504 test_succeed(
505 "--sink=party --food --sink=impulse",
506 "--sink=party",
507 descrs, 1);
508 }
509
510 /* Unknown option before non-option argument */
511 {
512 const struct argpar_opt_descr descrs[] = {
513 { 0, '\0', "thumb", true },
514 ARGPAR_OPT_DESCR_SENTINEL
515 };
516
517 test_succeed(
518 "--thumb=party --food bateau --thumb waves",
519 "--thumb=party",
520 descrs, 1);
521 }
522
523 /* Unknown option after non-option argument */
524 {
525 const struct argpar_opt_descr descrs[] = {
526 { 0, '\0', "thumb", true },
527 ARGPAR_OPT_DESCR_SENTINEL
528 };
529
530 test_succeed(
531 "--thumb=party wound --food --thumb waves",
532 "--thumb=party wound<1,0>",
533 descrs, 2);
534 }
535
536 /* Valid `---opt` */
537 {
538 const struct argpar_opt_descr descrs[] = {
539 { 0, '\0', "-fuel", true },
540 ARGPAR_OPT_DESCR_SENTINEL
541 };
542
543 test_succeed(
544 "---fuel=three",
545 "---fuel=three",
546 descrs, 1);
547 }
548
549 /* Long option containing `=` in argument (equal form) */
550 {
551 const struct argpar_opt_descr descrs[] = {
552 { 0, '\0', "zebra", true },
553 ARGPAR_OPT_DESCR_SENTINEL
554 };
555
556 test_succeed(
557 "--zebra=three=yes",
558 "--zebra=three=yes",
559 descrs, 1);
560 }
561
562 /* Short option's argument starting with `-` (glued form) */
563 {
564 const struct argpar_opt_descr descrs[] = {
565 { 0, 'z', NULL, true },
566 ARGPAR_OPT_DESCR_SENTINEL
567 };
568
569 test_succeed(
570 "-z-will",
571 "-z -will",
572 descrs, 1);
573 }
574
575 /* Short option's argument starting with `-` (space form) */
576 {
577 const struct argpar_opt_descr descrs[] = {
578 { 0, 'z', NULL, true },
579 ARGPAR_OPT_DESCR_SENTINEL
580 };
581
582 test_succeed(
583 "-z -will",
584 "-z -will",
585 descrs, 2);
586 }
587
588 /* Long option's argument starting with `-` (space form) */
589 {
590 const struct argpar_opt_descr descrs[] = {
591 { 0, '\0', "janine", true },
592 ARGPAR_OPT_DESCR_SENTINEL
593 };
594
595 test_succeed(
596 "--janine -sutto",
597 "--janine=-sutto",
598 descrs, 2);
599 }
600
601 /* Long option's argument starting with `-` (equal form) */
602 {
603 const struct argpar_opt_descr descrs[] = {
604 { 0, '\0', "janine", true },
605 ARGPAR_OPT_DESCR_SENTINEL
606 };
607
608 test_succeed(
609 "--janine=-sutto",
610 "--janine=-sutto",
611 descrs, 1);
612 }
613
614 /* Long option's empty argument (equal form) */
615 {
616 const struct argpar_opt_descr descrs[] = {
617 { 0, 'f', NULL, false },
618 { 0, '\0', "yeah", true },
619 ARGPAR_OPT_DESCR_SENTINEL
620 };
621
622 test_succeed(
623 "-f --yeah= -f",
624 "-f --yeah= -f",
625 descrs, 3);
626 }
627 }
628
629 /*
630 * Parses `cmdline` with argpar_parse() using the option descriptors
631 * `descrs`, and ensures that the function fails and that it sets an
632 * error which is equal to `expected_error`.
633 *
634 * This function splits `cmdline` on spaces to create an original
635 * argument array.
636 */
637 static
638 void test_fail_argpar_parse(const char * const cmdline,
639 const char * const expected_error,
640 const struct argpar_opt_descr * const descrs)
641 {
642 struct argpar_parse_ret parse_ret;
643 gchar ** const argv = g_strsplit(cmdline, " ", 0);
644
645 parse_ret = argpar_parse(g_strv_length(argv),
646 (const char * const *) argv, descrs, true);
647 ok(!parse_ret.items,
648 "argpar_parse() fails for command line `%s`", cmdline);
649 ok(parse_ret.error,
650 "argpar_parse() sets an error string for command line `%s`",
651 cmdline);
652
653 if (parse_ret.items) {
654 fail("argpar_parse() sets the expected error string");
655 goto end;
656 }
657
658 ok(strcmp(expected_error, parse_ret.error) == 0,
659 "argpar_parse() sets the expected error string "
660 "for command line `%s`", cmdline);
661
662 if (strcmp(expected_error, parse_ret.error) != 0) {
663 diag("Expected: `%s`", expected_error);
664 diag("Got: `%s`", parse_ret.error);
665 }
666
667 end:
668 argpar_parse_ret_fini(&parse_ret);
669 g_strfreev(argv);
670 }
671
672 /*
673 * Parses `cmdline` with the iterator API using the option descriptors
674 * `descrs`, and ensures that argpar_iter_next() fails with status
675 * `expected_status` and that it sets an error which is equal to
676 * `expected_error`.
677 *
678 * This function splits `cmdline` on spaces to create an original
679 * argument array.
680 */
681 static
682 void test_fail_argpar_iter(const char * const cmdline,
683 const char * const expected_error,
684 const enum argpar_iter_next_status expected_status,
685 const struct argpar_opt_descr * const descrs)
686 {
687 struct argpar_iter *iter = NULL;
688 const struct argpar_item *item = NULL;
689 gchar ** const argv = g_strsplit(cmdline, " ", 0);
690 unsigned int i;
691 char *error = NULL;
692
693 iter = argpar_iter_create(g_strv_length(argv),
694 (const char * const *) argv, descrs);
695 assert(iter);
696
697 for (i = 0; ; i++) {
698 enum argpar_iter_next_status status;
699
700 ARGPAR_ITEM_DESTROY_AND_RESET(item);
701 status = argpar_iter_next(iter, &item, &error);
702 ok(status == ARGPAR_ITER_NEXT_STATUS_OK ||
703 status == expected_status,
704 "argpar_iter_next() returns the expected status "
705 "(%d) for command line `%s` (call %u)",
706 status, cmdline, i + 1);
707
708 if (status != ARGPAR_ITER_NEXT_STATUS_OK) {
709 ok(!item,
710 "argpar_iter_next() doesn't set an item "
711 "for other status than "
712 "`ARGPAR_ITER_NEXT_STATUS_OK` "
713 "and command line `%s` (call %u)",
714 cmdline, i + 1);
715 ok(error,
716 "argpar_iter_next() sets an error for "
717 "other status than "
718 " `ARGPAR_ITER_NEXT_STATUS_OK` "
719 "and command line `%s` (call %u)",
720 cmdline, i + 1);
721 break;
722 }
723
724 ok(item,
725 "argpar_iter_next() sets an item for status "
726 "`ARGPAR_ITER_NEXT_STATUS_OK` "
727 "and command line `%s` (call %u)",
728 cmdline, i + 1);
729 ok(!error,
730 "argpar_iter_next() doesn't set an error for status "
731 "`ARGPAR_ITER_NEXT_STATUS_OK` "
732 "and command line `%s` (call %u)",
733 cmdline, i + 1);
734 }
735
736 ok(strcmp(expected_error, error) == 0,
737 "argpar_iter_next() sets the expected error string "
738 "for command line `%s`", cmdline);
739
740 if (strcmp(expected_error, error) != 0) {
741 diag("Expected: `%s`", expected_error);
742 diag("Got: `%s`", error);
743 }
744
745 argpar_item_destroy(item);
746 argpar_iter_destroy(iter);
747 free(error);
748 g_strfreev(argv);
749 }
750
751 /*
752 * Calls test_fail_argpar_parse() and test_fail_argpar_iter() with the
753 * provided parameters.
754 */
755 static
756 void test_fail(const char * const cmdline, const char * const expected_error,
757 const enum argpar_iter_next_status expected_iter_next_status,
758 const struct argpar_opt_descr * const descrs)
759 {
760 test_fail_argpar_parse(cmdline, expected_error, descrs);
761 test_fail_argpar_iter(cmdline, expected_error,
762 expected_iter_next_status, descrs);
763 }
764
765 static
766 void fail_tests(void)
767 {
768 /* Unknown long option */
769 {
770 const struct argpar_opt_descr descrs[] = {
771 { 0, '\0', "thumb", true },
772 ARGPAR_OPT_DESCR_SENTINEL
773 };
774
775 test_fail(
776 "--thumb=party --meow",
777 "While parsing argument #2 (`--meow`): Unknown option `--meow`",
778 ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
779 descrs);
780 }
781
782 /* Unknown short option */
783 {
784 const struct argpar_opt_descr descrs[] = {
785 { 0, '\0', "thumb", true },
786 ARGPAR_OPT_DESCR_SENTINEL
787 };
788
789 test_fail(
790 "--thumb=party -x",
791 "While parsing argument #2 (`-x`): Unknown option `-x`",
792 ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
793 descrs);
794 }
795
796 /* Missing long option argument */
797 {
798 const struct argpar_opt_descr descrs[] = {
799 { 0, '\0', "thumb", true },
800 ARGPAR_OPT_DESCR_SENTINEL
801 };
802
803 test_fail(
804 "--thumb",
805 "While parsing argument #1 (`--thumb`): Missing required argument for option `--thumb`",
806 ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG,
807 descrs);
808 }
809
810 /* Missing short option argument */
811 {
812 const struct argpar_opt_descr descrs[] = {
813 { 0, 'k', NULL, true },
814 ARGPAR_OPT_DESCR_SENTINEL
815 };
816
817 test_fail(
818 "-k",
819 "While parsing argument #1 (`-k`): Missing required argument for option `-k`",
820 ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG,
821 descrs);
822 }
823
824 /* Missing short option argument (multiple glued) */
825 {
826 const struct argpar_opt_descr descrs[] = {
827 { 0, 'a', NULL, false },
828 { 0, 'b', NULL, false },
829 { 0, 'c', NULL, true },
830 ARGPAR_OPT_DESCR_SENTINEL
831 };
832
833 test_fail(
834 "-abc",
835 "While parsing argument #1 (`-abc`): Missing required argument for option `-c`",
836 ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG,
837 descrs);
838 }
839
840 /* Invalid `-` */
841 {
842 const struct argpar_opt_descr descrs[] = {
843 { 0, 'a', NULL, false },
844 { 0, 'b', NULL, false },
845 { 0, 'c', NULL, true },
846 ARGPAR_OPT_DESCR_SENTINEL
847 };
848
849 test_fail(
850 "-ab - -c",
851 "While parsing argument #2 (`-`): Invalid argument",
852 ARGPAR_ITER_NEXT_STATUS_ERROR_INVALID_ARG,
853 descrs);
854 }
855
856 /* Invalid `--` */
857 {
858 const struct argpar_opt_descr descrs[] = {
859 { 0, 'a', NULL, false },
860 { 0, 'b', NULL, false },
861 { 0, 'c', NULL, true },
862 ARGPAR_OPT_DESCR_SENTINEL
863 };
864
865 test_fail(
866 "-ab -- -c",
867 "While parsing argument #2 (`--`): Invalid argument",
868 ARGPAR_ITER_NEXT_STATUS_ERROR_INVALID_ARG,
869 descrs);
870 }
871
872 {
873 const struct argpar_opt_descr descrs[] = {
874 { 0, 'c', "chevre", false },
875 ARGPAR_OPT_DESCR_SENTINEL
876 };
877
878 test_fail(
879 "--chevre=fromage",
880 "While parsing argument #1 (`--chevre=fromage`): Unexpected argument for option `--chevre`",
881 ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPT_ARG,
882 descrs);
883 }
884 }
885
886 int main(void)
887 {
888 plan_tests(419);
889 succeed_tests();
890 fail_tests();
891 return exit_status();
892 }
This page took 0.045025 seconds and 3 git commands to generate.