2 * Copyright (c) 2019 Philippe Proulx <pproulx@efficios.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; under version 2 of the License.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "argpar/argpar.h"
27 * Tests that the command line `cmdline`, with non-quoted
28 * space-delimited arguments, once parsed given the option descriptors
29 * `descrs` and the option `fail_on_unknown_opt`, succeeds and gives the
30 * expected command line `expected_cmd_line` and number of ingested
31 * original arguments `expected_ingested_orig_args`.
33 * The resulting command-line is built from the resulting arguments,
34 * space-delimiting each argument, preferring the `--long-opt=arg` style
35 * over the `-s arg` style, and using the `arg<A,B>` form for non-option
36 * arguments where `A` is the original argument index and `B` is the
37 * non-option argument index.
40 void test_succeed(const char *cmdline
,
41 const char *expected_cmd_line
,
42 const struct bt_argpar_opt_descr
*descrs
,
43 unsigned int expected_ingested_orig_args
)
45 struct bt_argpar_parse_ret parse_ret
;
46 GString
*res_str
= g_string_new(NULL
);
47 gchar
**argv
= g_strsplit(cmdline
, " ", 0);
52 parse_ret
= bt_argpar_parse(g_strv_length(argv
),
53 (const char * const *) argv
, descrs
, false);
55 "bt_argpar_parse() succeeds for command line `%s`", cmdline
);
57 "bt_argpar_parse() does not write an error for command line `%s`", cmdline
);
58 ok(parse_ret
.ingested_orig_args
== expected_ingested_orig_args
,
59 "bt_argpar_parse() returns the correct number of ingested "
60 "original arguments for command line `%s`", cmdline
);
61 if (parse_ret
.ingested_orig_args
!= expected_ingested_orig_args
) {
62 diag("Expected: %u Got: %u", expected_ingested_orig_args
,
63 parse_ret
.ingested_orig_args
);
66 if (!parse_ret
.items
) {
67 fail("bt_argpar_parse() returns the expected parsed arguments "
68 "for command line `%s`", cmdline
);
72 for (i
= 0; i
< parse_ret
.items
->n_items
; i
++) {
73 const struct bt_argpar_item
*arg
= parse_ret
.items
->items
[i
];
76 case BT_ARGPAR_ITEM_TYPE_OPT
:
78 const struct bt_argpar_item_opt
*arg_opt
=
81 if (arg_opt
->descr
->long_name
) {
82 g_string_append_printf(res_str
, "--%s",
83 arg_opt
->descr
->long_name
);
86 g_string_append_printf(res_str
, "=%s",
90 g_string_append_c(res_str
, ' ');
91 } else if (arg_opt
->descr
->short_name
) {
92 g_string_append_printf(res_str
, "-%c",
93 arg_opt
->descr
->short_name
);
96 g_string_append_printf(res_str
, " %s",
100 g_string_append_c(res_str
, ' ');
105 case BT_ARGPAR_ITEM_TYPE_NON_OPT
:
107 const struct bt_argpar_item_non_opt
*arg_non_opt
=
110 g_string_append_printf(res_str
, "%s<%u,%u> ",
111 arg_non_opt
->arg
, arg_non_opt
->orig_index
,
112 arg_non_opt
->non_opt_index
);
120 if (res_str
->len
> 0) {
121 g_string_truncate(res_str
, res_str
->len
- 1);
124 ok(strcmp(expected_cmd_line
, res_str
->str
) == 0,
125 "bt_argpar_parse() returns the expected parsed arguments "
126 "for command line `%s`", cmdline
);
127 if (strcmp(expected_cmd_line
, res_str
->str
) != 0) {
128 diag("Expected: `%s`", expected_cmd_line
);
129 diag("Got: `%s`", res_str
->str
);
133 bt_argpar_parse_ret_fini(&parse_ret
);
134 g_string_free(res_str
, TRUE
);
139 void succeed_tests(void)
143 const struct bt_argpar_opt_descr descrs
[] = {
144 BT_ARGPAR_OPT_DESCR_SENTINEL
153 /* Single long option */
155 const struct bt_argpar_opt_descr descrs
[] = {
156 { 0, '\0', "salut", false },
157 BT_ARGPAR_OPT_DESCR_SENTINEL
166 /* Single short option */
168 const struct bt_argpar_opt_descr descrs
[] = {
169 { 0, 'f', NULL
, false },
170 BT_ARGPAR_OPT_DESCR_SENTINEL
179 /* Short and long option (aliases) */
181 const struct bt_argpar_opt_descr descrs
[] = {
182 { 0, 'f', "flaw", false },
183 BT_ARGPAR_OPT_DESCR_SENTINEL
192 /* Long option with argument (space form) */
194 const struct bt_argpar_opt_descr descrs
[] = {
195 { 0, '\0', "tooth", true },
196 BT_ARGPAR_OPT_DESCR_SENTINEL
205 /* Long option with argument (equal form) */
207 const struct bt_argpar_opt_descr descrs
[] = {
208 { 0, '\0', "polish", true },
209 BT_ARGPAR_OPT_DESCR_SENTINEL
218 /* Short option with argument (space form) */
220 const struct bt_argpar_opt_descr descrs
[] = {
221 { 0, 'c', NULL
, true },
222 BT_ARGPAR_OPT_DESCR_SENTINEL
231 /* Short option with argument (glued form) */
233 const struct bt_argpar_opt_descr descrs
[] = {
234 { 0, 'c', NULL
, true },
235 BT_ARGPAR_OPT_DESCR_SENTINEL
244 /* Short and long option (aliases) with argument (all forms) */
246 const struct bt_argpar_opt_descr descrs
[] = {
247 { 0, 'd', "dry", true },
248 BT_ARGPAR_OPT_DESCR_SENTINEL
252 "--dry=rate -dthing --dry street --dry=shape",
253 "--dry=rate --dry=thing --dry=street --dry=shape",
257 /* Many short options, last one with argument (glued form) */
259 const struct bt_argpar_opt_descr descrs
[] = {
260 { 0, 'd', NULL
, false },
261 { 0, 'e', NULL
, false },
262 { 0, 'f', NULL
, true },
263 BT_ARGPAR_OPT_DESCR_SENTINEL
274 const struct bt_argpar_opt_descr descrs
[] = {
275 { 0, 'd', NULL
, false },
276 { 0, 'e', "east", true },
277 { 0, '\0', "mind", false },
278 BT_ARGPAR_OPT_DESCR_SENTINEL
282 "-d --mind -destart --mind --east cough -d --east=itch",
283 "-d --mind -d --east=start --mind --east=cough -d --east=itch",
287 /* Single non-option argument */
289 const struct bt_argpar_opt_descr descrs
[] = {
290 BT_ARGPAR_OPT_DESCR_SENTINEL
299 /* Two non-option arguments */
301 const struct bt_argpar_opt_descr descrs
[] = {
302 BT_ARGPAR_OPT_DESCR_SENTINEL
307 "kilojoule<0,0> mitaine<1,1>",
311 /* Single non-option argument mixed with options */
313 const struct bt_argpar_opt_descr descrs
[] = {
314 { 0, 'd', NULL
, false },
315 { 0, '\0', "squeeze", true },
316 BT_ARGPAR_OPT_DESCR_SENTINEL
320 "-d sprout yes --squeeze little bag -d",
321 "-d sprout<1,0> yes<2,1> --squeeze=little bag<5,2> -d",
325 /* Unknown short option (space form) */
327 const struct bt_argpar_opt_descr descrs
[] = {
328 { 0, 'd', NULL
, true },
329 BT_ARGPAR_OPT_DESCR_SENTINEL
333 "-d salut -e -d meow",
338 /* Unknown short option (glued form) */
340 const struct bt_argpar_opt_descr descrs
[] = {
341 { 0, 'd', NULL
, true },
342 BT_ARGPAR_OPT_DESCR_SENTINEL
346 "-dsalut -e -d meow",
351 /* Unknown long option (space form) */
353 const struct bt_argpar_opt_descr descrs
[] = {
354 { 0, '\0', "sink", true },
355 BT_ARGPAR_OPT_DESCR_SENTINEL
359 "--sink party --food --sink impulse",
364 /* Unknown long option (equal form) */
366 const struct bt_argpar_opt_descr descrs
[] = {
367 { 0, '\0', "sink", true },
368 BT_ARGPAR_OPT_DESCR_SENTINEL
372 "--sink=party --food --sink=impulse",
377 /* Unknown option before non-option argument */
379 const struct bt_argpar_opt_descr descrs
[] = {
380 { 0, '\0', "thumb", true },
381 BT_ARGPAR_OPT_DESCR_SENTINEL
385 "--thumb=party --food bateau --thumb waves",
390 /* Unknown option after non-option argument */
392 const struct bt_argpar_opt_descr descrs
[] = {
393 { 0, '\0', "thumb", true },
394 BT_ARGPAR_OPT_DESCR_SENTINEL
398 "--thumb=party wound --food --thumb waves",
399 "--thumb=party wound<1,0>",
405 const struct bt_argpar_opt_descr descrs
[] = {
406 { 0, '\0', "-fuel", true },
407 BT_ARGPAR_OPT_DESCR_SENTINEL
416 /* Long option containing `=` in argument (equal form) */
418 const struct bt_argpar_opt_descr descrs
[] = {
419 { 0, '\0', "zebra", true },
420 BT_ARGPAR_OPT_DESCR_SENTINEL
429 /* Short option's argument starting with `-` (glued form) */
431 const struct bt_argpar_opt_descr descrs
[] = {
432 { 0, 'z', NULL
, true },
433 BT_ARGPAR_OPT_DESCR_SENTINEL
442 /* Short option's argument starting with `-` (space form) */
444 const struct bt_argpar_opt_descr descrs
[] = {
445 { 0, 'z', NULL
, true },
446 BT_ARGPAR_OPT_DESCR_SENTINEL
455 /* Long option's argument starting with `-` (space form) */
457 const struct bt_argpar_opt_descr descrs
[] = {
458 { 0, '\0', "janine", true },
459 BT_ARGPAR_OPT_DESCR_SENTINEL
468 /* Long option's argument starting with `-` (equal form) */
470 const struct bt_argpar_opt_descr descrs
[] = {
471 { 0, '\0', "janine", true },
472 BT_ARGPAR_OPT_DESCR_SENTINEL
481 /* Long option's empty argument (equal form) */
483 const struct bt_argpar_opt_descr descrs
[] = {
484 { 0, 'f', NULL
, false },
485 { 0, '\0', "yeah", true },
486 BT_ARGPAR_OPT_DESCR_SENTINEL
497 * Tests that the command line `cmdline`, with non-quoted
498 * space-delimited arguments, once parsed given the option descriptors
499 * `descrs`, fails and gives the expected error `expected_error`.
502 void test_fail(const char *cmdline
, const char *expected_error
,
503 const struct bt_argpar_opt_descr
*descrs
)
505 struct bt_argpar_parse_ret parse_ret
;
506 gchar
**argv
= g_strsplit(cmdline
, " ", 0);
508 parse_ret
= bt_argpar_parse(g_strv_length(argv
),
509 (const char * const *) argv
, descrs
, true);
511 "bt_argpar_parse() fails for command line `%s`", cmdline
);
513 "bt_argpar_parse() writes an error string for command line `%s`",
515 if (parse_ret
.items
) {
516 fail("bt_argpar_parse() writes the expected error string");
520 ok(strcmp(expected_error
, parse_ret
.error
) == 0,
521 "bt_argpar_parse() writes the expected error string "
522 "for command line `%s`", cmdline
);
523 if (strcmp(expected_error
, parse_ret
.error
) != 0) {
524 diag("Expected: `%s`", expected_error
);
525 diag("Got: `%s`", parse_ret
.error
);
529 bt_argpar_parse_ret_fini(&parse_ret
);
534 void fail_tests(void)
536 /* Unknown long option */
538 const struct bt_argpar_opt_descr descrs
[] = {
539 { 0, '\0', "thumb", true },
540 BT_ARGPAR_OPT_DESCR_SENTINEL
544 "--thumb=party --meow",
545 "While parsing argument #2 (`--meow`): Unknown option `--meow`",
549 /* Unknown short option */
551 const struct bt_argpar_opt_descr descrs
[] = {
552 { 0, '\0', "thumb", true },
553 BT_ARGPAR_OPT_DESCR_SENTINEL
558 "While parsing argument #2 (`-x`): Unknown option `-x`",
562 /* Missing long option argument */
564 const struct bt_argpar_opt_descr descrs
[] = {
565 { 0, '\0', "thumb", true },
566 BT_ARGPAR_OPT_DESCR_SENTINEL
571 "While parsing argument #1 (`--thumb`): Missing required argument for option `--thumb`",
575 /* Missing short option argument */
577 const struct bt_argpar_opt_descr descrs
[] = {
578 { 0, 'k', NULL
, true },
579 BT_ARGPAR_OPT_DESCR_SENTINEL
584 "While parsing argument #1 (`-k`): Missing required argument for option `-k`",
588 /* Missing short option argument (multiple glued) */
590 const struct bt_argpar_opt_descr descrs
[] = {
591 { 0, 'a', NULL
, false },
592 { 0, 'b', NULL
, false },
593 { 0, 'c', NULL
, true },
594 BT_ARGPAR_OPT_DESCR_SENTINEL
599 "While parsing argument #1 (`-abc`): Missing required argument for option `-c`",
605 const struct bt_argpar_opt_descr descrs
[] = {
606 { 0, 'a', NULL
, false },
607 { 0, 'b', NULL
, false },
608 { 0, 'c', NULL
, true },
609 BT_ARGPAR_OPT_DESCR_SENTINEL
614 "While parsing argument #2 (`-`): Invalid argument",
620 const struct bt_argpar_opt_descr descrs
[] = {
621 { 0, 'a', NULL
, false },
622 { 0, 'b', NULL
, false },
623 { 0, 'c', NULL
, true },
624 BT_ARGPAR_OPT_DESCR_SENTINEL
629 "While parsing argument #2 (`--`): Invalid argument",
639 return exit_status();