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  }