github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/cli/flag_test.go (about) 1 package cli 2 3 import ( 4 "fmt" 5 "os" 6 "reflect" 7 "strings" 8 "testing" 9 "runtime" 10 ) 11 12 var boolFlagTests = []struct { 13 name string 14 expected string 15 }{ 16 {"help", "--help\t"}, 17 {"h", "-h\t"}, 18 } 19 20 func TestBoolFlagHelpOutput(t *testing.T) { 21 22 for _, test := range boolFlagTests { 23 flag := BoolFlag{Name: test.name} 24 output := flag.String() 25 26 if output != test.expected { 27 t.Errorf("%s does not match %s", output, test.expected) 28 } 29 } 30 } 31 32 var stringFlagTests = []struct { 33 name string 34 value string 35 expected string 36 }{ 37 {"help", "", "--help \t"}, 38 {"h", "", "-h \t"}, 39 {"h", "", "-h \t"}, 40 {"test", "Something", "--test \"Something\"\t"}, 41 } 42 43 func TestStringFlagHelpOutput(t *testing.T) { 44 45 for _, test := range stringFlagTests { 46 flag := StringFlag{Name: test.name, Value: test.value} 47 output := flag.String() 48 49 if output != test.expected { 50 t.Errorf("%s does not match %s", output, test.expected) 51 } 52 } 53 } 54 55 func TestStringFlagWithEnvVarHelpOutput(t *testing.T) { 56 os.Clearenv() 57 os.Setenv("APP_FOO", "derp") 58 for _, test := range stringFlagTests { 59 flag := StringFlag{Name: test.name, Value: test.value, EnvVar: "APP_FOO"} 60 output := flag.String() 61 62 expectedSuffix := " [$APP_FOO]" 63 if runtime.GOOS == "windows" { 64 expectedSuffix = " [%APP_FOO%]" 65 } 66 if !strings.HasSuffix(output, expectedSuffix) { 67 t.Errorf("%s does not end with" + expectedSuffix, output) 68 } 69 } 70 } 71 72 var stringSliceFlagTests = []struct { 73 name string 74 value *StringSlice 75 expected string 76 }{ 77 {"help", func() *StringSlice { 78 s := &StringSlice{} 79 s.Set("") 80 return s 81 }(), "--help [--help option --help option]\t"}, 82 {"h", func() *StringSlice { 83 s := &StringSlice{} 84 s.Set("") 85 return s 86 }(), "-h [-h option -h option]\t"}, 87 {"h", func() *StringSlice { 88 s := &StringSlice{} 89 s.Set("") 90 return s 91 }(), "-h [-h option -h option]\t"}, 92 {"test", func() *StringSlice { 93 s := &StringSlice{} 94 s.Set("Something") 95 return s 96 }(), "--test [--test option --test option]\t"}, 97 } 98 99 func TestStringSliceFlagHelpOutput(t *testing.T) { 100 101 for _, test := range stringSliceFlagTests { 102 flag := StringSliceFlag{Name: test.name, Value: test.value} 103 output := flag.String() 104 105 if output != test.expected { 106 t.Errorf("%q does not match %q", output, test.expected) 107 } 108 } 109 } 110 111 func TestStringSliceFlagWithEnvVarHelpOutput(t *testing.T) { 112 os.Clearenv() 113 os.Setenv("APP_QWWX", "11,4") 114 for _, test := range stringSliceFlagTests { 115 flag := StringSliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_QWWX"} 116 output := flag.String() 117 118 expectedSuffix := " [$APP_QWWX]" 119 if runtime.GOOS == "windows" { 120 expectedSuffix = " [%APP_QWWX%]" 121 } 122 if !strings.HasSuffix(output, expectedSuffix) { 123 t.Errorf("%q does not end with" + expectedSuffix, output) 124 } 125 } 126 } 127 128 var intFlagTests = []struct { 129 name string 130 expected string 131 }{ 132 {"help", "--help \"0\"\t"}, 133 {"h", "-h \"0\"\t"}, 134 } 135 136 func TestIntFlagHelpOutput(t *testing.T) { 137 138 for _, test := range intFlagTests { 139 flag := IntFlag{Name: test.name} 140 output := flag.String() 141 142 if output != test.expected { 143 t.Errorf("%s does not match %s", output, test.expected) 144 } 145 } 146 } 147 148 func TestIntFlagWithEnvVarHelpOutput(t *testing.T) { 149 os.Clearenv() 150 os.Setenv("APP_BAR", "2") 151 for _, test := range intFlagTests { 152 flag := IntFlag{Name: test.name, EnvVar: "APP_BAR"} 153 output := flag.String() 154 155 expectedSuffix := " [$APP_BAR]" 156 if runtime.GOOS == "windows" { 157 expectedSuffix = " [%APP_BAR%]" 158 } 159 if !strings.HasSuffix(output, expectedSuffix) { 160 t.Errorf("%s does not end with" + expectedSuffix, output) 161 } 162 } 163 } 164 165 var durationFlagTests = []struct { 166 name string 167 expected string 168 }{ 169 {"help", "--help \"0\"\t"}, 170 {"h", "-h \"0\"\t"}, 171 } 172 173 func TestDurationFlagHelpOutput(t *testing.T) { 174 175 for _, test := range durationFlagTests { 176 flag := DurationFlag{Name: test.name} 177 output := flag.String() 178 179 if output != test.expected { 180 t.Errorf("%s does not match %s", output, test.expected) 181 } 182 } 183 } 184 185 func TestDurationFlagWithEnvVarHelpOutput(t *testing.T) { 186 os.Clearenv() 187 os.Setenv("APP_BAR", "2h3m6s") 188 for _, test := range durationFlagTests { 189 flag := DurationFlag{Name: test.name, EnvVar: "APP_BAR"} 190 output := flag.String() 191 192 expectedSuffix := " [$APP_BAR]" 193 if runtime.GOOS == "windows" { 194 expectedSuffix = " [%APP_BAR%]" 195 } 196 if !strings.HasSuffix(output, expectedSuffix) { 197 t.Errorf("%s does not end with" + expectedSuffix, output) 198 } 199 } 200 } 201 202 var intSliceFlagTests = []struct { 203 name string 204 value *IntSlice 205 expected string 206 }{ 207 {"help", &IntSlice{}, "--help [--help option --help option]\t"}, 208 {"h", &IntSlice{}, "-h [-h option -h option]\t"}, 209 {"h", &IntSlice{}, "-h [-h option -h option]\t"}, 210 {"test", func() *IntSlice { 211 i := &IntSlice{} 212 i.Set("9") 213 return i 214 }(), "--test [--test option --test option]\t"}, 215 } 216 217 func TestIntSliceFlagHelpOutput(t *testing.T) { 218 219 for _, test := range intSliceFlagTests { 220 flag := IntSliceFlag{Name: test.name, Value: test.value} 221 output := flag.String() 222 223 if output != test.expected { 224 t.Errorf("%q does not match %q", output, test.expected) 225 } 226 } 227 } 228 229 func TestIntSliceFlagWithEnvVarHelpOutput(t *testing.T) { 230 os.Clearenv() 231 os.Setenv("APP_SMURF", "42,3") 232 for _, test := range intSliceFlagTests { 233 flag := IntSliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_SMURF"} 234 output := flag.String() 235 236 expectedSuffix := " [$APP_SMURF]" 237 if runtime.GOOS == "windows" { 238 expectedSuffix = " [%APP_SMURF%]" 239 } 240 if !strings.HasSuffix(output, expectedSuffix) { 241 t.Errorf("%q does not end with" + expectedSuffix, output) 242 } 243 } 244 } 245 246 var float64FlagTests = []struct { 247 name string 248 expected string 249 }{ 250 {"help", "--help \"0\"\t"}, 251 {"h", "-h \"0\"\t"}, 252 } 253 254 func TestFloat64FlagHelpOutput(t *testing.T) { 255 256 for _, test := range float64FlagTests { 257 flag := Float64Flag{Name: test.name} 258 output := flag.String() 259 260 if output != test.expected { 261 t.Errorf("%s does not match %s", output, test.expected) 262 } 263 } 264 } 265 266 func TestFloat64FlagWithEnvVarHelpOutput(t *testing.T) { 267 os.Clearenv() 268 os.Setenv("APP_BAZ", "99.4") 269 for _, test := range float64FlagTests { 270 flag := Float64Flag{Name: test.name, EnvVar: "APP_BAZ"} 271 output := flag.String() 272 273 expectedSuffix := " [$APP_BAZ]" 274 if runtime.GOOS == "windows" { 275 expectedSuffix = " [%APP_BAZ%]" 276 } 277 if !strings.HasSuffix(output, expectedSuffix) { 278 t.Errorf("%s does not end with" + expectedSuffix, output) 279 } 280 } 281 } 282 283 var genericFlagTests = []struct { 284 name string 285 value Generic 286 expected string 287 }{ 288 {"test", &Parser{"abc", "def"}, "--test \"abc,def\"\ttest flag"}, 289 {"t", &Parser{"abc", "def"}, "-t \"abc,def\"\ttest flag"}, 290 } 291 292 func TestGenericFlagHelpOutput(t *testing.T) { 293 294 for _, test := range genericFlagTests { 295 flag := GenericFlag{Name: test.name, Value: test.value, Usage: "test flag"} 296 output := flag.String() 297 298 if output != test.expected { 299 t.Errorf("%q does not match %q", output, test.expected) 300 } 301 } 302 } 303 304 func TestGenericFlagWithEnvVarHelpOutput(t *testing.T) { 305 os.Clearenv() 306 os.Setenv("APP_ZAP", "3") 307 for _, test := range genericFlagTests { 308 flag := GenericFlag{Name: test.name, EnvVar: "APP_ZAP"} 309 output := flag.String() 310 311 expectedSuffix := " [$APP_ZAP]" 312 if runtime.GOOS == "windows" { 313 expectedSuffix = " [%APP_ZAP%]" 314 } 315 if !strings.HasSuffix(output, expectedSuffix) { 316 t.Errorf("%s does not end with" + expectedSuffix, output) 317 } 318 } 319 } 320 321 func TestParseMultiString(t *testing.T) { 322 (&App{ 323 Flags: []Flag{ 324 StringFlag{Name: "serve, s"}, 325 }, 326 Action: func(ctx *Context) { 327 if ctx.String("serve") != "10" { 328 t.Errorf("main name not set") 329 } 330 if ctx.String("s") != "10" { 331 t.Errorf("short name not set") 332 } 333 }, 334 }).Run([]string{"run", "-s", "10"}) 335 } 336 337 func TestParseDestinationString(t *testing.T) { 338 var dest string 339 a := App{ 340 Flags: []Flag{ 341 StringFlag{ 342 Name: "dest", 343 Destination: &dest, 344 }, 345 }, 346 Action: func(ctx *Context) { 347 if dest != "10" { 348 t.Errorf("expected destination String 10") 349 } 350 }, 351 } 352 a.Run([]string{"run", "--dest", "10"}) 353 } 354 355 func TestParseMultiStringFromEnv(t *testing.T) { 356 os.Clearenv() 357 os.Setenv("APP_COUNT", "20") 358 (&App{ 359 Flags: []Flag{ 360 StringFlag{Name: "count, c", EnvVar: "APP_COUNT"}, 361 }, 362 Action: func(ctx *Context) { 363 if ctx.String("count") != "20" { 364 t.Errorf("main name not set") 365 } 366 if ctx.String("c") != "20" { 367 t.Errorf("short name not set") 368 } 369 }, 370 }).Run([]string{"run"}) 371 } 372 373 func TestParseMultiStringFromEnvCascade(t *testing.T) { 374 os.Clearenv() 375 os.Setenv("APP_COUNT", "20") 376 (&App{ 377 Flags: []Flag{ 378 StringFlag{Name: "count, c", EnvVar: "COMPAT_COUNT,APP_COUNT"}, 379 }, 380 Action: func(ctx *Context) { 381 if ctx.String("count") != "20" { 382 t.Errorf("main name not set") 383 } 384 if ctx.String("c") != "20" { 385 t.Errorf("short name not set") 386 } 387 }, 388 }).Run([]string{"run"}) 389 } 390 391 func TestParseMultiStringSlice(t *testing.T) { 392 (&App{ 393 Flags: []Flag{ 394 StringSliceFlag{Name: "serve, s", Value: &StringSlice{}}, 395 }, 396 Action: func(ctx *Context) { 397 if !reflect.DeepEqual(ctx.StringSlice("serve"), []string{"10", "20"}) { 398 t.Errorf("main name not set") 399 } 400 if !reflect.DeepEqual(ctx.StringSlice("s"), []string{"10", "20"}) { 401 t.Errorf("short name not set") 402 } 403 }, 404 }).Run([]string{"run", "-s", "10", "-s", "20"}) 405 } 406 407 func TestParseMultiStringSliceFromEnv(t *testing.T) { 408 os.Clearenv() 409 os.Setenv("APP_INTERVALS", "20,30,40") 410 411 (&App{ 412 Flags: []Flag{ 413 StringSliceFlag{Name: "intervals, i", Value: &StringSlice{}, EnvVar: "APP_INTERVALS"}, 414 }, 415 Action: func(ctx *Context) { 416 if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) { 417 t.Errorf("main name not set from env") 418 } 419 if !reflect.DeepEqual(ctx.StringSlice("i"), []string{"20", "30", "40"}) { 420 t.Errorf("short name not set from env") 421 } 422 }, 423 }).Run([]string{"run"}) 424 } 425 426 func TestParseMultiStringSliceFromEnvCascade(t *testing.T) { 427 os.Clearenv() 428 os.Setenv("APP_INTERVALS", "20,30,40") 429 430 (&App{ 431 Flags: []Flag{ 432 StringSliceFlag{Name: "intervals, i", Value: &StringSlice{}, EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"}, 433 }, 434 Action: func(ctx *Context) { 435 if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) { 436 t.Errorf("main name not set from env") 437 } 438 if !reflect.DeepEqual(ctx.StringSlice("i"), []string{"20", "30", "40"}) { 439 t.Errorf("short name not set from env") 440 } 441 }, 442 }).Run([]string{"run"}) 443 } 444 445 func TestParseMultiInt(t *testing.T) { 446 a := App{ 447 Flags: []Flag{ 448 IntFlag{Name: "serve, s"}, 449 }, 450 Action: func(ctx *Context) { 451 if ctx.Int("serve") != 10 { 452 t.Errorf("main name not set") 453 } 454 if ctx.Int("s") != 10 { 455 t.Errorf("short name not set") 456 } 457 }, 458 } 459 a.Run([]string{"run", "-s", "10"}) 460 } 461 462 func TestParseDestinationInt(t *testing.T) { 463 var dest int 464 a := App{ 465 Flags: []Flag{ 466 IntFlag{ 467 Name: "dest", 468 Destination: &dest, 469 }, 470 }, 471 Action: func(ctx *Context) { 472 if dest != 10 { 473 t.Errorf("expected destination Int 10") 474 } 475 }, 476 } 477 a.Run([]string{"run", "--dest", "10"}) 478 } 479 480 func TestParseMultiIntFromEnv(t *testing.T) { 481 os.Clearenv() 482 os.Setenv("APP_TIMEOUT_SECONDS", "10") 483 a := App{ 484 Flags: []Flag{ 485 IntFlag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"}, 486 }, 487 Action: func(ctx *Context) { 488 if ctx.Int("timeout") != 10 { 489 t.Errorf("main name not set") 490 } 491 if ctx.Int("t") != 10 { 492 t.Errorf("short name not set") 493 } 494 }, 495 } 496 a.Run([]string{"run"}) 497 } 498 499 func TestParseMultiIntFromEnvCascade(t *testing.T) { 500 os.Clearenv() 501 os.Setenv("APP_TIMEOUT_SECONDS", "10") 502 a := App{ 503 Flags: []Flag{ 504 IntFlag{Name: "timeout, t", EnvVar: "COMPAT_TIMEOUT_SECONDS,APP_TIMEOUT_SECONDS"}, 505 }, 506 Action: func(ctx *Context) { 507 if ctx.Int("timeout") != 10 { 508 t.Errorf("main name not set") 509 } 510 if ctx.Int("t") != 10 { 511 t.Errorf("short name not set") 512 } 513 }, 514 } 515 a.Run([]string{"run"}) 516 } 517 518 func TestParseMultiIntSlice(t *testing.T) { 519 (&App{ 520 Flags: []Flag{ 521 IntSliceFlag{Name: "serve, s", Value: &IntSlice{}}, 522 }, 523 Action: func(ctx *Context) { 524 if !reflect.DeepEqual(ctx.IntSlice("serve"), []int{10, 20}) { 525 t.Errorf("main name not set") 526 } 527 if !reflect.DeepEqual(ctx.IntSlice("s"), []int{10, 20}) { 528 t.Errorf("short name not set") 529 } 530 }, 531 }).Run([]string{"run", "-s", "10", "-s", "20"}) 532 } 533 534 func TestParseMultiIntSliceFromEnv(t *testing.T) { 535 os.Clearenv() 536 os.Setenv("APP_INTERVALS", "20,30,40") 537 538 (&App{ 539 Flags: []Flag{ 540 IntSliceFlag{Name: "intervals, i", Value: &IntSlice{}, EnvVar: "APP_INTERVALS"}, 541 }, 542 Action: func(ctx *Context) { 543 if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) { 544 t.Errorf("main name not set from env") 545 } 546 if !reflect.DeepEqual(ctx.IntSlice("i"), []int{20, 30, 40}) { 547 t.Errorf("short name not set from env") 548 } 549 }, 550 }).Run([]string{"run"}) 551 } 552 553 func TestParseMultiIntSliceFromEnvCascade(t *testing.T) { 554 os.Clearenv() 555 os.Setenv("APP_INTERVALS", "20,30,40") 556 557 (&App{ 558 Flags: []Flag{ 559 IntSliceFlag{Name: "intervals, i", Value: &IntSlice{}, EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"}, 560 }, 561 Action: func(ctx *Context) { 562 if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) { 563 t.Errorf("main name not set from env") 564 } 565 if !reflect.DeepEqual(ctx.IntSlice("i"), []int{20, 30, 40}) { 566 t.Errorf("short name not set from env") 567 } 568 }, 569 }).Run([]string{"run"}) 570 } 571 572 func TestParseMultiFloat64(t *testing.T) { 573 a := App{ 574 Flags: []Flag{ 575 Float64Flag{Name: "serve, s"}, 576 }, 577 Action: func(ctx *Context) { 578 if ctx.Float64("serve") != 10.2 { 579 t.Errorf("main name not set") 580 } 581 if ctx.Float64("s") != 10.2 { 582 t.Errorf("short name not set") 583 } 584 }, 585 } 586 a.Run([]string{"run", "-s", "10.2"}) 587 } 588 589 func TestParseDestinationFloat64(t *testing.T) { 590 var dest float64 591 a := App{ 592 Flags: []Flag{ 593 Float64Flag{ 594 Name: "dest", 595 Destination: &dest, 596 }, 597 }, 598 Action: func(ctx *Context) { 599 if dest != 10.2 { 600 t.Errorf("expected destination Float64 10.2") 601 } 602 }, 603 } 604 a.Run([]string{"run", "--dest", "10.2"}) 605 } 606 607 func TestParseMultiFloat64FromEnv(t *testing.T) { 608 os.Clearenv() 609 os.Setenv("APP_TIMEOUT_SECONDS", "15.5") 610 a := App{ 611 Flags: []Flag{ 612 Float64Flag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"}, 613 }, 614 Action: func(ctx *Context) { 615 if ctx.Float64("timeout") != 15.5 { 616 t.Errorf("main name not set") 617 } 618 if ctx.Float64("t") != 15.5 { 619 t.Errorf("short name not set") 620 } 621 }, 622 } 623 a.Run([]string{"run"}) 624 } 625 626 func TestParseMultiFloat64FromEnvCascade(t *testing.T) { 627 os.Clearenv() 628 os.Setenv("APP_TIMEOUT_SECONDS", "15.5") 629 a := App{ 630 Flags: []Flag{ 631 Float64Flag{Name: "timeout, t", EnvVar: "COMPAT_TIMEOUT_SECONDS,APP_TIMEOUT_SECONDS"}, 632 }, 633 Action: func(ctx *Context) { 634 if ctx.Float64("timeout") != 15.5 { 635 t.Errorf("main name not set") 636 } 637 if ctx.Float64("t") != 15.5 { 638 t.Errorf("short name not set") 639 } 640 }, 641 } 642 a.Run([]string{"run"}) 643 } 644 645 func TestParseMultiBool(t *testing.T) { 646 a := App{ 647 Flags: []Flag{ 648 BoolFlag{Name: "serve, s"}, 649 }, 650 Action: func(ctx *Context) { 651 if ctx.Bool("serve") != true { 652 t.Errorf("main name not set") 653 } 654 if ctx.Bool("s") != true { 655 t.Errorf("short name not set") 656 } 657 }, 658 } 659 a.Run([]string{"run", "--serve"}) 660 } 661 662 func TestParseDestinationBool(t *testing.T) { 663 var dest bool 664 a := App{ 665 Flags: []Flag{ 666 BoolFlag{ 667 Name: "dest", 668 Destination: &dest, 669 }, 670 }, 671 Action: func(ctx *Context) { 672 if dest != true { 673 t.Errorf("expected destination Bool true") 674 } 675 }, 676 } 677 a.Run([]string{"run", "--dest"}) 678 } 679 680 func TestParseMultiBoolFromEnv(t *testing.T) { 681 os.Clearenv() 682 os.Setenv("APP_DEBUG", "1") 683 a := App{ 684 Flags: []Flag{ 685 BoolFlag{Name: "debug, d", EnvVar: "APP_DEBUG"}, 686 }, 687 Action: func(ctx *Context) { 688 if ctx.Bool("debug") != true { 689 t.Errorf("main name not set from env") 690 } 691 if ctx.Bool("d") != true { 692 t.Errorf("short name not set from env") 693 } 694 }, 695 } 696 a.Run([]string{"run"}) 697 } 698 699 func TestParseMultiBoolFromEnvCascade(t *testing.T) { 700 os.Clearenv() 701 os.Setenv("APP_DEBUG", "1") 702 a := App{ 703 Flags: []Flag{ 704 BoolFlag{Name: "debug, d", EnvVar: "COMPAT_DEBUG,APP_DEBUG"}, 705 }, 706 Action: func(ctx *Context) { 707 if ctx.Bool("debug") != true { 708 t.Errorf("main name not set from env") 709 } 710 if ctx.Bool("d") != true { 711 t.Errorf("short name not set from env") 712 } 713 }, 714 } 715 a.Run([]string{"run"}) 716 } 717 718 func TestParseMultiBoolT(t *testing.T) { 719 a := App{ 720 Flags: []Flag{ 721 BoolTFlag{Name: "serve, s"}, 722 }, 723 Action: func(ctx *Context) { 724 if ctx.BoolT("serve") != true { 725 t.Errorf("main name not set") 726 } 727 if ctx.BoolT("s") != true { 728 t.Errorf("short name not set") 729 } 730 }, 731 } 732 a.Run([]string{"run", "--serve"}) 733 } 734 735 func TestParseDestinationBoolT(t *testing.T) { 736 var dest bool 737 a := App{ 738 Flags: []Flag{ 739 BoolTFlag{ 740 Name: "dest", 741 Destination: &dest, 742 }, 743 }, 744 Action: func(ctx *Context) { 745 if dest != true { 746 t.Errorf("expected destination BoolT true") 747 } 748 }, 749 } 750 a.Run([]string{"run", "--dest"}) 751 } 752 753 func TestParseMultiBoolTFromEnv(t *testing.T) { 754 os.Clearenv() 755 os.Setenv("APP_DEBUG", "0") 756 a := App{ 757 Flags: []Flag{ 758 BoolTFlag{Name: "debug, d", EnvVar: "APP_DEBUG"}, 759 }, 760 Action: func(ctx *Context) { 761 if ctx.BoolT("debug") != false { 762 t.Errorf("main name not set from env") 763 } 764 if ctx.BoolT("d") != false { 765 t.Errorf("short name not set from env") 766 } 767 }, 768 } 769 a.Run([]string{"run"}) 770 } 771 772 func TestParseMultiBoolTFromEnvCascade(t *testing.T) { 773 os.Clearenv() 774 os.Setenv("APP_DEBUG", "0") 775 a := App{ 776 Flags: []Flag{ 777 BoolTFlag{Name: "debug, d", EnvVar: "COMPAT_DEBUG,APP_DEBUG"}, 778 }, 779 Action: func(ctx *Context) { 780 if ctx.BoolT("debug") != false { 781 t.Errorf("main name not set from env") 782 } 783 if ctx.BoolT("d") != false { 784 t.Errorf("short name not set from env") 785 } 786 }, 787 } 788 a.Run([]string{"run"}) 789 } 790 791 type Parser [2]string 792 793 func (p *Parser) Set(value string) error { 794 parts := strings.Split(value, ",") 795 if len(parts) != 2 { 796 return fmt.Errorf("invalid format") 797 } 798 799 (*p)[0] = parts[0] 800 (*p)[1] = parts[1] 801 802 return nil 803 } 804 805 func (p *Parser) String() string { 806 return fmt.Sprintf("%s,%s", p[0], p[1]) 807 } 808 809 func TestParseGeneric(t *testing.T) { 810 a := App{ 811 Flags: []Flag{ 812 GenericFlag{Name: "serve, s", Value: &Parser{}}, 813 }, 814 Action: func(ctx *Context) { 815 if !reflect.DeepEqual(ctx.Generic("serve"), &Parser{"10", "20"}) { 816 t.Errorf("main name not set") 817 } 818 if !reflect.DeepEqual(ctx.Generic("s"), &Parser{"10", "20"}) { 819 t.Errorf("short name not set") 820 } 821 }, 822 } 823 a.Run([]string{"run", "-s", "10,20"}) 824 } 825 826 func TestParseGenericFromEnv(t *testing.T) { 827 os.Clearenv() 828 os.Setenv("APP_SERVE", "20,30") 829 a := App{ 830 Flags: []Flag{ 831 GenericFlag{Name: "serve, s", Value: &Parser{}, EnvVar: "APP_SERVE"}, 832 }, 833 Action: func(ctx *Context) { 834 if !reflect.DeepEqual(ctx.Generic("serve"), &Parser{"20", "30"}) { 835 t.Errorf("main name not set from env") 836 } 837 if !reflect.DeepEqual(ctx.Generic("s"), &Parser{"20", "30"}) { 838 t.Errorf("short name not set from env") 839 } 840 }, 841 } 842 a.Run([]string{"run"}) 843 } 844 845 func TestParseGenericFromEnvCascade(t *testing.T) { 846 os.Clearenv() 847 os.Setenv("APP_FOO", "99,2000") 848 a := App{ 849 Flags: []Flag{ 850 GenericFlag{Name: "foos", Value: &Parser{}, EnvVar: "COMPAT_FOO,APP_FOO"}, 851 }, 852 Action: func(ctx *Context) { 853 if !reflect.DeepEqual(ctx.Generic("foos"), &Parser{"99", "2000"}) { 854 t.Errorf("value not set from env") 855 } 856 }, 857 } 858 a.Run([]string{"run"}) 859 }