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