diff --git a/env/config.go b/env/config.go index 2c94d8e..628b2fc 100644 --- a/env/config.go +++ b/env/config.go @@ -40,10 +40,11 @@ func (c *VarNameConstructor) setReplacement(oldChar, newChar string) { } func (c *VarNameConstructor) VarFromFlagName(name string) string { - varName := strings.ReplaceAll(name, c.varNameReplacement.old, c.varNameReplacement.new) + varName := name if c.prefix != "" { varName = fmt.Sprintf("%s_%s", c.prefix, varName) } + varName = strings.ReplaceAll(varName, c.varNameReplacement.old, c.varNameReplacement.new) if c.capitalize { varName = strings.ToUpper(varName) } diff --git a/flag/flag_test.go b/flag/flag_test.go index 6531ef2..74cd246 100644 --- a/flag/flag_test.go +++ b/flag/flag_test.go @@ -94,7 +94,7 @@ func assertFlag[T any](t *testing.T, f flagPropertyGetter, tt flagTest) { assert.Equal(t, tt.expected.Shared(), f.IsShared()) } -func assertGetFlag[T any](t *testing.T, f flagPropertyGetter, tt getFlagTest[T]) { +func assertGetFlagCmd[T any](t *testing.T, f flagPropertyGetter, tt getFlagTest[T]) { assert.NotNil(t, f) if tt.input != nil { if tt.wanted.err { @@ -108,6 +108,24 @@ func assertGetFlag[T any](t *testing.T, f flagPropertyGetter, tt getFlagTest[T]) assert.Equal(t, tt.wanted.some, PtrOrDie[T](f.Value())) } +func assertGetFlagEnv[T any](t *testing.T, f flagPropertyGetter, tt getFlagTest[T]) { + assert.NotNil(t, f) + if tt.input != nil { + if tt.wanted.err { + assert.Error(t, f.FromEnvVariable(*tt.input)) + return + } + if *tt.input == "" { + assert.Error(t, f.FromEnvVariable(*tt.input)) + return + } + assert.NoError(t, f.FromEnvVariable(*tt.input)) + assert.True(t, f.IsSetFromCmd()) + } + assert.Equal(t, *tt.wanted.some, DerefOrDie[T](f.Value())) + assert.Equal(t, tt.wanted.some, PtrOrDie[T](f.Value())) +} + type custom struct { field int } @@ -128,8 +146,12 @@ func (p *customParser) ParseCmd(s string) (any, error) { return &custom{field: v}, nil } -func (p *customParser) ParseEnv(_ string) (any, error) { - return nil, nil +func (p *customParser) ParseEnv(s string) (any, error) { + v, err := strconv.Atoi(s) + if err != nil { + return nil, err + } + return &custom{field: v}, nil } func TestFlag_Custom(t *testing.T) { @@ -186,7 +208,8 @@ func TestFlag_GetCustom(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Typed[custom](tt.name, tt.opts...) - assertGetFlag[custom](t, f, tt) + assertGetFlagCmd[custom](t, f, tt) + assertGetFlagEnv[custom](t, f, tt) }) } } @@ -265,7 +288,8 @@ func TestFlag_GetString(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := String(tt.name, tt.opts...) - assertGetFlag[string](t, f, tt) + assertGetFlagCmd[string](t, f, tt) + assertGetFlagEnv[string](t, f, tt) }) } } @@ -353,7 +377,8 @@ func TestFlag_GetDuration(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Duration(tt.name, tt.opts...) - assertGetFlag[time.Duration](t, f, tt) + assertGetFlagCmd[time.Duration](t, f, tt) + assertGetFlagEnv[time.Duration](t, f, tt) }) } } @@ -450,7 +475,8 @@ func TestFlag_GetBool(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Bool(tt.name, tt.opts...) - assertGetFlag[bool](t, f, tt) + assertGetFlagCmd[bool](t, f, tt) + assertGetFlagEnv[bool](t, f, tt) }) } } @@ -526,7 +552,8 @@ func TestFlag_GetInt(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Int(tt.name, tt.opts...) - assertGetFlag[int](t, f, tt) + assertGetFlagCmd[int](t, f, tt) + assertGetFlagEnv[int](t, f, tt) }) } } @@ -602,7 +629,8 @@ func TestFlag_GetInt8(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Int8(tt.name, tt.opts...) - assertGetFlag[int8](t, f, tt) + assertGetFlagCmd[int8](t, f, tt) + assertGetFlagEnv[int8](t, f, tt) }) } } @@ -678,7 +706,8 @@ func TestFlag_GetInt16(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Int16(tt.name, tt.opts...) - assertGetFlag[int16](t, f, tt) + assertGetFlagCmd[int16](t, f, tt) + assertGetFlagEnv[int16](t, f, tt) }) } } @@ -754,7 +783,8 @@ func TestFlag_GetInt32(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Int32(tt.name, tt.opts...) - assertGetFlag[int32](t, f, tt) + assertGetFlagCmd[int32](t, f, tt) + assertGetFlagEnv[int32](t, f, tt) }) } } @@ -830,7 +860,8 @@ func TestFlag_GetInt64(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Int64(tt.name, tt.opts...) - assertGetFlag[int64](t, f, tt) + assertGetFlagCmd[int64](t, f, tt) + assertGetFlagEnv[int64](t, f, tt) }) } } @@ -906,7 +937,8 @@ func TestFlag_GetUint(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Uint(tt.name, tt.opts...) - assertGetFlag[uint](t, f, tt) + assertGetFlagCmd[uint](t, f, tt) + assertGetFlagEnv[uint](t, f, tt) }) } } @@ -982,7 +1014,8 @@ func TestFlag_GetUint8(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Uint8(tt.name, tt.opts...) - assertGetFlag[uint8](t, f, tt) + assertGetFlagCmd[uint8](t, f, tt) + assertGetFlagEnv[uint8](t, f, tt) }) } } @@ -1058,7 +1091,8 @@ func TestFlag_GetUint16(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Uint16(tt.name, tt.opts...) - assertGetFlag[uint16](t, f, tt) + assertGetFlagCmd[uint16](t, f, tt) + assertGetFlagEnv[uint16](t, f, tt) }) } } @@ -1134,7 +1168,8 @@ func TestFlag_GetUint32(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Uint32(tt.name, tt.opts...) - assertGetFlag[uint32](t, f, tt) + assertGetFlagCmd[uint32](t, f, tt) + assertGetFlagEnv[uint32](t, f, tt) }) } } @@ -1210,7 +1245,8 @@ func TestFlag_GetUint64(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Uint64(tt.name, tt.opts...) - assertGetFlag[uint64](t, f, tt) + assertGetFlagCmd[uint64](t, f, tt) + assertGetFlagEnv[uint64](t, f, tt) }) } } @@ -1286,7 +1322,8 @@ func TestFlag_GetFloat32(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Float32(tt.name, tt.opts...) - assertGetFlag[float32](t, f, tt) + assertGetFlagCmd[float32](t, f, tt) + assertGetFlagEnv[float32](t, f, tt) }) } } @@ -1362,7 +1399,8 @@ func TestFlag_GetFloat64(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Float64(tt.name, tt.opts...) - assertGetFlag[float64](t, f, tt) + assertGetFlagCmd[float64](t, f, tt) + assertGetFlagEnv[float64](t, f, tt) }) } } @@ -1449,7 +1487,8 @@ func TestFlag_GetIntSlice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := IntSlice(tt.name, tt.opts...) - assertGetFlag[[]int](t, f, tt) + assertGetFlagCmd[[]int](t, f, tt) + assertGetFlagEnv[[]int](t, f, tt) }) } } @@ -1536,7 +1575,8 @@ func TestFlag_GetInt8Slice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Int8Slice(tt.name, tt.opts...) - assertGetFlag[[]int8](t, f, tt) + assertGetFlagCmd[[]int8](t, f, tt) + assertGetFlagEnv[[]int8](t, f, tt) }) } } @@ -1623,7 +1663,8 @@ func TestFlag_GetInt16Slice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Int16Slice(tt.name, tt.opts...) - assertGetFlag[[]int16](t, f, tt) + assertGetFlagCmd[[]int16](t, f, tt) + assertGetFlagEnv[[]int16](t, f, tt) }) } } @@ -1710,7 +1751,8 @@ func TestFlag_GetInt32Slice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Int32Slice(tt.name, tt.opts...) - assertGetFlag[[]int32](t, f, tt) + assertGetFlagCmd[[]int32](t, f, tt) + assertGetFlagEnv[[]int32](t, f, tt) }) } } @@ -1797,7 +1839,8 @@ func TestFlag_GetInt64Slice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Int64Slice(tt.name, tt.opts...) - assertGetFlag[[]int64](t, f, tt) + assertGetFlagCmd[[]int64](t, f, tt) + assertGetFlagEnv[[]int64](t, f, tt) }) } } @@ -1884,7 +1927,8 @@ func TestFlag_GetUintSlice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := UintSlice(tt.name, tt.opts...) - assertGetFlag[[]uint](t, f, tt) + assertGetFlagCmd[[]uint](t, f, tt) + assertGetFlagEnv[[]uint](t, f, tt) }) } } @@ -1971,7 +2015,8 @@ func TestFlag_GetUint8Slice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Uint8Slice(tt.name, tt.opts...) - assertGetFlag[[]uint8](t, f, tt) + assertGetFlagCmd[[]uint8](t, f, tt) + assertGetFlagEnv[[]uint8](t, f, tt) }) } } @@ -2058,7 +2103,8 @@ func TestFlag_GetUint16Slice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Uint16Slice(tt.name, tt.opts...) - assertGetFlag[[]uint16](t, f, tt) + assertGetFlagCmd[[]uint16](t, f, tt) + assertGetFlagEnv[[]uint16](t, f, tt) }) } } @@ -2145,7 +2191,8 @@ func TestFlag_GetUint32Slice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Uint32Slice(tt.name, tt.opts...) - assertGetFlag[[]uint32](t, f, tt) + assertGetFlagCmd[[]uint32](t, f, tt) + assertGetFlagEnv[[]uint32](t, f, tt) }) } } @@ -2232,7 +2279,8 @@ func TestFlag_GetUint64Slice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Uint64Slice(tt.name, tt.opts...) - assertGetFlag[[]uint64](t, f, tt) + assertGetFlagCmd[[]uint64](t, f, tt) + assertGetFlagEnv[[]uint64](t, f, tt) }) } } @@ -2319,7 +2367,8 @@ func TestFlag_GetFloat32Slice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Float32Slice(tt.name, tt.opts...) - assertGetFlag[[]float32](t, f, tt) + assertGetFlagCmd[[]float32](t, f, tt) + assertGetFlagEnv[[]float32](t, f, tt) }) } } @@ -2406,7 +2455,8 @@ func TestFlag_GetFloat64Slice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Float64Slice(tt.name, tt.opts...) - assertGetFlag[[]float64](t, f, tt) + assertGetFlagCmd[[]float64](t, f, tt) + assertGetFlagEnv[[]float64](t, f, tt) }) } } @@ -2484,7 +2534,8 @@ func TestFlag_GetStringSlice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := StringSlice(tt.name, tt.opts...) - assertGetFlag[[]string](t, f, tt) + assertGetFlagCmd[[]string](t, f, tt) + assertGetFlagEnv[[]string](t, f, tt) }) } } @@ -2571,7 +2622,8 @@ func TestFlag_GetDurationSlice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := DurationSlice(tt.name, tt.opts...) - assertGetFlag[[]time.Duration](t, f, tt) + assertGetFlagCmd[[]time.Duration](t, f, tt) + assertGetFlagEnv[[]time.Duration](t, f, tt) }) } } @@ -2658,7 +2710,8 @@ func TestFlag_GetBoolSlice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := BoolSlice(tt.name, tt.opts...) - assertGetFlag[[]bool](t, f, tt) + assertGetFlagCmd[[]bool](t, f, tt) + assertGetFlagEnv[[]bool](t, f, tt) }) } } @@ -2737,7 +2790,8 @@ func TestFlag_GetCounter(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() f := Counter(tt.name, tt.opts...) - assertGetFlag[int](t, f, tt) + assertGetFlagCmd[int](t, f, tt) + assertGetFlagEnv[int](t, f, tt) }) } } diff --git a/flagset/flagset_test.go b/flagset/flagset_test.go index 055236e..7c7abb7 100644 --- a/flagset/flagset_test.go +++ b/flagset/flagset_test.go @@ -677,18 +677,27 @@ func TestFlagSet_BindEnvVars(t *testing.T) { fs := New(env.Prefix("test1"), env.Capitalized(), env.VarNameReplace("-", "_")). BindFlag(flag.String("sample-string")). BindFlag(flag.Bool("sample-bool")). + BindFlag(flag.Counter("sample-counter")). + BindFlag(flag.Float32("sample-float32")). + BindFlag(flag.Float64("sample-float64")). BindFlag(flag.Duration("sample-duration")).Build() return fs }, variables: map[string]string{ "TEST1_SAMPLE_STRING": "foo", "TEST1_SAMPLE_BOOL": "true", + "TEST1_SAMPLE_COUNTER": "1", + "TEST1_SAMPLE_FLOAT32": "3.14", + "TEST1_SAMPLE_FLOAT64": "3.14", "TEST1_SAMPLE_DURATION": "15m", }, expected: expected{ parsed: []result{ {flagName: "sample-duration", flagValue: time.Minute * 15, flagType: "duration"}, {flagName: "sample-string", flagValue: "foo", flagType: "string"}, + {flagName: "sample-counter", flagValue: 1, flagType: "counter"}, + {flagName: "sample-float32", flagValue: float32(3.14), flagType: "float32"}, + {flagName: "sample-float64", flagValue: 3.14, flagType: "float64"}, {flagName: "sample-bool", flagValue: true, flagType: "bool"}, }, err: false, @@ -700,20 +709,285 @@ func TestFlagSet_BindEnvVars(t *testing.T) { fs := New(env.Prefix("test2"), env.Capitalized(), env.VarNameReplace("-", "_")). BindFlag(flag.String("sample-string")). BindFlag(flag.Bool("sample-bool")). + BindFlag(flag.Counter("sample-counter")). + BindFlag(flag.Float32("sample-float32")). + BindFlag(flag.Float64("sample-float64")). BindFlag(flag.Duration("sample-duration")).Build() return fs }, variables: map[string]string{ "TEST2_SAMPLE_STRING": "foo", "TEST2_SAMPLE_BOOL": "yes", + "TEST2_SAMPLE_COUNTER": "one", + "TEST2_SAMPLE_FLOAT32": "3.4e+39", + "TEST2_SAMPLE_FLOAT64": "1.7e+308", "TEST2_SAMPLE_DURATION": "15m", }, + expected: expected{ + parsed: []result{}, + err: true, + expectedErr: ferrors.ErrParseFailed, + }, + }, + { + name: "env vars slices success", + flagSet: func() *FlagSet { + fs := New(env.Prefix("test1-slice"), env.Capitalized(), env.VarNameReplace("-", "_")). + BindFlag(flag.StringSlice("sample-string")). + BindFlag(flag.BoolSlice("sample-bool")). + BindFlag(flag.Float32Slice("sample-float32")). + BindFlag(flag.Float64Slice("sample-float64")). + BindFlag(flag.DurationSlice("sample-duration")).Build() + return fs + }, + variables: map[string]string{ + "TEST1_SLICE_SAMPLE_STRING": "foo", + "TEST1_SLICE_SAMPLE_BOOL": "true", + "TEST1_SLICE_SAMPLE_FLOAT32": "3.14", + "TEST1_SLICE_SAMPLE_FLOAT64": "3.14", + "TEST1_SLICE_SAMPLE_DURATION": "15m", + }, expected: expected{ parsed: []result{ - {flagName: "sample-duration", flagValue: time.Minute * 15, flagType: "duration"}, - {flagName: "sample-string", flagValue: "foo", flagType: "string"}, - {flagName: "sample-bool", flagValue: true, flagType: "bool"}, + {flagName: "sample-duration", flagValue: []time.Duration{time.Minute * 15}, flagType: "durationSlice"}, + {flagName: "sample-string", flagValue: []string{"foo"}, flagType: "stringSlice"}, + {flagName: "sample-float32", flagValue: []float32{3.14}, flagType: "float32slice"}, + {flagName: "sample-float64", flagValue: []float64{3.14}, flagType: "float64slice"}, + {flagName: "sample-bool", flagValue: []bool{true}, flagType: "boolSlice"}, }, + err: false, + }, + }, + { + name: "env vars slices failed", + flagSet: func() *FlagSet { + fs := New(env.Prefix("test2-slice"), env.Capitalized(), env.VarNameReplace("-", "_")). + BindFlag(flag.BoolSlice("sample-bool")). + BindFlag(flag.Float32Slice("sample-float32")). + BindFlag(flag.Float64Slice("sample-float64")). + BindFlag(flag.DurationSlice("sample-duration")).Build() + return fs + }, + variables: map[string]string{ + "TEST2_SLICE_SAMPLE_BOOL": "yes", + "TEST2_SLICE_SAMPLE_FLOAT32": "3.4e+39", + "TEST2_SLICE_SAMPLE_FLOAT64": "1.7e+308", + "TEST2_SLICE_SAMPLE_DURATION": "15m", + }, + expected: expected{ + parsed: []result{}, + err: true, + expectedErr: ferrors.ErrParseFailed, + }, + }, + { + name: "env vars signed integers success", + flagSet: func() *FlagSet { + fs := New(env.Prefix("integers-success"), env.Capitalized(), env.VarNameReplace("-", "_")). + BindFlag(flag.Int("sample-int")). + BindFlag(flag.Int8("sample-int8")). + BindFlag(flag.Int16("sample-int16")). + BindFlag(flag.Int32("sample-int32")). + BindFlag(flag.Int64("sample-int64")).Build() + return fs + }, + variables: map[string]string{ + "INTEGERS_SUCCESS_SAMPLE_INT": "42", + "INTEGERS_SUCCESS_SAMPLE_INT8": "42", + "INTEGERS_SUCCESS_SAMPLE_INT16": "42", + "INTEGERS_SUCCESS_SAMPLE_INT32": "42", + "INTEGERS_SUCCESS_SAMPLE_INT64": "42", + }, + expected: expected{ + parsed: []result{ + {flagName: "sample-int", flagValue: 42, flagType: "int"}, + {flagName: "sample-int8", flagValue: int8(42), flagType: "int8"}, + {flagName: "sample-int16", flagValue: int16(42), flagType: "int16"}, + {flagName: "sample-int32", flagValue: int32(42), flagType: "int32"}, + {flagName: "sample-int64", flagValue: int64(42), flagType: "int64"}, + }, + err: false, + }, + }, + { + name: "env vars signed integers failure", + flagSet: func() *FlagSet { + fs := New(env.Prefix("integers-fail"), env.Capitalized(), env.VarNameReplace("-", "_")). + BindFlag(flag.Int("sample-int")). + BindFlag(flag.Int8("sample-int8")). + BindFlag(flag.Int16("sample-int16")). + BindFlag(flag.Int32("sample-int32")). + BindFlag(flag.Int64("sample-int64")).Build() + return fs + }, + variables: map[string]string{ + "INTEGERS_FAIL_SAMPLE_INT": "42.", + "INTEGERS_FAIL_SAMPLE_INT8": "1000", + "INTEGERS_FAIL_SAMPLE_INT16": "-32800", + "INTEGERS_FAIL_SAMPLE_INT32": "65656", + "INTEGERS_FAIL_SAMPLE_INT64": "9223372036854775809", + }, + expected: expected{ + parsed: []result{}, + err: true, + expectedErr: ferrors.ErrParseFailed, + }, + }, + { + name: "env vars unsigned integers success", + flagSet: func() *FlagSet { + fs := New(env.Prefix("uintegers-success"), env.Capitalized(), env.VarNameReplace("-", "_")). + BindFlag(flag.Uint("sample-uint")). + BindFlag(flag.Uint8("sample-uint8")). + BindFlag(flag.Uint16("sample-uint16")). + BindFlag(flag.Uint32("sample-uint32")). + BindFlag(flag.Uint64("sample-uint64")).Build() + return fs + }, + variables: map[string]string{ + "UINTEGERS_SUCCESS_SAMPLE_UINT": "42", + "UINTEGERS_SUCCESS_SAMPLE_UINT8": "42", + "UINTEGERS_SUCCESS_SAMPLE_UINT16": "42", + "UINTEGERS_SUCCESS_SAMPLE_UINT32": "42", + "UINTEGERS_SUCCESS_SAMPLE_UINT64": "42", + }, + expected: expected{ + parsed: []result{ + {flagName: "sample-uint", flagValue: uint(42), flagType: "uint"}, + {flagName: "sample-uint8", flagValue: uint8(42), flagType: "uint8"}, + {flagName: "sample-uint16", flagValue: uint16(42), flagType: "uint16"}, + {flagName: "sample-uint32", flagValue: uint32(42), flagType: "uint32"}, + {flagName: "sample-uint64", flagValue: uint64(42), flagType: "uint64"}, + }, + err: false, + }, + }, + { + name: "env vars signed uintegers failure", + flagSet: func() *FlagSet { + fs := New(env.Prefix("uintegers-fail"), env.Capitalized(), env.VarNameReplace("-", "_")). + BindFlag(flag.Uint("sample-uint")). + BindFlag(flag.Uint8("sample-uint8")). + BindFlag(flag.Uint16("sample-uint16")). + BindFlag(flag.Uint32("sample-uint32")). + BindFlag(flag.Uint64("sample-uint64")).Build() + return fs + }, + variables: map[string]string{ + "UINTEGERS_FAIL_SAMPLE_UINT": "42.", + "UINTEGERS_FAIL_SAMPLE_UINT8": "1000", + "UINTEGERS_FAIL_SAMPLE_UINT16": "-32800", + "UINTEGERS_FAIL_SAMPLE_UINT32": "-165656", + "UINTEGERS_FAIL_SAMPLE_UINT64": "184467440737095516150", + }, + expected: expected{ + parsed: []result{}, + err: true, + expectedErr: ferrors.ErrParseFailed, + }, + }, + { + name: "env vars signed integers slices success", + flagSet: func() *FlagSet { + fs := New(env.Prefix("integers-slice-success"), env.Capitalized(), env.VarNameReplace("-", "_")). + BindFlag(flag.IntSlice("sample-int")). + BindFlag(flag.Int8Slice("sample-int8")). + BindFlag(flag.Int16Slice("sample-int16")). + BindFlag(flag.Int32Slice("sample-int32")). + BindFlag(flag.Int64Slice("sample-int64")).Build() + return fs + }, + variables: map[string]string{ + "INTEGERS_SLICE_SUCCESS_SAMPLE_INT": "42", + "INTEGERS_SLICE_SUCCESS_SAMPLE_INT8": "42", + "INTEGERS_SLICE_SUCCESS_SAMPLE_INT16": "42", + "INTEGERS_SLICE_SUCCESS_SAMPLE_INT32": "42", + "INTEGERS_SLICE_SUCCESS_SAMPLE_INT64": "42", + }, + expected: expected{ + parsed: []result{ + {flagName: "sample-int", flagValue: []int{42}, flagType: "intSlice"}, + {flagName: "sample-int8", flagValue: []int8{42}, flagType: "int8slice"}, + {flagName: "sample-int16", flagValue: []int16{42}, flagType: "int16slice"}, + {flagName: "sample-int32", flagValue: []int32{42}, flagType: "int32slice"}, + {flagName: "sample-int64", flagValue: []int64{42}, flagType: "int64slice"}, + }, + err: false, + }, + }, + { + name: "env vars signed integers slices failure", + flagSet: func() *FlagSet { + fs := New(env.Prefix("integers-slice-failure"), env.Capitalized(), env.VarNameReplace("-", "_")). + BindFlag(flag.IntSlice("sample-int")). + BindFlag(flag.Int8Slice("sample-int8")). + BindFlag(flag.Int16Slice("sample-int16")). + BindFlag(flag.Int32Slice("sample-int32")). + BindFlag(flag.Int64Slice("sample-int64")).Build() + return fs + }, + variables: map[string]string{ + "INTEGERS_SLICE_FAILURE_SAMPLE_INT": "42.", + "INTEGERS_SLICE_FAILURE_SAMPLE_INT8": "1000", + "INTEGERS_SLICE_FAILURE_SAMPLE_INT16": "-32800", + "INTEGERS_SLICE_FAILURE_SAMPLE_INT32": "65656", + "INTEGERS_SLICE_FAILURE_SAMPLE_INT64": "18446744073709551615", + }, + expected: expected{ + parsed: []result{}, + err: true, + expectedErr: ferrors.ErrParseFailed, + }, + }, + { + name: "env vars unsigned integers slices success", + flagSet: func() *FlagSet { + fs := New(env.Prefix("uintegers-slice-success"), env.Capitalized(), env.VarNameReplace("-", "_")). + BindFlag(flag.UintSlice("sample-uint")). + BindFlag(flag.Uint8Slice("sample-uint8")). + BindFlag(flag.Uint16Slice("sample-uint16")). + BindFlag(flag.Uint32Slice("sample-uint32")). + BindFlag(flag.Uint64Slice("sample-uint64")).Build() + return fs + }, + variables: map[string]string{ + "UINTEGERS_SLICE_SUCCESS_SAMPLE_UINT": "42", + "UINTEGERS_SLICE_SUCCESS_SAMPLE_UINT8": "42", + "UINTEGERS_SLICE_SUCCESS_SAMPLE_UINT16": "42", + "UINTEGERS_SLICE_SUCCESS_SAMPLE_UINT32": "42", + "UINTEGERS_SLICE_SUCCESS_SAMPLE_UINT64": "42", + }, + expected: expected{ + parsed: []result{ + {flagName: "sample-uint", flagValue: []uint{42}, flagType: "uintSlice"}, + {flagName: "sample-uint8", flagValue: []uint8{42}, flagType: "uint8slice"}, + {flagName: "sample-uint16", flagValue: []uint16{42}, flagType: "uint16slice"}, + {flagName: "sample-uint32", flagValue: []uint32{42}, flagType: "uint32slice"}, + {flagName: "sample-uint64", flagValue: []uint64{42}, flagType: "uint64slice"}, + }, + err: false, + }, + }, + { + name: "env vars unsigned integers slices failure", + flagSet: func() *FlagSet { + fs := New(env.Prefix("uintegers-slice-failure"), env.Capitalized(), env.VarNameReplace("-", "_")). + BindFlag(flag.IntSlice("sample-uint")). + BindFlag(flag.Int8Slice("sample-uint8")). + BindFlag(flag.Int16Slice("sample-uint16")). + BindFlag(flag.Int32Slice("sample-uint32")). + BindFlag(flag.Int64Slice("sample-uint64")).Build() + return fs + }, + variables: map[string]string{ + "UINTEGERS_SLICE_FAILURE_SAMPLE_UINT": "42.", + "UINTEGERS_SLICE_FAILURE_SAMPLE_UINT8": "1000", + "UINTEGERS_SLICE_FAILURE_SAMPLE_UINT16": "-32800", + "UINTEGERS_SLICE_FAILURE_SAMPLE_UINT32": "-65656", + "UINTEGERS_SLICE_FAILURE_SAMPLE_UINT64": "1018446744073709551615", + }, + expected: expected{ + parsed: []result{}, err: true, expectedErr: ferrors.ErrParseFailed, },