t / t0040-parse-options.shon commit push: the beginning of "git push --signed" (a85b377)
   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-parse-options -s;
 176        test $? = 129 &&
 177        test-parse-options --string;
 178        test $? = 129 &&
 179        test-parse-options --file;
 180        test $? = 129
 181'
 182
 183cat > expect << EOF
 184boolean: 1
 185integer: 13
 186timestamp: 0
 187string: 123
 188abbrev: 7
 189verbose: 0
 190quiet: no
 191dry run: no
 192file: (not set)
 193arg 00: a1
 194arg 01: b1
 195arg 02: --boolean
 196EOF
 197
 198test_expect_success 'intermingled arguments' '
 199        test-parse-options a1 --string 123 b1 --boolean -j 13 -- --boolean \
 200                > output 2> output.err &&
 201        test_must_be_empty output.err &&
 202        test_cmp expect output
 203'
 204
 205cat > expect << EOF
 206boolean: 0
 207integer: 2
 208timestamp: 0
 209string: (not set)
 210abbrev: 7
 211verbose: 0
 212quiet: no
 213dry run: no
 214file: (not set)
 215EOF
 216
 217test_expect_success 'unambiguously abbreviated option' '
 218        test-parse-options --int 2 --boolean --no-bo > output 2> output.err &&
 219        test_must_be_empty output.err &&
 220        test_cmp expect output
 221'
 222
 223test_expect_success 'unambiguously abbreviated option with "="' '
 224        test-parse-options --int=2 > output 2> output.err &&
 225        test_must_be_empty output.err &&
 226        test_cmp expect output
 227'
 228
 229test_expect_success 'ambiguously abbreviated option' '
 230        test-parse-options --strin 123;
 231        test $? = 129
 232'
 233
 234cat > expect << EOF
 235boolean: 0
 236integer: 0
 237timestamp: 0
 238string: 123
 239abbrev: 7
 240verbose: 0
 241quiet: no
 242dry run: no
 243file: (not set)
 244EOF
 245
 246test_expect_success 'non ambiguous option (after two options it abbreviates)' '
 247        test-parse-options --st 123 > output 2> output.err &&
 248        test_must_be_empty output.err &&
 249        test_cmp expect output
 250'
 251
 252cat > typo.err << EOF
 253error: did you mean \`--boolean\` (with two dashes ?)
 254EOF
 255
 256test_expect_success 'detect possible typos' '
 257        test_must_fail test-parse-options -boolean > output 2> output.err &&
 258        test_must_be_empty output &&
 259        test_cmp typo.err output.err
 260'
 261
 262cat > typo.err << EOF
 263error: did you mean \`--ambiguous\` (with two dashes ?)
 264EOF
 265
 266test_expect_success 'detect possible typos' '
 267        test_must_fail test-parse-options -ambiguous > output 2> output.err &&
 268        test_must_be_empty output &&
 269        test_cmp typo.err output.err
 270'
 271
 272cat > expect <<EOF
 273boolean: 0
 274integer: 0
 275timestamp: 0
 276string: (not set)
 277abbrev: 7
 278verbose: 0
 279quiet: no
 280dry run: no
 281file: (not set)
 282arg 00: --quux
 283EOF
 284
 285test_expect_success 'keep some options as arguments' '
 286        test-parse-options --quux > output 2> output.err &&
 287        test_must_be_empty output.err &&
 288        test_cmp expect output
 289'
 290
 291cat > expect <<EOF
 292boolean: 0
 293integer: 0
 294timestamp: 1
 295string: (not set)
 296abbrev: 7
 297verbose: 0
 298quiet: yes
 299dry run: no
 300file: (not set)
 301arg 00: foo
 302EOF
 303
 304test_expect_success 'OPT_DATE() works' '
 305        test-parse-options -t "1970-01-01 00:00:01 +0000" \
 306                foo -q > output 2> output.err &&
 307        test_must_be_empty output.err &&
 308        test_cmp expect output
 309'
 310
 311cat > expect <<EOF
 312Callback: "four", 0
 313boolean: 5
 314integer: 4
 315timestamp: 0
 316string: (not set)
 317abbrev: 7
 318verbose: 0
 319quiet: no
 320dry run: no
 321file: (not set)
 322EOF
 323
 324test_expect_success 'OPT_CALLBACK() and OPT_BIT() work' '
 325        test-parse-options --length=four -b -4 > output 2> output.err &&
 326        test_must_be_empty output.err &&
 327        test_cmp expect output
 328'
 329
 330cat > expect <<EOF
 331Callback: "not set", 1
 332EOF
 333
 334test_expect_success 'OPT_CALLBACK() and callback errors work' '
 335        test_must_fail test-parse-options --no-length > output 2> output.err &&
 336        test_i18ncmp expect output &&
 337        test_i18ncmp expect.err output.err
 338'
 339
 340cat > expect <<EOF
 341boolean: 1
 342integer: 23
 343timestamp: 0
 344string: (not set)
 345abbrev: 7
 346verbose: 0
 347quiet: no
 348dry run: no
 349file: (not set)
 350EOF
 351
 352test_expect_success 'OPT_BIT() and OPT_SET_INT() work' '
 353        test-parse-options --set23 -bbbbb --no-or4 > output 2> output.err &&
 354        test_must_be_empty output.err &&
 355        test_cmp expect output
 356'
 357
 358test_expect_success 'OPT_NEGBIT() and OPT_SET_INT() work' '
 359        test-parse-options --set23 -bbbbb --neg-or4 > output 2> output.err &&
 360        test_must_be_empty output.err &&
 361        test_cmp expect output
 362'
 363
 364cat > expect <<EOF
 365boolean: 6
 366integer: 0
 367timestamp: 0
 368string: (not set)
 369abbrev: 7
 370verbose: 0
 371quiet: no
 372dry run: no
 373file: (not set)
 374EOF
 375
 376test_expect_success 'OPT_BIT() works' '
 377        test-parse-options -bb --or4 > output 2> output.err &&
 378        test_must_be_empty output.err &&
 379        test_cmp expect output
 380'
 381
 382test_expect_success 'OPT_NEGBIT() works' '
 383        test-parse-options -bb --no-neg-or4 > output 2> output.err &&
 384        test_must_be_empty output.err &&
 385        test_cmp expect output
 386'
 387
 388test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' '
 389        test-parse-options + + + + + + > output 2> output.err &&
 390        test_must_be_empty output.err &&
 391        test_cmp expect output
 392'
 393
 394cat > expect <<EOF
 395boolean: 0
 396integer: 12345
 397timestamp: 0
 398string: (not set)
 399abbrev: 7
 400verbose: 0
 401quiet: no
 402dry run: no
 403file: (not set)
 404EOF
 405
 406test_expect_success 'OPT_NUMBER_CALLBACK() works' '
 407        test-parse-options -12345 > output 2> output.err &&
 408        test_must_be_empty output.err &&
 409        test_cmp expect output
 410'
 411
 412cat >expect <<EOF
 413boolean: 0
 414integer: 0
 415timestamp: 0
 416string: (not set)
 417abbrev: 7
 418verbose: 0
 419quiet: no
 420dry run: no
 421file: (not set)
 422EOF
 423
 424test_expect_success 'negation of OPT_NONEG flags is not ambiguous' '
 425        test-parse-options --no-ambig >output 2>output.err &&
 426        test_must_be_empty output.err &&
 427        test_cmp expect output
 428'
 429
 430cat >>expect <<'EOF'
 431list: foo
 432list: bar
 433list: baz
 434EOF
 435test_expect_success '--list keeps list of strings' '
 436        test-parse-options --list foo --list=bar --list=baz >output &&
 437        test_cmp expect output
 438'
 439
 440test_expect_success '--no-list resets list' '
 441        test-parse-options --list=other --list=irrelevant --list=options \
 442                --no-list --list=foo --list=bar --list=baz >output &&
 443        test_cmp expect output
 444'
 445
 446test_done