...

Source file src/github.com/urfave/cli/v2/altsrc/flag_test.go

Documentation: github.com/urfave/cli/v2/altsrc

     1  package altsrc
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  	"runtime"
     9  	"strings"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/urfave/cli/v2"
    14  )
    15  
    16  type testApplyInputSource struct {
    17  	Flag               FlagInputSourceExtension
    18  	FlagName           string
    19  	FlagSetName        string
    20  	Expected           string
    21  	ContextValueString string
    22  	ContextValue       flag.Value
    23  	EnvVarValue        string
    24  	EnvVarName         string
    25  	SourcePath         string
    26  	MapValue           interface{}
    27  }
    28  
    29  type racyInputSource struct {
    30  	*MapInputSource
    31  }
    32  
    33  func (ris *racyInputSource) isSet(name string) bool {
    34  	if _, ok := ris.MapInputSource.valueMap[name]; ok {
    35  		ris.MapInputSource.valueMap[name] = bogus{0}
    36  	}
    37  	return true
    38  }
    39  
    40  func TestGenericApplyInputSourceValue_Alias(t *testing.T) {
    41  	v := &Parser{"abc", "def"}
    42  	tis := testApplyInputSource{
    43  		Flag:     NewGenericFlag(&cli.GenericFlag{Name: "test", Aliases: []string{"test_alias"}, Value: &Parser{}}),
    44  		FlagName: "test_alias",
    45  		MapValue: v,
    46  	}
    47  	c := runTest(t, tis)
    48  	expect(t, v, c.Generic("test_alias"))
    49  
    50  	c = runRacyTest(t, tis)
    51  	refute(t, v, c.Generic("test_alias"))
    52  }
    53  
    54  func TestGenericApplyInputSourceValue(t *testing.T) {
    55  	v := &Parser{"abc", "def"}
    56  	tis := testApplyInputSource{
    57  		Flag:     NewGenericFlag(&cli.GenericFlag{Name: "test", Value: &Parser{}}),
    58  		FlagName: "test",
    59  		MapValue: v,
    60  	}
    61  	c := runTest(t, tis)
    62  	expect(t, v, c.Generic("test"))
    63  
    64  	c = runRacyTest(t, tis)
    65  	refute(t, v, c.Generic("test"))
    66  }
    67  
    68  func TestGenericApplyInputSourceValueError(t *testing.T) {
    69  	set := flag.NewFlagSet("", flag.ContinueOnError)
    70  	c := cli.NewContext(nil, set, nil)
    71  
    72  	testFlag := &GenericFlag{
    73  		GenericFlag: &cli.GenericFlag{
    74  			Name:  "test",
    75  			Value: &cli.StringSlice{},
    76  		},
    77  		set: set,
    78  	}
    79  
    80  	err := testFlag.ApplyInputSourceValue(c, NewMapInputSource("", map[interface{}]interface{}{
    81  		"test": testFlag.Value,
    82  	}))
    83  	expect(t, err, fmt.Errorf("no such flag -test"))
    84  }
    85  
    86  func TestGenericApplyInputSourceMethodContextSet(t *testing.T) {
    87  	p := &Parser{"abc", "def"}
    88  	tis := testApplyInputSource{
    89  		Flag:               NewGenericFlag(&cli.GenericFlag{Name: "test", Value: &Parser{}}),
    90  		FlagName:           "test",
    91  		MapValue:           &Parser{"efg", "hig"},
    92  		ContextValueString: p.String(),
    93  	}
    94  	c := runTest(t, tis)
    95  	expect(t, p, c.Generic("test"))
    96  
    97  	c = runRacyTest(t, tis)
    98  	refute(t, p, c.Generic("test"))
    99  }
   100  
   101  func TestGenericApplyInputSourceMethodEnvVarSet(t *testing.T) {
   102  	tis := testApplyInputSource{
   103  		Flag: NewGenericFlag(&cli.GenericFlag{
   104  			Name:    "test",
   105  			Value:   &Parser{},
   106  			EnvVars: []string{"TEST"},
   107  		}),
   108  		FlagName:    "test",
   109  		MapValue:    &Parser{"efg", "hij"},
   110  		EnvVarName:  "TEST",
   111  		EnvVarValue: "abc,def",
   112  	}
   113  	c := runTest(t, tis)
   114  	expect(t, &Parser{"abc", "def"}, c.Generic("test"))
   115  
   116  	c = runRacyTest(t, tis)
   117  	refute(t, &Parser{"abc", "def"}, c.Generic("test"))
   118  }
   119  
   120  func TestStringSliceApplyInputSourceValue_Alias(t *testing.T) {
   121  	dest := cli.NewStringSlice()
   122  	tis := testApplyInputSource{
   123  		Flag:     NewStringSliceFlag(&cli.StringSliceFlag{Name: "test", Aliases: []string{"test_alias"}, Destination: dest}),
   124  		FlagName: "test_alias",
   125  		MapValue: []interface{}{"hello", "world"},
   126  	}
   127  	c := runTest(t, tis)
   128  	expect(t, c.StringSlice("test_alias"), []string{"hello", "world"})
   129  	expect(t, dest.Value(), []string{"hello", "world"})
   130  
   131  	// reset dest
   132  	dest = cli.NewStringSlice()
   133  	tis = testApplyInputSource{
   134  		Flag:     NewStringSliceFlag(&cli.StringSliceFlag{Name: "test", Aliases: []string{"test_alias"}, Destination: dest}),
   135  		FlagName: "test_alias",
   136  		MapValue: []interface{}{"hello", "world"},
   137  	}
   138  	c = runRacyTest(t, tis)
   139  	refute(t, c.StringSlice("test_alias"), []string{"hello", "world"})
   140  	refute(t, dest.Value(), []string{"hello", "world"})
   141  }
   142  
   143  func TestStringSliceApplyInputSourceValue(t *testing.T) {
   144  	dest := cli.NewStringSlice()
   145  	tis := testApplyInputSource{
   146  		Flag:     NewStringSliceFlag(&cli.StringSliceFlag{Name: "test", Destination: dest}),
   147  		FlagName: "test",
   148  		MapValue: []interface{}{"hello", "world"},
   149  	}
   150  	c := runTest(t, tis)
   151  	expect(t, c.StringSlice("test"), []string{"hello", "world"})
   152  	expect(t, dest.Value(), []string{"hello", "world"})
   153  
   154  	// reset dest
   155  	dest = cli.NewStringSlice()
   156  	tis = testApplyInputSource{
   157  		Flag:     NewStringSliceFlag(&cli.StringSliceFlag{Name: "test", Destination: dest}),
   158  		FlagName: "test",
   159  		MapValue: []interface{}{"hello", "world"},
   160  	}
   161  	c = runRacyTest(t, tis)
   162  	refute(t, c.StringSlice("test"), []string{"hello", "world"})
   163  	refute(t, dest.Value(), []string{"hello", "world"})
   164  }
   165  
   166  func TestStringSliceApplyInputSourceMethodContextSet(t *testing.T) {
   167  	dest := cli.NewStringSlice()
   168  	c := runTest(t, testApplyInputSource{
   169  		Flag:               NewStringSliceFlag(&cli.StringSliceFlag{Name: "test", Destination: dest}),
   170  		FlagName:           "test",
   171  		MapValue:           []interface{}{"hello", "world"},
   172  		ContextValueString: "ohno",
   173  	})
   174  	expect(t, c.StringSlice("test"), []string{"ohno"})
   175  	expect(t, dest.Value(), []string{"ohno"})
   176  }
   177  
   178  func TestStringSliceApplyInputSourceMethodEnvVarSet(t *testing.T) {
   179  	tis := testApplyInputSource{
   180  		Flag:        NewStringSliceFlag(&cli.StringSliceFlag{Name: "test", EnvVars: []string{"TEST"}}),
   181  		FlagName:    "test",
   182  		MapValue:    []interface{}{"hello", "world"},
   183  		EnvVarName:  "TEST",
   184  		EnvVarValue: "oh,no",
   185  	}
   186  	c := runTest(t, tis)
   187  	expect(t, c.StringSlice("test"), []string{"oh", "no"})
   188  
   189  	c = runRacyTest(t, tis)
   190  	refute(t, c.StringSlice("test"), []string{"oh", "no"})
   191  }
   192  
   193  func TestIntSliceApplyInputSourceValue_Alias(t *testing.T) {
   194  	dest := cli.NewIntSlice()
   195  	tis := testApplyInputSource{
   196  		Flag:     NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", Aliases: []string{"test_alias"}, Destination: dest}),
   197  		FlagName: "test_alias",
   198  		MapValue: []interface{}{1, 2},
   199  	}
   200  	c := runTest(t, tis)
   201  	expect(t, c.IntSlice("test_alias"), []int{1, 2})
   202  	expect(t, dest.Value(), []int{1, 2})
   203  
   204  	dest = cli.NewIntSlice()
   205  	tis = testApplyInputSource{
   206  		Flag:     NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", Aliases: []string{"test_alias"}, Destination: dest}),
   207  		FlagName: "test_alias",
   208  		MapValue: []interface{}{1, 2},
   209  	}
   210  	c = runRacyTest(t, tis)
   211  	refute(t, c.IntSlice("test_alias"), []int{1, 2})
   212  	refute(t, dest.Value(), []int{1, 2})
   213  }
   214  
   215  func TestIntSliceApplyInputSourceValue(t *testing.T) {
   216  	dest := cli.NewIntSlice()
   217  	tis := testApplyInputSource{
   218  		Flag:     NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", Destination: dest}),
   219  		FlagName: "test",
   220  		MapValue: []interface{}{1, 2},
   221  	}
   222  	c := runTest(t, tis)
   223  	expect(t, c.IntSlice("test"), []int{1, 2})
   224  	expect(t, dest.Value(), []int{1, 2})
   225  
   226  	// reset dest
   227  	dest = cli.NewIntSlice()
   228  	tis = testApplyInputSource{
   229  		Flag:     NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", Destination: dest}),
   230  		FlagName: "test",
   231  		MapValue: []interface{}{1, 2},
   232  	}
   233  	c = runRacyTest(t, tis)
   234  	refute(t, c.IntSlice("test"), []int{1, 2})
   235  	refute(t, dest.Value(), []int{1, 2})
   236  }
   237  
   238  func TestIntSliceApplyInputSourceMethodContextSet(t *testing.T) {
   239  	dest := cli.NewIntSlice()
   240  	tis := testApplyInputSource{
   241  		Flag:               NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", Destination: dest}),
   242  		FlagName:           "test",
   243  		MapValue:           []interface{}{1, 2},
   244  		ContextValueString: "3",
   245  	}
   246  	c := runTest(t, tis)
   247  	expect(t, c.IntSlice("test"), []int{3})
   248  	expect(t, dest.Value(), []int{3})
   249  
   250  	// reset dest
   251  	dest = cli.NewIntSlice()
   252  	tis = testApplyInputSource{
   253  		Flag:               NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", Destination: dest}),
   254  		FlagName:           "test",
   255  		MapValue:           []interface{}{1, 2},
   256  		ContextValueString: "3",
   257  	}
   258  	c = runRacyTest(t, tis)
   259  	refute(t, c.IntSlice("test"), []int{3})
   260  	refute(t, dest.Value(), []int{3})
   261  }
   262  
   263  func TestIntSliceApplyInputSourceMethodEnvVarSet(t *testing.T) {
   264  	tis := testApplyInputSource{
   265  		Flag:        NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", EnvVars: []string{"TEST"}}),
   266  		FlagName:    "test",
   267  		MapValue:    []interface{}{1, 2},
   268  		EnvVarName:  "TEST",
   269  		EnvVarValue: "3,4",
   270  	}
   271  	c := runTest(t, tis)
   272  	expect(t, c.IntSlice("test"), []int{3, 4})
   273  
   274  	c = runRacyTest(t, tis)
   275  	refute(t, c.IntSlice("test"), []int{3, 4})
   276  }
   277  
   278  func TestInt64SliceFlagApplyInputSourceValue(t *testing.T) {
   279  	dest := cli.NewInt64Slice()
   280  	tis := testApplyInputSource{
   281  		Flag:     NewInt64SliceFlag(&cli.Int64SliceFlag{Name: "test", Destination: dest}),
   282  		FlagName: "test",
   283  		MapValue: []interface{}{int64(1), int64(2)},
   284  	}
   285  	c := runTest(t, tis)
   286  	expect(t, c.Int64Slice("test"), []int64{1, 2})
   287  	expect(t, dest.Value(), []int64{1, 2})
   288  
   289  	// reset dest
   290  	dest = cli.NewInt64Slice()
   291  	tis = testApplyInputSource{
   292  		Flag:     NewInt64SliceFlag(&cli.Int64SliceFlag{Name: "test", Destination: dest}),
   293  		FlagName: "test",
   294  		MapValue: []interface{}{int64(1), int64(2)},
   295  	}
   296  	c = runRacyTest(t, tis)
   297  	refute(t, c.IntSlice("test"), []int64{1, 2})
   298  	refute(t, dest.Value(), []int64{1, 2})
   299  }
   300  
   301  func TestInt64SliceFlagApplyInputSourceValueNotSet(t *testing.T) {
   302  	dest := cli.NewInt64Slice()
   303  	tis := testApplyInputSource{
   304  		Flag:     NewInt64SliceFlag(&cli.Int64SliceFlag{Name: "test", Destination: dest}),
   305  		FlagName: "test1",
   306  		MapValue: []interface{}{int64(1), int64(2)},
   307  	}
   308  	c := runTest(t, tis)
   309  	expect(t, c.Int64Slice("test"), []int64{})
   310  	expect(t, dest.Value(), []int64{})
   311  }
   312  
   313  func TestFloat64SliceFlagApplyInputSourceValue(t *testing.T) {
   314  	dest := cli.NewFloat64Slice()
   315  	tis := testApplyInputSource{
   316  		Flag:     NewFloat64SliceFlag(&cli.Float64SliceFlag{Name: "test", Destination: dest}),
   317  		FlagName: "test",
   318  		MapValue: []interface{}{float64(1.0), float64(2.1)},
   319  	}
   320  	c := runTest(t, tis)
   321  	expect(t, c.Float64Slice("test"), []float64{1.0, 2.1})
   322  	expect(t, dest.Value(), []float64{1.0, 2.1})
   323  
   324  	// reset dest
   325  	dest = cli.NewFloat64Slice()
   326  	tis = testApplyInputSource{
   327  		Flag:     NewFloat64SliceFlag(&cli.Float64SliceFlag{Name: "test", Destination: dest}),
   328  		FlagName: "test",
   329  		MapValue: []interface{}{float64(1.0), float64(2.1)},
   330  	}
   331  	c = runRacyTest(t, tis)
   332  	refute(t, c.IntSlice("test"), []int64{1, 2})
   333  	refute(t, dest.Value(), []int64{1, 2})
   334  }
   335  
   336  func TestFloat64SliceFlagApplyInputSourceValueNotSet(t *testing.T) {
   337  	dest := cli.NewFloat64Slice()
   338  	tis := testApplyInputSource{
   339  		Flag:     NewFloat64SliceFlag(&cli.Float64SliceFlag{Name: "test", Destination: dest}),
   340  		FlagName: "test1",
   341  		MapValue: []interface{}{float64(1.0), float64(2.1)},
   342  	}
   343  	c := runTest(t, tis)
   344  	expect(t, c.Float64Slice("test"), []float64{})
   345  	expect(t, dest.Value(), []float64{})
   346  }
   347  
   348  func TestFloat64SliceFlagApplyInputSourceValueInvalidType(t *testing.T) {
   349  	dest := cli.NewFloat64Slice()
   350  	tis := testApplyInputSource{
   351  		Flag:     NewFloat64SliceFlag(&cli.Float64SliceFlag{Name: "test", Destination: dest}),
   352  		FlagName: "test",
   353  		MapValue: []interface{}{1, 2},
   354  	}
   355  	c := runTest(t, tis)
   356  	expect(t, c.Float64Slice("test"), []float64{})
   357  	expect(t, dest.Value(), []float64{})
   358  }
   359  
   360  func TestBoolApplyInputSourceMethodSet(t *testing.T) {
   361  	tis := testApplyInputSource{
   362  		Flag:     NewBoolFlag(&cli.BoolFlag{Name: "test"}),
   363  		FlagName: "test",
   364  		MapValue: true,
   365  	}
   366  	c := runTest(t, tis)
   367  	expect(t, true, c.Bool("test"))
   368  
   369  	c = runRacyTest(t, tis)
   370  	refute(t, true, c.Bool("test"))
   371  }
   372  
   373  func TestBoolApplyInputSourceMethodSet_Alias(t *testing.T) {
   374  	tis := testApplyInputSource{
   375  		Flag:     NewBoolFlag(&cli.BoolFlag{Name: "test", Aliases: []string{"test_alias"}}),
   376  		FlagName: "test_alias",
   377  		MapValue: true,
   378  	}
   379  	c := runTest(t, tis)
   380  	expect(t, true, c.Bool("test_alias"))
   381  
   382  	c = runRacyTest(t, tis)
   383  	refute(t, true, c.Bool("test_alias"))
   384  }
   385  
   386  func TestBoolApplyInputSourceMethodContextSet(t *testing.T) {
   387  	tis := testApplyInputSource{
   388  		Flag:               NewBoolFlag(&cli.BoolFlag{Name: "test"}),
   389  		FlagName:           "test",
   390  		MapValue:           false,
   391  		ContextValueString: "true",
   392  	}
   393  	c := runTest(t, tis)
   394  	expect(t, true, c.Bool("test"))
   395  
   396  	c = runRacyTest(t, tis)
   397  	refute(t, true, c.Bool("test"))
   398  }
   399  
   400  func TestBoolApplyInputSourceMethodEnvVarSet(t *testing.T) {
   401  	tis := testApplyInputSource{
   402  		Flag:        NewBoolFlag(&cli.BoolFlag{Name: "test", EnvVars: []string{"TEST"}}),
   403  		FlagName:    "test",
   404  		MapValue:    false,
   405  		EnvVarName:  "TEST",
   406  		EnvVarValue: "true",
   407  	}
   408  	c := runTest(t, tis)
   409  	expect(t, true, c.Bool("test"))
   410  
   411  	c = runRacyTest(t, tis)
   412  	refute(t, true, c.Bool("test"))
   413  }
   414  
   415  func TestStringApplyInputSourceMethodSet_Alias(t *testing.T) {
   416  	tis := testApplyInputSource{
   417  		Flag:     NewStringFlag(&cli.StringFlag{Name: "test", Aliases: []string{"test_alias"}}),
   418  		FlagName: "test_alias",
   419  		MapValue: "hello",
   420  	}
   421  	c := runTest(t, tis)
   422  	expect(t, "hello", c.String("test_alias"))
   423  
   424  	c = runRacyTest(t, tis)
   425  	refute(t, "hello", c.String("test_alias"))
   426  }
   427  
   428  func TestStringApplyInputSourceMethodSet(t *testing.T) {
   429  	tis := testApplyInputSource{
   430  		Flag:     NewStringFlag(&cli.StringFlag{Name: "test"}),
   431  		FlagName: "test",
   432  		MapValue: "hello",
   433  	}
   434  	c := runTest(t, tis)
   435  	expect(t, "hello", c.String("test"))
   436  
   437  	c = runRacyTest(t, tis)
   438  	refute(t, "hello", c.String("test"))
   439  }
   440  
   441  func TestStringApplyInputSourceMethodContextSet(t *testing.T) {
   442  	tis := testApplyInputSource{
   443  		Flag:               NewStringFlag(&cli.StringFlag{Name: "test"}),
   444  		FlagName:           "test",
   445  		MapValue:           "hello",
   446  		ContextValueString: "goodbye",
   447  	}
   448  	c := runTest(t, tis)
   449  	expect(t, "goodbye", c.String("test"))
   450  
   451  	c = runRacyTest(t, tis)
   452  	refute(t, "goodbye", c.String("test"))
   453  }
   454  
   455  func TestStringApplyInputSourceMethodEnvVarSet(t *testing.T) {
   456  	tis := testApplyInputSource{
   457  		Flag:        NewStringFlag(&cli.StringFlag{Name: "test", EnvVars: []string{"TEST"}}),
   458  		FlagName:    "test",
   459  		MapValue:    "hello",
   460  		EnvVarName:  "TEST",
   461  		EnvVarValue: "goodbye",
   462  	}
   463  	c := runTest(t, tis)
   464  	expect(t, "goodbye", c.String("test"))
   465  
   466  	c = runRacyTest(t, tis)
   467  	refute(t, "goodbye", c.String("test"))
   468  }
   469  
   470  func TestPathApplyInputSourceMethodSet_Alias(t *testing.T) {
   471  	tis := testApplyInputSource{
   472  		Flag:       NewPathFlag(&cli.PathFlag{Name: "test", Aliases: []string{"test_alias"}}),
   473  		FlagName:   "test_alias",
   474  		MapValue:   "hello",
   475  		SourcePath: "/path/to/source/file",
   476  	}
   477  	c := runTest(t, tis)
   478  
   479  	expected := "/path/to/source/hello"
   480  	if runtime.GOOS == "windows" {
   481  		var err error
   482  		// Prepend the corresponding drive letter (or UNC path?), and change
   483  		// to windows-style path:
   484  		expected, err = filepath.Abs(expected)
   485  		if err != nil {
   486  			t.Fatal(err)
   487  		}
   488  	}
   489  	expect(t, expected, c.String("test_alias"))
   490  
   491  	c = runRacyTest(t, tis)
   492  	refute(t, expected, c.String("test_alias"))
   493  }
   494  
   495  func TestPathApplyInputSourceMethodSet(t *testing.T) {
   496  	tis := testApplyInputSource{
   497  		Flag:       NewPathFlag(&cli.PathFlag{Name: "test"}),
   498  		FlagName:   "test",
   499  		MapValue:   "hello",
   500  		SourcePath: "/path/to/source/file",
   501  	}
   502  	c := runTest(t, tis)
   503  
   504  	expected := "/path/to/source/hello"
   505  	if runtime.GOOS == "windows" {
   506  		var err error
   507  		// Prepend the corresponding drive letter (or UNC path?), and change
   508  		// to windows-style path:
   509  		expected, err = filepath.Abs(expected)
   510  		if err != nil {
   511  			t.Fatal(err)
   512  		}
   513  	}
   514  	expect(t, expected, c.String("test"))
   515  
   516  	c = runRacyTest(t, tis)
   517  	refute(t, expected, c.String("test"))
   518  }
   519  
   520  func TestPathApplyInputSourceMethodContextSet(t *testing.T) {
   521  	tis := testApplyInputSource{
   522  		Flag:               NewPathFlag(&cli.PathFlag{Name: "test"}),
   523  		FlagName:           "test",
   524  		MapValue:           "hello",
   525  		ContextValueString: "goodbye",
   526  		SourcePath:         "/path/to/source/file",
   527  	}
   528  	c := runTest(t, tis)
   529  	expect(t, "goodbye", c.String("test"))
   530  
   531  	c = runRacyTest(t, tis)
   532  	refute(t, "goodbye", c.String("test"))
   533  }
   534  
   535  func TestPathApplyInputSourceMethodEnvVarSet(t *testing.T) {
   536  	tis := testApplyInputSource{
   537  		Flag:        NewPathFlag(&cli.PathFlag{Name: "test", EnvVars: []string{"TEST"}}),
   538  		FlagName:    "test",
   539  		MapValue:    "hello",
   540  		EnvVarName:  "TEST",
   541  		EnvVarValue: "goodbye",
   542  		SourcePath:  "/path/to/source/file",
   543  	}
   544  	c := runTest(t, tis)
   545  	expect(t, "goodbye", c.String("test"))
   546  
   547  	c = runRacyTest(t, tis)
   548  	refute(t, "goodbye", c.String("test"))
   549  }
   550  
   551  func TestIntApplyInputSourceMethodSet_Alias(t *testing.T) {
   552  	tis := testApplyInputSource{
   553  		Flag:     NewIntFlag(&cli.IntFlag{Name: "test", Aliases: []string{"test_alias"}}),
   554  		FlagName: "test_alias",
   555  		MapValue: 15,
   556  	}
   557  	c := runTest(t, tis)
   558  	expect(t, 15, c.Int("test_alias"))
   559  
   560  	c = runRacyTest(t, tis)
   561  	refute(t, 15, c.Int("test_alias"))
   562  }
   563  
   564  func TestIntApplyInputSourceMethodSet(t *testing.T) {
   565  	tis := testApplyInputSource{
   566  		Flag:     NewIntFlag(&cli.IntFlag{Name: "test"}),
   567  		FlagName: "test",
   568  		MapValue: 15,
   569  	}
   570  	c := runTest(t, tis)
   571  	expect(t, 15, c.Int("test"))
   572  
   573  	c = runRacyTest(t, tis)
   574  	refute(t, 15, c.Int("test"))
   575  }
   576  
   577  func TestIntApplyInputSourceMethodSetNegativeValue(t *testing.T) {
   578  	tis := testApplyInputSource{
   579  		Flag:     NewIntFlag(&cli.IntFlag{Name: "test"}),
   580  		FlagName: "test",
   581  		MapValue: -1,
   582  	}
   583  	c := runTest(t, tis)
   584  	expect(t, -1, c.Int("test"))
   585  
   586  	c = runRacyTest(t, tis)
   587  	refute(t, -1, c.Int("test"))
   588  }
   589  
   590  func TestIntApplyInputSourceMethodContextSet(t *testing.T) {
   591  	tis := testApplyInputSource{
   592  		Flag:               NewIntFlag(&cli.IntFlag{Name: "test"}),
   593  		FlagName:           "test",
   594  		MapValue:           15,
   595  		ContextValueString: "7",
   596  	}
   597  	c := runTest(t, tis)
   598  	expect(t, 7, c.Int("test"))
   599  
   600  	c = runRacyTest(t, tis)
   601  	refute(t, 7, c.Int("test"))
   602  }
   603  
   604  func TestIntApplyInputSourceMethodContextNotSet(t *testing.T) {
   605  	tis := testApplyInputSource{
   606  		Flag:               NewIntFlag(&cli.IntFlag{Name: "test"}),
   607  		FlagName:           "test1",
   608  		MapValue:           15,
   609  		ContextValueString: "7",
   610  	}
   611  	c := runTest(t, tis)
   612  	expect(t, 0, c.Int("test"))
   613  }
   614  
   615  func TestIntApplyInputSourceMethodContextSetInvalidType(t *testing.T) {
   616  	tis := testApplyInputSource{
   617  		Flag:               NewIntFlag(&cli.IntFlag{Name: "test"}),
   618  		FlagName:           "test",
   619  		ContextValueString: "d",
   620  	}
   621  	c := runTest(t, tis)
   622  	expect(t, 0, c.Int("test"))
   623  }
   624  
   625  func TestIntApplyInputSourceMethodEnvVarSet(t *testing.T) {
   626  	tis := testApplyInputSource{
   627  		Flag:        NewIntFlag(&cli.IntFlag{Name: "test", EnvVars: []string{"TEST"}}),
   628  		FlagName:    "test",
   629  		MapValue:    15,
   630  		EnvVarName:  "TEST",
   631  		EnvVarValue: "12",
   632  	}
   633  	c := runTest(t, tis)
   634  	expect(t, 12, c.Int("test"))
   635  
   636  	c = runRacyTest(t, tis)
   637  	refute(t, 12, c.Int("test"))
   638  }
   639  
   640  func TestInt64ApplyInputSourceMethodSet_Alias(t *testing.T) {
   641  	tis := testApplyInputSource{
   642  		Flag:     NewInt64Flag(&cli.Int64Flag{Name: "test", Aliases: []string{"test_alias"}}),
   643  		FlagName: "test_alias",
   644  		MapValue: int64(15),
   645  	}
   646  	c := runTest(t, tis)
   647  	expect(t, int64(15), c.Int64("test_alias"))
   648  
   649  	c = runRacyTest(t, tis)
   650  	refute(t, int64(15), c.Int64("test_alias"))
   651  }
   652  
   653  func TestInt64ApplyInputSourceMethodSet(t *testing.T) {
   654  	tis := testApplyInputSource{
   655  		Flag:     NewInt64Flag(&cli.Int64Flag{Name: "test"}),
   656  		FlagName: "test",
   657  		MapValue: int64(15),
   658  	}
   659  	c := runTest(t, tis)
   660  	expect(t, int64(15), c.Int64("test"))
   661  
   662  	c = runRacyTest(t, tis)
   663  	refute(t, int64(15), c.Int("test"))
   664  }
   665  
   666  func TestInt64ApplyInputSourceMethodSetNegativeValue(t *testing.T) {
   667  	tis := testApplyInputSource{
   668  		Flag:     NewInt64Flag(&cli.Int64Flag{Name: "test"}),
   669  		FlagName: "test",
   670  		MapValue: int64(-1),
   671  	}
   672  	c := runTest(t, tis)
   673  	expect(t, int64(-1), c.Int64("test"))
   674  
   675  	c = runRacyTest(t, tis)
   676  	refute(t, int64(-1), c.Int("test"))
   677  }
   678  
   679  func TestInt64ApplyInputSourceMethodContextSet(t *testing.T) {
   680  	tis := testApplyInputSource{
   681  		Flag:               NewInt64Flag(&cli.Int64Flag{Name: "test"}),
   682  		FlagName:           "test",
   683  		MapValue:           15,
   684  		ContextValueString: "7",
   685  	}
   686  	c := runTest(t, tis)
   687  	expect(t, int64(7), c.Int64("test"))
   688  
   689  	c = runRacyTest(t, tis)
   690  	refute(t, int64(7), c.Int64("test"))
   691  }
   692  
   693  func TestInt64ApplyInputSourceMethodContextNotSet(t *testing.T) {
   694  	tis := testApplyInputSource{
   695  		Flag:               NewInt64Flag(&cli.Int64Flag{Name: "test"}),
   696  		FlagName:           "test1",
   697  		MapValue:           15,
   698  		ContextValueString: "7",
   699  	}
   700  	c := runTest(t, tis)
   701  	expect(t, int64(0), c.Int64("test"))
   702  }
   703  
   704  func TestInt64ApplyInputSourceMethodContextSetInvalidType(t *testing.T) {
   705  	tis := testApplyInputSource{
   706  		Flag:               NewInt64Flag(&cli.Int64Flag{Name: "test"}),
   707  		FlagName:           "test",
   708  		ContextValueString: "d",
   709  	}
   710  	c := runTest(t, tis)
   711  	expect(t, int64(0), c.Int64("test"))
   712  }
   713  
   714  func TestInt64ApplyInputSourceMethodEnvVarSet(t *testing.T) {
   715  	tis := testApplyInputSource{
   716  		Flag:        NewInt64Flag(&cli.Int64Flag{Name: "test", EnvVars: []string{"TEST"}}),
   717  		FlagName:    "test",
   718  		MapValue:    15,
   719  		EnvVarName:  "TEST",
   720  		EnvVarValue: "12",
   721  	}
   722  	c := runTest(t, tis)
   723  	expect(t, int64(12), c.Int64("test"))
   724  
   725  	c = runRacyTest(t, tis)
   726  	refute(t, int64(12), c.Int64("test"))
   727  }
   728  
   729  func TestUintApplyInputSourceMethodSet_Alias(t *testing.T) {
   730  	tis := testApplyInputSource{
   731  		Flag:     NewUintFlag(&cli.UintFlag{Name: "test", Aliases: []string{"test_alias"}}),
   732  		FlagName: "test_alias",
   733  		MapValue: uint(15),
   734  	}
   735  	c := runTest(t, tis)
   736  	expect(t, uint(15), c.Uint("test_alias"))
   737  
   738  	c = runRacyTest(t, tis)
   739  	refute(t, uint(15), c.Uint("test_alias"))
   740  }
   741  
   742  func TestUintApplyInputSourceMethodSet(t *testing.T) {
   743  	tis := testApplyInputSource{
   744  		Flag:     NewUintFlag(&cli.UintFlag{Name: "test"}),
   745  		FlagName: "test",
   746  		MapValue: uint(15),
   747  	}
   748  	c := runTest(t, tis)
   749  	expect(t, uint(15), c.Uint("test"))
   750  
   751  	c = runRacyTest(t, tis)
   752  	refute(t, uint(15), c.Uint("test"))
   753  }
   754  
   755  func TestUintApplyInputSourceMethodContextSet(t *testing.T) {
   756  	tis := testApplyInputSource{
   757  		Flag:               NewUintFlag(&cli.UintFlag{Name: "test"}),
   758  		FlagName:           "test",
   759  		MapValue:           uint(15),
   760  		ContextValueString: "7",
   761  	}
   762  	c := runTest(t, tis)
   763  	expect(t, uint(7), c.Uint("test"))
   764  
   765  	c = runRacyTest(t, tis)
   766  	refute(t, uint(7), c.Uint("test"))
   767  }
   768  
   769  func TestUint64ApplyInputSourceMethodSet_Alias(t *testing.T) {
   770  	tis := testApplyInputSource{
   771  		Flag:     NewUint64Flag(&cli.Uint64Flag{Name: "test", Aliases: []string{"test_alias"}}),
   772  		FlagName: "test_alias",
   773  		MapValue: uint64(15),
   774  	}
   775  	c := runTest(t, tis)
   776  	expect(t, uint64(15), c.Uint64("test_alias"))
   777  
   778  	c = runRacyTest(t, tis)
   779  	refute(t, uint64(15), c.Uint64("test_alias"))
   780  }
   781  
   782  func TestUint64ApplyInputSourceMethodSet(t *testing.T) {
   783  	tis := testApplyInputSource{
   784  		Flag:     NewUint64Flag(&cli.Uint64Flag{Name: "test"}),
   785  		FlagName: "test",
   786  		MapValue: uint64(15),
   787  	}
   788  	c := runTest(t, tis)
   789  	expect(t, uint64(15), c.Uint64("test"))
   790  
   791  	c = runRacyTest(t, tis)
   792  	refute(t, uint64(15), c.Uint64("test"))
   793  }
   794  
   795  func TestUint64ApplyInputSourceMethodContextSet(t *testing.T) {
   796  	tis := testApplyInputSource{
   797  		Flag:               NewUint64Flag(&cli.Uint64Flag{Name: "test"}),
   798  		FlagName:           "test",
   799  		MapValue:           uint64(15),
   800  		ContextValueString: "7",
   801  	}
   802  	c := runTest(t, tis)
   803  	expect(t, uint64(7), c.Uint64("test"))
   804  
   805  	c = runRacyTest(t, tis)
   806  	refute(t, uint64(7), c.Uint64("test"))
   807  }
   808  
   809  func TestUint64ApplyInputSourceMethodEnvVarSet(t *testing.T) {
   810  	tis := testApplyInputSource{
   811  		Flag:        NewUint64Flag(&cli.Uint64Flag{Name: "test", EnvVars: []string{"TEST"}}),
   812  		FlagName:    "test",
   813  		MapValue:    uint64(15),
   814  		EnvVarName:  "TEST",
   815  		EnvVarValue: "12",
   816  	}
   817  	c := runTest(t, tis)
   818  	expect(t, uint64(12), c.Uint64("test"))
   819  
   820  	c = runRacyTest(t, tis)
   821  	refute(t, uint64(12), c.Uint64("test"))
   822  }
   823  
   824  func TestDurationApplyInputSourceMethodSet_Alias(t *testing.T) {
   825  	tis := testApplyInputSource{
   826  		Flag:     NewDurationFlag(&cli.DurationFlag{Name: "test", Aliases: []string{"test_alias"}}),
   827  		FlagName: "test_alias",
   828  		MapValue: 30 * time.Second,
   829  	}
   830  	c := runTest(t, tis)
   831  	expect(t, 30*time.Second, c.Duration("test_alias"))
   832  
   833  	c = runRacyTest(t, tis)
   834  	refute(t, 30*time.Second, c.Duration("test_alias"))
   835  }
   836  
   837  func TestDurationApplyInputSourceMethodSet(t *testing.T) {
   838  	tis := testApplyInputSource{
   839  		Flag:     NewDurationFlag(&cli.DurationFlag{Name: "test"}),
   840  		FlagName: "test",
   841  		MapValue: 30 * time.Second,
   842  	}
   843  	c := runTest(t, tis)
   844  	expect(t, 30*time.Second, c.Duration("test"))
   845  
   846  	c = runRacyTest(t, tis)
   847  	refute(t, 30*time.Second, c.Duration("test"))
   848  }
   849  
   850  func TestDurationApplyInputSourceMethodSetNegativeValue(t *testing.T) {
   851  	tis := testApplyInputSource{
   852  		Flag:     NewDurationFlag(&cli.DurationFlag{Name: "test"}),
   853  		FlagName: "test",
   854  		MapValue: -30 * time.Second,
   855  	}
   856  	c := runTest(t, tis)
   857  	expect(t, -30*time.Second, c.Duration("test"))
   858  
   859  	c = runRacyTest(t, tis)
   860  	refute(t, -30*time.Second, c.Duration("test"))
   861  }
   862  
   863  func TestDurationApplyInputSourceMethodContextSet(t *testing.T) {
   864  	tis := testApplyInputSource{
   865  		Flag:               NewDurationFlag(&cli.DurationFlag{Name: "test"}),
   866  		FlagName:           "test",
   867  		MapValue:           30 * time.Second,
   868  		ContextValueString: (15 * time.Second).String(),
   869  	}
   870  	c := runTest(t, tis)
   871  	expect(t, 15*time.Second, c.Duration("test"))
   872  
   873  	c = runRacyTest(t, tis)
   874  	refute(t, 15*time.Second, c.Duration("test"))
   875  }
   876  
   877  func TestDurationApplyInputSourceMethodEnvVarSet(t *testing.T) {
   878  	tis := testApplyInputSource{
   879  		Flag:        NewDurationFlag(&cli.DurationFlag{Name: "test", EnvVars: []string{"TEST"}}),
   880  		FlagName:    "test",
   881  		MapValue:    30 * time.Second,
   882  		EnvVarName:  "TEST",
   883  		EnvVarValue: (15 * time.Second).String(),
   884  	}
   885  	c := runTest(t, tis)
   886  	expect(t, 15*time.Second, c.Duration("test"))
   887  
   888  	c = runRacyTest(t, tis)
   889  	refute(t, 15*time.Second, c.Duration("test"))
   890  }
   891  
   892  func TestFloat64ApplyInputSourceMethodSet(t *testing.T) {
   893  	tis := testApplyInputSource{
   894  		Flag:     NewFloat64Flag(&cli.Float64Flag{Name: "test"}),
   895  		FlagName: "test",
   896  		MapValue: 1.3,
   897  	}
   898  	c := runTest(t, tis)
   899  	expect(t, 1.3, c.Float64("test"))
   900  
   901  	c = runRacyTest(t, tis)
   902  	refute(t, 1.3, c.Float64("test"))
   903  }
   904  
   905  func TestFloat64ApplyInputSourceMethodSetNegativeValue_Alias(t *testing.T) {
   906  	tis := testApplyInputSource{
   907  		Flag:     NewFloat64Flag(&cli.Float64Flag{Name: "test", Aliases: []string{"test_alias"}}),
   908  		FlagName: "test_alias",
   909  		MapValue: -1.3,
   910  	}
   911  	c := runTest(t, tis)
   912  	expect(t, -1.3, c.Float64("test_alias"))
   913  
   914  	c = runRacyTest(t, tis)
   915  	refute(t, -1.3, c.Float64("test_alias"))
   916  }
   917  
   918  func TestFloat64ApplyInputSourceMethodSetNegativeValue(t *testing.T) {
   919  	tis := testApplyInputSource{
   920  		Flag:     NewFloat64Flag(&cli.Float64Flag{Name: "test"}),
   921  		FlagName: "test",
   922  		MapValue: -1.3,
   923  	}
   924  	c := runTest(t, tis)
   925  	expect(t, -1.3, c.Float64("test"))
   926  
   927  	c = runRacyTest(t, tis)
   928  	refute(t, -1.3, c.Float64("test"))
   929  }
   930  
   931  func TestFloat64ApplyInputSourceMethodSetNegativeValueNotSet(t *testing.T) {
   932  	c := runTest(t, testApplyInputSource{
   933  		Flag:     NewFloat64Flag(&cli.Float64Flag{Name: "test1"}),
   934  		FlagName: "test1",
   935  		// dont set map value
   936  	})
   937  	expect(t, 0.0, c.Float64("test1"))
   938  }
   939  
   940  func TestFloat64ApplyInputSourceMethodContextSet(t *testing.T) {
   941  	tis := testApplyInputSource{
   942  		Flag:               NewFloat64Flag(&cli.Float64Flag{Name: "test"}),
   943  		FlagName:           "test",
   944  		MapValue:           1.3,
   945  		ContextValueString: fmt.Sprintf("%v", 1.4),
   946  	}
   947  	c := runTest(t, tis)
   948  	expect(t, 1.4, c.Float64("test"))
   949  
   950  	c = runRacyTest(t, tis)
   951  	refute(t, 1.4, c.Float64("test"))
   952  }
   953  
   954  func TestFloat64ApplyInputSourceMethodEnvVarSet(t *testing.T) {
   955  	tis := testApplyInputSource{
   956  		Flag:        NewFloat64Flag(&cli.Float64Flag{Name: "test", EnvVars: []string{"TEST"}}),
   957  		FlagName:    "test",
   958  		MapValue:    1.3,
   959  		EnvVarName:  "TEST",
   960  		EnvVarValue: fmt.Sprintf("%v", 1.4),
   961  	}
   962  	c := runTest(t, tis)
   963  	expect(t, 1.4, c.Float64("test"))
   964  
   965  	c = runRacyTest(t, tis)
   966  	refute(t, 1.4, c.Float64("test"))
   967  }
   968  
   969  func runTest(t *testing.T, test testApplyInputSource) *cli.Context {
   970  	inputSource := &MapInputSource{
   971  		file:     test.SourcePath,
   972  		valueMap: map[interface{}]interface{}{test.FlagName: test.MapValue},
   973  	}
   974  	set := flag.NewFlagSet(test.FlagSetName, flag.ContinueOnError)
   975  	c := cli.NewContext(nil, set, nil)
   976  	if test.EnvVarName != "" && test.EnvVarValue != "" {
   977  		_ = os.Setenv(test.EnvVarName, test.EnvVarValue)
   978  		defer os.Setenv(test.EnvVarName, "")
   979  	}
   980  
   981  	_ = test.Flag.Apply(set)
   982  	if test.ContextValue != nil {
   983  		f := set.Lookup(test.FlagName)
   984  		f.Value = test.ContextValue
   985  	}
   986  	if test.ContextValueString != "" {
   987  		_ = set.Set(test.FlagName, test.ContextValueString)
   988  	}
   989  	_ = test.Flag.ApplyInputSourceValue(c, inputSource)
   990  
   991  	return c
   992  }
   993  
   994  func runRacyTest(t *testing.T, test testApplyInputSource) *cli.Context {
   995  	set := flag.NewFlagSet(test.FlagSetName, flag.ContinueOnError)
   996  	c := cli.NewContext(nil, set, nil)
   997  	_ = test.Flag.ApplyInputSourceValue(c, &racyInputSource{
   998  		MapInputSource: &MapInputSource{
   999  			file:     test.SourcePath,
  1000  			valueMap: map[interface{}]interface{}{test.FlagName: test.MapValue},
  1001  		},
  1002  	})
  1003  
  1004  	return c
  1005  }
  1006  
  1007  type Parser [2]string
  1008  
  1009  func (p *Parser) Set(value string) error {
  1010  	parts := strings.Split(value, ",")
  1011  	if len(parts) != 2 {
  1012  		return fmt.Errorf("invalid format")
  1013  	}
  1014  
  1015  	(*p)[0] = parts[0]
  1016  	(*p)[1] = parts[1]
  1017  
  1018  	return nil
  1019  }
  1020  
  1021  func (p *Parser) String() string {
  1022  	return fmt.Sprintf("%s,%s", p[0], p[1])
  1023  }
  1024  
  1025  type bogus [1]uint
  1026  

View as plain text