t / t0040-parse-options.shon commit t/t6132-pathspec-exclude.sh: use the $( ... ) construct for command substitution (7b8c0b5)
   1#!/bin/sh
   2#
   3# Copyright (c) 2007 Johannes Schindelin
   4#
   5
   6test_description='our own option parser'
   7
   8. ./test-lib.sh
   9
  10cat > expect << EOF
  11usage: test-parse-options <options>
  12
  13    --yes                 get a boolean
  14    -D, --no-doubt        begins with 'no-'
  15    -B, --no-fear         be brave
  16    -b, --boolean         increment by one
  17    -4, --or4             bitwise-or boolean with ...0100
  18    --neg-or4             same as --no-or4
  19
  20    -i, --integer <n>     get a integer
  21    -j <n>                get a integer, too
  22    -m, --magnitude <n>   get a magnitude
  23    --set23               set integer to 23
  24    -t <time>             get timestamp of <time>
  25    -L, --length <str>    get length of <str>
  26    -F, --file <file>     set file to <file>
  27
  28String options
  29    -s, --string <string>
  30                          get a string
  31    --string2 <str>       get another string
  32    --st <st>             get another string (pervert ordering)
  33    -o <str>              get another string
  34    --list <str>          add str to list
  35
  36Magic arguments
  37    --quux                means --quux
  38    -NUM                  set integer to NUM
  39    +                     same as -b
  40    --ambiguous           positive ambiguity
  41    --no-ambiguous        negative ambiguity
  42
  43Standard options
  44    --abbrev[=<n>]        use <n> digits to display SHA-1s
  45    -v, --verbose         be verbose
  46    -n, --dry-run         dry run
  47    -q, --quiet           be quiet
  48
  49EOF
  50
  51test_expect_success 'test help' '
  52        test_must_fail test-parse-options -h > output 2> output.err &&
  53        test_must_be_empty output.err &&
  54        test_i18ncmp expect output
  55'
  56
  57mv expect expect.err
  58
  59cat >expect.template <<EOF
  60boolean: 0
  61integer: 0
  62magnitude: 0
  63timestamp: 0
  64string: (not set)
  65abbrev: 7
  66verbose: 0
  67quiet: no
  68dry run: no
  69file: (not set)
  70EOF
  71
  72check() {
  73        what="$1" &&
  74        shift &&
  75        expect="$1" &&
  76        shift &&
  77        sed "s/^$what .*/$what $expect/" <expect.template >expect &&
  78        test-parse-options $* >output 2>output.err &&
  79        test_must_be_empty output.err &&
  80        test_cmp expect output
  81}
  82
  83check_i18n() {
  84        what="$1" &&
  85        shift &&
  86        expect="$1" &&
  87        shift &&
  88        sed "s/^$what .*/$what $expect/" <expect.template >expect &&
  89        test-parse-options $* >output 2>output.err &&
  90        test_must_be_empty output.err &&
  91        test_i18ncmp expect output
  92}
  93
  94check_unknown() {
  95        case "$1" in
  96        --*)
  97                echo error: unknown option \`${1#--}\' >expect ;;
  98        -*)
  99                echo error: unknown switch \`${1#-}\' >expect ;;
 100        esac &&
 101        cat expect.err >>expect &&
 102        test_must_fail test-parse-options $* >output 2>output.err &&
 103        test_must_be_empty output &&
 104        test_cmp expect output.err
 105}
 106
 107check_unknown_i18n() {
 108        case "$1" in
 109        --*)
 110                echo error: unknown option \`${1#--}\' >expect ;;
 111        -*)
 112                echo error: unknown switch \`${1#-}\' >expect ;;
 113        esac &&
 114        cat expect.err >>expect &&
 115        test_must_fail test-parse-options $* >output 2>output.err &&
 116        test_must_be_empty output &&
 117        test_i18ncmp expect output.err
 118}
 119
 120test_expect_success 'OPT_BOOL() #1' 'check boolean: 1 --yes'
 121test_expect_success 'OPT_BOOL() #2' 'check boolean: 1 --no-doubt'
 122test_expect_success 'OPT_BOOL() #3' 'check boolean: 1 -D'
 123test_expect_success 'OPT_BOOL() #4' 'check boolean: 1 --no-fear'
 124test_expect_success 'OPT_BOOL() #5' 'check boolean: 1 -B'
 125
 126test_expect_success 'OPT_BOOL() is idempotent #1' 'check boolean: 1 --yes --yes'
 127test_expect_success 'OPT_BOOL() is idempotent #2' 'check boolean: 1 -DB'
 128
 129test_expect_success 'OPT_BOOL() negation #1' 'check boolean: 0 -D --no-yes'
 130test_expect_success 'OPT_BOOL() negation #2' 'check boolean: 0 -D --no-no-doubt'
 131
 132test_expect_success 'OPT_BOOL() no negation #1' 'check_unknown_i18n --fear'
 133test_expect_success 'OPT_BOOL() no negation #2' 'check_unknown_i18n --no-no-fear'
 134
 135test_expect_success 'OPT_BOOL() positivation' 'check boolean: 0 -D --doubt'
 136
 137test_expect_success 'OPT_INT() negative' 'check integer: -2345 -i -2345'
 138
 139test_expect_success 'OPT_MAGNITUDE() simple' '
 140        check magnitude: 2345678 -m 2345678
 141'
 142
 143test_expect_success 'OPT_MAGNITUDE() kilo' '
 144        check magnitude: 239616 -m 234k
 145'
 146
 147test_expect_success 'OPT_MAGNITUDE() mega' '
 148        check magnitude: 104857600 -m 100m
 149'
 150
 151test_expect_success 'OPT_MAGNITUDE() giga' '
 152        check magnitude: 1073741824 -m 1g
 153'
 154
 155test_expect_success 'OPT_MAGNITUDE() 3giga' '
 156        check magnitude: 3221225472 -m 3g
 157'
 158
 159cat > expect << EOF
 160boolean: 2
 161integer: 1729
 162magnitude: 16384
 163timestamp: 0
 164string: 123
 165abbrev: 7
 166verbose: 2
 167quiet: no
 168dry run: yes
 169file: prefix/my.file
 170EOF
 171
 172test_expect_success 'short options' '
 173        test-parse-options -s123 -b -i 1729 -m 16k -b -vv -n -F my.file \
 174        >output 2>output.err &&
 175        test_cmp expect output &&
 176        test_must_be_empty output.err
 177'
 178
 179cat > expect << EOF
 180boolean: 2
 181integer: 1729
 182magnitude: 16384
 183timestamp: 0
 184string: 321
 185abbrev: 10
 186verbose: 2
 187quiet: no
 188dry run: no
 189file: prefix/fi.le
 190EOF
 191
 192test_expect_success 'long options' '
 193        test-parse-options --boolean --integer 1729 --magnitude 16k \
 194                --boolean --string2=321 --verbose --verbose --no-dry-run \
 195                --abbrev=10 --file fi.le --obsolete \
 196                >output 2>output.err &&
 197        test_must_be_empty output.err &&
 198        test_cmp expect output
 199'
 200
 201test_expect_success 'missing required value' '
 202        test_expect_code 129 test-parse-options -s &&
 203        test_expect_code 129 test-parse-options --string &&
 204        test_expect_code 129 test-parse-options --file
 205'
 206
 207cat > expect << EOF
 208boolean: 1
 209integer: 13
 210magnitude: 0
 211timestamp: 0
 212string: 123
 213abbrev: 7
 214verbose: 0
 215quiet: no
 216dry run: no
 217file: (not set)
 218arg 00: a1
 219arg 01: b1
 220arg 02: --boolean
 221EOF
 222
 223test_expect_success 'intermingled arguments' '
 224        test-parse-options a1 --string 123 b1 --boolean -j 13 -- --boolean \
 225                > output 2> output.err &&
 226        test_must_be_empty output.err &&
 227        test_cmp expect output
 228'
 229
 230cat > expect << EOF
 231boolean: 0
 232integer: 2
 233magnitude: 0
 234timestamp: 0
 235string: (not set)
 236abbrev: 7
 237verbose: 0
 238quiet: no
 239dry run: no
 240file: (not set)
 241EOF
 242
 243test_expect_success 'unambiguously abbreviated option' '
 244        test-parse-options --int 2 --boolean --no-bo > output 2> output.err &&
 245        test_must_be_empty output.err &&
 246        test_cmp expect output
 247'
 248
 249test_expect_success 'unambiguously abbreviated option with "="' '
 250        test-parse-options --int=2 > output 2> output.err &&
 251        test_must_be_empty output.err &&
 252        test_cmp expect output
 253'
 254
 255test_expect_success 'ambiguously abbreviated option' '
 256        test_expect_code 129 test-parse-options --strin 123
 257'
 258
 259cat > expect << EOF
 260boolean: 0
 261integer: 0
 262magnitude: 0
 263timestamp: 0
 264string: 123
 265abbrev: 7
 266verbose: 0
 267quiet: no
 268dry run: no
 269file: (not set)
 270EOF
 271
 272test_expect_success 'non ambiguous option (after two options it abbreviates)' '
 273        test-parse-options --st 123 > output 2> output.err &&
 274        test_must_be_empty output.err &&
 275        test_cmp expect output
 276'
 277
 278cat > typo.err << EOF
 279error: did you mean \`--boolean\` (with two dashes ?)
 280EOF
 281
 282test_expect_success 'detect possible typos' '
 283        test_must_fail test-parse-options -boolean > output 2> output.err &&
 284        test_must_be_empty output &&
 285        test_cmp typo.err output.err
 286'
 287
 288cat > typo.err << EOF
 289error: did you mean \`--ambiguous\` (with two dashes ?)
 290EOF
 291
 292test_expect_success 'detect possible typos' '
 293        test_must_fail test-parse-options -ambiguous > output 2> output.err &&
 294        test_must_be_empty output &&
 295        test_cmp typo.err output.err
 296'
 297
 298cat > expect <<EOF
 299boolean: 0
 300integer: 0
 301magnitude: 0
 302timestamp: 0
 303string: (not set)
 304abbrev: 7
 305verbose: 0
 306quiet: no
 307dry run: no
 308file: (not set)
 309arg 00: --quux
 310EOF
 311
 312test_expect_success 'keep some options as arguments' '
 313        test-parse-options --quux > output 2> output.err &&
 314        test_must_be_empty output.err &&
 315        test_cmp expect output
 316'
 317
 318cat > expect <<EOF
 319boolean: 0
 320integer: 0
 321magnitude: 0
 322timestamp: 1
 323string: (not set)
 324abbrev: 7
 325verbose: 0
 326quiet: yes
 327dry run: no
 328file: (not set)
 329arg 00: foo
 330EOF
 331
 332test_expect_success 'OPT_DATE() works' '
 333        test-parse-options -t "1970-01-01 00:00:01 +0000" \
 334                foo -q > output 2> output.err &&
 335        test_must_be_empty output.err &&
 336        test_cmp expect output
 337'
 338
 339cat > expect <<EOF
 340Callback: "four", 0
 341boolean: 5
 342integer: 4
 343magnitude: 0
 344timestamp: 0
 345string: (not set)
 346abbrev: 7
 347verbose: 0
 348quiet: no
 349dry run: no
 350file: (not set)
 351EOF
 352
 353test_expect_success 'OPT_CALLBACK() and OPT_BIT() work' '
 354        test-parse-options --length=four -b -4 > output 2> output.err &&
 355        test_must_be_empty output.err &&
 356        test_cmp expect output
 357'
 358
 359cat > expect <<EOF
 360Callback: "not set", 1
 361EOF
 362
 363test_expect_success 'OPT_CALLBACK() and callback errors work' '
 364        test_must_fail test-parse-options --no-length > output 2> output.err &&
 365        test_i18ncmp expect output &&
 366        test_i18ncmp expect.err output.err
 367'
 368
 369cat > expect <<EOF
 370boolean: 1
 371integer: 23
 372magnitude: 0
 373timestamp: 0
 374string: (not set)
 375abbrev: 7
 376verbose: 0
 377quiet: no
 378dry run: no
 379file: (not set)
 380EOF
 381
 382test_expect_success 'OPT_BIT() and OPT_SET_INT() work' '
 383        test-parse-options --set23 -bbbbb --no-or4 > output 2> output.err &&
 384        test_must_be_empty output.err &&
 385        test_cmp expect output
 386'
 387
 388test_expect_success 'OPT_NEGBIT() and OPT_SET_INT() work' '
 389        test-parse-options --set23 -bbbbb --neg-or4 > output 2> output.err &&
 390        test_must_be_empty output.err &&
 391        test_cmp expect output
 392'
 393
 394cat > expect <<EOF
 395boolean: 6
 396integer: 0
 397magnitude: 0
 398timestamp: 0
 399string: (not set)
 400abbrev: 7
 401verbose: 0
 402quiet: no
 403dry run: no
 404file: (not set)
 405EOF
 406
 407test_expect_success 'OPT_BIT() works' '
 408        test-parse-options -bb --or4 > output 2> output.err &&
 409        test_must_be_empty output.err &&
 410        test_cmp expect output
 411'
 412
 413test_expect_success 'OPT_NEGBIT() works' '
 414        test-parse-options -bb --no-neg-or4 > output 2> output.err &&
 415        test_must_be_empty output.err &&
 416        test_cmp expect output
 417'
 418
 419test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' '
 420        test-parse-options + + + + + + > output 2> output.err &&
 421        test_must_be_empty output.err &&
 422        test_cmp expect output
 423'
 424
 425cat > expect <<EOF
 426boolean: 0
 427integer: 12345
 428magnitude: 0
 429timestamp: 0
 430string: (not set)
 431abbrev: 7
 432verbose: 0
 433quiet: no
 434dry run: no
 435file: (not set)
 436EOF
 437
 438test_expect_success 'OPT_NUMBER_CALLBACK() works' '
 439        test-parse-options -12345 > output 2> output.err &&
 440        test_must_be_empty output.err &&
 441        test_cmp expect output
 442'
 443
 444cat >expect <<EOF
 445boolean: 0
 446integer: 0
 447magnitude: 0
 448timestamp: 0
 449string: (not set)
 450abbrev: 7
 451verbose: 0
 452quiet: no
 453dry run: no
 454file: (not set)
 455EOF
 456
 457test_expect_success 'negation of OPT_NONEG flags is not ambiguous' '
 458        test-parse-options --no-ambig >output 2>output.err &&
 459        test_must_be_empty output.err &&
 460        test_cmp expect output
 461'
 462
 463cat >>expect <<'EOF'
 464list: foo
 465list: bar
 466list: baz
 467EOF
 468test_expect_success '--list keeps list of strings' '
 469        test-parse-options --list foo --list=bar --list=baz >output &&
 470        test_cmp expect output
 471'
 472
 473test_expect_success '--no-list resets list' '
 474        test-parse-options --list=other --list=irrelevant --list=options \
 475                --no-list --list=foo --list=bar --list=baz >output &&
 476        test_cmp expect output
 477'
 478
 479test_done