1
0
Fork 0
mirror of https://github.com/Luzifer/rconfig.git synced 2024-12-20 19:21:19 +00:00

Update deps, fix linter errors, bump min Go version

Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
Knut Ahlers 2023-12-20 12:13:59 +01:00
parent 4c83f34ecf
commit c1c878fab9
Signed by: luzifer
SSH key fingerprint: SHA256:/xtE5lCgiRDQr8SLxHMS92ZBlACmATUmF1crK16Ks4E
10 changed files with 120 additions and 116 deletions

View file

@ -2,6 +2,8 @@ package rconfig
import ( import (
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestDeriveEnvVarName(t *testing.T) { func TestDeriveEnvVarName(t *testing.T) {
@ -22,8 +24,6 @@ func TestDeriveEnvVarName(t *testing.T) {
"MyFieldName": "MY_FIELD_NAME", "MyFieldName": "MY_FIELD_NAME",
"SmallCASE": "SMALL_CASE", "SmallCASE": "SMALL_CASE",
} { } {
if d := deriveEnvVarName(test); d != expect { assert.Equal(t, expect, deriveEnvVarName(test))
t.Errorf("Derived variable %q did not match expectation %q", d, expect)
}
} }
} }

View file

@ -57,13 +57,12 @@ func init() {
// //
// The format you need to specify those values you can see in the example to this // The format you need to specify those values you can see in the example to this
// function. // function.
//
func Parse(config interface{}) error { func Parse(config interface{}) error {
return parse(config, nil) return parse(config, nil)
} }
// ParseAndValidate works exactly like Parse but implements an additional run of // ParseAndValidate works exactly like Parse but implements an additional run of
// the go-validator package on the configuration struct. Therefore additonal struct // the go-validator package on the configuration struct. Therefore additional struct
// tags are supported like described in the readme file of the go-validator package: // tags are supported like described in the readme file of the go-validator package:
// //
// https://github.com/go-validator/validator/tree/v2#usage // https://github.com/go-validator/validator/tree/v2#usage
@ -103,14 +102,20 @@ func SetVariableDefaults(defaults map[string]string) {
variableDefaults = defaults variableDefaults = defaults
} }
func parseAndValidate(in interface{}, args []string) error { //revive:disable-next-line:confusing-naming // The public function is only a wrapper with less args
if err := parse(in, args); err != nil { func parseAndValidate(in interface{}, args []string) (err error) {
if err = parse(in, args); err != nil {
return err return err
} }
return validator.Validate(in) if err = validator.Validate(in); err != nil {
return fmt.Errorf("validating values: %w", err)
} }
return nil
}
//revive:disable-next-line:confusing-naming // The public function is only a wrapper with less args
func parse(in interface{}, args []string) error { func parse(in interface{}, args []string) error {
if args == nil { if args == nil {
args = os.Args args = os.Args
@ -123,27 +128,26 @@ func parse(in interface{}, args []string) error {
} }
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
return err return fmt.Errorf("parsing flag-set: %w", err)
} }
if afterFuncs != nil {
for _, f := range afterFuncs { for _, f := range afterFuncs {
if err := f(); err != nil { if err := f(); err != nil {
return err return err
} }
} }
}
return nil return nil
} }
//nolint:funlen,gocognit,gocyclo // Hard to split
func execTags(in interface{}, fs *pflag.FlagSet) ([]afterFunc, error) { func execTags(in interface{}, fs *pflag.FlagSet) ([]afterFunc, error) {
if reflect.TypeOf(in).Kind() != reflect.Ptr { if reflect.TypeOf(in).Kind() != reflect.Ptr {
return nil, errors.New("Calling parser with non-pointer") return nil, errors.New("calling parser with non-pointer")
} }
if reflect.ValueOf(in).Elem().Kind() != reflect.Struct { if reflect.ValueOf(in).Elem().Kind() != reflect.Struct {
return nil, errors.New("Calling parser with pointer to non-struct") return nil, errors.New("calling parser with pointer to non-struct")
} }
afterFuncs := []afterFunc{} afterFuncs := []afterFunc{}
@ -166,11 +170,10 @@ func execTags(in interface{}, fs *pflag.FlagSet) ([]afterFunc, error) {
case reflect.TypeOf(time.Duration(0)): case reflect.TypeOf(time.Duration(0)):
v, err := time.ParseDuration(value) v, err := time.ParseDuration(value)
if err != nil { if err != nil {
if value == "" { if value != "" {
v = time.Duration(0) return nil, fmt.Errorf("parsing time.Duration: %w", err)
} else {
return nil, err
} }
v = time.Duration(0)
} }
if typeField.Tag.Get("flag") != "" { if typeField.Tag.Get("flag") != "" {
@ -215,14 +218,13 @@ func execTags(in interface{}, fs *pflag.FlagSet) ([]afterFunc, error) {
matched := false matched := false
for _, tf := range timeParserFormats { for _, tf := range timeParserFormats {
if t, err := time.Parse(tf, *sVar); err == nil { if t, err := time.Parse(tf, *sVar); err == nil {
matched = true
valField.Set(reflect.ValueOf(t)) valField.Set(reflect.ValueOf(t))
return nil return nil
} }
} }
if !matched { if !matched {
return fmt.Errorf("Value %q did not match expected time formats", *sVar) return fmt.Errorf("value %q did not match expected time formats", *sVar)
} }
return nil return nil
@ -259,11 +261,10 @@ func execTags(in interface{}, fs *pflag.FlagSet) ([]afterFunc, error) {
case reflect.Int, reflect.Int8, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int32, reflect.Int64:
vt, err := strconv.ParseInt(value, 10, 64) vt, err := strconv.ParseInt(value, 10, 64)
if err != nil { if err != nil {
if value == "" { if value != "" {
vt = 0 return nil, fmt.Errorf("parsing int: %w", err)
} else {
return nil, err
} }
vt = 0
} }
if typeField.Tag.Get("flag") != "" { if typeField.Tag.Get("flag") != "" {
registerFlagInt(typeField.Type.Kind(), fs, valField.Addr().Interface(), parts, vt, typeField.Tag.Get("description")) registerFlagInt(typeField.Type.Kind(), fs, valField.Addr().Interface(), parts, vt, typeField.Tag.Get("description"))
@ -274,11 +275,10 @@ func execTags(in interface{}, fs *pflag.FlagSet) ([]afterFunc, error) {
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
vt, err := strconv.ParseUint(value, 10, 64) vt, err := strconv.ParseUint(value, 10, 64)
if err != nil { if err != nil {
if value == "" { if value != "" {
vt = 0 return nil, fmt.Errorf("parsing uint: %w", err)
} else {
return nil, err
} }
vt = 0
} }
if typeField.Tag.Get("flag") != "" { if typeField.Tag.Get("flag") != "" {
registerFlagUint(typeField.Type.Kind(), fs, valField.Addr().Interface(), parts, vt, typeField.Tag.Get("description")) registerFlagUint(typeField.Type.Kind(), fs, valField.Addr().Interface(), parts, vt, typeField.Tag.Get("description"))
@ -289,11 +289,10 @@ func execTags(in interface{}, fs *pflag.FlagSet) ([]afterFunc, error) {
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
vt, err := strconv.ParseFloat(value, 64) vt, err := strconv.ParseFloat(value, 64)
if err != nil { if err != nil {
if value == "" { if value != "" {
vt = 0.0 return nil, fmt.Errorf("parsing float: %w", err)
} else {
return nil, err
} }
vt = 0.0
} }
if typeField.Tag.Get("flag") != "" { if typeField.Tag.Get("flag") != "" {
registerFlagFloat(typeField.Type.Kind(), fs, valField.Addr().Interface(), parts, vt, typeField.Tag.Get("description")) registerFlagFloat(typeField.Type.Kind(), fs, valField.Addr().Interface(), parts, vt, typeField.Tag.Get("description"))
@ -315,7 +314,7 @@ func execTags(in interface{}, fs *pflag.FlagSet) ([]afterFunc, error) {
for _, v := range strings.Split(value, ",") { for _, v := range strings.Split(value, ",") {
it, err := strconv.ParseInt(strings.TrimSpace(v), 10, 64) it, err := strconv.ParseInt(strings.TrimSpace(v), 10, 64)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("parsing int: %w", err)
} }
def = append(def, int(it)) def = append(def, int(it))
} }
@ -329,7 +328,7 @@ func execTags(in interface{}, fs *pflag.FlagSet) ([]afterFunc, error) {
if len(del) == 0 { if len(del) == 0 {
del = "," del = ","
} }
var def = []string{} def := []string{}
if value != "" { if value != "" {
def = strings.Split(value, del) def = strings.Split(value, del)
} }
@ -355,9 +354,9 @@ func registerFlagFloat(t reflect.Kind, fs *pflag.FlagSet, field interface{}, par
} }
case reflect.Float64: case reflect.Float64:
if len(parts) == 1 { if len(parts) == 1 {
fs.Float64Var(field.(*float64), parts[0], float64(vt), desc) fs.Float64Var(field.(*float64), parts[0], vt, desc)
} else { } else {
fs.Float64VarP(field.(*float64), parts[0], parts[1], float64(vt), desc) fs.Float64VarP(field.(*float64), parts[0], parts[1], vt, desc)
} }
} }
} }
@ -384,9 +383,9 @@ func registerFlagInt(t reflect.Kind, fs *pflag.FlagSet, field interface{}, parts
} }
case reflect.Int64: case reflect.Int64:
if len(parts) == 1 { if len(parts) == 1 {
fs.Int64Var(field.(*int64), parts[0], int64(vt), desc) fs.Int64Var(field.(*int64), parts[0], vt, desc)
} else { } else {
fs.Int64VarP(field.(*int64), parts[0], parts[1], int64(vt), desc) fs.Int64VarP(field.(*int64), parts[0], parts[1], vt, desc)
} }
} }
} }
@ -419,9 +418,9 @@ func registerFlagUint(t reflect.Kind, fs *pflag.FlagSet, field interface{}, part
} }
case reflect.Uint64: case reflect.Uint64:
if len(parts) == 1 { if len(parts) == 1 {
fs.Uint64Var(field.(*uint64), parts[0], uint64(vt), desc) fs.Uint64Var(field.(*uint64), parts[0], vt, desc)
} else { } else {
fs.Uint64VarP(field.(*uint64), parts[0], parts[1], uint64(vt), desc) fs.Uint64VarP(field.(*uint64), parts[0], parts[1], vt, desc)
} }
} }
} }

View file

@ -2,12 +2,14 @@ package rconfig
import ( import (
"testing" "testing"
"github.com/stretchr/testify/assert"
) )
func TestErrors(t *testing.T) { func TestErrors(t *testing.T) {
for test, parsable := range map[string]interface{}{ for test, parsable := range map[string]interface{}{
"use string as default to int": struct { "use string as default to int": struct {
A int `default:"a"` A int `default:"a"` //revive:disable-line:struct-tag // Intentional error for testing
}{}, }{},
"use string as default to float": struct { "use string as default to float": struct {
A float32 `default:"a"` A float32 `default:"a"`
@ -24,18 +26,12 @@ func TestErrors(t *testing.T) {
A []int `default:"a,b"` A []int `default:"a,b"`
}{}, }{},
} { } {
if err := parse(&parsable, nil); err == nil { assert.Error(t, parse(&parsable, nil), test) //#nosec:G601 // Fine for this test
t.Errorf("Expected error but got none. Test: %s", test)
}
} }
if err := parse(struct { assert.Error(t, parse(struct {
A string `default:"a"` A string `default:"a"`
}{}, nil); err == nil { }{}, nil), "feeding non-pointer to parse")
t.Errorf("Expected error when feeding non-pointer struct to parse")
}
if err := parse("test", nil); err == nil { assert.Error(t, parse("test", nil), "feeding non-pointer string to parse")
t.Errorf("Expected error when feeding non-pointer string to parse")
}
} }

View file

@ -1,8 +1,10 @@
package rconfig package rconfig_test
import ( import (
"fmt" "fmt"
"os" "os"
"github.com/Luzifer/rconfig/v2"
) )
func ExampleParse() { func ExampleParse() {
@ -23,14 +25,16 @@ func ExampleParse() {
"--user=Luzifer", "--user=Luzifer",
} }
Parse(&config) if err := rconfig.Parse(&config); err != nil {
panic(err)
}
fmt.Printf("Hello %s, happy birthday for your %dth birthday.", fmt.Printf("Hello %s, happy birthday for your %dth birthday.",
config.Username, config.Username,
config.Details.Age) config.Details.Age)
// You can also show an usage message for your user // You can also show an usage message for your user
Usage() rconfig.Usage()
// Output: // Output:
// Hello Luzifer, happy birthday for your 25th birthday. // Hello Luzifer, happy birthday for your 25th birthday.

View file

@ -4,6 +4,9 @@ import (
"os" "os"
"reflect" "reflect"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestGeneralExecution(t *testing.T) { func TestGeneralExecution(t *testing.T) {
@ -20,14 +23,10 @@ func TestGeneralExecution(t *testing.T) {
) )
exec := func(desc string, tests [][2]interface{}) { exec := func(desc string, tests [][2]interface{}) {
if err := parse(&cfg, args); err != nil { require.NoError(t, parse(&cfg, args))
t.Fatalf("Parsing options caused error: %s", err)
}
for _, test := range tests { for _, test := range tests {
if !reflect.DeepEqual(reflect.ValueOf(test[0]).Elem().Interface(), test[1]) { assert.Equal(t, test[1], reflect.ValueOf(test[0]).Elem().Interface(), desc)
t.Errorf("%q expected value does not match: %#v != %#v", desc, test[0], test[1])
}
} }
} }
@ -51,11 +50,11 @@ func TestGeneralExecution(t *testing.T) {
cfg = test{} cfg = test{}
args = []string{} args = []string{}
os.Setenv("shell", "test546") require.NoError(t, os.Setenv("shell", "test546"))
exec("no arguments and set env", [][2]interface{}{ exec("no arguments and set env", [][2]interface{}{
{&cfg.Test, "test546"}, {&cfg.Test, "test546"},
}) })
os.Unsetenv("shell") require.NoError(t, os.Unsetenv("shell"))
cfg = test{} cfg = test{}
args = []string{ args = []string{
@ -70,9 +69,7 @@ func TestGeneralExecution(t *testing.T) {
{&cfg.DefaultFlag, "goo"}, {&cfg.DefaultFlag, "goo"},
}) })
if !reflect.DeepEqual(Args(), []string{"positional1", "positional2"}) { assert.Equal(t, []string{"positional1", "positional2"}, Args())
t.Errorf("expected positional arguments to match")
}
} }
func TestValidationIntegration(t *testing.T) { func TestValidationIntegration(t *testing.T) {
@ -85,7 +82,5 @@ func TestValidationIntegration(t *testing.T) {
args = []string{} args = []string{}
) )
if err := parseAndValidate(&cfgValidated, args); err == nil { assert.Error(t, parseAndValidate(&cfgValidated, args))
t.Errorf("Expected error, got none")
}
} }

12
go.mod
View file

@ -1,9 +1,15 @@
module github.com/Luzifer/rconfig/v2 module github.com/Luzifer/rconfig/v2
go 1.17 go 1.20
require ( require (
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5
gopkg.in/validator.v2 v2.0.0-20210331031555-b37d688a7fb0 github.com/stretchr/testify v1.8.4
gopkg.in/yaml.v2 v2.4.0 gopkg.in/validator.v2 v2.0.1
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
) )

18
go.sum
View file

@ -1,8 +1,16 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/validator.v2 v2.0.0-20210331031555-b37d688a7fb0 h1:EFLtLCwd8tGN+r/ePz3cvRtdsfYNhDEdt/vp6qsT+0A= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/validator.v2 v2.0.0-20210331031555-b37d688a7fb0/go.mod h1:o4V0GXN9/CAmCsvJ0oXYZvrZOe7syiDZSN1GWGZTGzc= gopkg.in/validator.v2 v2.0.1 h1:xF0KWyGWXm/LM2G1TrEjqOu4pa6coO9AlWSf3msVfDY=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/validator.v2 v2.0.1/go.mod h1:lIUZBlB3Im4s/eYp39Ry/wkR02yOPhZ9IwIRBjuPuG8=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -3,6 +3,9 @@ package rconfig
import ( import (
"os" "os"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestPrecedence(t *testing.T) { func TestPrecedence(t *testing.T) {
@ -11,7 +14,6 @@ func TestPrecedence(t *testing.T) {
} }
var ( var (
err error
cfg testcfg cfg testcfg
args []string args []string
vardefaults map[string]string vardefaults map[string]string
@ -20,20 +22,14 @@ func TestPrecedence(t *testing.T) {
exec := func(desc string, fn func() interface{}, exp interface{}) { exec := func(desc string, fn func() interface{}, exp interface{}) {
cfg = testcfg{} cfg = testcfg{}
SetVariableDefaults(vardefaults) SetVariableDefaults(vardefaults)
err = parse(&cfg, args) assert.NoError(t, parse(&cfg, args), desc)
if err != nil { assert.Equal(t, exp, fn())
t.Errorf("%q parsing caused error: %s", desc, err)
}
if res := fn(); res != exp {
t.Errorf("%q expected value does not match: %#v != %#v", desc, res, exp)
}
} }
// Provided: Flag, Env, Default, VarDefault // Provided: Flag, Env, Default, VarDefault
args = []string{"-a", "5"} args = []string{"-a", "5"}
os.Setenv("a", "8") require.NoError(t, os.Setenv("a", "8"))
vardefaults = map[string]string{ vardefaults = map[string]string{
"a": "3", "a": "3",
} }
@ -42,7 +38,7 @@ func TestPrecedence(t *testing.T) {
// Provided: Env, Default, VarDefault // Provided: Env, Default, VarDefault
args = []string{} args = []string{}
os.Setenv("a", "8") require.NoError(t, os.Setenv("a", "8"))
vardefaults = map[string]string{ vardefaults = map[string]string{
"a": "3", "a": "3",
} }
@ -51,7 +47,7 @@ func TestPrecedence(t *testing.T) {
// Provided: Default, VarDefault // Provided: Default, VarDefault
args = []string{} args = []string{}
os.Unsetenv("a") require.NoError(t, os.Unsetenv("a"))
vardefaults = map[string]string{ vardefaults = map[string]string{
"a": "3", "a": "3",
} }
@ -60,7 +56,7 @@ func TestPrecedence(t *testing.T) {
// Provided: Default // Provided: Default
args = []string{} args = []string{}
os.Unsetenv("a") require.NoError(t, os.Unsetenv("a"))
vardefaults = map[string]string{} vardefaults = map[string]string{}
exec("Provided: Default", func() interface{} { return cfg.A }, 1) exec("Provided: Default", func() interface{} { return cfg.A }, 1)

View file

@ -1,14 +1,14 @@
package rconfig package rconfig
import ( import (
"io/ioutil" "os"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v3"
) )
// VarDefaultsFromYAMLFile reads contents of a file and calls VarDefaultsFromYAML // VarDefaultsFromYAMLFile reads contents of a file and calls VarDefaultsFromYAML
func VarDefaultsFromYAMLFile(filename string) map[string]string { func VarDefaultsFromYAMLFile(filename string) map[string]string {
data, err := ioutil.ReadFile(filename) data, err := os.ReadFile(filename) //#nosec:G304 // Loading file from var is intended
if err != nil { if err != nil {
return make(map[string]string) return make(map[string]string)
} }

View file

@ -1,10 +1,12 @@
package rconfig package rconfig
import ( import (
"io/ioutil"
"os" "os"
"reflect" "reflect"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestVardefaultParsing(t *testing.T) { func TestVardefaultParsing(t *testing.T) {
@ -18,6 +20,7 @@ func TestVardefaultParsing(t *testing.T) {
var ( var (
cfg test cfg test
args = []string{} args = []string{}
err error
vardefaults = map[string]string{ vardefaults = map[string]string{
"my_secret_value": "veryverysecretkey", "my_secret_value": "veryverysecretkey",
"unkownkey": "hi there", "unkownkey": "hi there",
@ -26,14 +29,10 @@ func TestVardefaultParsing(t *testing.T) {
) )
exec := func(desc string, tests [][2]interface{}) { exec := func(desc string, tests [][2]interface{}) {
if err := parse(&cfg, args); err != nil { require.NoError(t, parse(&cfg, args))
t.Fatalf("Parsing options caused error: %s", err)
}
for _, test := range tests { for _, test := range tests {
if !reflect.DeepEqual(reflect.ValueOf(test[0]).Elem().Interface(), test[1]) { assert.Equal(t, test[1], reflect.ValueOf(test[0]).Elem().Interface(), desc)
t.Errorf("%q expected value does not match: %#v != %#v", desc, test[0], test[1])
}
} }
} }
@ -53,13 +52,14 @@ func TestVardefaultParsing(t *testing.T) {
{&cfg.SomeVar, ""}, {&cfg.SomeVar, ""},
}) })
tmp, _ := ioutil.TempFile("", "") tmp, _ := os.CreateTemp("", "")
defer func() { t.Cleanup(func() {
tmp.Close() tmp.Close() //nolint:errcheck,gosec,revive // Just cleanup, will be closed automatically
os.Remove(tmp.Name()) os.Remove(tmp.Name()) //nolint:errcheck,gosec,revive // Just cleanup of tmp-file
}() })
yamlData := "---\nmy_secret_value: veryverysecretkey\nunknownkey: hi there\nint_var: 42\n" yamlData := "---\nmy_secret_value: veryverysecretkey\nunknownkey: hi there\nint_var: 42\n"
tmp.WriteString(yamlData) _, err = tmp.WriteString(yamlData)
require.NoError(t, err)
SetVariableDefaults(VarDefaultsFromYAMLFile(tmp.Name())) SetVariableDefaults(VarDefaultsFromYAMLFile(tmp.Name()))
exec("defaults from YAML file", [][2]interface{}{ exec("defaults from YAML file", [][2]interface{}{
{&cfg.IntVar, int64(42)}, {&cfg.IntVar, int64(42)},