diff --git a/ffenv/env_test.go b/ffenv/env_test.go index 0240cd0..a4c18c7 100644 --- a/ffenv/env_test.go +++ b/ffenv/env_test.go @@ -1,6 +1,8 @@ package ffenv_test import ( + "flag" + "fmt" "os" "testing" "time" @@ -10,6 +12,43 @@ import ( "github.com/peterbourgon/ff/v3/fftest" ) +type Vars struct { + *fftest.Vars + S_S string + SDotS string + SDashS string + SSlashS string +} + +func Pair() (*flag.FlagSet, *Vars) { + fs, v := fftest.Pair() + + var vv Vars + vv.Vars = v + + fs.StringVar(&vv.S_S, "s_s", "", "string") + fs.StringVar(&vv.SDashS, "s-s", "", "string") + fs.StringVar(&vv.SDotS, "s.s", "", "string") + fs.StringVar(&vv.SSlashS, "s/s", "", "string") + return fs, &vv +} + +func Compare(want, have *Vars) error { + if want.SDashS != have.SDashS { + return fmt.Errorf("var SDashS: want %q, have %q", want.SDashS, have.SDashS) + } + if want.SDotS != have.SDotS { + return fmt.Errorf("var SDotS: want %q, have %q", want.SDotS, have.SDotS) + } + if want.SSlashS != have.SSlashS { + return fmt.Errorf("var SSlashS: want %q, have %q", want.SSlashS, have.SSlashS) + } + if want.S_S != have.S_S { + return fmt.Errorf("var S_S: want %q, have %q", want.S_S, have.S_S) + } + return fftest.Compare(want.Vars, have.Vars) +} + func TestParseBasics(t *testing.T) { t.Parallel() @@ -19,49 +58,49 @@ func TestParseBasics(t *testing.T) { file string args []string opts []ff.Option - want fftest.Vars + want Vars }{ { name: "empty", args: []string{}, - want: fftest.Vars{}, + want: Vars{Vars: &fftest.Vars{}}, }, { name: "args only", args: []string{"-s", "foo", "-i", "123", "-b", "-d", "24m"}, - want: fftest.Vars{S: "foo", I: 123, B: true, D: 24 * time.Minute}, + want: Vars{Vars: &fftest.Vars{S: "foo", I: 123, B: true, D: 24 * time.Minute}}, }, { name: "file only", file: "testdata/1.env", opts: []ff.Option{ff.WithEnvVarPrefix("TEST_PARSE")}, - want: fftest.Vars{S: "bar", I: 99, B: true, D: time.Hour}, + want: Vars{Vars: &fftest.Vars{S: "bar", I: 99, B: true, D: time.Hour}}, }, { name: "env only", env: map[string]string{"TEST_PARSE_S": "baz", "TEST_PARSE_F": "0.99", "TEST_PARSE_D": "100s"}, opts: []ff.Option{ff.WithEnvVarPrefix("TEST_PARSE")}, - want: fftest.Vars{S: "baz", F: 0.99, D: 100 * time.Second}, + want: Vars{Vars: &fftest.Vars{S: "baz", F: 0.99, D: 100 * time.Second}}, }, { name: "file args", file: "testdata/2.env", args: []string{"-s", "foo", "-i", "1234"}, - want: fftest.Vars{S: "foo", I: 1234, D: 3 * time.Second}, + want: Vars{Vars: &fftest.Vars{S: "foo", I: 1234, D: 3 * time.Second}}, }, { name: "env args", env: map[string]string{"TEST_PARSE_S": "should be overridden", "TEST_PARSE_B": "true"}, args: []string{"-s", "explicit wins", "-i", "7"}, opts: []ff.Option{ff.WithEnvVarPrefix("TEST_PARSE")}, - want: fftest.Vars{S: "explicit wins", I: 7, B: true}, + want: Vars{Vars: &fftest.Vars{S: "explicit wins", I: 7, B: true}}, }, { name: "file env", env: map[string]string{"TEST_PARSE_S": "env takes priority", "TEST_PARSE_B": "true"}, file: "testdata/3.env", opts: []ff.Option{ff.WithEnvVarPrefix("TEST_PARSE")}, - want: fftest.Vars{S: "env takes priority", I: 99, B: true, D: 34 * time.Second}, + want: Vars{Vars: &fftest.Vars{S: "env takes priority", I: 99, B: true, D: 34 * time.Second}}, }, { name: "file env args", @@ -69,17 +108,17 @@ func TestParseBasics(t *testing.T) { env: map[string]string{"TEST_PARSE_S": "from env", "TEST_PARSE_I": "300", "TEST_PARSE_F": "0.15", "TEST_PARSE_B": "true"}, args: []string{"-s", "from arg", "-i", "100"}, opts: []ff.Option{ff.WithEnvVarPrefix("TEST_PARSE")}, - want: fftest.Vars{S: "from arg", I: 100, F: 0.15, B: true, D: time.Minute}, + want: Vars{Vars: &fftest.Vars{S: "from arg", I: 100, F: 0.15, B: true, D: time.Minute}}, }, { name: "repeated args", args: []string{"-s", "foo", "-s", "bar", "-d", "1m", "-d", "1h", "-x", "1", "-x", "2", "-x", "3"}, - want: fftest.Vars{S: "bar", D: time.Hour, X: []string{"1", "2", "3"}}, + want: Vars{Vars: &fftest.Vars{S: "bar", D: time.Hour, X: []string{"1", "2", "3"}}}, }, { name: "long args", args: []string{"-s_s", "f_oo", "-s-s", "f-oo", "-s.s", "f.oo", "-s/s", "f/oo"}, - want: fftest.Vars{S_S: "f_oo", SDashS: "f-oo", SDotS: "f.oo", SSlashS: "f/oo"}, + want: Vars{S_S: "f_oo", SDashS: "f-oo", SDotS: "f.oo", SSlashS: "f/oo", Vars: &fftest.Vars{}}, }, { name: "priority repeats", @@ -87,46 +126,46 @@ func TestParseBasics(t *testing.T) { file: "testdata/5.env", args: []string{"-s", "s.arg.1", "-s", "s.arg.2", "-x", "x.arg.1", "-x", "x.arg.2"}, opts: []ff.Option{ff.WithEnvVarPrefix("TEST_PARSE")}, - want: fftest.Vars{S: "s.arg.2", X: []string{"x.arg.1", "x.arg.2"}}, // highest prio wins and no others are called + want: Vars{Vars: &fftest.Vars{S: "s.arg.2", X: []string{"x.arg.1", "x.arg.2"}}}, // highest prio wins and no others are called }, { name: "PlainParser string with spaces", file: "testdata/equals.env", - want: fftest.Vars{S: "i=am=the=very=model=of=a=modern=major=general"}, + want: Vars{Vars: &fftest.Vars{S: "i=am=the=very=model=of=a=modern=major=general"}}, }, { name: "default comma behavior", env: map[string]string{"TEST_PARSE_S": "one,two,three", "TEST_PARSE_X": "one,two,three"}, opts: []ff.Option{ff.WithEnvVarPrefix("TEST_PARSE")}, - want: fftest.Vars{S: "one,two,three", X: []string{"one,two,three"}}, + want: Vars{Vars: &fftest.Vars{S: "one,two,three", X: []string{"one,two,three"}}}, }, { name: "WithEnvVarSplit", env: map[string]string{"TEST_PARSE_S": "one,two,three", "TEST_PARSE_X": "one,two,three"}, opts: []ff.Option{ff.WithEnvVarPrefix("TEST_PARSE"), ff.WithEnvVarSplit(",")}, - want: fftest.Vars{S: "three", X: []string{"one", "two", "three"}}, + want: Vars{Vars: &fftest.Vars{S: "three", X: []string{"one", "two", "three"}}}, }, { name: "WithEnvVarNoPrefix", env: map[string]string{"TEST_PARSE_S": "foo", "S": "bar"}, opts: []ff.Option{ff.WithEnvVarNoPrefix()}, - want: fftest.Vars{S: "bar"}, + want: Vars{Vars: &fftest.Vars{S: "bar"}}, }, { name: "env var split comma whitespace", env: map[string]string{"TEST_PARSE_S": "one, two, three ", "TEST_PARSE_X": "one, two, three "}, opts: []ff.Option{ff.WithEnvVarPrefix("TEST_PARSE"), ff.WithEnvVarSplit(",")}, - want: fftest.Vars{S: " three ", X: []string{"one", " two", " three "}}, + want: Vars{Vars: &fftest.Vars{S: " three ", X: []string{"one", " two", " three "}}}, }, { name: "flags with . from env", env: map[string]string{"TEST_PARSE_S_S": "one"}, opts: []ff.Option{ff.WithEnvVarPrefix("TEST_PARSE")}, - want: fftest.Vars{S_S: "one", SDashS: "one", SDotS: "one", SSlashS: "one"}, + want: Vars{S_S: "one", SDashS: "one", SDotS: "one", SSlashS: "one", Vars: &fftest.Vars{}}, }, } { t.Run(testcase.name, func(t *testing.T) { - fs, vars := fftest.Pair() + fs, vars := Pair() if testcase.file != "" { testcase.opts = append(testcase.opts, ff.WithConfigFile(testcase.file), ff.WithConfigFileParser(ffenv.ParserWithPrefix(fs, "TEST_PARSE"))) } @@ -139,7 +178,7 @@ func TestParseBasics(t *testing.T) { } vars.ParseError = ff.Parse(fs, testcase.args, testcase.opts...) - if err := fftest.Compare(&testcase.want, vars); err != nil { + if err := Compare(&testcase.want, vars); err != nil { t.Fatal(err) } }) diff --git a/fftest/vars.go b/fftest/vars.go index 47fa273..a181c8c 100644 --- a/fftest/vars.go +++ b/fftest/vars.go @@ -18,10 +18,6 @@ func Pair() (*flag.FlagSet, *Vars) { var v Vars fs.StringVar(&v.S, "s", "", "string") - fs.StringVar(&v.S_S, "s_s", "", "string") - fs.StringVar(&v.SDashS, "s-s", "", "string") - fs.StringVar(&v.SDotS, "s.s", "", "string") - fs.StringVar(&v.SSlashS, "s/s", "", "string") fs.IntVar(&v.I, "i", 0, "int") fs.Float64Var(&v.F, "f", 0., "float64") fs.BoolVar(&v.B, "b", false, "bool") @@ -33,16 +29,12 @@ func Pair() (*flag.FlagSet, *Vars) { // Vars are a common set of variables used for testing. type Vars struct { - S string - S_S string - SDotS string - SDashS string - SSlashS string - I int - F float64 - B bool - D time.Duration - X StringSlice + S string + I int + F float64 + B bool + D time.Duration + X StringSlice // ParseError should be assigned as the result of Parse in tests. ParseError error @@ -88,18 +80,6 @@ func Compare(want, have *Vars) error { if want.S != have.S { return fmt.Errorf("var S: want %q, have %q", want.S, have.S) } - if want.SDashS != have.SDashS { - return fmt.Errorf("var SDashS: want %q, have %q", want.SDashS, have.SDashS) - } - if want.SDotS != have.SDotS { - return fmt.Errorf("var SDotS: want %q, have %q", want.SDotS, have.SDotS) - } - if want.SSlashS != have.SSlashS { - return fmt.Errorf("var SSlashS: want %q, have %q", want.SSlashS, have.SSlashS) - } - if want.S_S != have.S_S { - return fmt.Errorf("var S_S: want %q, have %q", want.S_S, have.S_S) - } if want.I != have.I { return fmt.Errorf("var I: want %d, have %d", want.I, have.I) }