d678fbf1b781c2d9920a54ef45013e321883dc97
   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    --expect <string>     expected output in the variable dump
  49
  50EOF
  51
  52test_expect_success 'test help' '
  53        test_must_fail test-parse-options -h >output 2>output.err &&
  54        test_must_be_empty output.err &&
  55        test_i18ncmp expect output
  56'
  57
  58mv expect expect.err
  59
  60cat >expect.template <<\EOF
  61boolean: 0
  62integer: 0
  63magnitude: 0
  64timestamp: 0
  65string: (not set)
  66abbrev: 7
  67verbose: -1
  68quiet: 0
  69dry run: no
  70file: (not set)
  71EOF
  72
  73check() {
  74        what="$1" &&
  75        shift &&
  76        expect="$1" &&
  77        shift &&
  78        sed "s/^$what .*/$what $expect/" <expect.template >expect &&
  79        test-parse-options $* >output 2>output.err &&
  80        test_must_be_empty output.err &&
  81        test_cmp expect output
  82}
  83
  84check_i18n() {
  85        what="$1" &&
  86        shift &&
  87        expect="$1" &&
  88        shift &&
  89        sed "s/^$what .*/$what $expect/" <expect.template >expect &&
  90        test-parse-options $* >output 2>output.err &&
  91        test_must_be_empty output.err &&
  92        test_i18ncmp expect output
  93}
  94
  95check_unknown() {
  96        case "$1" in
  97        --*)
  98                echo error: unknown option \`${1#--}\' >expect ;;
  99        -*)
 100                echo error: unknown switch \`${1#-}\' >expect ;;
 101        esac &&
 102        cat expect.err >>expect &&
 103        test_must_fail test-parse-options $* >output 2>output.err &&
 104        test_must_be_empty output &&
 105        test_cmp expect output.err
 106}
 107
 108check_unknown_i18n() {
 109        case "$1" in
 110        --*)
 111                echo error: unknown option \`${1#--}\' >expect ;;
 112        -*)
 113                echo error: unknown switch \`${1#-}\' >expect ;;
 114        esac &&
 115        cat expect.err >>expect &&
 116        test_must_fail test-parse-options $* >output 2>output.err &&
 117        test_must_be_empty output &&
 118        test_i18ncmp expect output.err
 119}
 120
 121test_expect_success 'OPT_BOOL() #1' 'check boolean: 1 --yes'
 122test_expect_success 'OPT_BOOL() #2' 'check boolean: 1 --no-doubt'
 123test_expect_success 'OPT_BOOL() #3' 'check boolean: 1 -D'
 124test_expect_success 'OPT_BOOL() #4' 'check boolean: 1 --no-fear'
 125test_expect_success 'OPT_BOOL() #5' 'check boolean: 1 -B'
 126
 127test_expect_success 'OPT_BOOL() is idempotent #1' 'check boolean: 1 --yes --yes'
 128test_expect_success 'OPT_BOOL() is idempotent #2' 'check boolean: 1 -DB'
 129
 130test_expect_success 'OPT_BOOL() negation #1' 'check boolean: 0 -D --no-yes'
 131test_expect_success 'OPT_BOOL() negation #2' 'check boolean: 0 -D --no-no-doubt'
 132
 133test_expect_success 'OPT_BOOL() no negation #1' 'check_unknown_i18n --fear'
 134test_expect_success 'OPT_BOOL() no negation #2' 'check_unknown_i18n --no-no-fear'
 135
 136test_expect_success 'OPT_BOOL() positivation' 'check boolean: 0 -D --doubt'
 137
 138test_expect_success 'OPT_INT() negative' 'check integer: -2345 -i -2345'
 139
 140test_expect_success 'OPT_MAGNITUDE() simple' '
 141        check magnitude: 2345678 -m 2345678
 142'
 143
 144test_expect_success 'OPT_MAGNITUDE() kilo' '
 145        check magnitude: 239616 -m 234k
 146'
 147
 148test_expect_success 'OPT_MAGNITUDE() mega' '
 149        check magnitude: 104857600 -m 100m
 150'
 151
 152test_expect_success 'OPT_MAGNITUDE() giga' '
 153        check magnitude: 1073741824 -m 1g
 154'
 155
 156test_expect_success 'OPT_MAGNITUDE() 3giga' '
 157        check magnitude: 3221225472 -m 3g
 158'
 159
 160cat >expect <<\EOF
 161boolean: 2
 162integer: 1729
 163magnitude: 16384
 164timestamp: 0
 165string: 123
 166abbrev: 7
 167verbose: 2
 168quiet: 0
 169dry run: yes
 170file: prefix/my.file
 171EOF
 172
 173test_expect_success 'short options' '
 174        test-parse-options -s123 -b -i 1729 -m 16k -b -vv -n -F my.file \
 175        >output 2>output.err &&
 176        test_cmp expect output &&
 177        test_must_be_empty output.err
 178'
 179
 180cat >expect <<\EOF
 181boolean: 2
 182integer: 1729
 183magnitude: 16384
 184timestamp: 0
 185string: 321
 186abbrev: 10
 187verbose: 2
 188quiet: 0
 189dry run: no
 190file: prefix/fi.le
 191EOF
 192
 193test_expect_success 'long options' '
 194        test-parse-options --boolean --integer 1729 --magnitude 16k \
 195                --boolean --string2=321 --verbose --verbose --no-dry-run \
 196                --abbrev=10 --file fi.le --obsolete \
 197                >output 2>output.err &&
 198        test_must_be_empty output.err &&
 199        test_cmp expect output
 200'
 201
 202test_expect_success 'missing required value' '
 203        test_expect_code 129 test-parse-options -s &&
 204        test_expect_code 129 test-parse-options --string &&
 205        test_expect_code 129 test-parse-options --file
 206'
 207
 208cat >expect <<\EOF
 209boolean: 1
 210integer: 13
 211magnitude: 0
 212timestamp: 0
 213string: 123
 214abbrev: 7
 215verbose: -1
 216quiet: 0
 217dry run: no
 218file: (not set)
 219arg 00: a1
 220arg 01: b1
 221arg 02: --boolean
 222EOF
 223
 224test_expect_success 'intermingled arguments' '
 225        test-parse-options a1 --string 123 b1 --boolean -j 13 -- --boolean \
 226                >output 2>output.err &&
 227        test_must_be_empty output.err &&
 228        test_cmp expect output
 229'
 230
 231cat >expect <<\EOF
 232boolean: 0
 233integer: 2
 234magnitude: 0
 235timestamp: 0
 236string: (not set)
 237abbrev: 7
 238verbose: -1
 239quiet: 0
 240dry run: no
 241file: (not set)
 242EOF
 243
 244test_expect_success 'unambiguously abbreviated option' '
 245        test-parse-options --int 2 --boolean --no-bo >output 2>output.err &&
 246        test_must_be_empty output.err &&
 247        test_cmp expect output
 248'
 249
 250test_expect_success 'unambiguously abbreviated option with "="' '
 251        test-parse-options --int=2 >output 2>output.err &&
 252        test_must_be_empty output.err &&
 253        test_cmp expect output
 254'
 255
 256test_expect_success 'ambiguously abbreviated option' '
 257        test_expect_code 129 test-parse-options --strin 123
 258'
 259
 260cat >expect <<\EOF
 261boolean: 0
 262integer: 0
 263magnitude: 0
 264timestamp: 0
 265string: 123
 266abbrev: 7
 267verbose: -1
 268quiet: 0
 269dry run: no
 270file: (not set)
 271EOF
 272
 273test_expect_success 'non ambiguous option (after two options it abbreviates)' '
 274        test-parse-options --st 123 >output 2>output.err &&
 275        test_must_be_empty output.err &&
 276        test_cmp expect output
 277'
 278
 279cat >typo.err <<\EOF
 280error: did you mean `--boolean` (with two dashes ?)
 281EOF
 282
 283test_expect_success 'detect possible typos' '
 284        test_must_fail test-parse-options -boolean >output 2>output.err &&
 285        test_must_be_empty output &&
 286        test_cmp typo.err output.err
 287'
 288
 289cat >typo.err <<\EOF
 290error: did you mean `--ambiguous` (with two dashes ?)
 291EOF
 292
 293test_expect_success 'detect possible typos' '
 294        test_must_fail test-parse-options -ambiguous >output 2>output.err &&
 295        test_must_be_empty output &&
 296        test_cmp typo.err output.err
 297'
 298
 299cat >expect <<\EOF
 300boolean: 0
 301integer: 0
 302magnitude: 0
 303timestamp: 0
 304string: (not set)
 305abbrev: 7
 306verbose: -1
 307quiet: 0
 308dry run: no
 309file: (not set)
 310arg 00: --quux
 311EOF
 312
 313test_expect_success 'keep some options as arguments' '
 314        test-parse-options --quux >output 2>output.err &&
 315        test_must_be_empty output.err &&
 316        test_cmp expect output
 317'
 318
 319cat >expect <<\EOF
 320boolean: 0
 321integer: 0
 322magnitude: 0
 323timestamp: 1
 324string: (not set)
 325abbrev: 7
 326verbose: -1
 327quiet: 1
 328dry run: no
 329file: (not set)
 330arg 00: foo
 331EOF
 332
 333test_expect_success 'OPT_DATE() works' '
 334        test-parse-options -t "1970-01-01 00:00:01 +0000" \
 335                foo -q >output 2>output.err &&
 336        test_must_be_empty output.err &&
 337        test_cmp expect output
 338'
 339
 340cat >expect <<\EOF
 341Callback: "four", 0
 342boolean: 5
 343integer: 4
 344magnitude: 0
 345timestamp: 0
 346string: (not set)
 347abbrev: 7
 348verbose: -1
 349quiet: 0
 350dry run: no
 351file: (not set)
 352EOF
 353
 354test_expect_success 'OPT_CALLBACK() and OPT_BIT() work' '
 355        test-parse-options --length=four -b -4 >output 2>output.err &&
 356        test_must_be_empty output.err &&
 357        test_cmp expect output
 358'
 359
 360>expect
 361
 362test_expect_success 'OPT_CALLBACK() and callback errors work' '
 363        test_must_fail test-parse-options --no-length >output 2>output.err &&
 364        test_i18ncmp expect output &&
 365        test_i18ncmp expect.err output.err
 366'
 367
 368cat >expect <<\EOF
 369boolean: 1
 370integer: 23
 371magnitude: 0
 372timestamp: 0
 373string: (not set)
 374abbrev: 7
 375verbose: -1
 376quiet: 0
 377dry run: no
 378file: (not set)
 379EOF
 380
 381test_expect_success 'OPT_BIT() and OPT_SET_INT() work' '
 382        test-parse-options --set23 -bbbbb --no-or4 >output 2>output.err &&
 383        test_must_be_empty output.err &&
 384        test_cmp expect output
 385'
 386
 387test_expect_success 'OPT_NEGBIT() and OPT_SET_INT() work' '
 388        test-parse-options --set23 -bbbbb --neg-or4 >output 2>output.err &&
 389        test_must_be_empty output.err &&
 390        test_cmp expect output
 391'
 392
 393cat >expect <<\EOF
 394boolean: 6
 395integer: 0
 396magnitude: 0
 397timestamp: 0
 398string: (not set)
 399abbrev: 7
 400verbose: -1
 401quiet: 0
 402dry run: no
 403file: (not set)
 404EOF
 405
 406test_expect_success 'OPT_BIT() works' '
 407        test-parse-options -bb --or4 >output 2>output.err &&
 408        test_must_be_empty output.err &&
 409        test_cmp expect output
 410'
 411
 412test_expect_success 'OPT_NEGBIT() works' '
 413        test-parse-options -bb --no-neg-or4 >output 2>output.err &&
 414        test_must_be_empty output.err &&
 415        test_cmp expect output
 416'
 417
 418test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' '
 419        test-parse-options + + + + + + >output 2>output.err &&
 420        test_must_be_empty output.err &&
 421        test_cmp expect output
 422'
 423
 424cat >expect <<\EOF
 425boolean: 0
 426integer: 12345
 427magnitude: 0
 428timestamp: 0
 429string: (not set)
 430abbrev: 7
 431verbose: -1
 432quiet: 0
 433dry run: no
 434file: (not set)
 435EOF
 436
 437test_expect_success 'OPT_NUMBER_CALLBACK() works' '
 438        test-parse-options -12345 >output 2>output.err &&
 439        test_must_be_empty output.err &&
 440        test_cmp expect output
 441'
 442
 443cat >expect <<\EOF
 444boolean: 0
 445integer: 0
 446magnitude: 0
 447timestamp: 0
 448string: (not set)
 449abbrev: 7
 450verbose: -1
 451quiet: 0
 452dry run: no
 453file: (not set)
 454EOF
 455
 456test_expect_success 'negation of OPT_NONEG flags is not ambiguous' '
 457        test-parse-options --no-ambig >output 2>output.err &&
 458        test_must_be_empty output.err &&
 459        test_cmp expect output
 460'
 461
 462cat >>expect <<\EOF
 463list: foo
 464list: bar
 465list: baz
 466EOF
 467test_expect_success '--list keeps list of strings' '
 468        test-parse-options --list foo --list=bar --list=baz >output &&
 469        test_cmp expect output
 470'
 471
 472test_expect_success '--no-list resets list' '
 473        test-parse-options --list=other --list=irrelevant --list=options \
 474                --no-list --list=foo --list=bar --list=baz >output &&
 475        test_cmp expect output
 476'
 477
 478cat >expect <<\EOF
 479boolean: 0
 480integer: 0
 481magnitude: 0
 482timestamp: 0
 483string: (not set)
 484abbrev: 7
 485verbose: -1
 486quiet: 3
 487dry run: no
 488file: (not set)
 489EOF
 490
 491test_expect_success 'multiple quiet levels' '
 492        test-parse-options -q -q -q >output 2>output.err &&
 493        test_must_be_empty output.err &&
 494        test_cmp expect output
 495'
 496
 497cat >expect <<\EOF
 498boolean: 0
 499integer: 0
 500magnitude: 0
 501timestamp: 0
 502string: (not set)
 503abbrev: 7
 504verbose: 3
 505quiet: 0
 506dry run: no
 507file: (not set)
 508EOF
 509
 510test_expect_success 'multiple verbose levels' '
 511        test-parse-options -v -v -v >output 2>output.err &&
 512        test_must_be_empty output.err &&
 513        test_cmp expect output
 514'
 515
 516cat >expect <<\EOF
 517boolean: 0
 518integer: 0
 519magnitude: 0
 520timestamp: 0
 521string: (not set)
 522abbrev: 7
 523verbose: -1
 524quiet: 0
 525dry run: no
 526file: (not set)
 527EOF
 528
 529test_expect_success '--no-quiet sets --quiet to 0' '
 530        test-parse-options --no-quiet >output 2>output.err &&
 531        test_must_be_empty output.err &&
 532        test_cmp expect output
 533'
 534
 535cat >expect <<\EOF
 536boolean: 0
 537integer: 0
 538magnitude: 0
 539timestamp: 0
 540string: (not set)
 541abbrev: 7
 542verbose: -1
 543quiet: 0
 544dry run: no
 545file: (not set)
 546EOF
 547
 548test_expect_success '--no-quiet resets multiple -q to 0' '
 549        test-parse-options -q -q -q --no-quiet >output 2>output.err &&
 550        test_must_be_empty output.err &&
 551        test_cmp expect output
 552'
 553
 554cat >expect <<\EOF
 555boolean: 0
 556integer: 0
 557magnitude: 0
 558timestamp: 0
 559string: (not set)
 560abbrev: 7
 561verbose: 0
 562quiet: 0
 563dry run: no
 564file: (not set)
 565EOF
 566
 567test_expect_success '--no-verbose sets verbose to 0' '
 568        test-parse-options --no-verbose >output 2>output.err &&
 569        test_must_be_empty output.err &&
 570        test_cmp expect output
 571'
 572
 573cat >expect <<\EOF
 574boolean: 0
 575integer: 0
 576magnitude: 0
 577timestamp: 0
 578string: (not set)
 579abbrev: 7
 580verbose: 0
 581quiet: 0
 582dry run: no
 583file: (not set)
 584EOF
 585
 586test_expect_success '--no-verbose resets multiple verbose to 0' '
 587        test-parse-options -v -v -v --no-verbose >output 2>output.err &&
 588        test_must_be_empty output.err &&
 589        test_cmp expect output
 590'
 591
 592test_done