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