From 7cee89f28249eadc1e51a464c6d76a9ab1cefc8d Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Mon, 19 Jun 2023 11:51:33 -0400 Subject: [PATCH 1/3] Begin collapsing `Int64Flag` and `Int64SliceFlag` into `IntFlag` and `IntSliceFlag` --- command_test.go | 42 +--- context_test.go | 12 - examples_test.go | 21 +- flag_int.go | 31 +-- flag_int64.go | 52 ---- flag_int64_slice.go | 29 --- flag_int_slice.go | 12 +- flag_mutex_test.go | 2 +- flag_test.go | 533 ++++++++-------------------------------- godoc-current.txt | 26 +- help_test.go | 6 +- testdata/godoc-v3.x.txt | 26 +- 12 files changed, 153 insertions(+), 639 deletions(-) delete mode 100644 flag_int64.go delete mode 100644 flag_int64_slice.go diff --git a/command_test.go b/command_test.go index 62135fa6f9..738f31bb68 100644 --- a/command_test.go +++ b/command_test.go @@ -543,7 +543,7 @@ func TestCommand_VisibleFlagCategories(t *testing.T) { &StringFlag{ Name: "strd", // no category set }, - &Int64Flag{ + &IntFlag{ Name: "intd", Aliases: []string{"altd1", "altd2"}, Category: "cat1", @@ -1233,7 +1233,7 @@ func TestCommand_Float64Flag(t *testing.T) { } func TestCommand_ParseSliceFlags(t *testing.T) { - var parsedIntSlice []int + var parsedIntSlice []int64 var parsedStringSlice []string cmd := &Command{ @@ -1241,7 +1241,7 @@ func TestCommand_ParseSliceFlags(t *testing.T) { { Name: "cmd", Flags: []Flag{ - &IntSliceFlag{Name: "p", Value: []int{}, Usage: "set one or more ip addr"}, + &IntSliceFlag{Name: "p", Value: []int64{}, Usage: "set one or more ip addr"}, &StringSliceFlag{Name: "ip", Value: []string{}, Usage: "set one or more ports to open"}, }, Action: func(c *Context) error { @@ -1255,7 +1255,7 @@ func TestCommand_ParseSliceFlags(t *testing.T) { _ = cmd.Run(buildTestContext(t), []string{"", "cmd", "-p", "22", "-p", "80", "-ip", "8.8.8.8", "-ip", "8.8.4.4"}) - IntsEquals := func(a, b []int) bool { + IntsEquals := func(a, b []int64) bool { if len(a) != len(b) { return false } @@ -1278,7 +1278,7 @@ func TestCommand_ParseSliceFlags(t *testing.T) { } return true } - expectedIntSlice := []int{22, 80} + expectedIntSlice := []int64{22, 80} expectedStringSlice := []string{"8.8.8.8", "8.8.4.4"} if !IntsEquals(parsedIntSlice, expectedIntSlice) { @@ -1291,7 +1291,7 @@ func TestCommand_ParseSliceFlags(t *testing.T) { } func TestCommand_ParseSliceFlagsWithMissingValue(t *testing.T) { - var parsedIntSlice []int + var parsedIntSlice []int64 var parsedStringSlice []string cmd := &Command{ @@ -1313,7 +1313,7 @@ func TestCommand_ParseSliceFlagsWithMissingValue(t *testing.T) { _ = cmd.Run(buildTestContext(t), []string{"", "cmd", "-a", "2", "-str", "A"}) - expectedIntSlice := []int{2} + expectedIntSlice := []int64{2} expectedStringSlice := []string{"A"} if parsedIntSlice[0] != expectedIntSlice[0] { @@ -2929,7 +2929,7 @@ func TestFlagAction(t *testing.T) { }, &IntFlag{ Name: "f_int", - Action: func(cCtx *Context, v int) error { + Action: func(cCtx *Context, v int64) error { if v < 0 { return fmt.Errorf("negative int") } @@ -2939,7 +2939,7 @@ func TestFlagAction(t *testing.T) { }, &IntSliceFlag{ Name: "f_int_slice", - Action: func(cCtx *Context, v []int) error { + Action: func(cCtx *Context, v []int64) error { if len(v) > 0 && v[0] < 0 { return fmt.Errorf("invalid int slice") } @@ -2947,7 +2947,7 @@ func TestFlagAction(t *testing.T) { return err }, }, - &Int64Flag{ + &IntFlag{ Name: "f_int64", Action: func(cCtx *Context, v int64) error { if v < 0 { @@ -2957,16 +2957,6 @@ func TestFlagAction(t *testing.T) { return err }, }, - &Int64SliceFlag{ - Name: "f_int64_slice", - Action: func(cCtx *Context, v []int64) error { - if len(v) > 0 && v[0] < 0 { - return fmt.Errorf("invalid int64 slice") - } - _, err := cCtx.Command.Root().Writer.Write([]byte(fmt.Sprintf("%v ", v))) - return err - }, - }, &TimestampFlag{ Name: "f_timestamp", Config: TimestampConfig{ @@ -3030,7 +3020,7 @@ func TestFlagAction(t *testing.T) { } func TestPersistentFlag(t *testing.T) { - var topInt, topPersistentInt, subCommandInt, appOverrideInt int + var topInt, topPersistentInt, subCommandInt, appOverrideInt int64 var appFlag string var appOverrideCmdInt int64 var appSliceFloat64 []float64 @@ -3048,11 +3038,6 @@ func TestPersistentFlag(t *testing.T) { return nil }, }, - &Int64SliceFlag{ - Name: "persistentCommandSliceFlag", - Persistent: true, - Destination: &persistentCommandSliceInt, - }, &Float64SliceFlag{ Name: "persistentCommandFloatSliceFlag", Persistent: true, @@ -3077,7 +3062,7 @@ func TestPersistentFlag(t *testing.T) { Persistent: true, Destination: &topPersistentInt, }, - &Int64Flag{ + &IntFlag{ Name: "paof", Aliases: []string{"persistentCommandOverrideFlag"}, Destination: &appOverrideCmdInt, @@ -3171,9 +3156,6 @@ func TestFlagDuplicates(t *testing.T) { Name: "sflag", OnlyOnce: true, }, - &Int64SliceFlag{ - Name: "isflag", - }, &Float64SliceFlag{ Name: "fsflag", OnlyOnce: true, diff --git a/context_test.go b/context_test.go index fc3fa497f1..47e31f9d03 100644 --- a/context_test.go +++ b/context_test.go @@ -28,7 +28,6 @@ func TestNewContext(t *testing.T) { c := NewContext(nil, set, globalCtx) c.Command = command expect(t, c.Int("myflag"), 12) - expect(t, c.Int64("myflagInt64"), int64(12)) expect(t, c.Uint("myflagUint"), uint(93)) expect(t, c.Uint64("myflagUint64"), uint64(93)) expect(t, c.Float64("myflag64"), float64(17)) @@ -46,17 +45,6 @@ func TestContext_Int(t *testing.T) { expect(t, c.Int("top-flag"), 13) } -func TestContext_Int64(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Int64("myflagInt64", 12, "doc") - parentSet := flag.NewFlagSet("test", 0) - parentSet.Int64("top-flag", 13, "doc") - parentCtx := NewContext(nil, parentSet, nil) - c := NewContext(nil, set, parentCtx) - expect(t, c.Int64("myflagInt64"), int64(12)) - expect(t, c.Int64("top-flag"), int64(13)) -} - func TestContext_Uint(t *testing.T) { set := flag.NewFlagSet("test", 0) set.Uint("myflagUint", uint(13), "doc") diff --git a/examples_test.go b/examples_test.go index a4c3ec135b..74ae42071d 100644 --- a/examples_test.go +++ b/examples_test.go @@ -419,10 +419,9 @@ func ExampleCommand_Run_sliceValues() { cmd := &cli.Command{ Name: "multi_values", Flags: []cli.Flag{ - &cli.StringSliceFlag{Name: "stringSclice"}, - &cli.Float64SliceFlag{Name: "float64Sclice"}, - &cli.Int64SliceFlag{Name: "int64Sclice"}, - &cli.IntSliceFlag{Name: "intSclice"}, + &cli.StringSliceFlag{Name: "stringSlice"}, + &cli.Float64SliceFlag{Name: "float64Slice"}, + &cli.IntSliceFlag{Name: "intSlice"}, }, Action: func(cCtx *cli.Context) error { for i, v := range cCtx.FlagNames() { @@ -437,18 +436,16 @@ func ExampleCommand_Run_sliceValues() { // Simulate command line arguments os.Args = []string{ "multi_values", - "--stringSclice", "parsed1,parsed2", "--stringSclice", "parsed3,parsed4", - "--float64Sclice", "13.3,14.4", "--float64Sclice", "15.5,16.6", - "--int64Sclice", "13,14", "--int64Sclice", "15,16", - "--intSclice", "13,14", "--intSclice", "15,16", + "--stringSlice", "parsed1,parsed2", "--stringSlice", "parsed3,parsed4", + "--float64Slice", "13.3,14.4", "--float64Slice", "15.5,16.6", + "--intSlice", "13,14", "--intSlice", "15,16", } _ = cmd.Run(context.Background(), os.Args) // Output: - // 0-float64Sclice []float64{13.3, 14.4, 15.5, 16.6} - // 1-int64Sclice []int64{13, 14, 15, 16} - // 2-intSclice []int{13, 14, 15, 16} - // 3-stringSclice []string{"parsed1", "parsed2", "parsed3", "parsed4"} + // 0-float64Slice []float64{13.3, 14.4, 15.5, 16.6} + // 1-intSlice []int64{13, 14, 15, 16} + // 2-stringSlice []string{"parsed1", "parsed2", "parsed3", "parsed4"} // error: } diff --git a/flag_int.go b/flag_int.go index 5dbd56f5cb..69b7b79d90 100644 --- a/flag_int.go +++ b/flag_int.go @@ -5,22 +5,22 @@ import ( "strconv" ) -type IntFlag = FlagBase[int, IntegerConfig, intValue] +type IntFlag = FlagBase[int64, IntegerConfig, intValue] // IntegerConfig is the configuration for all integer type flags type IntegerConfig struct { Base int } -// -- int Value +// -- int64 Value type intValue struct { - val *int + val *int64 base int } // Below functions are to satisfy the ValueCreator interface -func (i intValue) Create(val int, p *int, c IntegerConfig) Value { +func (i intValue) Create(val int64, p *int64, c IntegerConfig) Value { *p = val return &intValue{ val: p, @@ -28,34 +28,29 @@ func (i intValue) Create(val int, p *int, c IntegerConfig) Value { } } -func (i intValue) ToString(b int) string { - return fmt.Sprintf("%v", b) +func (i intValue) ToString(b int64) string { + return fmt.Sprintf("%d", b) } // Below functions are to satisfy the flag.Value interface func (i *intValue) Set(s string) error { - v, err := strconv.ParseInt(s, i.base, strconv.IntSize) + v, err := strconv.ParseInt(s, 0, 64) if err != nil { return err } - *i.val = int(v) + *i.val = v return err } -func (i *intValue) Get() any { return int(*i.val) } +func (i *intValue) Get() any { return int64(*i.val) } -func (i *intValue) String() string { - if i == nil || i.val == nil { - return "" - } - return strconv.Itoa(int(*i.val)) -} +func (i *intValue) String() string { return strconv.FormatInt(int64(*i.val), 10) } -// Int looks up the value of a local IntFlag, returns +// Int64 looks up the value of a local Int64Flag, returns // 0 if not found -func (cCtx *Context) Int(name string) int { - if v, ok := cCtx.Value(name).(int); ok { +func (cCtx *Context) Int(name string) int64 { + if v, ok := cCtx.Value(name).(int64); ok { return v } return 0 diff --git a/flag_int64.go b/flag_int64.go deleted file mode 100644 index 9ba3080189..0000000000 --- a/flag_int64.go +++ /dev/null @@ -1,52 +0,0 @@ -package cli - -import ( - "fmt" - "strconv" -) - -type Int64Flag = FlagBase[int64, IntegerConfig, int64Value] - -// -- int64 Value -type int64Value struct { - val *int64 - base int -} - -// Below functions are to satisfy the ValueCreator interface - -func (i int64Value) Create(val int64, p *int64, c IntegerConfig) Value { - *p = val - return &int64Value{ - val: p, - base: c.Base, - } -} - -func (i int64Value) ToString(b int64) string { - return fmt.Sprintf("%d", b) -} - -// Below functions are to satisfy the flag.Value interface - -func (i *int64Value) Set(s string) error { - v, err := strconv.ParseInt(s, 0, 64) - if err != nil { - return err - } - *i.val = v - return err -} - -func (i *int64Value) Get() any { return int64(*i.val) } - -func (i *int64Value) String() string { return strconv.FormatInt(int64(*i.val), 10) } - -// Int64 looks up the value of a local Int64Flag, returns -// 0 if not found -func (cCtx *Context) Int64(name string) int64 { - if v, ok := cCtx.Value(name).(int64); ok { - return v - } - return 0 -} diff --git a/flag_int64_slice.go b/flag_int64_slice.go deleted file mode 100644 index 152b9980a0..0000000000 --- a/flag_int64_slice.go +++ /dev/null @@ -1,29 +0,0 @@ -package cli - -import ( - "flag" -) - -type Int64Slice = SliceBase[int64, IntegerConfig, int64Value] -type Int64SliceFlag = FlagBase[[]int64, IntegerConfig, Int64Slice] - -var NewInt64Slice = NewSliceBase[int64, IntegerConfig, int64Value] - -// Int64Slice looks up the value of a local Int64SliceFlag, returns -// nil if not found -func (cCtx *Context) Int64Slice(name string) []int64 { - if fs := cCtx.lookupFlagSet(name); fs != nil { - return lookupInt64Slice(name, fs) - } - return nil -} - -func lookupInt64Slice(name string, set *flag.FlagSet) []int64 { - f := set.Lookup(name) - if f != nil { - if slice, ok := f.Value.(flag.Getter).Get().([]int64); ok { - return slice - } - } - return nil -} diff --git a/flag_int_slice.go b/flag_int_slice.go index 95451ad720..bea6b8724c 100644 --- a/flag_int_slice.go +++ b/flag_int_slice.go @@ -2,24 +2,24 @@ package cli import "flag" -type IntSlice = SliceBase[int, IntegerConfig, intValue] -type IntSliceFlag = FlagBase[[]int, IntegerConfig, IntSlice] +type IntSlice = SliceBase[int64, IntegerConfig, intValue] +type IntSliceFlag = FlagBase[[]int64, IntegerConfig, IntSlice] -var NewIntSlice = NewSliceBase[int, IntegerConfig, intValue] +var NewIntSlice = NewSliceBase[int64, IntegerConfig, intValue] // IntSlice looks up the value of a local IntSliceFlag, returns // nil if not found -func (cCtx *Context) IntSlice(name string) []int { +func (cCtx *Context) IntSlice(name string) []int64 { if fs := cCtx.lookupFlagSet(name); fs != nil { return lookupIntSlice(name, fs) } return nil } -func lookupIntSlice(name string, set *flag.FlagSet) []int { +func lookupIntSlice(name string, set *flag.FlagSet) []int64 { f := set.Lookup(name) if f != nil { - if slice, ok := f.Value.(flag.Getter).Get().([]int); ok { + if slice, ok := f.Value.(flag.Getter).Get().([]int64); ok { return slice } } diff --git a/flag_mutex_test.go b/flag_mutex_test.go index ba277fb6de..61f0a9f0f6 100644 --- a/flag_mutex_test.go +++ b/flag_mutex_test.go @@ -19,7 +19,7 @@ func TestFlagMutuallyExclusiveFlags(t *testing.T) { }, }, []Flag{ - &Int64Flag{ + &IntFlag{ Name: "t", Aliases: []string{"ai"}, }, diff --git a/flag_test.go b/flag_test.go index 423de9a696..8b16a351f3 100644 --- a/flag_test.go +++ b/flag_test.go @@ -10,6 +10,8 @@ import ( "strings" "testing" "time" + + "github.com/stretchr/testify/require" ) var boolFlagTests = []struct { @@ -124,9 +126,9 @@ func TestFlagsFromEnv(t *testing.T) { {"1", 1.0, &Float64Flag{Name: "seconds", Sources: EnvVars("SECONDS")}, ""}, {"foobar", 0, &Float64Flag{Name: "seconds", Sources: EnvVars("SECONDS")}, `could not parse "foobar" as float64 value from environment variable "SECONDS" for flag seconds: .*`}, - {"1", int64(1), &Int64Flag{Name: "seconds", Sources: EnvVars("SECONDS")}, ""}, - {"1.2", 0, &Int64Flag{Name: "seconds", Sources: EnvVars("SECONDS")}, `could not parse "1.2" as int64 value from environment variable "SECONDS" for flag seconds: .*`}, - {"foobar", 0, &Int64Flag{Name: "seconds", Sources: EnvVars("SECONDS")}, `could not parse "foobar" as int64 value from environment variable "SECONDS" for flag seconds: .*`}, + {"1", int64(1), &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, ""}, + {"1.2", 0, &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, `could not parse "1.2" as int64 value from environment variable "SECONDS" for flag seconds: .*`}, + {"foobar", 0, &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, `could not parse "foobar" as int64 value from environment variable "SECONDS" for flag seconds: .*`}, {"1", 1, &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, ""}, {"08", 8, &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 10}}, ""}, @@ -147,10 +149,6 @@ func TestFlagsFromEnv(t *testing.T) { {"1.2,2", []uint{}, &UintSliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, `could not parse "1.2,2" as \[\]uint value from environment variable "SECONDS" for flag seconds: .*`}, {"foobar", []uint{}, &UintSliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, `could not parse "foobar" as \[\]uint value from environment variable "SECONDS" for flag seconds: .*`}, - {"1,2", []int64{1, 2}, &Int64SliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, ""}, - {"1.2,2", []int64{}, &Int64SliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, `could not parse "1.2,2" as \[\]int64 value from environment variable "SECONDS" for flag seconds: .*`}, - {"foobar", []int64{}, &Int64SliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, `could not parse "foobar" as \[\]int64 value from environment variable "SECONDS" for flag seconds: .*`}, - {"1,2", []uint64{1, 2}, &Uint64SliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, ""}, {"1.2,2", []uint64{}, &Uint64SliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, `could not parse "1.2,2" as \[\]uint64 value from environment variable "SECONDS" for flag seconds: .*`}, {"foobar", []uint64{}, &Uint64SliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, `could not parse "foobar" as \[\]uint64 value from environment variable "SECONDS" for flag seconds: .*`}, @@ -311,24 +309,14 @@ func TestFlagStringifying(t *testing.T) { }, { name: "int64-flag", - fl: &Int64Flag{Name: "flume"}, + fl: &IntFlag{Name: "flume"}, expected: "--flume value\t(default: 0)", }, { name: "int64-flag-with-default-text", - fl: &Int64Flag{Name: "shattering", DefaultText: "22"}, + fl: &IntFlag{Name: "shattering", DefaultText: "22"}, expected: "--shattering value\t(default: 22)", }, - { - name: "int64-slice-flag", - fl: &Int64SliceFlag{Name: "drawers"}, - expected: "--drawers value [ --drawers value ]\t", - }, - { - name: "int64-slice-flag-with-default-text", - fl: &Int64SliceFlag{Name: "handles", DefaultText: "-2"}, - expected: "--handles value [ --handles value ]\t(default: -2)", - }, { name: "uint64-slice-flag", fl: &Uint64SliceFlag{Name: "drawers"}, @@ -684,22 +672,22 @@ func TestIntFlagWithEnvVarHelpOutput(t *testing.T) { } func TestIntFlagApply_SetsAllNames(t *testing.T) { - v := 3 + v := int64(3) fl := IntFlag{Name: "banana", Aliases: []string{"B", "banannanana"}, Destination: &v} set := flag.NewFlagSet("test", 0) - _ = fl.Apply(set) + r := require.New(t) + r.NoError(fl.Apply(set)) - err := set.Parse([]string{"--banana", "1", "-B", "2", "--banannanana", "5"}) - expect(t, err, nil) - expect(t, v, 5) + r.NoError(set.Parse([]string{"--banana", "1", "-B", "2", "--banannanana", "5"})) + r.Equal(int64(5), v) } func TestIntFlagValueFromContext(t *testing.T) { set := flag.NewFlagSet("test", 0) - set.Int("myflag", 42, "doc") - ctx := NewContext(nil, set, nil) - f := &IntFlag{Name: "myflag"} - expect(t, f.Get(ctx), 42) + set.Int64("myflag", int64(42), "doc") + cCtx := NewContext(nil, set, nil) + fl := &IntFlag{Name: "myflag"} + require.Equal(t, int64(42), fl.Get(cCtx)) } var int64FlagTests = []struct { @@ -710,49 +698,6 @@ var int64FlagTests = []struct { {"H", "-H value\t(default: 8589934592)"}, } -func TestInt64FlagHelpOutput(t *testing.T) { - for _, test := range int64FlagTests { - fl := Int64Flag{Name: test.name, Value: 8589934592} - - // create a temporary flag set to apply - tfs := flag.NewFlagSet("test", 0) - if err := fl.Apply(tfs); err != nil { - t.Error(err) - return - } - - output := fl.String() - - if output != test.expected { - t.Errorf("%s does not match %s", output, test.expected) - } - } -} - -func TestInt64FlagWithEnvVarHelpOutput(t *testing.T) { - defer resetEnv(os.Environ()) - os.Clearenv() - _ = os.Setenv("APP_BAR", "2") - - for _, test := range int64FlagTests { - fl := IntFlag{Name: test.name, Sources: EnvVars("APP_BAR")} - output := fl.String() - - expectedSuffix := withEnvHint([]string{"APP_BAR"}, "") - if !strings.HasSuffix(output, expectedSuffix) { - t.Errorf("%s does not end with"+expectedSuffix, output) - } - } -} - -func TestInt64FlagValueFromContext(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Int64("myflag", 42, "doc") - ctx := NewContext(nil, set, nil) - f := &Int64Flag{Name: "myflag"} - expect(t, f.Get(ctx), int64(42)) -} - var uintFlagTests = []struct { name string expected string @@ -920,12 +865,12 @@ func TestDurationFlagValueFromContext(t *testing.T) { var intSliceFlagTests = []struct { name string aliases []string - value []int + value []int64 expected string }{ - {"heads", nil, []int{}, "--heads value [ --heads value ]\t"}, - {"H", nil, []int{}, "-H value [ -H value ]\t"}, - {"H", []string{"heads"}, []int{9, 3}, "-H value, --heads value [ -H value, --heads value ]\t(default: 9, 3)"}, + {"heads", nil, []int64{}, "--heads value [ --heads value ]\t"}, + {"H", nil, []int64{}, "-H value [ -H value ]\t"}, + {"H", []string{"heads"}, []int64{9, 3}, "-H value, --heads value [ -H value, --heads value ]\t(default: 9, 3)"}, } func TestIntSliceFlagHelpOutput(t *testing.T) { @@ -965,36 +910,33 @@ func TestIntSliceFlagApply_SetsAllNames(t *testing.T) { } func TestIntSliceFlagApply_UsesEnvValues_noDefault(t *testing.T) { - defer resetEnv(os.Environ()) - os.Clearenv() - _ = os.Setenv("MY_GOAT", "1 , 2") + t.Setenv("MY_GOAT", "1 , 2") - fl := IntSliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT")} + fl := &IntSliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT")} set := flag.NewFlagSet("test", 0) - _ = fl.Apply(set) - err := set.Parse(nil) - expect(t, err, nil) - expect(t, set.Lookup("goat").Value.(flag.Getter).Get(), []int{1, 2}) + r := require.New(t) + r.NoError(fl.Apply(set)) + r.NoError(set.Parse(nil)) + r.Equal([]int64{1, 2}, set.Lookup("goat").Value.(flag.Getter).Get()) } func TestIntSliceFlagApply_UsesEnvValues_withDefault(t *testing.T) { - defer resetEnv(os.Environ()) - os.Clearenv() - _ = os.Setenv("MY_GOAT", "1 , 2") - val := []int{3, 4} - fl := IntSliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT"), Value: val} + t.Setenv("MY_GOAT", "1 , 2") + val := []int64{3, 4} + fl := &IntSliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT"), Value: val} set := flag.NewFlagSet("test", 0) - _ = fl.Apply(set) - err := set.Parse(nil) - expect(t, err, nil) - expect(t, val, []int{3, 4}) - expect(t, set.Lookup("goat").Value.(flag.Getter).Get(), []int{1, 2}) + + r := require.New(t) + r.NoError(fl.Apply(set)) + r.NoError(set.Parse(nil)) + r.Equal([]int64{3, 4}, val) + r.Equal([]int64{1, 2}, set.Lookup("goat").Value.(flag.Getter).Get()) } func TestIntSliceFlagApply_DefaultValueWithDestination(t *testing.T) { - defValue := []int{1, 2} - dest := []int{3} + defValue := []int64{1, 2} + dest := []int64{3} fl := IntSliceFlag{Name: "country", Value: defValue, Destination: &dest} set := flag.NewFlagSet("test", 0) @@ -1008,19 +950,14 @@ func TestIntSliceFlagApply_DefaultValueWithDestination(t *testing.T) { func TestIntSliceFlagApply_ParentContext(t *testing.T) { _ = (&Command{ Flags: []Flag{ - &IntSliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []int{1, 2, 3}}, + &IntSliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []int64{1, 2, 3}}, }, Commands: []*Command{ { Name: "child", Action: func(ctx *Context) error { - expected := []int{1, 2, 3} - if !reflect.DeepEqual(ctx.IntSlice("numbers"), expected) { - t.Errorf("child context unable to view parent flag: %v != %v", expected, ctx.IntSlice("numbers")) - } - if !reflect.DeepEqual(ctx.IntSlice("n"), expected) { - t.Errorf("child context unable to view parent flag: %v != %v", expected, ctx.IntSlice("n")) - } + require.Equalf(t, []int64{1, 2, 3}, ctx.IntSlice("numbers"), "child context unable to view parent flag") + return nil }, }, @@ -1029,27 +966,25 @@ func TestIntSliceFlagApply_ParentContext(t *testing.T) { } func TestIntSliceFlag_SetFromParentContext(t *testing.T) { - fl := &IntSliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []int{1, 2, 3, 4}} + fl := &IntSliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []int64{1, 2, 3, 4}} set := flag.NewFlagSet("test", 0) _ = fl.Apply(set) - ctx := &Context{ + cCtx := &Context{ parent: &Context{ flagSet: set, }, flagSet: flag.NewFlagSet("empty", 0), } - expected := []int{1, 2, 3, 4} - if !reflect.DeepEqual(ctx.IntSlice("numbers"), expected) { - t.Errorf("child context unable to view parent flag: %v != %v", expected, ctx.IntSlice("numbers")) - } + + require.Equalf(t, []int64{1, 2, 3, 4}, cCtx.IntSlice("numbers"), "child context unable to view parent flag") } func TestIntSliceFlagValueFromContext(t *testing.T) { set := flag.NewFlagSet("test", 0) set.Var(NewIntSlice(1, 2, 3), "myflag", "doc") - ctx := NewContext(nil, set, nil) + cCtx := NewContext(nil, set, nil) f := &IntSliceFlag{Name: "myflag"} - expect(t, f.Get(ctx), []int{1, 2, 3}) + require.Equal(t, f.Get(cCtx), []int64{1, 2, 3}) } var int64SliceFlagTests = []struct { @@ -1068,145 +1003,6 @@ var int64SliceFlagTests = []struct { }, } -func TestInt64SliceFlagHelpOutput(t *testing.T) { - for _, test := range int64SliceFlagTests { - fl := Int64SliceFlag{Name: test.name, Aliases: test.aliases, Value: test.value} - output := fl.String() - - if output != test.expected { - t.Errorf("%q does not match %q", output, test.expected) - } - } -} - -func TestInt64SliceFlagWithEnvVarHelpOutput(t *testing.T) { - defer resetEnv(os.Environ()) - os.Clearenv() - _ = os.Setenv("APP_SMURF", "42,17179869184") - - for _, test := range int64SliceFlagTests { - fl := Int64SliceFlag{Name: test.name, Value: test.value, Sources: EnvVars("APP_SMURF")} - output := fl.String() - - expectedSuffix := withEnvHint([]string{"APP_SMURF"}, "") - if !strings.HasSuffix(output, expectedSuffix) { - t.Errorf("%q does not end with"+expectedSuffix, output) - } - } -} - -func TestInt64SliceFlagApply_SetsAllNames(t *testing.T) { - fl := Int64SliceFlag{Name: "bits", Aliases: []string{"B", "bips"}} - set := flag.NewFlagSet("test", 0) - _ = fl.Apply(set) - - err := set.Parse([]string{"--bits", "23", "-B", "3", "--bips", "99"}) - expect(t, err, nil) -} - -func TestInt64SliceFlagApply_UsesEnvValues_noDefault(t *testing.T) { - defer resetEnv(os.Environ()) - os.Clearenv() - _ = os.Setenv("MY_GOAT", "1 , 2") - fl := Int64SliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT")} - set := flag.NewFlagSet("test", 0) - _ = fl.Apply(set) - - err := set.Parse(nil) - expect(t, err, nil) - expect(t, set.Lookup("goat").Value.(flag.Getter).Get(), []int64{1, 2}) -} - -func TestInt64SliceFlagApply_UsesEnvValues_withDefault(t *testing.T) { - defer resetEnv(os.Environ()) - os.Clearenv() - _ = os.Setenv("MY_GOAT", "1 , 2") - val := NewInt64Slice(3, 4) - fl := Int64SliceFlag{Name: "goat", Sources: EnvVars("MY_GOAT"), Value: val.Value()} - set := flag.NewFlagSet("test", 0) - _ = fl.Apply(set) - err := set.Parse(nil) - expect(t, err, nil) - expect(t, val.Value(), []int64{3, 4}) - expect(t, set.Lookup("goat").Value.(flag.Getter).Get().([]int64), []int64{1, 2}) -} - -func TestInt64SliceFlagApply_DefaultValueWithDestination(t *testing.T) { - defValue := []int64{1, 2} - dest := []int64{3} - - fl := Int64SliceFlag{Name: "country", Value: defValue, Destination: &dest} - set := flag.NewFlagSet("test", 0) - _ = fl.Apply(set) - - err := set.Parse([]string{}) - expect(t, err, nil) - expect(t, defValue, dest) -} - -func TestInt64SliceFlagApply_ParentContext(t *testing.T) { - _ = (&Command{ - Flags: []Flag{ - &Int64SliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []int64{1, 2, 3}}, - }, - Commands: []*Command{ - { - Name: "child", - Action: func(ctx *Context) error { - expected := []int64{1, 2, 3} - if !reflect.DeepEqual(ctx.Int64Slice("numbers"), expected) { - t.Errorf("child context unable to view parent flag: %v != %v", expected, ctx.Int64Slice("numbers")) - } - if !reflect.DeepEqual(ctx.Int64Slice("n"), expected) { - t.Errorf("child context unable to view parent flag: %v != %v", expected, ctx.Int64Slice("n")) - } - return nil - }, - }, - }, - }).Run(buildTestContext(t), []string{"run", "child"}) -} - -func TestInt64SliceFlag_SetFromParentContext(t *testing.T) { - fl := &Int64SliceFlag{Name: "numbers", Aliases: []string{"n"}, Value: []int64{1, 2, 3, 4}} - set := flag.NewFlagSet("test", 0) - _ = fl.Apply(set) - ctx := &Context{ - parent: &Context{ - flagSet: set, - }, - flagSet: flag.NewFlagSet("empty", 0), - } - expected := []int64{1, 2, 3, 4} - if !reflect.DeepEqual(ctx.Int64Slice("numbers"), expected) { - t.Errorf("child context unable to view parent flag: %v != %v", expected, ctx.Int64Slice("numbers")) - } -} - -func TestInt64SliceFlag_ReturnNil(t *testing.T) { - fl := &Int64SliceFlag{} - set := flag.NewFlagSet("test", 0) - _ = fl.Apply(set) - ctx := &Context{ - parent: &Context{ - flagSet: set, - }, - flagSet: flag.NewFlagSet("empty", 0), - } - expected := []int64(nil) - if !reflect.DeepEqual(ctx.Int64Slice("numbers"), expected) { - t.Errorf("child context unable to view parent flag: %v != %v", expected, ctx.Int64Slice("numbers")) - } -} - -func TestInt64SliceFlagValueFromContext(t *testing.T) { - set := flag.NewFlagSet("test", 0) - set.Var(NewInt64Slice(1, 2, 3), "myflag", "doc") - ctx := NewContext(nil, set, nil) - f := &Int64SliceFlag{Name: "myflag"} - expect(t, f.Get(ctx), []int64{1, 2, 3}) -} - var uintSliceFlagTests = []struct { name string aliases []string @@ -1852,48 +1648,17 @@ func TestParseMultiFloat64SliceWithDestinationAndEnv(t *testing.T) { }).Run(buildTestContext(t), []string{"run", "-s", "10", "-s", "20"}) } -func TestParseMultiInt64SliceWithDestinationAndEnv(t *testing.T) { - defer resetEnv(os.Environ()) - os.Clearenv() - _ = os.Setenv("APP_INTERVALS", "20,30,40") - - var dest []int64 - - _ = (&Command{ - Flags: []Flag{ - &Int64SliceFlag{Name: "serve", Aliases: []string{"s"}, Destination: &dest, Sources: EnvVars("APP_INTERVALS")}, - }, - Action: func(ctx *Context) error { - expected := []int64{10, 20} - if !reflect.DeepEqual(dest, expected) { - t.Errorf("main name not set: %v != %v", expected, ctx.StringSlice("serve")) - } - if !reflect.DeepEqual(dest, expected) { - t.Errorf("short name not set: %v != %v", expected, ctx.StringSlice("s")) - } - return nil - }, - }).Run(buildTestContext(t), []string{"run", "-s", "10", "-s", "20"}) -} - func TestParseMultiIntSliceWithDestinationAndEnv(t *testing.T) { - defer resetEnv(os.Environ()) - os.Clearenv() - _ = os.Setenv("APP_INTERVALS", "20,30,40") + t.Setenv("APP_INTERVALS", "20,30,40") - dest := []int{} + dest := []int64{} _ = (&Command{ Flags: []Flag{ &IntSliceFlag{Name: "serve", Aliases: []string{"s"}, Destination: &dest, Sources: EnvVars("APP_INTERVALS")}, }, Action: func(ctx *Context) error { - expected := []int{10, 20} - if !reflect.DeepEqual(dest, expected) { - t.Errorf("main name not set: %v != %v %v", expected, ctx.IntSlice("serve"), dest) - } - if !reflect.DeepEqual(dest, expected) { - t.Errorf("short name not set: %v != %v", expected, ctx.IntSlice("s")) - } + require.Equalf(t, []int64{10, 20}, dest, "main name not set") + return nil }, }).Run(buildTestContext(t), []string{"run", "-s", "10", "-s", "20"}) @@ -2040,7 +1805,7 @@ func TestParseMultiInt(t *testing.T) { } func TestParseDestinationInt(t *testing.T) { - var dest int + var dest int64 _ = (&Command{ Flags: []Flag{ &IntFlag{ @@ -2100,15 +1865,14 @@ func TestParseMultiIntFromEnvCascade(t *testing.T) { func TestParseMultiIntSlice(t *testing.T) { _ = (&Command{ Flags: []Flag{ - &IntSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: []int{}}, + &IntSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: []int64{}}, }, Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.IntSlice("serve"), []int{10, 20}) { - t.Errorf("main name not set") - } - if !reflect.DeepEqual(ctx.IntSlice("s"), []int{10, 20}) { - t.Errorf("short name not set") - } + r := require.New(t) + + r.Equalf([]int64{10, 20}, ctx.IntSlice("serve"), "main name not set") + r.Equalf([]int64{10, 20}, ctx.IntSlice("s"), "short name not set") + return nil }, }).Run(buildTestContext(t), []string{"run", "-s", "10", "-s", "20"}) @@ -2117,15 +1881,14 @@ func TestParseMultiIntSlice(t *testing.T) { func TestParseMultiIntSliceWithDefaults(t *testing.T) { _ = (&Command{ Flags: []Flag{ - &IntSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: []int{9, 2}}, + &IntSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: []int64{9, 2}}, }, Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.IntSlice("serve"), []int{10, 20}) { - t.Errorf("main name not set") - } - if !reflect.DeepEqual(ctx.IntSlice("s"), []int{10, 20}) { - t.Errorf("short name not set") - } + r := require.New(t) + + r.Equalf([]int64{10, 20}, ctx.IntSlice("serve"), "main name not set") + r.Equalf([]int64{10, 20}, ctx.IntSlice("s"), "short name not set") + return nil }, }).Run(buildTestContext(t), []string{"run", "-s", "10", "-s", "20"}) @@ -2134,13 +1897,13 @@ func TestParseMultiIntSliceWithDefaults(t *testing.T) { func TestParseMultiIntSliceWithDefaultsUnset(t *testing.T) { _ = (&Command{ Flags: []Flag{ - &IntSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: []int{9, 2}}, + &IntSliceFlag{Name: "serve", Aliases: []string{"s"}, Value: []int64{9, 2}}, }, Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.IntSlice("serve"), []int{9, 2}) { + if !reflect.DeepEqual(ctx.IntSlice("serve"), []int64{9, 2}) { t.Errorf("main name not set") } - if !reflect.DeepEqual(ctx.IntSlice("s"), []int{9, 2}) { + if !reflect.DeepEqual(ctx.IntSlice("s"), []int64{9, 2}) { t.Errorf("short name not set") } return nil @@ -2149,61 +1912,37 @@ func TestParseMultiIntSliceWithDefaultsUnset(t *testing.T) { } func TestParseMultiIntSliceFromEnv(t *testing.T) { - defer resetEnv(os.Environ()) - os.Clearenv() - _ = os.Setenv("APP_INTERVALS", "20,30,40") + t.Setenv("APP_INTERVALS", "20,30,40") _ = (&Command{ Flags: []Flag{ - &IntSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: []int{}, Sources: EnvVars("APP_INTERVALS")}, + &IntSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: []int64{}, Sources: EnvVars("APP_INTERVALS")}, }, Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) { - t.Errorf("main name not set from env") - } - if !reflect.DeepEqual(ctx.IntSlice("i"), []int{20, 30, 40}) { - t.Errorf("short name not set from env") - } - return nil - }, - }).Run(buildTestContext(t), []string{"run"}) -} + r := require.New(t) -func TestParseMultiIntSliceFromEnvWithDefaults(t *testing.T) { - defer resetEnv(os.Environ()) - os.Clearenv() - _ = os.Setenv("APP_INTERVALS", "20,30,40") + r.Equalf([]int64{20, 30, 40}, ctx.IntSlice("intervals"), "main name not set from env") + r.Equalf([]int64{20, 30, 40}, ctx.IntSlice("i"), "short name not set from env") - _ = (&Command{ - Flags: []Flag{ - &IntSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: []int{1, 2, 5}, Sources: EnvVars("APP_INTERVALS")}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) { - t.Errorf("main name not set from env") - } - if !reflect.DeepEqual(ctx.IntSlice("i"), []int{20, 30, 40}) { - t.Errorf("short name not set from env") - } return nil }, }).Run(buildTestContext(t), []string{"run"}) } -func TestParseMultiIntSliceFromEnvCascade(t *testing.T) { +func TestParseMultiIntSliceFromEnvWithDefaults(t *testing.T) { defer resetEnv(os.Environ()) os.Clearenv() _ = os.Setenv("APP_INTERVALS", "20,30,40") _ = (&Command{ Flags: []Flag{ - &IntSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: []int{}, Sources: EnvVars("COMPAT_INTERVALS", "APP_INTERVALS")}, + &IntSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: []int64{1, 2, 5}, Sources: EnvVars("APP_INTERVALS")}, }, Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) { + if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int64{20, 30, 40}) { t.Errorf("main name not set from env") } - if !reflect.DeepEqual(ctx.IntSlice("i"), []int{20, 30, 40}) { + if !reflect.DeepEqual(ctx.IntSlice("i"), []int64{20, 30, 40}) { t.Errorf("short name not set from env") } return nil @@ -2211,60 +1950,19 @@ func TestParseMultiIntSliceFromEnvCascade(t *testing.T) { }).Run(buildTestContext(t), []string{"run"}) } -func TestParseMultiInt64Slice(t *testing.T) { - _ = (&Command{ - Flags: []Flag{ - &Int64SliceFlag{Name: "serve", Aliases: []string{"s"}}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.Int64Slice("serve"), []int64{10, 17179869184}) { - t.Errorf("main name not set") - } - if !reflect.DeepEqual(ctx.Int64Slice("s"), []int64{10, 17179869184}) { - t.Errorf("short name not set") - } - return nil - }, - }).Run(buildTestContext(t), []string{"run", "-s", "10", "-s", "17179869184"}) -} - -func TestParseMultiInt64SliceFromEnv(t *testing.T) { - defer resetEnv(os.Environ()) - os.Clearenv() - _ = os.Setenv("APP_INTERVALS", "20,30,17179869184") +func TestParseMultiIntSliceFromEnvCascade(t *testing.T) { + t.Setenv("APP_INTERVALS", "20,30,40") _ = (&Command{ Flags: []Flag{ - &Int64SliceFlag{Name: "intervals", Aliases: []string{"i"}, Sources: EnvVars("APP_INTERVALS")}, + &IntSliceFlag{Name: "intervals", Aliases: []string{"i"}, Value: []int64{}, Sources: EnvVars("COMPAT_INTERVALS", "APP_INTERVALS")}, }, Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.Int64Slice("intervals"), []int64{20, 30, 17179869184}) { - t.Errorf("main name not set from env") - } - if !reflect.DeepEqual(ctx.Int64Slice("i"), []int64{20, 30, 17179869184}) { - t.Errorf("short name not set from env") - } - return nil - }, - }).Run(buildTestContext(t), []string{"run"}) -} + r := require.New(t) -func TestParseMultiInt64SliceFromEnvCascade(t *testing.T) { - defer resetEnv(os.Environ()) - os.Clearenv() - _ = os.Setenv("APP_INTERVALS", "20,30,17179869184") + r.Equalf([]int64{20, 30, 40}, ctx.IntSlice("intervals"), "main name not set from env") + r.Equalf([]int64{20, 30, 40}, ctx.IntSlice("i"), "short name not set from env") - _ = (&Command{ - Flags: []Flag{ - &Int64SliceFlag{Name: "intervals", Aliases: []string{"i"}, Sources: EnvVars("COMPAT_INTERVALS", "APP_INTERVALS")}, - }, - Action: func(ctx *Context) error { - if !reflect.DeepEqual(ctx.Int64Slice("intervals"), []int64{20, 30, 17179869184}) { - t.Errorf("main name not set from env") - } - if !reflect.DeepEqual(ctx.Int64Slice("i"), []int64{20, 30, 17179869184}) { - t.Errorf("short name not set from env") - } return nil }, }).Run(buildTestContext(t), []string{"run"}) @@ -2590,22 +2288,6 @@ func TestIntSlice_Serialized_Set(t *testing.T) { } } -func TestInt64Slice_Serialized_Set(t *testing.T) { - sl0 := NewInt64Slice(int64(1), int64(2)) - ser0 := sl0.Serialize() - - if len(ser0) < len(slPfx) { - t.Fatalf("serialized shorter than expected: %q", ser0) - } - - sl1 := NewInt64Slice(int64(3), int64(4)) - _ = sl1.Set(ser0) - - if sl0.String() != sl1.String() { - t.Fatalf("pre and post serialization do not match: %v != %v", sl0, sl1) - } -} - func TestUintSlice_Serialized_Set(t *testing.T) { sl0 := NewUintSlice(1, 2) ser0 := sl0.Serialize() @@ -2764,15 +2446,9 @@ func TestFlagDefaultValue(t *testing.T) { toParse: []string{"--flag", "13.3"}, expect: `--flag value [ --flag value ] (default: 1.1, 2.2)`, }, - { - name: "int64Slice", - flag: &Int64SliceFlag{Name: "flag", Value: []int64{1, 2}}, - toParse: []string{"--flag", "13"}, - expect: `--flag value [ --flag value ] (default: 1, 2)`, - }, { name: "intSlice", - flag: &IntSliceFlag{Name: "flag", Value: []int{1, 2}}, + flag: &IntSliceFlag{Name: "flag", Value: []int64{1, 2}}, toParse: []string{"--flag", "13"}, expect: `--flag value [ --flag value ] (default: 1, 2)`, }, @@ -2861,18 +2537,9 @@ func TestFlagDefaultValueWithEnv(t *testing.T) { "fsflag": "20304.222", }, }, - { - name: "int64Slice", - flag: &Int64SliceFlag{Name: "flag", Value: []int64{1, 2}, Sources: EnvVars("isflag")}, - toParse: []string{"--flag", "13"}, - expect: `--flag value [ --flag value ] (default: 1, 2)` + withEnvHint([]string{"isflag"}, ""), - environ: map[string]string{ - "isflag": "101", - }, - }, { name: "intSlice", - flag: &IntSliceFlag{Name: "flag", Value: []int{1, 2}, Sources: EnvVars("isflag")}, + flag: &IntSliceFlag{Name: "flag", Value: []int64{1, 2}, Sources: EnvVars("isflag")}, toParse: []string{"--flag", "13"}, expect: `--flag value [ --flag value ] (default: 1, 2)` + withEnvHint([]string{"isflag"}, ""), environ: map[string]string{ @@ -2935,7 +2602,7 @@ func TestFlagDefaultValueWithEnv(t *testing.T) { }, { name: "int64", - flag: &Int64Flag{Name: "flag", Value: 1, Sources: EnvVars("uflag")}, + flag: &IntFlag{Name: "flag", Value: 1, Sources: EnvVars("uflag")}, toParse: []string{"--flag", "13"}, expect: `--flag value (default: 1)` + withEnvHint([]string{"uflag"}, ""), environ: map[string]string{ @@ -3018,17 +2685,11 @@ func TestFlagValue(t *testing.T) { toParse: []string{"--flag", "13.3,14.4", "--flag", "15.5,16.6"}, expect: `[]float64{13.3, 14.4, 15.5, 16.6}`, }, - { - name: "int64Slice", - flag: &Int64SliceFlag{Name: "flag", Value: []int64{1, 2}}, - toParse: []string{"--flag", "13,14", "--flag", "15,16"}, - expect: `[]int64{13, 14, 15, 16}`, - }, { name: "intSlice", - flag: &IntSliceFlag{Name: "flag", Value: []int{1, 2}}, + flag: &IntSliceFlag{Name: "flag", Value: []int64{1, 2}}, toParse: []string{"--flag", "13,14", "--flag", "15,16"}, - expect: `[]int{13, 14, 15, 16}`, + expect: `[]int64{13, 14, 15, 16}`, }, { name: "uint64Slice", @@ -3049,17 +2710,17 @@ func TestFlagValue(t *testing.T) { expect: `map[parsed:parsed2 parsed3:parsed4]`, }, } - for i, v := range cases { - set := flag.NewFlagSet("test", 0) - set.SetOutput(io.Discard) - _ = v.flag.Apply(set) - if err := set.Parse(v.toParse); err != nil { - t.Error(err) - } - f := set.Lookup("flag") - if got := f.Value.String(); got != v.expect { - t.Errorf("TestFlagValue %d-%s\nexpect:%s\ngot:%s", i, v.name, v.expect, got) - } + for _, v := range cases { + t.Run(v.name, func(t *testing.T) { + set := flag.NewFlagSet("test", 0) + set.SetOutput(io.Discard) + _ = v.flag.Apply(set) + if err := set.Parse(v.toParse); err != nil { + t.Error(err) + } + f := set.Lookup("flag") + require.Equal(t, v.expect, f.Value.String()) + }) } } diff --git a/godoc-current.txt b/godoc-current.txt index 36328a220d..1916550a35 100644 --- a/godoc-current.txt +++ b/godoc-current.txt @@ -175,8 +175,7 @@ Global flags: {{ end }} {{- end }}` var NewFloat64Slice = NewSliceBase[float64, NoConfig, float64Value] -var NewInt64Slice = NewSliceBase[int64, IntegerConfig, int64Value] -var NewIntSlice = NewSliceBase[int, IntegerConfig, intValue] +var NewIntSlice = NewSliceBase[int64, IntegerConfig, intValue] var NewStringMap = NewMapBase[string, StringConfig, stringValue] var NewStringSlice = NewSliceBase[string, StringConfig, stringValue] var NewUint64Slice = NewSliceBase[uint64, IntegerConfig, uint64Value] @@ -597,17 +596,10 @@ func (cCtx *Context) Float64Slice(name string) []float64 Float64Slice looks up the value of a local Float64SliceFlag, returns nil if not found -func (cCtx *Context) Int(name string) int - Int looks up the value of a local IntFlag, returns 0 if not found - -func (cCtx *Context) Int64(name string) int64 +func (cCtx *Context) Int(name string) int64 Int64 looks up the value of a local Int64Flag, returns 0 if not found -func (cCtx *Context) Int64Slice(name string) []int64 - Int64Slice looks up the value of a local Int64SliceFlag, returns nil if not - found - -func (cCtx *Context) IntSlice(name string) []int +func (cCtx *Context) IntSlice(name string) []int64 IntSlice looks up the value of a local IntSliceFlag, returns nil if not found @@ -923,17 +915,11 @@ type Float64Slice = SliceBase[float64, NoConfig, float64Value] type Float64SliceFlag = FlagBase[[]float64, NoConfig, Float64Slice] -type Int64Flag = FlagBase[int64, IntegerConfig, int64Value] - -type Int64Slice = SliceBase[int64, IntegerConfig, int64Value] - -type Int64SliceFlag = FlagBase[[]int64, IntegerConfig, Int64Slice] - -type IntFlag = FlagBase[int, IntegerConfig, intValue] +type IntFlag = FlagBase[int64, IntegerConfig, intValue] -type IntSlice = SliceBase[int, IntegerConfig, intValue] +type IntSlice = SliceBase[int64, IntegerConfig, intValue] -type IntSliceFlag = FlagBase[[]int, IntegerConfig, IntSlice] +type IntSliceFlag = FlagBase[[]int64, IntegerConfig, IntSlice] type IntegerConfig struct { Base int diff --git a/help_test.go b/help_test.go index e3084d0ce3..915bd63bd0 100644 --- a/help_test.go +++ b/help_test.go @@ -1202,7 +1202,7 @@ func TestDefaultCompleteWithFlags(t *testing.T) { Name: "cmd", Flags: []Flag{ &BoolFlag{Name: "happiness"}, - &Int64Flag{Name: "everybody-jump-on"}, + &IntFlag{Name: "everybody-jump-on"}, }, Commands: []*Command{ {Name: "putz"}, @@ -1223,7 +1223,7 @@ func TestDefaultCompleteWithFlags(t *testing.T) { Name: "cmd", Flags: []Flag{ &BoolFlag{Name: "happiness"}, - &Int64Flag{Name: "everybody-jump-on"}, + &IntFlag{Name: "everybody-jump-on"}, }, }}, cmd: &Command{ @@ -1245,7 +1245,7 @@ func TestDefaultCompleteWithFlags(t *testing.T) { Name: "cmd", Flags: []Flag{ &BoolFlag{Name: "happiness"}, - &Int64Flag{Name: "everybody-jump-on"}, + &IntFlag{Name: "everybody-jump-on"}, }, }}, cmd: &Command{ diff --git a/testdata/godoc-v3.x.txt b/testdata/godoc-v3.x.txt index 36328a220d..1916550a35 100644 --- a/testdata/godoc-v3.x.txt +++ b/testdata/godoc-v3.x.txt @@ -175,8 +175,7 @@ Global flags: {{ end }} {{- end }}` var NewFloat64Slice = NewSliceBase[float64, NoConfig, float64Value] -var NewInt64Slice = NewSliceBase[int64, IntegerConfig, int64Value] -var NewIntSlice = NewSliceBase[int, IntegerConfig, intValue] +var NewIntSlice = NewSliceBase[int64, IntegerConfig, intValue] var NewStringMap = NewMapBase[string, StringConfig, stringValue] var NewStringSlice = NewSliceBase[string, StringConfig, stringValue] var NewUint64Slice = NewSliceBase[uint64, IntegerConfig, uint64Value] @@ -597,17 +596,10 @@ func (cCtx *Context) Float64Slice(name string) []float64 Float64Slice looks up the value of a local Float64SliceFlag, returns nil if not found -func (cCtx *Context) Int(name string) int - Int looks up the value of a local IntFlag, returns 0 if not found - -func (cCtx *Context) Int64(name string) int64 +func (cCtx *Context) Int(name string) int64 Int64 looks up the value of a local Int64Flag, returns 0 if not found -func (cCtx *Context) Int64Slice(name string) []int64 - Int64Slice looks up the value of a local Int64SliceFlag, returns nil if not - found - -func (cCtx *Context) IntSlice(name string) []int +func (cCtx *Context) IntSlice(name string) []int64 IntSlice looks up the value of a local IntSliceFlag, returns nil if not found @@ -923,17 +915,11 @@ type Float64Slice = SliceBase[float64, NoConfig, float64Value] type Float64SliceFlag = FlagBase[[]float64, NoConfig, Float64Slice] -type Int64Flag = FlagBase[int64, IntegerConfig, int64Value] - -type Int64Slice = SliceBase[int64, IntegerConfig, int64Value] - -type Int64SliceFlag = FlagBase[[]int64, IntegerConfig, Int64Slice] - -type IntFlag = FlagBase[int, IntegerConfig, intValue] +type IntFlag = FlagBase[int64, IntegerConfig, intValue] -type IntSlice = SliceBase[int, IntegerConfig, intValue] +type IntSlice = SliceBase[int64, IntegerConfig, intValue] -type IntSliceFlag = FlagBase[[]int, IntegerConfig, IntSlice] +type IntSliceFlag = FlagBase[[]int64, IntegerConfig, IntSlice] type IntegerConfig struct { Base int From e6fce948e9ec1dc318d1171fd190a36ccf20fa30 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Mon, 19 Jun 2023 12:46:13 -0400 Subject: [PATCH 2/3] Finish fixing tests for Int64 -> Int collapse --- command_test.go | 38 ++++++-------------------- context_test.go | 57 +++++++++++++++++++++++---------------- flag_int.go | 2 +- flag_test.go | 72 +++++-------------------------------------------- 4 files changed, 50 insertions(+), 119 deletions(-) diff --git a/command_test.go b/command_test.go index df56bd82f3..c33d7f375f 100644 --- a/command_test.go +++ b/command_test.go @@ -2758,26 +2758,6 @@ func TestFlagAction(t *testing.T) { args: []string{"app", "--f_int_slice=-1"}, err: "invalid int slice", }, - { - name: "flag_int64", - args: []string{"app", "--f_int64=1"}, - exp: "1 ", - }, - { - name: "flag_int64_error", - args: []string{"app", "--f_int64=-1"}, - err: "negative int64", - }, - { - name: "flag_int64_slice", - args: []string{"app", "--f_int64_slice=1,2,3"}, - exp: "[1 2 3] ", - }, - { - name: "flag_int64_slice", - args: []string{"app", "--f_int64_slice=-1"}, - err: "invalid int64 slice", - }, { name: "flag_timestamp", args: []string{"app", "--f_timestamp", "2022-05-01 02:26:20"}, @@ -2947,16 +2927,6 @@ func TestFlagAction(t *testing.T) { return err }, }, - &IntFlag{ - Name: "f_int64", - Action: func(cCtx *Context, v int64) error { - if v < 0 { - return fmt.Errorf("negative int64") - } - _, err := cCtx.Command.Root().Writer.Write([]byte(fmt.Sprintf("%v ", v))) - return err - }, - }, &TimestampFlag{ Name: "f_timestamp", Config: TimestampConfig{ @@ -3038,6 +3008,11 @@ func TestPersistentFlag(t *testing.T) { return nil }, }, + &IntSliceFlag{ + Name: "persistentCommandSliceFlag", + Persistent: true, + Destination: &persistentCommandSliceInt, + }, &Float64SliceFlag{ Name: "persistentCommandFloatSliceFlag", Persistent: true, @@ -3156,6 +3131,9 @@ func TestFlagDuplicates(t *testing.T) { Name: "sflag", OnlyOnce: true, }, + &IntSliceFlag{ + Name: "isflag", + }, &Float64SliceFlag{ Name: "fsflag", OnlyOnce: true, diff --git a/context_test.go b/context_test.go index 47e31f9d03..cc3ca87a98 100644 --- a/context_test.go +++ b/context_test.go @@ -8,41 +8,50 @@ import ( "strings" "testing" "time" + + "github.com/stretchr/testify/require" ) func TestNewContext(t *testing.T) { set := flag.NewFlagSet("test", 0) - set.Int("myflag", 12, "doc") - set.Int64("myflagInt64", int64(12), "doc") + set.Int64("myflag", 12, "doc") set.Uint("myflagUint", uint(93), "doc") set.Uint64("myflagUint64", uint64(93), "doc") set.Float64("myflag64", float64(17), "doc") + globalSet := flag.NewFlagSet("test", 0) - globalSet.Int("myflag", 42, "doc") - globalSet.Int64("myflagInt64", int64(42), "doc") + globalSet.Int64("myflag", 42, "doc") globalSet.Uint("myflagUint", uint(33), "doc") globalSet.Uint64("myflagUint64", uint64(33), "doc") globalSet.Float64("myflag64", float64(47), "doc") + globalCtx := NewContext(nil, globalSet, nil) + command := &Command{Name: "mycommand"} - c := NewContext(nil, set, globalCtx) - c.Command = command - expect(t, c.Int("myflag"), 12) - expect(t, c.Uint("myflagUint"), uint(93)) - expect(t, c.Uint64("myflagUint64"), uint64(93)) - expect(t, c.Float64("myflag64"), float64(17)) - expect(t, c.Command.Name, "mycommand") + cCtx := NewContext(nil, set, globalCtx) + cCtx.Command = command + + r := require.New(t) + r.Equal(int64(12), cCtx.Int("myflag")) + r.Equal(uint(93), cCtx.Uint("myflagUint")) + r.Equal(uint64(93), cCtx.Uint64("myflagUint64")) + r.Equal(float64(17), cCtx.Float64("myflag64")) + r.Equal("mycommand", cCtx.Command.Name) } func TestContext_Int(t *testing.T) { set := flag.NewFlagSet("test", 0) - set.Int("myflag", 12, "doc") + set.Int64("myflag", 12, "doc") + parentSet := flag.NewFlagSet("test", 0) - parentSet.Int("top-flag", 13, "doc") - parentCtx := NewContext(nil, parentSet, nil) - c := NewContext(nil, set, parentCtx) - expect(t, c.Int("myflag"), 12) - expect(t, c.Int("top-flag"), 13) + parentSet.Int64("top-flag", 13, "doc") + parentCctx := NewContext(nil, parentSet, nil) + + cCtx := NewContext(nil, set, parentCctx) + + r := require.New(t) + r.Equal(int64(12), cCtx.Int("myflag")) + r.Equal(int64(13), cCtx.Int("top-flag")) } func TestContext_Uint(t *testing.T) { @@ -253,13 +262,15 @@ func TestContext_NumFlags(t *testing.T) { func TestContext_Set(t *testing.T) { set := flag.NewFlagSet("test", 0) - set.Int("int", 5, "an int") - c := NewContext(nil, set, nil) + set.Int64("int", int64(5), "an int") + cCtx := NewContext(nil, set, nil) + + r := require.New(t) - expect(t, c.IsSet("int"), false) - _ = c.Set("int", "1") - expect(t, c.Int("int"), 1) - expect(t, c.IsSet("int"), true) + r.False(cCtx.IsSet("int")) + r.NoError(cCtx.Set("int", "1")) + r.Equal(int64(1), cCtx.Int("int")) + r.True(cCtx.IsSet("int")) } func TestContext_Set_InvalidFlagAccessHandler(t *testing.T) { diff --git a/flag_int.go b/flag_int.go index 69b7b79d90..585084d1bb 100644 --- a/flag_int.go +++ b/flag_int.go @@ -35,7 +35,7 @@ func (i intValue) ToString(b int64) string { // Below functions are to satisfy the flag.Value interface func (i *intValue) Set(s string) error { - v, err := strconv.ParseInt(s, 0, 64) + v, err := strconv.ParseInt(s, i.base, 64) if err != nil { return err } diff --git a/flag_test.go b/flag_test.go index de5211bb41..56475f0e9e 100644 --- a/flag_test.go +++ b/flag_test.go @@ -194,29 +194,10 @@ func TestFlagsFromEnv(t *testing.T) { errContains: `could not parse "foobar" as int64 value from environment variable ` + `"SECONDS" for flag seconds:`, }, - - { - name: "IntFlag valid", - input: "1", - output: 1, - fl: &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, - }, - { - name: "IntFlag invalid from octal", - input: "08", - output: 8, - fl: &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 10}}, - }, - { - name: "IntFlag valid from octal", - input: "755", - output: 493, - fl: &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 8}}, - }, { name: "IntFlag valid from hex", input: "deadBEEF", - output: 3735928559, + output: int64(3735928559), fl: &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 16}}, }, { @@ -224,23 +205,7 @@ func TestFlagsFromEnv(t *testing.T) { input: "08", output: 0, fl: &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS"), Config: IntegerConfig{Base: 0}}, - errContains: `could not parse "08" as int value from environment variable ` + - `"SECONDS" for flag seconds:`, - }, - { - name: "IntFlag invalid from float", - input: "1.2", - output: 0, - fl: &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, - errContains: `could not parse "1.2" as int value from environment variable ` + - `"SECONDS" for flag seconds:`, - }, - { - name: "IntFlag invalid", - input: "foobar", - output: 0, - fl: &IntFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, - errContains: `could not parse "foobar" as int value from environment variable ` + + errContains: `could not parse "08" as int64 value from environment variable ` + `"SECONDS" for flag seconds:`, }, @@ -262,23 +227,23 @@ func TestFlagsFromEnv(t *testing.T) { { name: "IntSliceFlag valid", input: "1,2", - output: []int{1, 2}, + output: []int64{1, 2}, fl: &IntSliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, }, { name: "IntSliceFlag invalid from float", input: "1.2,2", - output: []int{}, + output: []int64{}, fl: &IntSliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, - errContains: `could not parse "1.2,2" as []int value from environment variable ` + + errContains: `could not parse "1.2,2" as []int64 value from environment variable ` + `"SECONDS" for flag seconds:`, }, { name: "IntSliceFlag invalid", input: "foobar", - output: []int{}, + output: []int64{}, fl: &IntSliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, - errContains: `could not parse "foobar" as []int value from environment variable ` + + errContains: `could not parse "foobar" as []int64 value from environment variable ` + `"SECONDS" for flag seconds:`, }, @@ -305,29 +270,6 @@ func TestFlagsFromEnv(t *testing.T) { `"SECONDS" for flag seconds:`, }, - { - name: "IntSliceFlag valid", - input: "1,2", - output: []int64{1, 2}, - fl: &IntSliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, - }, - { - name: "IntSliceFlag invalid with float", - input: "1.2,2", - output: []int64{}, - fl: &IntSliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, - errContains: `could not parse "1.2,2" as []int64 value from environment variable ` + - `"SECONDS" for flag seconds:`, - }, - { - name: "IntSliceFlag invalid", - input: "foobar", - output: []int64{}, - fl: &IntSliceFlag{Name: "seconds", Sources: EnvVars("SECONDS")}, - errContains: `could not parse "foobar" as []int64 value from environment variable ` + - `"SECONDS" for flag seconds:`, - }, - { name: "Uint64SliceFlag valid", input: "1,2", From 8a19f93da9f309f7e6c5bc4e376c2aba2dedaa30 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Mon, 19 Jun 2023 12:52:50 -0400 Subject: [PATCH 3/3] Remove unused test case slices --- flag_test.go | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/flag_test.go b/flag_test.go index 56475f0e9e..96ecd9f68e 100644 --- a/flag_test.go +++ b/flag_test.go @@ -931,14 +931,6 @@ func TestIntFlagValueFromContext(t *testing.T) { require.Equal(t, int64(42), fl.Get(cCtx)) } -var int64FlagTests = []struct { - name string - expected string -}{ - {"hats", "--hats value\t(default: 8589934592)"}, - {"H", "-H value\t(default: 8589934592)"}, -} - var uintFlagTests = []struct { name string expected string @@ -1228,22 +1220,6 @@ func TestIntSliceFlagValueFromContext(t *testing.T) { require.Equal(t, f.Get(cCtx), []int64{1, 2, 3}) } -var int64SliceFlagTests = []struct { - name string - aliases []string - value []int64 - expected string -}{ - {"heads", nil, []int64{}, "--heads value [ --heads value ]\t"}, - {"H", nil, []int64{}, "-H value [ -H value ]\t"}, - { - "heads", - []string{"H"}, - []int64{2, 17179869184}, - "--heads value, -H value [ --heads value, -H value ]\t(default: 2, 17179869184)", - }, -} - var uintSliceFlagTests = []struct { name string aliases []string