Remove the argpar_parse() API
[argpar.git] / tests / test_argpar.c
CommitLineData
903a5b8a 1/*
fc07e526
SM
2 * Copyright (c) 2019-2021 Philippe Proulx <pproulx@efficios.com>
3 * Copyright (c) 2020-2021 Simon Marchi <simon.marchi@efficios.com>
903a5b8a
SM
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
7ac57709 19#include <assert.h>
903a5b8a 20#include <stdlib.h>
d1f7bbdb 21#include <stdio.h>
903a5b8a 22#include <string.h>
11003cd5 23#include <stdbool.h>
903a5b8a
SM
24#include <glib.h>
25
26#include "tap/tap.h"
903a5b8a
SM
27#include "argpar/argpar.h"
28
29/*
11003cd5
PP
30 * Formats `item` and appends the resulting string to `res_str` to
31 * incrementally build an expected command line string.
32 *
33 * This function:
34 *
35 * * Prefers the `--long-opt=arg` style over the `-s arg` style.
36 *
37 * * Uses the `arg<A,B>` form for non-option arguments, where `A` is the
38 * original argument index and `B` is the non-option argument index.
903a5b8a
SM
39 */
40static
11003cd5
PP
41void append_to_res_str(GString * const res_str,
42 const struct argpar_item * const item)
fc07e526
SM
43{
44 if (res_str->len > 0) {
45 g_string_append_c(res_str, ' ');
46 }
47
d4539a90 48 switch (argpar_item_type(item)) {
fc07e526
SM
49 case ARGPAR_ITEM_TYPE_OPT:
50 {
d4539a90
PP
51 const struct argpar_opt_descr * const descr =
52 argpar_item_opt_descr(item);
53 const char * const arg = argpar_item_opt_arg(item);
fc07e526 54
d4539a90 55 if (descr->long_name) {
fc07e526 56 g_string_append_printf(res_str, "--%s",
d4539a90 57 descr->long_name);
fc07e526 58
d4539a90
PP
59 if (arg) {
60 g_string_append_printf(res_str, "=%s", arg);
fc07e526 61 }
d4539a90 62 } else if (descr->short_name) {
fc07e526 63 g_string_append_printf(res_str, "-%c",
d4539a90 64 descr->short_name);
fc07e526 65
d4539a90
PP
66 if (arg) {
67 g_string_append_printf(res_str, " %s", arg);
fc07e526
SM
68 }
69 }
70
71 break;
72 }
73 case ARGPAR_ITEM_TYPE_NON_OPT:
74 {
d4539a90
PP
75 const char * const arg = argpar_item_non_opt_arg(item);
76 const unsigned int orig_index =
77 argpar_item_non_opt_orig_index(item);
78 const unsigned int non_opt_index =
79 argpar_item_non_opt_non_opt_index(item);
fc07e526 80
d4539a90
PP
81 g_string_append_printf(res_str, "%s<%u,%u>", arg, orig_index,
82 non_opt_index);
fc07e526
SM
83 break;
84 }
85 default:
86 abort();
87 }
88}
89
11003cd5 90/*
4d6198b5 91 * Parses `cmdline` with the argpar API using the option descriptors
11003cd5
PP
92 * `descrs`, and ensures that the resulting effective command line is
93 * `expected_cmd_line` and that the number of ingested original
94 * arguments is `expected_ingested_orig_args`.
95 *
96 * This function splits `cmdline` on spaces to create an original
97 * argument array.
98 *
99 * This function builds the resulting command line from parsing items
100 * by space-separating each formatted item (see append_to_res_str()).
101 */
fc07e526 102static
4d6198b5 103void test_succeed(const char * const cmdline,
11003cd5
PP
104 const char * const expected_cmd_line,
105 const struct argpar_opt_descr * const descrs,
106 const unsigned int expected_ingested_orig_args)
fc07e526
SM
107{
108 struct argpar_iter *iter = NULL;
109 const struct argpar_item *item = NULL;
110 char *error = NULL;
11003cd5
PP
111 GString * const res_str = g_string_new(NULL);
112 gchar ** const argv = g_strsplit(cmdline, " ", 0);
fc07e526
SM
113 unsigned int i, actual_ingested_orig_args;
114
115 assert(argv);
116 assert(res_str);
fc07e526
SM
117 iter = argpar_iter_create(g_strv_length(argv),
118 (const char * const *) argv, descrs);
119 assert(iter);
120
121 for (i = 0; ; i++) {
2af370d0 122 enum argpar_iter_next_status status;
fc07e526
SM
123
124 ARGPAR_ITEM_DESTROY_AND_RESET(item);
2af370d0 125 status = argpar_iter_next(iter, &item, &error);
fc07e526 126
2af370d0
PP
127 ok(status == ARGPAR_ITER_NEXT_STATUS_OK ||
128 status == ARGPAR_ITER_NEXT_STATUS_END ||
129 status == ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
130 "argpar_iter_next() returns the expected status "
11003cd5
PP
131 "(%d) for command line `%s` (call %u)",
132 status, cmdline, i + 1);
fc07e526 133
2af370d0 134 if (status == ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
11003cd5 135 ok(error,
2af370d0
PP
136 "argpar_iter_next() sets an error for "
137 "status `ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT` "
11003cd5
PP
138 "and command line `%s` (call %u)",
139 cmdline, i + 1);
fc07e526 140 } else {
11003cd5 141 ok(!error,
2af370d0 142 "argpar_iter_next() doesn't set an error "
11003cd5 143 "for other status than "
2af370d0 144 "`ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT` "
11003cd5
PP
145 "and command line `%s` (call %u)",
146 cmdline, i + 1);
903a5b8a 147 }
fc07e526 148
2af370d0
PP
149 if (status == ARGPAR_ITER_NEXT_STATUS_END ||
150 status == ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT) {
11003cd5 151 ok(!item,
2af370d0
PP
152 "argpar_iter_next() doesn't set an item "
153 "for status `ARGPAR_ITER_NEXT_STATUS_END` "
154 "or `ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT` "
11003cd5
PP
155 "and command line `%s` (call %u)",
156 cmdline, i + 1);
903a5b8a
SM
157 break;
158 }
fc07e526
SM
159
160 append_to_res_str(res_str, item);
903a5b8a
SM
161 }
162
f3ab5ca1 163 actual_ingested_orig_args = argpar_iter_ingested_orig_args(iter);
fc07e526 164 ok(actual_ingested_orig_args == expected_ingested_orig_args,
f3ab5ca1 165 "argpar_iter_ingested_orig_args() returns the expected "
11003cd5
PP
166 "number of ingested original arguments for command line `%s`",
167 cmdline);
168
fc07e526
SM
169 if (actual_ingested_orig_args != expected_ingested_orig_args) {
170 diag("Expected: %u Got: %u", expected_ingested_orig_args,
171 actual_ingested_orig_args);
903a5b8a
SM
172 }
173
174 ok(strcmp(expected_cmd_line, res_str->str) == 0,
2af370d0 175 "argpar_iter_next() returns the expected parsing items "
903a5b8a 176 "for command line `%s`", cmdline);
11003cd5 177
903a5b8a
SM
178 if (strcmp(expected_cmd_line, res_str->str) != 0) {
179 diag("Expected: `%s`", expected_cmd_line);
180 diag("Got: `%s`", res_str->str);
181 }
182
fc07e526
SM
183 argpar_item_destroy(item);
184 argpar_iter_destroy(iter);
903a5b8a
SM
185 g_string_free(res_str, TRUE);
186 g_strfreev(argv);
fc07e526
SM
187 free(error);
188}
189
903a5b8a
SM
190static
191void succeed_tests(void)
192{
193 /* No arguments */
194 {
1c9a6bde
SM
195 const struct argpar_opt_descr descrs[] = {
196 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
197 };
198
199 test_succeed(
200 "",
201 "",
202 descrs, 0);
203 }
204
205 /* Single long option */
206 {
1c9a6bde 207 const struct argpar_opt_descr descrs[] = {
903a5b8a 208 { 0, '\0', "salut", false },
1c9a6bde 209 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
210 };
211
212 test_succeed(
213 "--salut",
214 "--salut",
215 descrs, 1);
216 }
217
218 /* Single short option */
219 {
1c9a6bde 220 const struct argpar_opt_descr descrs[] = {
903a5b8a 221 { 0, 'f', NULL, false },
1c9a6bde 222 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
223 };
224
225 test_succeed(
226 "-f",
227 "-f",
228 descrs, 1);
229 }
230
231 /* Short and long option (aliases) */
232 {
1c9a6bde 233 const struct argpar_opt_descr descrs[] = {
903a5b8a 234 { 0, 'f', "flaw", false },
1c9a6bde 235 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
236 };
237
238 test_succeed(
239 "-f --flaw",
240 "--flaw --flaw",
241 descrs, 2);
242 }
243
244 /* Long option with argument (space form) */
245 {
1c9a6bde 246 const struct argpar_opt_descr descrs[] = {
903a5b8a 247 { 0, '\0', "tooth", true },
1c9a6bde 248 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
249 };
250
251 test_succeed(
252 "--tooth 67",
253 "--tooth=67",
254 descrs, 2);
255 }
256
257 /* Long option with argument (equal form) */
258 {
1c9a6bde 259 const struct argpar_opt_descr descrs[] = {
903a5b8a 260 { 0, '\0', "polish", true },
1c9a6bde 261 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
262 };
263
264 test_succeed(
265 "--polish=brick",
266 "--polish=brick",
267 descrs, 1);
268 }
269
270 /* Short option with argument (space form) */
271 {
1c9a6bde 272 const struct argpar_opt_descr descrs[] = {
903a5b8a 273 { 0, 'c', NULL, true },
1c9a6bde 274 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
275 };
276
277 test_succeed(
278 "-c chilly",
279 "-c chilly",
280 descrs, 2);
281 }
282
283 /* Short option with argument (glued form) */
284 {
1c9a6bde 285 const struct argpar_opt_descr descrs[] = {
903a5b8a 286 { 0, 'c', NULL, true },
1c9a6bde 287 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
288 };
289
290 test_succeed(
291 "-cchilly",
292 "-c chilly",
293 descrs, 1);
294 }
295
296 /* Short and long option (aliases) with argument (all forms) */
297 {
1c9a6bde 298 const struct argpar_opt_descr descrs[] = {
903a5b8a 299 { 0, 'd', "dry", true },
1c9a6bde 300 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
301 };
302
303 test_succeed(
304 "--dry=rate -dthing --dry street --dry=shape",
305 "--dry=rate --dry=thing --dry=street --dry=shape",
306 descrs, 5);
307 }
308
309 /* Many short options, last one with argument (glued form) */
310 {
1c9a6bde 311 const struct argpar_opt_descr descrs[] = {
903a5b8a
SM
312 { 0, 'd', NULL, false },
313 { 0, 'e', NULL, false },
314 { 0, 'f', NULL, true },
1c9a6bde 315 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
316 };
317
318 test_succeed(
319 "-defmeow",
320 "-d -e -f meow",
321 descrs, 1);
322 }
323
324 /* Many options */
325 {
1c9a6bde 326 const struct argpar_opt_descr descrs[] = {
903a5b8a
SM
327 { 0, 'd', NULL, false },
328 { 0, 'e', "east", true },
329 { 0, '\0', "mind", false },
1c9a6bde 330 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
331 };
332
333 test_succeed(
334 "-d --mind -destart --mind --east cough -d --east=itch",
335 "-d --mind -d --east=start --mind --east=cough -d --east=itch",
336 descrs, 8);
337 }
338
339 /* Single non-option argument */
340 {
1c9a6bde
SM
341 const struct argpar_opt_descr descrs[] = {
342 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
343 };
344
345 test_succeed(
346 "kilojoule",
347 "kilojoule<0,0>",
348 descrs, 1);
349 }
350
351 /* Two non-option arguments */
352 {
1c9a6bde
SM
353 const struct argpar_opt_descr descrs[] = {
354 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
355 };
356
357 test_succeed(
358 "kilojoule mitaine",
359 "kilojoule<0,0> mitaine<1,1>",
360 descrs, 2);
361 }
362
363 /* Single non-option argument mixed with options */
364 {
1c9a6bde 365 const struct argpar_opt_descr descrs[] = {
903a5b8a
SM
366 { 0, 'd', NULL, false },
367 { 0, '\0', "squeeze", true },
1c9a6bde 368 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
369 };
370
371 test_succeed(
372 "-d sprout yes --squeeze little bag -d",
373 "-d sprout<1,0> yes<2,1> --squeeze=little bag<5,2> -d",
374 descrs, 7);
375 }
376
377 /* Unknown short option (space form) */
378 {
1c9a6bde 379 const struct argpar_opt_descr descrs[] = {
903a5b8a 380 { 0, 'd', NULL, true },
1c9a6bde 381 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
382 };
383
384 test_succeed(
385 "-d salut -e -d meow",
386 "-d salut",
387 descrs, 2);
388 }
389
390 /* Unknown short option (glued form) */
391 {
1c9a6bde 392 const struct argpar_opt_descr descrs[] = {
903a5b8a 393 { 0, 'd', NULL, true },
1c9a6bde 394 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
395 };
396
397 test_succeed(
398 "-dsalut -e -d meow",
399 "-d salut",
400 descrs, 1);
401 }
402
403 /* Unknown long option (space form) */
404 {
1c9a6bde 405 const struct argpar_opt_descr descrs[] = {
903a5b8a 406 { 0, '\0', "sink", true },
1c9a6bde 407 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
408 };
409
410 test_succeed(
411 "--sink party --food --sink impulse",
412 "--sink=party",
413 descrs, 2);
414 }
415
416 /* Unknown long option (equal form) */
417 {
1c9a6bde 418 const struct argpar_opt_descr descrs[] = {
903a5b8a 419 { 0, '\0', "sink", true },
1c9a6bde 420 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
421 };
422
423 test_succeed(
424 "--sink=party --food --sink=impulse",
425 "--sink=party",
426 descrs, 1);
427 }
428
429 /* Unknown option before non-option argument */
430 {
1c9a6bde 431 const struct argpar_opt_descr descrs[] = {
903a5b8a 432 { 0, '\0', "thumb", true },
1c9a6bde 433 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
434 };
435
436 test_succeed(
437 "--thumb=party --food bateau --thumb waves",
438 "--thumb=party",
439 descrs, 1);
440 }
441
442 /* Unknown option after non-option argument */
443 {
1c9a6bde 444 const struct argpar_opt_descr descrs[] = {
903a5b8a 445 { 0, '\0', "thumb", true },
1c9a6bde 446 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
447 };
448
449 test_succeed(
450 "--thumb=party wound --food --thumb waves",
451 "--thumb=party wound<1,0>",
452 descrs, 2);
453 }
454
455 /* Valid `---opt` */
456 {
1c9a6bde 457 const struct argpar_opt_descr descrs[] = {
903a5b8a 458 { 0, '\0', "-fuel", true },
1c9a6bde 459 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
460 };
461
462 test_succeed(
463 "---fuel=three",
464 "---fuel=three",
465 descrs, 1);
466 }
467
468 /* Long option containing `=` in argument (equal form) */
469 {
1c9a6bde 470 const struct argpar_opt_descr descrs[] = {
903a5b8a 471 { 0, '\0', "zebra", true },
1c9a6bde 472 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
473 };
474
475 test_succeed(
476 "--zebra=three=yes",
477 "--zebra=three=yes",
478 descrs, 1);
479 }
480
481 /* Short option's argument starting with `-` (glued form) */
482 {
1c9a6bde 483 const struct argpar_opt_descr descrs[] = {
903a5b8a 484 { 0, 'z', NULL, true },
1c9a6bde 485 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
486 };
487
488 test_succeed(
489 "-z-will",
490 "-z -will",
491 descrs, 1);
492 }
493
494 /* Short option's argument starting with `-` (space form) */
495 {
1c9a6bde 496 const struct argpar_opt_descr descrs[] = {
903a5b8a 497 { 0, 'z', NULL, true },
1c9a6bde 498 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
499 };
500
501 test_succeed(
502 "-z -will",
503 "-z -will",
504 descrs, 2);
505 }
506
507 /* Long option's argument starting with `-` (space form) */
508 {
1c9a6bde 509 const struct argpar_opt_descr descrs[] = {
903a5b8a 510 { 0, '\0', "janine", true },
1c9a6bde 511 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
512 };
513
514 test_succeed(
515 "--janine -sutto",
516 "--janine=-sutto",
517 descrs, 2);
518 }
519
520 /* Long option's argument starting with `-` (equal form) */
521 {
1c9a6bde 522 const struct argpar_opt_descr descrs[] = {
903a5b8a 523 { 0, '\0', "janine", true },
1c9a6bde 524 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
525 };
526
527 test_succeed(
528 "--janine=-sutto",
529 "--janine=-sutto",
530 descrs, 1);
531 }
532
533 /* Long option's empty argument (equal form) */
534 {
1c9a6bde 535 const struct argpar_opt_descr descrs[] = {
903a5b8a
SM
536 { 0, 'f', NULL, false },
537 { 0, '\0', "yeah", true },
1c9a6bde 538 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
539 };
540
541 test_succeed(
542 "-f --yeah= -f",
543 "-f --yeah= -f",
544 descrs, 3);
545 }
dd757a65
PP
546
547 /* `-` non-option argument */
548 {
549 const struct argpar_opt_descr descrs[] = {
550 { 0, 'f', NULL, false },
551 ARGPAR_OPT_DESCR_SENTINEL
552 };
553
554 test_succeed(
555 "-f - -f",
556 "-f -<1,0> -f",
557 descrs, 3);
558 }
559
560 /* `--` non-option argument */
561 {
562 const struct argpar_opt_descr descrs[] = {
563 { 0, 'f', NULL, false },
564 ARGPAR_OPT_DESCR_SENTINEL
565 };
566
567 test_succeed(
568 "-f -- -f",
569 "-f --<1,0> -f",
570 descrs, 3);
571 }
d1f7bbdb
PP
572
573 /* Very long name of long option */
574 {
575 const char opt_name[] =
576 "kale-chips-waistcoat-yr-bicycle-rights-gochujang-"
577 "woke-tumeric-flexitarian-biodiesel-chillwave-cliche-"
578 "ethical-cardigan-listicle-pok-pok-sustainable-live-"
579 "edge-jianbing-gochujang-butcher-disrupt-tattooed-"
580 "tumeric-prism-photo-booth-vape-kogi-jean-shorts-"
581 "blog-williamsburg-fingerstache-palo-santo-artisan-"
582 "affogato-occupy-skateboard-adaptogen-neutra-celiac-"
583 "put-a-bird-on-it-kombucha-everyday-carry-hot-chicken-"
584 "craft-beer-subway-tile-tote-bag-disrupt-selvage-"
585 "raclette-art-party-readymade-paleo-heirloom-trust-"
586 "fund-small-batch-kinfolk-woke-cardigan-prism-"
587 "chambray-la-croix-hashtag-unicorn-edison-bulb-tbh-"
588 "cornhole-cliche-tattooed-green-juice-adaptogen-"
589 "kitsch-lo-fi-vexillologist-migas-gentrify-"
590 "viral-raw-denim";
591 const struct argpar_opt_descr descrs[] = {
592 { 0, '\0', opt_name, true },
593 ARGPAR_OPT_DESCR_SENTINEL
594 };
595 char cmdline[1024];
596
597 sprintf(cmdline, "--%s=23", opt_name);
598 test_succeed(cmdline, cmdline, descrs, 1);
599 }
903a5b8a
SM
600}
601
11003cd5 602/*
4d6198b5 603 * Parses `cmdline` with the argpar API using the option descriptors
2af370d0 604 * `descrs`, and ensures that argpar_iter_next() fails with status
d4d05805
PP
605 * `expected_status` and that it sets an error which is equal to
606 * `expected_error`.
11003cd5
PP
607 *
608 * This function splits `cmdline` on spaces to create an original
609 * argument array.
610 */
fc07e526 611static
4d6198b5 612void test_fail(const char * const cmdline, const char * const expected_error,
2af370d0 613 const enum argpar_iter_next_status expected_status,
11003cd5 614 const struct argpar_opt_descr * const descrs)
fc07e526
SM
615{
616 struct argpar_iter *iter = NULL;
617 const struct argpar_item *item = NULL;
11003cd5 618 gchar ** const argv = g_strsplit(cmdline, " ", 0);
fc07e526
SM
619 unsigned int i;
620 char *error = NULL;
621
622 iter = argpar_iter_create(g_strv_length(argv),
623 (const char * const *) argv, descrs);
624 assert(iter);
625
626 for (i = 0; ; i++) {
2af370d0 627 enum argpar_iter_next_status status;
fc07e526
SM
628
629 ARGPAR_ITEM_DESTROY_AND_RESET(item);
2af370d0
PP
630 status = argpar_iter_next(iter, &item, &error);
631 ok(status == ARGPAR_ITER_NEXT_STATUS_OK ||
d4d05805 632 status == expected_status,
2af370d0 633 "argpar_iter_next() returns the expected status "
11003cd5
PP
634 "(%d) for command line `%s` (call %u)",
635 status, cmdline, i + 1);
fc07e526 636
2af370d0 637 if (status != ARGPAR_ITER_NEXT_STATUS_OK) {
11003cd5 638 ok(!item,
2af370d0 639 "argpar_iter_next() doesn't set an item "
11003cd5 640 "for other status than "
2af370d0 641 "`ARGPAR_ITER_NEXT_STATUS_OK` "
11003cd5
PP
642 "and command line `%s` (call %u)",
643 cmdline, i + 1);
644 ok(error,
2af370d0 645 "argpar_iter_next() sets an error for "
11003cd5 646 "other status than "
2af370d0 647 " `ARGPAR_ITER_NEXT_STATUS_OK` "
11003cd5
PP
648 "and command line `%s` (call %u)",
649 cmdline, i + 1);
fc07e526
SM
650 break;
651 }
652
11003cd5 653 ok(item,
2af370d0
PP
654 "argpar_iter_next() sets an item for status "
655 "`ARGPAR_ITER_NEXT_STATUS_OK` "
11003cd5
PP
656 "and command line `%s` (call %u)",
657 cmdline, i + 1);
658 ok(!error,
2af370d0
PP
659 "argpar_iter_next() doesn't set an error for status "
660 "`ARGPAR_ITER_NEXT_STATUS_OK` "
11003cd5
PP
661 "and command line `%s` (call %u)",
662 cmdline, i + 1);
fc07e526
SM
663 }
664
665 ok(strcmp(expected_error, error) == 0,
2af370d0 666 "argpar_iter_next() sets the expected error string "
fc07e526 667 "for command line `%s`", cmdline);
11003cd5 668
fc07e526
SM
669 if (strcmp(expected_error, error) != 0) {
670 diag("Expected: `%s`", expected_error);
671 diag("Got: `%s`", error);
672 }
673
674 argpar_item_destroy(item);
675 argpar_iter_destroy(iter);
676 free(error);
677 g_strfreev(argv);
678}
679
903a5b8a
SM
680static
681void fail_tests(void)
682{
683 /* Unknown long option */
684 {
1c9a6bde 685 const struct argpar_opt_descr descrs[] = {
903a5b8a 686 { 0, '\0', "thumb", true },
1c9a6bde 687 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
688 };
689
690 test_fail(
691 "--thumb=party --meow",
692 "While parsing argument #2 (`--meow`): Unknown option `--meow`",
2af370d0 693 ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
903a5b8a
SM
694 descrs);
695 }
696
697 /* Unknown short option */
698 {
1c9a6bde 699 const struct argpar_opt_descr descrs[] = {
903a5b8a 700 { 0, '\0', "thumb", true },
1c9a6bde 701 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
702 };
703
704 test_fail(
705 "--thumb=party -x",
706 "While parsing argument #2 (`-x`): Unknown option `-x`",
2af370d0 707 ARGPAR_ITER_NEXT_STATUS_ERROR_UNKNOWN_OPT,
903a5b8a
SM
708 descrs);
709 }
710
711 /* Missing long option argument */
712 {
1c9a6bde 713 const struct argpar_opt_descr descrs[] = {
903a5b8a 714 { 0, '\0', "thumb", true },
1c9a6bde 715 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
716 };
717
718 test_fail(
719 "--thumb",
720 "While parsing argument #1 (`--thumb`): Missing required argument for option `--thumb`",
2af370d0 721 ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG,
903a5b8a
SM
722 descrs);
723 }
724
725 /* Missing short option argument */
726 {
1c9a6bde 727 const struct argpar_opt_descr descrs[] = {
903a5b8a 728 { 0, 'k', NULL, true },
1c9a6bde 729 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
730 };
731
732 test_fail(
733 "-k",
734 "While parsing argument #1 (`-k`): Missing required argument for option `-k`",
2af370d0 735 ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG,
903a5b8a
SM
736 descrs);
737 }
738
739 /* Missing short option argument (multiple glued) */
740 {
1c9a6bde 741 const struct argpar_opt_descr descrs[] = {
903a5b8a
SM
742 { 0, 'a', NULL, false },
743 { 0, 'b', NULL, false },
744 { 0, 'c', NULL, true },
1c9a6bde 745 ARGPAR_OPT_DESCR_SENTINEL
903a5b8a
SM
746 };
747
748 test_fail(
749 "-abc",
750 "While parsing argument #1 (`-abc`): Missing required argument for option `-c`",
2af370d0 751 ARGPAR_ITER_NEXT_STATUS_ERROR_MISSING_OPT_ARG,
903a5b8a
SM
752 descrs);
753 }
754
dd757a65 755 /* Unexpected long option argument */
430fe886
SM
756 {
757 const struct argpar_opt_descr descrs[] = {
758 { 0, 'c', "chevre", false },
759 ARGPAR_OPT_DESCR_SENTINEL
760 };
761
762 test_fail(
763 "--chevre=fromage",
764 "While parsing argument #1 (`--chevre=fromage`): Unexpected argument for option `--chevre`",
2af370d0 765 ARGPAR_ITER_NEXT_STATUS_ERROR_UNEXPECTED_OPT_ARG,
430fe886
SM
766 descrs);
767 }
903a5b8a
SM
768}
769
770int main(void)
771{
4d6198b5 772 plan_tests(296);
903a5b8a
SM
773 succeed_tests();
774 fail_tests();
775 return exit_status();
776}
This page took 0.056457 seconds and 4 git commands to generate.