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