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