package override import ( "context" "testing" "github.com/influxdata/influxdb/v2/kit/feature" ) func TestFlagger(t *testing.T) { cases := []struct { name string env map[string]string defaults []feature.Flag expected map[string]interface{} expectMakeErr bool expectFlagsErr bool byKey feature.ByKeyFn }{ { name: "enabled happy path filtering", env: map[string]string{ "flag1": "new1", "flag3": "new3", }, defaults: []feature.Flag{ newFlag("flag0", "original0"), newFlag("flag1", "original1"), newFlag("flag2", "original2"), newFlag("flag3", "original3"), newFlag("flag4", "original4"), }, byKey: newByKey(map[string]feature.Flag{ "flag0": newFlag("flag0", "original0"), "flag1": newFlag("flag1", "original1"), "flag2": newFlag("flag2", "original2"), "flag3": newFlag("flag3", "original3"), "flag4": newFlag("flag4", "original4"), }), expected: map[string]interface{}{ "flag0": "original0", "flag1": "new1", "flag2": "original2", "flag3": "new3", "flag4": "original4", }, }, { name: "enabled happy path types", env: map[string]string{ "intflag": "43", "floatflag": "43.43", "boolflag": "true", }, defaults: []feature.Flag{ newFlag("intflag", 42), newFlag("floatflag", 42.42), newFlag("boolflag", false), }, byKey: newByKey(map[string]feature.Flag{ "intflag": newFlag("intflag", 42), "floatflag": newFlag("floatflag", 43.43), "boolflag": newFlag("boolflag", false), }), expected: map[string]interface{}{ "intflag": 43, "floatflag": 43.43, "boolflag": true, }, }, { name: "type coerce error", env: map[string]string{ "key": "not_an_int", }, defaults: []feature.Flag{ newFlag("key", 42), }, byKey: newByKey(map[string]feature.Flag{ "key": newFlag("key", 42), }), expectFlagsErr: true, }, { name: "typed base flags", env: map[string]string{ "flag1": "411", "flag2": "new2", "flag3": "true", }, defaults: []feature.Flag{ newBaseFlag("flag0", "original0"), newBaseFlag("flag1", 41), newBaseFlag("flag2", "original2"), newBaseFlag("flag3", false), newBaseFlag("flag4", "original4"), }, byKey: newByKey(map[string]feature.Flag{ "flag0": newFlag("flag0", "original0"), "flag1": newFlag("flag1", 41), "flag2": newFlag("flag2", "original2"), "flag3": newFlag("flag3", false), "flag4": newFlag("flag4", "original4"), }), expected: map[string]interface{}{ "flag0": "original0", "flag1": 411, "flag2": "new2", "flag3": true, "flag4": "original4", }, }, { name: "override for non-existent flag", env: map[string]string{ "dne": "foobar", }, defaults: []feature.Flag{ newBaseFlag("key", "value"), }, byKey: newByKey(map[string]feature.Flag{ "key": newFlag("key", "value"), }), expectMakeErr: true, }, } for _, test := range cases { t.Run(test.name, func(t *testing.T) { subject, err := Make(test.env, test.byKey) if err != nil { if test.expectMakeErr { return } t.Fatalf("unexpected error making Flagger: %v", err) } computed, err := subject.Flags(context.Background(), test.defaults...) if err != nil { if test.expectFlagsErr { return } t.Fatalf("unexpected error calling Flags: %v", err) } if len(computed) != len(test.expected) { t.Fatalf("incorrect number of flags computed: expected %d, got %d", len(test.expected), len(computed)) } // check for extra or incorrect keys for k, v := range computed { if xv, found := test.expected[k]; !found { t.Errorf("unexpected key %s", k) } else if v != xv { t.Errorf("incorrect value for key %s: expected %v [%T], got %v [%T]", k, xv, xv, v, v) } } // check for missing keys for k := range test.expected { if _, found := computed[k]; !found { t.Errorf("missing expected key %s", k) } } }) } } func newFlag(key string, defaultValue interface{}) feature.Flag { return feature.MakeFlag(key, key, "", defaultValue, feature.Temporary, false) } func newBaseFlag(key string, defaultValue interface{}) feature.Base { return feature.MakeBase(key, key, "", defaultValue, feature.Temporary, false) } func newByKey(m map[string]feature.Flag) feature.ByKeyFn { return func(k string) (feature.Flag, bool) { v, found := m[k] return v, found } }