Raw
1 #!/bin/sh
2 #
3 # Copyright (c) 2007 Johannes Schindelin
4 #
5
6 test_description='our own option parser'
7
8 . ./test-lib.sh
9
10 cat >expect-part1 <<\EOF
11 usage: test-tool parse-options <options>
12
13 A helper function for the parse-options API.
14
15 --[no-]yes get a boolean
16 -D, --no-doubt begins with 'no-'
17 --doubt opposite of --no-doubt
18 -B, --no-fear be brave
19 -b, --[no-]boolean increment by one
20 -4, --[no-]or4 bitwise-or boolean with ...0100
21 --[no-]neg-or4 same as --no-or4
22
23 -i, --[no-]integer <n>
24 get a integer
25 --[no-]i16 <n> get a 16 bit integer
26 -j <n> get a integer, too
27 -u, --unsigned <n> get an unsigned integer
28 --u16 <n> get a 16 bit unsigned integer
29 --[no-]set23 set integer to 23
30 --mode1 set integer to 1 (cmdmode option)
31 --mode2 set integer to 2 (cmdmode option)
32 --[no-]mode34 (3|4) set integer to 3 or 4 (cmdmode option)
33 -L, --[no-]length <str>
34 get length of <str>
35 -F, --[no-]file <file>
36 set file to <file>
37
38 String options
39 -s, --[no-]string <string>
40 get a string
41 --[no-]string2 <str> get another string
42 --[no-]st <st> get another string (pervert ordering)
43 -o <str> get another string
44 EOF
45
46 cat >expect-part2 <<\EOF
47 --longhelp help text of this entry
48 spans multiple lines
49 --[no-]list <str> add str to list
50
51 Magic arguments
52 -NUM set integer to NUM
53 + same as -b
54 --ambiguous positive ambiguity
55 --no-ambiguous negative ambiguity
56
57 Standard options
58 --[no-]abbrev[=<n>] use <n> digits to display object names
59 -v, --[no-]verbose be verbose
60 -n, --[no-]dry-run dry run
61 -q, --[no-]quiet be quiet
62 --[no-]expect <string>
63 expected output in the variable dump
64
65 Alias
66 -A, --[no-]alias-source <string>
67 get a string
68 -Z, --[no-]alias-target <string>
69 alias of --alias-source
70
71 EOF
72
73 cat >expect-noop <<\EOF
74 --[no-]obsolete no-op (backward compatibility)
75 EOF
76
77 cat >expect-hidden <<\EOF
78 Hidden options
79 --[no-]hidden-bool get a boolean
80 -k, --[no-]hidden-integer <n>
81 get a integer
82
83 EOF
84
85 test_expect_success 'test help' '
86 cat expect-part1 expect-part2 >expect &&
87 test-tool parse-options -h >output 2>output.err &&
88 test_must_be_empty output.err &&
89 test_cmp expect output
90 '
91
92 test_expect_success 'test --help-all shows hidden group and options' '
93 cat expect-part1 expect-noop expect-part2 expect-hidden >expect-help-all &&
94 test-tool parse-options --help-all >output 2>output.err &&
95 test_must_be_empty output.err &&
96 test_cmp expect-help-all output
97 '
98
99 mv expect expect.err
100
101 check () {
102 what="$1" &&
103 shift &&
104 expect="$1" &&
105 shift &&
106 test-tool parse-options --expect="$what $expect" "$@"
107 }
108
109 check_unknown_i18n() {
110 case "$1" in
111 --*)
112 echo error: unknown option \`${1#--}\' >expect ;;
113 -*)
114 echo error: unknown switch \`${1#-}\' >expect ;;
115 esac &&
116 cat expect.err >>expect &&
117 test_must_fail test-tool parse-options $* >output 2>output.err &&
118 test_must_be_empty output &&
119 test_cmp expect output.err
120 }
121
122 test_expect_success 'OPT_BOOL() #1' 'check boolean: 1 --yes'
123 test_expect_success 'OPT_BOOL() #2' 'check boolean: 1 --no-doubt'
124 test_expect_success 'OPT_BOOL() #3' 'check boolean: 1 -D'
125 test_expect_success 'OPT_BOOL() #4' 'check boolean: 1 --no-fear'
126 test_expect_success 'OPT_BOOL() #5' 'check boolean: 1 -B'
127
128 test_expect_success 'OPT_BOOL() is idempotent #1' 'check boolean: 1 --yes --yes'
129 test_expect_success 'OPT_BOOL() is idempotent #2' 'check boolean: 1 -DB'
130
131 test_expect_success 'OPT_BOOL() negation #1' 'check boolean: 0 -D --no-yes'
132 test_expect_success 'OPT_BOOL() negation #2' 'check boolean: 0 -D --no-no-doubt'
133
134 test_expect_success 'OPT_BOOL() no negation #1' 'check_unknown_i18n --fear'
135 test_expect_success 'OPT_BOOL() no negation #2' 'check_unknown_i18n --no-no-fear'
136
137 test_expect_success 'OPT_BOOL() positivation' 'check boolean: 0 -D --doubt'
138
139 test_expect_success 'OPT_INTEGER() negative' 'check integer: -2345 -i -2345'
140 test_expect_success 'OPT_INTEGER() kilo' 'check integer: 239616 -i 234k'
141 test_expect_success 'OPT_INTEGER() negative kilo' 'check integer: -239616 -i -234k'
142
143 test_expect_success 'OPT_UNSIGNED() simple' '
144 check unsigned: 2345678 -u 2345678
145 '
146
147 test_expect_success 'OPT_UNSIGNED() kilo' '
148 check unsigned: 239616 -u 234k
149 '
150
151 test_expect_success 'OPT_UNSIGNED() mega' '
152 check unsigned: 104857600 -u 100m
153 '
154
155 test_expect_success 'OPT_UNSIGNED() giga' '
156 check unsigned: 1073741824 -u 1g
157 '
158
159 test_expect_success 'OPT_UNSIGNED() 3giga' '
160 check unsigned: 3221225472 -u 3g
161 '
162
163 cat >expect <<\EOF
164 boolean: 2
165 integer: 1729
166 i16: 0
167 unsigned: 16384
168 u16: 0
169 timestamp: 0
170 string: 123
171 abbrev: 7
172 verbose: 2
173 quiet: 0
174 dry run: yes
175 file: prefix/my.file
176 EOF
177
178 test_expect_success 'short options' '
179 test-tool parse-options -s123 -b -i 1729 -u 16k -b -vv -n -F my.file \
180 >output 2>output.err &&
181 test_cmp expect output &&
182 test_must_be_empty output.err
183 '
184
185 cat >expect <<\EOF
186 boolean: 2
187 integer: 1729
188 i16: 9000
189 unsigned: 16384
190 u16: 32768
191 timestamp: 0
192 string: 321
193 abbrev: 10
194 verbose: 2
195 quiet: 0
196 dry run: no
197 file: prefix/fi.le
198 EOF
199
200 test_expect_success 'long options' '
201 test-tool parse-options --boolean --integer 1729 --i16 9000 --unsigned 16k \
202 --u16 32k --boolean --string2=321 --verbose --verbose --no-dry-run \
203 --abbrev=10 --file fi.le --obsolete \
204 >output 2>output.err &&
205 test_must_be_empty output.err &&
206 test_cmp expect output
207 '
208
209 test_expect_success 'abbreviate to something longer than SHA1 length' '
210 cat >expect <<-EOF &&
211 boolean: 0
212 integer: 0
213 i16: 0
214 unsigned: 0
215 u16: 0
216 timestamp: 0
217 string: (not set)
218 abbrev: 100
219 verbose: -1
220 quiet: 0
221 dry run: no
222 file: (not set)
223 EOF
224 test-tool parse-options --abbrev=100 >output &&
225 test_cmp expect output
226 '
227
228 test_expect_success 'missing required value' '
229 cat >expect <<-\EOF &&
230 error: switch `s'\'' requires a value
231 EOF
232 test_expect_code 129 test-tool parse-options -s 2>actual &&
233 test_cmp expect actual &&
234
235 cat >expect <<-\EOF &&
236 error: option `string'\'' requires a value
237 EOF
238 test_expect_code 129 test-tool parse-options --string 2>actual &&
239 test_cmp expect actual &&
240
241 cat >expect <<-\EOF &&
242 error: option `file'\'' requires a value
243 EOF
244 test_expect_code 129 test-tool parse-options --file 2>actual &&
245 test_cmp expect actual
246 '
247
248 test_expect_success 'superfluous value provided: boolean' '
249 cat >expect <<-\EOF &&
250 error: option `yes'\'' takes no value
251 EOF
252 test_expect_code 129 test-tool parse-options --yes=hi 2>actual &&
253 test_cmp expect actual &&
254
255 cat >expect <<-\EOF &&
256 error: option `no-yes'\'' takes no value
257 EOF
258 test_expect_code 129 test-tool parse-options --no-yes=hi 2>actual &&
259 test_cmp expect actual
260 '
261
262 test_expect_success 'superfluous value provided: boolean, abbreviated' '
263 cat >expect <<-\EOF &&
264 error: option `yes'\'' takes no value
265 EOF
266 test_expect_code 129 env GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \
267 test-tool parse-options --ye=hi 2>actual &&
268 test_cmp expect actual &&
269
270 cat >expect <<-\EOF &&
271 error: option `no-yes'\'' takes no value
272 EOF
273 test_expect_code 129 env GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \
274 test-tool parse-options --no-ye=hi 2>actual &&
275 test_cmp expect actual
276 '
277
278 test_expect_success 'superfluous value provided: cmdmode' '
279 cat >expect <<-\EOF &&
280 error: option `mode1'\'' takes no value
281 EOF
282 test_expect_code 129 test-tool parse-options --mode1=hi 2>actual &&
283 test_cmp expect actual
284 '
285
286 cat >expect <<\EOF
287 boolean: 1
288 integer: 13
289 i16: 0
290 unsigned: 0
291 u16: 0
292 timestamp: 0
293 string: 123
294 abbrev: 7
295 verbose: -1
296 quiet: 0
297 dry run: no
298 file: (not set)
299 arg 00: a1
300 arg 01: b1
301 arg 02: --boolean
302 EOF
303
304 test_expect_success 'intermingled arguments' '
305 test-tool parse-options a1 --string 123 b1 --boolean -j 13 -- --boolean \
306 >output 2>output.err &&
307 test_must_be_empty output.err &&
308 test_cmp expect output
309 '
310
311 cat >expect <<\EOF
312 boolean: 0
313 integer: 2
314 i16: 0
315 unsigned: 0
316 u16: 0
317 timestamp: 0
318 string: (not set)
319 abbrev: 7
320 verbose: -1
321 quiet: 0
322 dry run: no
323 file: (not set)
324 EOF
325
326 test_expect_success 'unambiguously abbreviated option' '
327 GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \
328 test-tool parse-options --int 2 --boolean --no-bo >output 2>output.err &&
329 test_must_be_empty output.err &&
330 test_cmp expect output
331 '
332
333 test_expect_success 'unambiguously abbreviated option with "="' '
334 GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \
335 test-tool parse-options --expect="integer: 2" --int=2
336 '
337
338 test_expect_success 'ambiguously abbreviated option' '
339 test_expect_code 129 env GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \
340 test-tool parse-options --strin 123
341 '
342
343 test_expect_success 'non ambiguous option (after two options it abbreviates)' '
344 GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \
345 test-tool parse-options --expect="string: 123" --st 123
346 '
347
348 test_expect_success 'Alias options do not contribute to abbreviation' '
349 test-tool parse-options --alias-source 123 >output &&
350 test_grep "^string: 123" output &&
351 test-tool parse-options --alias-target 123 >output &&
352 test_grep "^string: 123" output &&
353 test_must_fail test-tool parse-options --alias &&
354 GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \
355 test-tool parse-options --alias 123 >output &&
356 test_grep "^string: 123" output
357 '
358
359 cat >typo.err <<\EOF
360 error: did you mean `--boolean` (with two dashes)?
361 EOF
362
363 test_expect_success 'detect possible typos' '
364 test_must_fail test-tool parse-options -boolean >output 2>output.err &&
365 test_must_be_empty output &&
366 test_cmp typo.err output.err
367 '
368
369 cat >typo.err <<\EOF
370 error: did you mean `--ambiguous` (with two dashes)?
371 EOF
372
373 test_expect_success 'detect possible typos' '
374 test_must_fail test-tool parse-options -ambiguous >output 2>output.err &&
375 test_must_be_empty output &&
376 test_cmp typo.err output.err
377 '
378
379 cat >expect <<\EOF
380 Callback: "four", 0
381 boolean: 5
382 integer: 4
383 i16: 0
384 unsigned: 0
385 u16: 0
386 timestamp: 0
387 string: (not set)
388 abbrev: 7
389 verbose: -1
390 quiet: 0
391 dry run: no
392 file: (not set)
393 EOF
394
395 test_expect_success 'OPT_CALLBACK() and OPT_BIT() work' '
396 test-tool parse-options --length=four -b -4 >output 2>output.err &&
397 test_must_be_empty output.err &&
398 test_cmp expect output
399 '
400
401 test_expect_success 'OPT_CALLBACK() and callback errors work' '
402 test_must_fail test-tool parse-options --no-length >output 2>output.err &&
403 test_must_be_empty output &&
404 test_must_be_empty output.err
405 '
406
407 cat >expect <<\EOF
408 boolean: 1
409 integer: 23
410 i16: 0
411 unsigned: 0
412 u16: 0
413 timestamp: 0
414 string: (not set)
415 abbrev: 7
416 verbose: -1
417 quiet: 0
418 dry run: no
419 file: (not set)
420 EOF
421
422 test_expect_success 'OPT_BIT() and OPT_SET_INT() work' '
423 test-tool parse-options --set23 -bbbbb --no-or4 >output 2>output.err &&
424 test_must_be_empty output.err &&
425 test_cmp expect output
426 '
427
428 test_expect_success 'OPT_NEGBIT() and OPT_SET_INT() work' '
429 test-tool parse-options --set23 -bbbbb --neg-or4 >output 2>output.err &&
430 test_must_be_empty output.err &&
431 test_cmp expect output
432 '
433
434 test_expect_success 'OPT_BIT() works' '
435 test-tool parse-options --expect="boolean: 6" -bb --or4
436 '
437
438 test_expect_success 'OPT_NEGBIT() works' '
439 test-tool parse-options --expect="boolean: 6" -bb --no-neg-or4
440 '
441
442 test_expect_success 'OPT_CMDMODE() works' '
443 test-tool parse-options --expect="integer: 1" --mode1 &&
444 test-tool parse-options --expect="integer: 3" --mode34=3
445 '
446
447 test_expect_success 'OPT_CMDMODE() detects incompatibility (1)' '
448 test_must_fail test-tool parse-options --mode1 --mode2 >output 2>output.err &&
449 test_must_be_empty output &&
450 test_grep "mode1" output.err &&
451 test_grep "mode2" output.err &&
452 test_grep "cannot be used together" output.err
453 '
454
455 test_expect_success 'OPT_CMDMODE() detects incompatibility (2)' '
456 test_must_fail test-tool parse-options --set23 --mode2 >output 2>output.err &&
457 test_must_be_empty output &&
458 test_grep "mode2" output.err &&
459 test_grep "set23" output.err &&
460 test_grep "cannot be used together" output.err
461 '
462
463 test_expect_success 'OPT_CMDMODE() detects incompatibility (3)' '
464 test_must_fail test-tool parse-options --mode2 --set23 >output 2>output.err &&
465 test_must_be_empty output &&
466 test_grep "mode2" output.err &&
467 test_grep "set23" output.err &&
468 test_grep "cannot be used together" output.err
469 '
470
471 test_expect_success 'OPT_CMDMODE() detects incompatibility (4)' '
472 test_must_fail test-tool parse-options --mode2 --mode34=3 \
473 >output 2>output.err &&
474 test_must_be_empty output &&
475 test_grep "mode2" output.err &&
476 test_grep "mode34.3" output.err &&
477 test_grep "cannot be used together" output.err
478 '
479
480 test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' '
481 test-tool parse-options --expect="boolean: 6" + + + + + +
482 '
483
484 test_expect_success 'OPT_NUMBER_CALLBACK() works' '
485 test-tool parse-options --expect="integer: 12345" -12345
486 '
487
488 cat >expect <<\EOF
489 boolean: 0
490 integer: 0
491 i16: 0
492 unsigned: 0
493 u16: 0
494 timestamp: 0
495 string: (not set)
496 abbrev: 7
497 verbose: -1
498 quiet: 0
499 dry run: no
500 file: (not set)
501 EOF
502
503 test_expect_success 'negation of OPT_NONEG flags is not ambiguous' '
504 GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \
505 test-tool parse-options --no-ambig >output 2>output.err &&
506 test_must_be_empty output.err &&
507 test_cmp expect output
508 '
509
510 cat >>expect <<\EOF
511 list: foo
512 list: bar
513 list: baz
514 EOF
515 test_expect_success '--list keeps list of strings' '
516 test-tool parse-options --list foo --list=bar --list=baz >output &&
517 test_cmp expect output
518 '
519
520 test_expect_success '--no-list resets list' '
521 test-tool parse-options --list=other --list=irrelevant --list=options \
522 --no-list --list=foo --list=bar --list=baz >output &&
523 test_cmp expect output
524 '
525
526 test_expect_success 'multiple quiet levels' '
527 test-tool parse-options --expect="quiet: 3" -q -q -q
528 '
529
530 test_expect_success 'multiple verbose levels' '
531 test-tool parse-options --expect="verbose: 3" -v -v -v
532 '
533
534 test_expect_success '--no-quiet sets --quiet to 0' '
535 test-tool parse-options --expect="quiet: 0" --no-quiet
536 '
537
538 test_expect_success '--no-quiet resets multiple -q to 0' '
539 test-tool parse-options --expect="quiet: 0" -q -q -q --no-quiet
540 '
541
542 test_expect_success '--no-verbose sets verbose to 0' '
543 test-tool parse-options --expect="verbose: 0" --no-verbose
544 '
545
546 test_expect_success '--no-verbose resets multiple verbose to 0' '
547 test-tool parse-options --expect="verbose: 0" -v -v -v --no-verbose
548 '
549
550 test_expect_success 'GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS works' '
551 GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \
552 test-tool parse-options --ye &&
553 test_must_fail env GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=true \
554 test-tool parse-options --ye
555 '
556
557 test_expect_success '--end-of-options treats remainder as args' '
558 test-tool parse-options \
559 --expect="verbose: -1" \
560 --expect="arg 00: --verbose" \
561 --end-of-options --verbose
562 '
563
564 test_expect_success 'KEEP_DASHDASH works' '
565 test-tool parse-options-flags --keep-dashdash cmd --opt=1 -- --opt=2 --unknown >actual &&
566 cat >expect <<-\EOF &&
567 opt: 1
568 arg 00: --
569 arg 01: --opt=2
570 arg 02: --unknown
571 EOF
572 test_cmp expect actual
573 '
574
575 test_expect_success 'KEEP_ARGV0 works' '
576 test-tool parse-options-flags --keep-argv0 cmd arg0 --opt=3 >actual &&
577 cat >expect <<-\EOF &&
578 opt: 3
579 arg 00: cmd
580 arg 01: arg0
581 EOF
582 test_cmp expect actual
583 '
584
585 test_expect_success 'STOP_AT_NON_OPTION works' '
586 test-tool parse-options-flags --stop-at-non-option cmd --opt=4 arg0 --opt=5 --unknown >actual &&
587 cat >expect <<-\EOF &&
588 opt: 4
589 arg 00: arg0
590 arg 01: --opt=5
591 arg 02: --unknown
592 EOF
593 test_cmp expect actual
594 '
595
596 test_expect_success 'KEEP_UNKNOWN_OPT works' '
597 test-tool parse-options-flags --keep-unknown-opt cmd --unknown=1 --opt=6 -u2 >actual &&
598 cat >expect <<-\EOF &&
599 opt: 6
600 arg 00: --unknown=1
601 arg 01: -u2
602 EOF
603 test_cmp expect actual
604 '
605
606 test_expect_success 'NO_INTERNAL_HELP works for -h' '
607 test_expect_code 129 test-tool parse-options-flags --no-internal-help cmd -h 2>err &&
608 test_grep "^error: unknown switch \`h$SQ" err &&
609 test_grep "^usage: " err
610 '
611
612 for help_opt in help help-all
613 do
614 test_expect_success "NO_INTERNAL_HELP works for --$help_opt" "
615 test_expect_code 129 test-tool parse-options-flags --no-internal-help cmd --$help_opt 2>err &&
616 test_grep '^error: unknown option \`'$help_opt\' err &&
617 test_grep '^usage: ' err
618 "
619 done
620
621 test_expect_success 'KEEP_UNKNOWN_OPT | NO_INTERNAL_HELP works' '
622 test-tool parse-options-flags --keep-unknown-opt --no-internal-help cmd -h --help --help-all >actual &&
623 cat >expect <<-\EOF &&
624 opt: 0
625 arg 00: -h
626 arg 01: --help
627 arg 02: --help-all
628 EOF
629 test_cmp expect actual
630 '
631
632 test_expect_success 'subcommand - no subcommand shows error and usage' '
633 test_expect_code 129 test-tool parse-subcommand cmd 2>err &&
634 test_grep "^error: need a subcommand" err &&
635 test_grep ^usage: err
636 '
637
638 test_expect_success 'subcommand - subcommand after -- shows error and usage' '
639 test_expect_code 129 test-tool parse-subcommand cmd -- subcmd-one 2>err &&
640 test_grep "^error: need a subcommand" err &&
641 test_grep ^usage: err
642 '
643
644 test_expect_success 'subcommand - subcommand after --end-of-options shows error and usage' '
645 test_expect_code 129 test-tool parse-subcommand cmd --end-of-options subcmd-one 2>err &&
646 test_grep "^error: need a subcommand" err &&
647 test_grep ^usage: err
648 '
649
650 test_expect_success 'subcommand - unknown subcommand shows error and usage' '
651 test_expect_code 129 test-tool parse-subcommand cmd nope 2>err &&
652 test_grep "^error: unknown subcommand: \`nope$SQ" err &&
653 test_grep ^usage: err
654 '
655
656 test_expect_success 'subcommand - subcommands cannot be abbreviated' '
657 test_expect_code 129 test-tool parse-subcommand cmd subcmd-o 2>err &&
658 test_grep "^error: unknown subcommand: \`subcmd-o$SQ$" err &&
659 test_grep ^usage: err
660 '
661
662 test_expect_success 'subcommand - no negated subcommands' '
663 test_expect_code 129 test-tool parse-subcommand cmd no-subcmd-one 2>err &&
664 test_grep "^error: unknown subcommand: \`no-subcmd-one$SQ" err &&
665 test_grep ^usage: err
666 '
667
668 test_expect_success 'subcommand - simple' '
669 test-tool parse-subcommand cmd subcmd-two >actual &&
670 cat >expect <<-\EOF &&
671 opt: 0
672 fn: subcmd_two
673 arg 00: subcmd-two
674 EOF
675 test_cmp expect actual
676 '
677
678 test_expect_success 'subcommand - stop parsing at the first subcommand' '
679 test-tool parse-subcommand cmd --opt=1 subcmd-two subcmd-one --opt=2 >actual &&
680 cat >expect <<-\EOF &&
681 opt: 1
682 fn: subcmd_two
683 arg 00: subcmd-two
684 arg 01: subcmd-one
685 arg 02: --opt=2
686 EOF
687 test_cmp expect actual
688 '
689
690 test_expect_success 'subcommand - KEEP_ARGV0' '
691 test-tool parse-subcommand --keep-argv0 cmd subcmd-two >actual &&
692 cat >expect <<-\EOF &&
693 opt: 0
694 fn: subcmd_two
695 arg 00: cmd
696 arg 01: subcmd-two
697 EOF
698 test_cmp expect actual
699 '
700
701 test_expect_success 'subcommand - SUBCOMMAND_OPTIONAL + subcommand not given' '
702 test-tool parse-subcommand --subcommand-optional cmd >actual &&
703 cat >expect <<-\EOF &&
704 opt: 0
705 fn: subcmd_one
706 EOF
707 test_cmp expect actual
708 '
709
710 test_expect_success 'subcommand - SUBCOMMAND_OPTIONAL + given subcommand' '
711 test-tool parse-subcommand --subcommand-optional cmd subcmd-two branch file >actual &&
712 cat >expect <<-\EOF &&
713 opt: 0
714 fn: subcmd_two
715 arg 00: subcmd-two
716 arg 01: branch
717 arg 02: file
718 EOF
719 test_cmp expect actual
720 '
721
722 test_expect_success 'subcommand - SUBCOMMAND_OPTIONAL + subcommand not given + unknown dashless args' '
723 test-tool parse-subcommand --subcommand-optional cmd branch file >actual &&
724 cat >expect <<-\EOF &&
725 opt: 0
726 fn: subcmd_one
727 arg 00: branch
728 arg 01: file
729 EOF
730 test_cmp expect actual
731 '
732
733 test_expect_success 'subcommand - SUBCOMMAND_OPTIONAL + subcommand not given + unknown option' '
734 test_expect_code 129 test-tool parse-subcommand --subcommand-optional cmd --subcommand-opt 2>err &&
735 test_grep "^error: unknown option" err &&
736 test_grep ^usage: err
737 '
738
739 test_expect_success 'subcommand - SUBCOMMAND_OPTIONAL | KEEP_UNKNOWN_OPT + subcommand not given + unknown option' '
740 test-tool parse-subcommand --subcommand-optional --keep-unknown-opt cmd --subcommand-opt >actual &&
741 cat >expect <<-\EOF &&
742 opt: 0
743 fn: subcmd_one
744 arg 00: --subcommand-opt
745 EOF
746 test_cmp expect actual
747 '
748
749 test_expect_success 'subcommand - SUBCOMMAND_OPTIONAL | KEEP_UNKNOWN_OPT + subcommand ignored after unknown option' '
750 test-tool parse-subcommand --subcommand-optional --keep-unknown-opt cmd --subcommand-opt subcmd-two >actual &&
751 cat >expect <<-\EOF &&
752 opt: 0
753 fn: subcmd_one
754 arg 00: --subcommand-opt
755 arg 01: subcmd-two
756 EOF
757 test_cmp expect actual
758 '
759
760 test_expect_success 'subcommand - SUBCOMMAND_OPTIONAL | KEEP_UNKNOWN_OPT + command and subcommand options cannot be mixed' '
761 test-tool parse-subcommand --subcommand-optional --keep-unknown-opt cmd --subcommand-opt branch --opt=1 >actual &&
762 cat >expect <<-\EOF &&
763 opt: 0
764 fn: subcmd_one
765 arg 00: --subcommand-opt
766 arg 01: branch
767 arg 02: --opt=1
768 EOF
769 test_cmp expect actual
770 '
771
772 test_expect_success 'subcommand - SUBCOMMAND_OPTIONAL | KEEP_UNKNOWN_OPT | KEEP_ARGV0' '
773 test-tool parse-subcommand --subcommand-optional --keep-unknown-opt --keep-argv0 cmd --subcommand-opt branch >actual &&
774 cat >expect <<-\EOF &&
775 opt: 0
776 fn: subcmd_one
777 arg 00: cmd
778 arg 01: --subcommand-opt
779 arg 02: branch
780 EOF
781 test_cmp expect actual
782 '
783
784 test_expect_success 'subcommand - SUBCOMMAND_OPTIONAL | KEEP_UNKNOWN_OPT | KEEP_DASHDASH' '
785 test-tool parse-subcommand --subcommand-optional --keep-unknown-opt --keep-dashdash cmd -- --subcommand-opt file >actual &&
786 cat >expect <<-\EOF &&
787 opt: 0
788 fn: subcmd_one
789 arg 00: --
790 arg 01: --subcommand-opt
791 arg 02: file
792 EOF
793 test_cmp expect actual
794 '
795
796 test_expect_success 'subcommand - completion helper' '
797 test-tool parse-subcommand cmd --git-completion-helper >actual &&
798 echo "subcmd-one subcmd-two --opt= --no-opt" >expect &&
799 test_cmp expect actual
800 '
801
802 test_expect_success 'subcommands are incompatible with STOP_AT_NON_OPTION' '
803 test_must_fail test-tool parse-subcommand --stop-at-non-option cmd subcmd-one 2>err &&
804 test_grep ^BUG err
805 '
806
807 test_expect_success 'subcommands are incompatible with KEEP_UNKNOWN_OPT unless in combination with SUBCOMMAND_OPTIONAL' '
808 test_must_fail test-tool parse-subcommand --keep-unknown-opt cmd subcmd-two 2>err &&
809 test_grep ^BUG err
810 '
811
812 test_expect_success 'subcommands are incompatible with KEEP_DASHDASH unless in combination with SUBCOMMAND_OPTIONAL' '
813 test_must_fail test-tool parse-subcommand --keep-dashdash cmd subcmd-two 2>err &&
814 test_grep ^BUG err
815 '
816
817 test_expect_success 'negative unsigned' '
818 test_must_fail test-tool parse-options --unsigned -1 >out 2>err &&
819 test_grep "non-negative integer" err &&
820 test_must_be_empty out
821 '
822
823 test_expect_success 'unsigned with units but no numbers' '
824 test_must_fail test-tool parse-options --unsigned m >out 2>err &&
825 test_grep "non-negative integer" err &&
826 test_must_be_empty out
827 '
828
829 test_expect_success 'i16 limits range' '
830 test-tool parse-options --i16 32767 >out &&
831 test_grep "i16: 32767" out &&
832 test_must_fail test-tool parse-options --i16 32768 2>err &&
833 test_grep "value 32768 for option .i16. not in range \[-32768,32767\]" err &&
834
835 test-tool parse-options --i16 -32768 >out &&
836 test_grep "i16: -32768" out &&
837 test_must_fail test-tool parse-options --i16 -32769 2>err &&
838 test_grep "value -32769 for option .i16. not in range \[-32768,32767\]" err
839 '
840
841 test_expect_success 'u16 limits range' '
842 test-tool parse-options --u16 65535 >out &&
843 test_grep "u16: 65535" out &&
844 test_must_fail test-tool parse-options --u16 65536 2>err &&
845 test_grep "value 65536 for option .u16. not in range \[0,65535\]" err
846 '
847
848 test_done