diff --git a/v7/eval.go b/v7/eval.go index 4a27c9c..0125560 100644 --- a/v7/eval.go +++ b/v7/eval.go @@ -7,6 +7,7 @@ import ( "fmt" "math" "reflect" + "sort" "strconv" "strings" @@ -907,6 +908,7 @@ func keysForRootNode(root *rootNode) []string { for k := range root.Entries { keys = append(keys, k) } + sort.Strings(keys) return keys } diff --git a/v7/flag.go b/v7/flag.go index e906473..b9f60f7 100644 --- a/v7/flag.go +++ b/v7/flag.go @@ -18,6 +18,7 @@ import ( func Bool(key string, defaultValue bool) BoolFlag { return BoolFlag{ id: idForKey(key, true), + key: key, defaultValue: defaultValue, } } @@ -28,6 +29,14 @@ type BoolFlag struct { defaultValue bool } +// Key returns the name of the flag as passed to Bool. +func (f BoolFlag) Key() string { + return f.key +} + +// Get reports whether the flag is enabled with respect to the +// given snapshot. It returns the flag's default value if snap is nil +// or the key isn't in the configuration. func (f BoolFlag) Get(snap *Snapshot) bool { if v, ok := snap.value(f.id, f.key).(bool); ok { return v @@ -50,6 +59,14 @@ type IntFlag struct { defaultValue int } +// Key returns the name of the flag as passed to Int. +func (f IntFlag) Key() string { + return f.key +} + +// Get reports the value of the flag with respect to the +// given snapshot. It returns the flag's default value if snap is nil +// or the key isn't in the configuration. func (f IntFlag) Get(snap *Snapshot) int { if v, ok := snap.value(f.id, f.key).(int); ok { return v @@ -72,6 +89,14 @@ type StringFlag struct { defaultValue string } +// Key returns the name of the flag as passed to String. +func (f StringFlag) Key() string { + return f.key +} + +// Get reports the value of the flag with respect to the +// given snapshot. It returns the flag's default value if snap is nil +// or the key isn't in the configuration. func (f StringFlag) Get(snap *Snapshot) string { if v, ok := snap.value(f.id, f.key).(string); ok { return v @@ -94,6 +119,14 @@ type FloatFlag struct { defaultValue float64 } +// Key returns the name of the flag as passed to Float. +func (f FloatFlag) Key() string { + return f.key +} + +// Get reports the value of the flag with respect to the +// given snapshot. It returns the flag's default value if snap is nil +// or the key isn't in the configuration. func (f FloatFlag) Get(snap *Snapshot) float64 { if v, ok := snap.value(f.id, f.key).(float64); ok { return v diff --git a/v7/snapshot_test.go b/v7/snapshot_test.go index de2aa02..66add21 100644 --- a/v7/snapshot_test.go +++ b/v7/snapshot_test.go @@ -199,6 +199,26 @@ var loggingTests = []struct { "INFO: Evaluating rule: [Identifier:1.2.3] [< (SemVer)] [bogus] => SKIP rule. Validation error: No Major.Minor.Patch elements found", "INFO: Returning key=defaultValue.", }, +}, { + testName: "UnknownKey", + config: &rootNode{ + Entries: map[string]*entry{ + "key1": { + Value: "v1", + Type: stringEntry, + }, + "key2": { + Value: "v2", + Type: stringEntry, + }, + }, + }, + key: "unknownKey", + expectValue: nil, + expectLogs: []string{ + "INFO: fetching from $HOST_URL", + "ERROR: error getting value: value not found for key unknownKey. Here are the available keys: key1,key2", + }, }} func TestLogging(t *testing.T) { @@ -228,7 +248,7 @@ func TestLogging(t *testing.T) { expectLogs[i] = strings.ReplaceAll(expectLogs[i], "$HOST_URL", cfg.BaseURL) } - value := client.GetStringValue(test.key, "", test.user) + value := client.Snapshot(test.user).GetValue(test.key) c.Check(value, qt.Equals, test.expectValue) c.Check(logs, qt.DeepEquals, expectLogs) }) @@ -254,6 +274,9 @@ func TestNewSnapshot(t *testing.T) { } // Sanity check that it works OK with Flag values. c.Assert(Int("intFlag", 0).Get(snap), qt.Equals, 1) + c.Assert(Float("floatFlag", 0).Get(snap), qt.Equals, 2.0) + c.Assert(String("stringFlag", "").Get(snap), qt.Equals, "three") + c.Assert(Bool("boolFlag", false).Get(snap), qt.Equals, true) c.Assert(snap.GetAllKeys(), qt.ContentEquals, []string{ "intFlag", "floatFlag", @@ -277,3 +300,22 @@ func TestNewSnapshotWithUnknownType(t *testing.T) { c.Check(err, qt.ErrorMatches, `value for flag "badVal" has unexpected type int64 \(1\); must be bool, int, float64 or string`) c.Check(snap, qt.IsNil) } + +func TestFlagKey(t *testing.T) { + c := qt.New(t) + intFlag := Int("intFlag", 99) + c.Assert(intFlag.Get(nil), qt.Equals, 99) + c.Assert(intFlag.Key(), qt.Equals, "intFlag") + + floatFlag := Float("floatFlag", 2.5) + c.Assert(floatFlag.Get(nil), qt.Equals, 2.5) + c.Assert(floatFlag.Key(), qt.Equals, "floatFlag") + + stringFlag := String("stringFlag", "default") + c.Assert(stringFlag.Get(nil), qt.Equals, "default") + c.Assert(stringFlag.Key(), qt.Equals, "stringFlag") + + boolFlag := Bool("boolFlag", true) + c.Assert(boolFlag.Get(nil), qt.Equals, true) + c.Assert(boolFlag.Key(), qt.Equals, "boolFlag") +}