From eadd22c79d76616ae013e0d45edb3679d2b50907 Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Sun, 15 Jan 2023 17:39:19 -0500 Subject: [PATCH 1/4] Fix:(issue_1592) Add support for float64slice, uint, int, int64 for altsrc --- altsrc/flag.go | 88 ++++++++++++++++++++++++ altsrc/flag_test.go | 118 +++++++++++++++++++++++++++++++++ altsrc/input_source_context.go | 4 ++ altsrc/json_source_context.go | 80 ++++++++++++++++++++++ altsrc/map_input_source.go | 95 ++++++++++++++++++++++++++ godoc-current.txt | 26 ++++++++ testdata/godoc-v2.x.txt | 26 ++++++++ 7 files changed, 437 insertions(+) diff --git a/altsrc/flag.go b/altsrc/flag.go index d8256d7605..5a4bd1b7f8 100644 --- a/altsrc/flag.go +++ b/altsrc/flag.go @@ -179,6 +179,37 @@ func (f *Int64SliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourc return nil } +// ApplyInputSourceValue applies a Float64Slice value if required +func (f *Float64SliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error { + if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) { + return nil + } + for _, name := range f.Float64SliceFlag.Names() { + if !isc.isSet(name) { + continue + } + value, err := isc.Float64Slice(name) + if err != nil { + return err + } + if value == nil { + continue + } + var sliceValue = *(cli.NewFloat64Slice(value...)) + for _, n := range f.Names() { + underlyingFlag := f.set.Lookup(n) + if underlyingFlag == nil { + continue + } + underlyingFlag.Value = &sliceValue + } + if f.Destination != nil { + f.Destination.Set(sliceValue.Serialize()) + } + } + return nil +} + // ApplyInputSourceValue applies a Bool value to the flagSet if required func (f *BoolFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error { if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) { @@ -269,6 +300,63 @@ func (f *IntFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContex return nil } +func (f *Int64Flag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error { + if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) { + return nil + } + for _, name := range f.Int64Flag.Names() { + if !isc.isSet(name) { + continue + } + value, err := isc.Int64(name) + if err != nil { + return err + } + for _, n := range f.Names() { + _ = f.set.Set(n, strconv.FormatInt(value, 10)) + } + } + return nil +} + +func (f *UintFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error { + if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) { + return nil + } + for _, name := range f.UintFlag.Names() { + if !isc.isSet(name) { + continue + } + value, err := isc.Uint(name) + if err != nil { + return err + } + for _, n := range f.Names() { + _ = f.set.Set(n, strconv.FormatUint(uint64(value), 10)) + } + } + return nil +} + +func (f *Uint64Flag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error { + if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) { + return nil + } + for _, name := range f.Uint64Flag.Names() { + if !isc.isSet(name) { + continue + } + value, err := isc.Uint64(name) + if err != nil { + return err + } + for _, n := range f.Names() { + _ = f.set.Set(n, strconv.FormatUint(value, 10)) + } + } + return nil +} + // ApplyInputSourceValue applies a Duration value to the flagSet if required func (f *DurationFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error { if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) { diff --git a/altsrc/flag_test.go b/altsrc/flag_test.go index ad66dab43c..74cacaf123 100644 --- a/altsrc/flag_test.go +++ b/altsrc/flag_test.go @@ -280,6 +280,29 @@ func TestInt64SliceFlagApplyInputSourceValue(t *testing.T) { refute(t, dest.Value(), []int64{1, 2}) } +func TestFloat64SliceFlagApplyInputSourceValue(t *testing.T) { + dest := cli.NewFloat64Slice() + tis := testApplyInputSource{ + Flag: NewFloat64SliceFlag(&cli.Float64SliceFlag{Name: "test", Destination: dest}), + FlagName: "test", + MapValue: []interface{}{float64(1.0), float64(2.1)}, + } + c := runTest(t, tis) + expect(t, c.Float64Slice("test"), []float64{1.0, 2.1}) + expect(t, dest.Value(), []float64{1.0, 2.1}) + + // reset dest + dest = cli.NewFloat64Slice() + tis = testApplyInputSource{ + Flag: NewFloat64SliceFlag(&cli.Float64SliceFlag{Name: "test", Destination: dest}), + FlagName: "test", + MapValue: []interface{}{float64(1.0), float64(2.1)}, + } + c = runRacyTest(t, tis) + refute(t, c.IntSlice("test"), []int64{1, 2}) + refute(t, dest.Value(), []int64{1, 2}) +} + func TestBoolApplyInputSourceMethodSet(t *testing.T) { tis := testApplyInputSource{ Flag: NewBoolFlag(&cli.BoolFlag{Name: "test"}), @@ -539,6 +562,101 @@ func TestIntApplyInputSourceMethodEnvVarSet(t *testing.T) { refute(t, 12, c.Int("test")) } +func TestUintApplyInputSourceMethodSet_Alias(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewUintFlag(&cli.UintFlag{Name: "test", Aliases: []string{"test_alias"}}), + FlagName: "test_alias", + MapValue: uint(15), + } + c := runTest(t, tis) + expect(t, uint(15), c.Uint("test_alias")) + + c = runRacyTest(t, tis) + refute(t, uint(15), c.Uint("test_alias")) +} + +func TestUintApplyInputSourceMethodSet(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewUintFlag(&cli.UintFlag{Name: "test"}), + FlagName: "test", + MapValue: uint(15), + } + c := runTest(t, tis) + expect(t, uint(15), c.Uint("test")) + + c = runRacyTest(t, tis) + refute(t, uint(15), c.Uint("test")) +} + +func TestUintApplyInputSourceMethodContextSet(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewUintFlag(&cli.UintFlag{Name: "test"}), + FlagName: "test", + MapValue: uint(15), + ContextValueString: "7", + } + c := runTest(t, tis) + expect(t, uint(7), c.Uint("test")) + + c = runRacyTest(t, tis) + refute(t, uint(7), c.Uint("test")) +} + +func TestUint64ApplyInputSourceMethodSet_Alias(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewUint64Flag(&cli.Uint64Flag{Name: "test", Aliases: []string{"test_alias"}}), + FlagName: "test_alias", + MapValue: uint64(15), + } + c := runTest(t, tis) + expect(t, uint64(15), c.Uint64("test_alias")) + + c = runRacyTest(t, tis) + refute(t, uint64(15), c.Uint64("test_alias")) +} + +func TestUint64ApplyInputSourceMethodSet(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewUint64Flag(&cli.Uint64Flag{Name: "test"}), + FlagName: "test", + MapValue: uint64(15), + } + c := runTest(t, tis) + expect(t, uint64(15), c.Uint64("test")) + + c = runRacyTest(t, tis) + refute(t, uint64(15), c.Uint64("test")) +} + +func TestUint64ApplyInputSourceMethodContextSet(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewUint64Flag(&cli.Uint64Flag{Name: "test"}), + FlagName: "test", + MapValue: uint64(15), + ContextValueString: "7", + } + c := runTest(t, tis) + expect(t, uint64(7), c.Uint64("test")) + + c = runRacyTest(t, tis) + refute(t, uint64(7), c.Uint64("test")) +} + +func TestUint64ApplyInputSourceMethodEnvVarSet(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewUint64Flag(&cli.Uint64Flag{Name: "test", EnvVars: []string{"TEST"}}), + FlagName: "test", + MapValue: uint64(15), + EnvVarName: "TEST", + EnvVarValue: "12", + } + c := runTest(t, tis) + expect(t, uint64(12), c.Uint64("test")) + + c = runRacyTest(t, tis) + refute(t, uint64(12), c.Uint64("test")) +} + func TestDurationApplyInputSourceMethodSet_Alias(t *testing.T) { tis := testApplyInputSource{ Flag: NewDurationFlag(&cli.DurationFlag{Name: "test", Aliases: []string{"test_alias"}}), diff --git a/altsrc/input_source_context.go b/altsrc/input_source_context.go index 24579d16a9..8e6293aeb0 100644 --- a/altsrc/input_source_context.go +++ b/altsrc/input_source_context.go @@ -15,12 +15,16 @@ type InputSourceContext interface { Source() string Int(name string) (int, error) + Int64(name string) (int64, error) + Uint(name string) (uint, error) + Uint64(name string) (uint64, error) Duration(name string) (time.Duration, error) Float64(name string) (float64, error) String(name string) (string, error) StringSlice(name string) ([]string, error) IntSlice(name string) ([]int, error) Int64Slice(name string) ([]int64, error) + Float64Slice(name string) ([]float64, error) Generic(name string) (cli.Generic, error) Bool(name string) (bool, error) diff --git a/altsrc/json_source_context.go b/altsrc/json_source_context.go index ac0532076c..9beaca135e 100644 --- a/altsrc/json_source_context.go +++ b/altsrc/json_source_context.go @@ -78,6 +78,63 @@ func (x *jsonSource) Int(name string) (int, error) { } } +func (x *jsonSource) Int64(name string) (int64, error) { + i, err := x.getValue(name) + if err != nil { + return 0, err + } + switch v := i.(type) { + default: + return 0, fmt.Errorf("unexpected type %T for %q", i, name) + case int64: + return v, nil + case int: + return int64(v), nil + case float32: + return int64(v), nil + case float64: + return int64(v), nil + } +} + +func (x *jsonSource) Uint(name string) (uint, error) { + i, err := x.getValue(name) + if err != nil { + return 0, err + } + switch v := i.(type) { + default: + return 0, fmt.Errorf("unexpected type %T for %q", i, name) + case uint: + return v, nil + case uint64: + return uint(v), nil + case float32: + return uint(v), nil + case float64: + return uint(v), nil + } +} + +func (x *jsonSource) Uint64(name string) (uint64, error) { + i, err := x.getValue(name) + if err != nil { + return 0, err + } + switch v := i.(type) { + default: + return 0, fmt.Errorf("unexpected type %T for %q", i, name) + case uint64: + return v, nil + case uint: + return uint64(v), nil + case float32: + return uint64(v), nil + case float64: + return uint64(v), nil + } +} + func (x *jsonSource) Duration(name string) (time.Duration, error) { i, err := x.getValue(name) if err != nil { @@ -183,6 +240,29 @@ func (x *jsonSource) Int64Slice(name string) ([]int64, error) { } } +func (x *jsonSource) Float64Slice(name string) ([]float64, error) { + i, err := x.getValue(name) + if err != nil { + return nil, err + } + switch v := i.(type) { + default: + return nil, fmt.Errorf("unexpected type %T for %q", i, name) + case []float64: + return v, nil + case []interface{}: + c := []float64{} + for _, s := range v { + if i2, ok := s.(float64); ok { + c = append(c, i2) + } else { + return c, fmt.Errorf("unexpected item type %T in %T for %q", s, c, name) + } + } + return c, nil + } +} + func (x *jsonSource) Generic(name string) (cli.Generic, error) { i, err := x.getValue(name) if err != nil { diff --git a/altsrc/map_input_source.go b/altsrc/map_input_source.go index 2505b270eb..f401edb06e 100644 --- a/altsrc/map_input_source.go +++ b/altsrc/map_input_source.go @@ -127,6 +127,72 @@ func (fsm *MapInputSource) Float64(name string) (float64, error) { return 0, nil } +// Int64 returns an int64 from the map if it exists otherwise returns 0 +func (fsm *MapInputSource) Int64(name string) (int64, error) { + otherGenericValue, exists := fsm.valueMap[name] + if exists { + otherValue, isType := otherGenericValue.(int64) + if !isType { + return 0, incorrectTypeForFlagError(name, "int64", otherGenericValue) + } + return otherValue, nil + } + nestedGenericValue, exists := nestedVal(name, fsm.valueMap) + if exists { + otherValue, isType := nestedGenericValue.(int64) + if !isType { + return 0, incorrectTypeForFlagError(name, "int64", nestedGenericValue) + } + return otherValue, nil + } + + return 0, nil +} + +// Int64 returns an int64 from the map if it exists otherwise returns 0 +func (fsm *MapInputSource) Uint(name string) (uint, error) { + otherGenericValue, exists := fsm.valueMap[name] + if exists { + otherValue, isType := otherGenericValue.(uint) + if !isType { + return 0, incorrectTypeForFlagError(name, "uint", otherGenericValue) + } + return otherValue, nil + } + nestedGenericValue, exists := nestedVal(name, fsm.valueMap) + if exists { + otherValue, isType := nestedGenericValue.(uint) + if !isType { + return 0, incorrectTypeForFlagError(name, "uint", nestedGenericValue) + } + return otherValue, nil + } + + return 0, nil +} + +// UInt64 returns an uint64 from the map if it exists otherwise returns 0 +func (fsm *MapInputSource) Uint64(name string) (uint64, error) { + otherGenericValue, exists := fsm.valueMap[name] + if exists { + otherValue, isType := otherGenericValue.(uint64) + if !isType { + return 0, incorrectTypeForFlagError(name, "uint64", otherGenericValue) + } + return otherValue, nil + } + nestedGenericValue, exists := nestedVal(name, fsm.valueMap) + if exists { + otherValue, isType := nestedGenericValue.(uint64) + if !isType { + return 0, incorrectTypeForFlagError(name, "uint64", nestedGenericValue) + } + return otherValue, nil + } + + return 0, nil +} + // String returns a string from the map if it exists otherwise returns an empty string func (fsm *MapInputSource) String(name string) (string, error) { otherGenericValue, exists := fsm.valueMap[name] @@ -236,6 +302,35 @@ func (fsm *MapInputSource) Int64Slice(name string) ([]int64, error) { return int64Slice, nil } +// Float64Slice returns an []float64 from the map if it exists otherwise returns nil +func (fsm *MapInputSource) Float64Slice(name string) ([]float64, error) { + otherGenericValue, exists := fsm.valueMap[name] + if !exists { + otherGenericValue, exists = nestedVal(name, fsm.valueMap) + if !exists { + return nil, nil + } + } + + otherValue, isType := otherGenericValue.([]interface{}) + if !isType { + return nil, incorrectTypeForFlagError(name, "[]interface{}", otherGenericValue) + } + + var float64Slice = make([]float64, 0, len(otherValue)) + for i, v := range otherValue { + float64Value, isType := v.(float64) + + if !isType { + return nil, incorrectTypeForFlagError(fmt.Sprintf("%s[%d]", name, i), "int", v) + } + + float64Slice = append(float64Slice, float64Value) + } + + return float64Slice, nil +} + // Generic returns an cli.Generic from the map if it exists otherwise returns nil func (fsm *MapInputSource) Generic(name string) (cli.Generic, error) { otherGenericValue, exists := fsm.valueMap[name] diff --git a/godoc-current.txt b/godoc-current.txt index 1b0bef3112..c1eb170573 100644 --- a/godoc-current.txt +++ b/godoc-current.txt @@ -2417,6 +2417,9 @@ func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error Apply saves the flagSet for later usage calls, then calls the wrapped Float64SliceFlag.Apply +func (f *Float64SliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a Float64Slice value if required + type GenericFlag struct { *cli.GenericFlag // Has unexported fields. @@ -2438,12 +2441,16 @@ type InputSourceContext interface { Source() string Int(name string) (int, error) + Int64(name string) (int64, error) + Uint(name string) (uint, error) + Uint64(name string) (uint64, error) Duration(name string) (time.Duration, error) Float64(name string) (float64, error) String(name string) (string, error) StringSlice(name string) ([]string, error) IntSlice(name string) ([]int, error) Int64Slice(name string) ([]int64, error) + Float64Slice(name string) ([]float64, error) Generic(name string) (cli.Generic, error) Bool(name string) (bool, error) @@ -2487,6 +2494,8 @@ func (f *Int64Flag) Apply(set *flag.FlagSet) error Apply saves the flagSet for later usage calls, then calls the wrapped Int64Flag.Apply +func (f *Int64Flag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + type Int64SliceFlag struct { *cli.Int64SliceFlag // Has unexported fields. @@ -2557,6 +2566,10 @@ func (fsm *MapInputSource) Duration(name string) (time.Duration, error) func (fsm *MapInputSource) Float64(name string) (float64, error) Float64 returns an float64 from the map if it exists otherwise returns 0 +func (fsm *MapInputSource) Float64Slice(name string) ([]float64, error) + Float64Slice returns an []float64 from the map if it exists otherwise + returns nil + func (fsm *MapInputSource) Generic(name string) (cli.Generic, error) Generic returns an cli.Generic from the map if it exists otherwise returns nil @@ -2564,6 +2577,9 @@ func (fsm *MapInputSource) Generic(name string) (cli.Generic, error) func (fsm *MapInputSource) Int(name string) (int, error) Int returns an int from the map if it exists otherwise returns 0 +func (fsm *MapInputSource) Int64(name string) (int64, error) + Int64 returns an int64 from the map if it exists otherwise returns 0 + func (fsm *MapInputSource) Int64Slice(name string) ([]int64, error) Int64Slice returns an []int64 from the map if it exists otherwise returns nil @@ -2582,6 +2598,12 @@ func (fsm *MapInputSource) StringSlice(name string) ([]string, error) StringSlice returns an []string from the map if it exists otherwise returns nil +func (fsm *MapInputSource) Uint(name string) (uint, error) + Int64 returns an int64 from the map if it exists otherwise returns 0 + +func (fsm *MapInputSource) Uint64(name string) (uint64, error) + UInt64 returns an uint64 from the map if it exists otherwise returns 0 + type PathFlag struct { *cli.PathFlag // Has unexported fields. @@ -2647,6 +2669,8 @@ func (f *Uint64Flag) Apply(set *flag.FlagSet) error Apply saves the flagSet for later usage calls, then calls the wrapped Uint64Flag.Apply +func (f *Uint64Flag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + type UintFlag struct { *cli.UintFlag // Has unexported fields. @@ -2661,3 +2685,5 @@ func (f *UintFlag) Apply(set *flag.FlagSet) error Apply saves the flagSet for later usage calls, then calls the wrapped UintFlag.Apply +func (f *UintFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + diff --git a/testdata/godoc-v2.x.txt b/testdata/godoc-v2.x.txt index 1b0bef3112..c1eb170573 100644 --- a/testdata/godoc-v2.x.txt +++ b/testdata/godoc-v2.x.txt @@ -2417,6 +2417,9 @@ func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error Apply saves the flagSet for later usage calls, then calls the wrapped Float64SliceFlag.Apply +func (f *Float64SliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + ApplyInputSourceValue applies a Float64Slice value if required + type GenericFlag struct { *cli.GenericFlag // Has unexported fields. @@ -2438,12 +2441,16 @@ type InputSourceContext interface { Source() string Int(name string) (int, error) + Int64(name string) (int64, error) + Uint(name string) (uint, error) + Uint64(name string) (uint64, error) Duration(name string) (time.Duration, error) Float64(name string) (float64, error) String(name string) (string, error) StringSlice(name string) ([]string, error) IntSlice(name string) ([]int, error) Int64Slice(name string) ([]int64, error) + Float64Slice(name string) ([]float64, error) Generic(name string) (cli.Generic, error) Bool(name string) (bool, error) @@ -2487,6 +2494,8 @@ func (f *Int64Flag) Apply(set *flag.FlagSet) error Apply saves the flagSet for later usage calls, then calls the wrapped Int64Flag.Apply +func (f *Int64Flag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + type Int64SliceFlag struct { *cli.Int64SliceFlag // Has unexported fields. @@ -2557,6 +2566,10 @@ func (fsm *MapInputSource) Duration(name string) (time.Duration, error) func (fsm *MapInputSource) Float64(name string) (float64, error) Float64 returns an float64 from the map if it exists otherwise returns 0 +func (fsm *MapInputSource) Float64Slice(name string) ([]float64, error) + Float64Slice returns an []float64 from the map if it exists otherwise + returns nil + func (fsm *MapInputSource) Generic(name string) (cli.Generic, error) Generic returns an cli.Generic from the map if it exists otherwise returns nil @@ -2564,6 +2577,9 @@ func (fsm *MapInputSource) Generic(name string) (cli.Generic, error) func (fsm *MapInputSource) Int(name string) (int, error) Int returns an int from the map if it exists otherwise returns 0 +func (fsm *MapInputSource) Int64(name string) (int64, error) + Int64 returns an int64 from the map if it exists otherwise returns 0 + func (fsm *MapInputSource) Int64Slice(name string) ([]int64, error) Int64Slice returns an []int64 from the map if it exists otherwise returns nil @@ -2582,6 +2598,12 @@ func (fsm *MapInputSource) StringSlice(name string) ([]string, error) StringSlice returns an []string from the map if it exists otherwise returns nil +func (fsm *MapInputSource) Uint(name string) (uint, error) + Int64 returns an int64 from the map if it exists otherwise returns 0 + +func (fsm *MapInputSource) Uint64(name string) (uint64, error) + UInt64 returns an uint64 from the map if it exists otherwise returns 0 + type PathFlag struct { *cli.PathFlag // Has unexported fields. @@ -2647,6 +2669,8 @@ func (f *Uint64Flag) Apply(set *flag.FlagSet) error Apply saves the flagSet for later usage calls, then calls the wrapped Uint64Flag.Apply +func (f *Uint64Flag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + type UintFlag struct { *cli.UintFlag // Has unexported fields. @@ -2661,3 +2685,5 @@ func (f *UintFlag) Apply(set *flag.FlagSet) error Apply saves the flagSet for later usage calls, then calls the wrapped UintFlag.Apply +func (f *UintFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error + From 9d56eb7b453c64bb5d6b49ee6810f71aa460a3ef Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Sun, 22 Jan 2023 11:29:41 -0500 Subject: [PATCH 2/4] Add more tests --- altsrc/flag_test.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/altsrc/flag_test.go b/altsrc/flag_test.go index 74cacaf123..f617999560 100644 --- a/altsrc/flag_test.go +++ b/altsrc/flag_test.go @@ -280,6 +280,18 @@ func TestInt64SliceFlagApplyInputSourceValue(t *testing.T) { refute(t, dest.Value(), []int64{1, 2}) } +func TestInt64SliceFlagApplyInputSourceValueNotSet(t *testing.T) { + dest := cli.NewInt64Slice() + tis := testApplyInputSource{ + Flag: NewInt64SliceFlag(&cli.Int64SliceFlag{Name: "test", Destination: dest}), + FlagName: "test1", + MapValue: []interface{}{int64(1), int64(2)}, + } + c := runTest(t, tis) + expect(t, c.Int64Slice("test"), []int64{}) + expect(t, dest.Value(), []int64{}) +} + func TestFloat64SliceFlagApplyInputSourceValue(t *testing.T) { dest := cli.NewFloat64Slice() tis := testApplyInputSource{ @@ -303,6 +315,18 @@ func TestFloat64SliceFlagApplyInputSourceValue(t *testing.T) { refute(t, dest.Value(), []int64{1, 2}) } +func TestFloat64SliceFlagApplyInputSourceValueNotSet(t *testing.T) { + dest := cli.NewFloat64Slice() + tis := testApplyInputSource{ + Flag: NewFloat64SliceFlag(&cli.Float64SliceFlag{Name: "test", Destination: dest}), + FlagName: "test1", + MapValue: []interface{}{float64(1.0), float64(2.1)}, + } + c := runTest(t, tis) + expect(t, c.Float64Slice("test"), []float64{}) + expect(t, dest.Value(), []float64{}) +} + func TestBoolApplyInputSourceMethodSet(t *testing.T) { tis := testApplyInputSource{ Flag: NewBoolFlag(&cli.BoolFlag{Name: "test"}), From b8d3bbef98e23b15ed0ca0b49ad9a8ab4010caa7 Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Sun, 22 Jan 2023 11:41:06 -0500 Subject: [PATCH 3/4] Add more tests --- altsrc/flag_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/altsrc/flag_test.go b/altsrc/flag_test.go index f617999560..fff943579d 100644 --- a/altsrc/flag_test.go +++ b/altsrc/flag_test.go @@ -327,6 +327,18 @@ func TestFloat64SliceFlagApplyInputSourceValueNotSet(t *testing.T) { expect(t, dest.Value(), []float64{}) } +func TestFloat64SliceFlagApplyInputSourceValueInvalidType(t *testing.T) { + dest := cli.NewFloat64Slice() + tis := testApplyInputSource{ + Flag: NewFloat64SliceFlag(&cli.Float64SliceFlag{Name: "test", Destination: dest}), + FlagName: "test", + MapValue: []interface{}{1, 2}, + } + c := runTest(t, tis) + expect(t, c.Float64Slice("test"), []float64{}) + expect(t, dest.Value(), []float64{}) +} + func TestBoolApplyInputSourceMethodSet(t *testing.T) { tis := testApplyInputSource{ Flag: NewBoolFlag(&cli.BoolFlag{Name: "test"}), From 3f207ee26759c0cf5f43b7af7fa37ac10b62c962 Mon Sep 17 00:00:00 2001 From: Naveen Gogineni Date: Sun, 22 Jan 2023 11:53:21 -0500 Subject: [PATCH 4/4] Add more tests --- altsrc/flag_test.go | 110 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/altsrc/flag_test.go b/altsrc/flag_test.go index fff943579d..9341ff2f24 100644 --- a/altsrc/flag_test.go +++ b/altsrc/flag_test.go @@ -583,6 +583,27 @@ func TestIntApplyInputSourceMethodContextSet(t *testing.T) { refute(t, 7, c.Int("test")) } +func TestIntApplyInputSourceMethodContextNotSet(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewIntFlag(&cli.IntFlag{Name: "test"}), + FlagName: "test1", + MapValue: 15, + ContextValueString: "7", + } + c := runTest(t, tis) + expect(t, 0, c.Int("test")) +} + +func TestIntApplyInputSourceMethodContextSetInvalidType(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewIntFlag(&cli.IntFlag{Name: "test"}), + FlagName: "test", + ContextValueString: "d", + } + c := runTest(t, tis) + expect(t, 0, c.Int("test")) +} + func TestIntApplyInputSourceMethodEnvVarSet(t *testing.T) { tis := testApplyInputSource{ Flag: NewIntFlag(&cli.IntFlag{Name: "test", EnvVars: []string{"TEST"}}), @@ -598,6 +619,95 @@ func TestIntApplyInputSourceMethodEnvVarSet(t *testing.T) { refute(t, 12, c.Int("test")) } +func TestInt64ApplyInputSourceMethodSet_Alias(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewInt64Flag(&cli.Int64Flag{Name: "test", Aliases: []string{"test_alias"}}), + FlagName: "test_alias", + MapValue: int64(15), + } + c := runTest(t, tis) + expect(t, int64(15), c.Int64("test_alias")) + + c = runRacyTest(t, tis) + refute(t, int64(15), c.Int64("test_alias")) +} + +func TestInt64ApplyInputSourceMethodSet(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewInt64Flag(&cli.Int64Flag{Name: "test"}), + FlagName: "test", + MapValue: int64(15), + } + c := runTest(t, tis) + expect(t, int64(15), c.Int64("test")) + + c = runRacyTest(t, tis) + refute(t, int64(15), c.Int("test")) +} + +func TestInt64ApplyInputSourceMethodSetNegativeValue(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewInt64Flag(&cli.Int64Flag{Name: "test"}), + FlagName: "test", + MapValue: int64(-1), + } + c := runTest(t, tis) + expect(t, int64(-1), c.Int64("test")) + + c = runRacyTest(t, tis) + refute(t, int64(-1), c.Int("test")) +} + +func TestInt64ApplyInputSourceMethodContextSet(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewInt64Flag(&cli.Int64Flag{Name: "test"}), + FlagName: "test", + MapValue: 15, + ContextValueString: "7", + } + c := runTest(t, tis) + expect(t, int64(7), c.Int64("test")) + + c = runRacyTest(t, tis) + refute(t, int64(7), c.Int64("test")) +} + +func TestInt64ApplyInputSourceMethodContextNotSet(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewInt64Flag(&cli.Int64Flag{Name: "test"}), + FlagName: "test1", + MapValue: 15, + ContextValueString: "7", + } + c := runTest(t, tis) + expect(t, int64(0), c.Int64("test")) +} + +func TestInt64ApplyInputSourceMethodContextSetInvalidType(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewInt64Flag(&cli.Int64Flag{Name: "test"}), + FlagName: "test", + ContextValueString: "d", + } + c := runTest(t, tis) + expect(t, int64(0), c.Int64("test")) +} + +func TestInt64ApplyInputSourceMethodEnvVarSet(t *testing.T) { + tis := testApplyInputSource{ + Flag: NewInt64Flag(&cli.Int64Flag{Name: "test", EnvVars: []string{"TEST"}}), + FlagName: "test", + MapValue: 15, + EnvVarName: "TEST", + EnvVarValue: "12", + } + c := runTest(t, tis) + expect(t, int64(12), c.Int64("test")) + + c = runRacyTest(t, tis) + refute(t, int64(12), c.Int64("test")) +} + func TestUintApplyInputSourceMethodSet_Alias(t *testing.T) { tis := testApplyInputSource{ Flag: NewUintFlag(&cli.UintFlag{Name: "test", Aliases: []string{"test_alias"}}),