125 lines
3.7 KiB
Go
125 lines
3.7 KiB
Go
package runtimeflags
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
type memoryStore struct {
|
|
values map[string]bool
|
|
}
|
|
|
|
func (m *memoryStore) ListOverrides(context.Context) (map[string]bool, error) {
|
|
out := make(map[string]bool, len(m.values))
|
|
for k, v := range m.values {
|
|
out[k] = v
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (m *memoryStore) SetOverride(_ context.Context, key string, value bool) error {
|
|
if m.values == nil {
|
|
m.values = map[string]bool{}
|
|
}
|
|
m.values[key] = value
|
|
return nil
|
|
}
|
|
|
|
func (m *memoryStore) DeleteOverride(_ context.Context, key string) error {
|
|
delete(m.values, key)
|
|
return nil
|
|
}
|
|
|
|
func TestServiceOverrideWinsOverProfileDefault(t *testing.T) {
|
|
svc := NewService(&memoryStore{values: map[string]bool{"features.office": true}}, Options{
|
|
DefaultValues: map[string]bool{"features.office": false},
|
|
RuntimeValues: map[string]bool{"features.office": false},
|
|
IsExplicitEnv: func(string) bool { return false },
|
|
})
|
|
states, err := svc.ListStates(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("ListStates: %v", err)
|
|
}
|
|
office := stateByKey(t, states, "features.office")
|
|
if !office.EffectiveValue {
|
|
t.Fatal("EffectiveValue = false, want true")
|
|
}
|
|
if office.Source != SourceOverride {
|
|
t.Fatalf("Source = %q, want %q", office.Source, SourceOverride)
|
|
}
|
|
if !office.RequiresRestartToApply {
|
|
t.Fatal("RequiresRestartToApply = false, want true")
|
|
}
|
|
}
|
|
|
|
func TestServiceExplicitEnvLocksOverride(t *testing.T) {
|
|
svc := NewService(&memoryStore{values: map[string]bool{"features.office": false}}, Options{
|
|
DefaultValues: map[string]bool{"features.office": false},
|
|
RuntimeValues: map[string]bool{"features.office": true},
|
|
EnvValues: map[string]bool{"KANDEV_FEATURES_OFFICE": true},
|
|
IsExplicitEnv: func(name string) bool { return name == "KANDEV_FEATURES_OFFICE" },
|
|
})
|
|
states, err := svc.ListStates(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("ListStates: %v", err)
|
|
}
|
|
office := stateByKey(t, states, "features.office")
|
|
if !office.EffectiveValue {
|
|
t.Fatal("EffectiveValue = false, want true")
|
|
}
|
|
if office.Source != SourceEnv {
|
|
t.Fatalf("Source = %q, want %q", office.Source, SourceEnv)
|
|
}
|
|
if !office.EnvLocked {
|
|
t.Fatal("EnvLocked = false, want true")
|
|
}
|
|
}
|
|
|
|
func TestServiceExplicitImpliedEnvLocksDebugMode(t *testing.T) {
|
|
svc := NewService(&memoryStore{values: map[string]bool{"debug.devMode": false}}, Options{
|
|
DefaultValues: map[string]bool{"debug.devMode": false},
|
|
RuntimeValues: map[string]bool{"debug.devMode": false},
|
|
EnvValues: map[string]bool{
|
|
"KANDEV_DEBUG_DEV_MODE": false,
|
|
"KANDEV_DEBUG_PPROF_ENABLED": true,
|
|
},
|
|
IsExplicitEnv: func(name string) bool { return name == "KANDEV_DEBUG_PPROF_ENABLED" },
|
|
})
|
|
states, err := svc.ListStates(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("ListStates: %v", err)
|
|
}
|
|
debug := stateByKey(t, states, "debug.devMode")
|
|
if !debug.EffectiveValue {
|
|
t.Fatal("EffectiveValue = false, want true")
|
|
}
|
|
if debug.Source != SourceEnv {
|
|
t.Fatalf("Source = %q, want %q", debug.Source, SourceEnv)
|
|
}
|
|
if !debug.EnvLocked {
|
|
t.Fatal("EnvLocked = false, want true")
|
|
}
|
|
}
|
|
|
|
func TestServiceNilStoreFailsFast(t *testing.T) {
|
|
svc := NewService(nil, Options{})
|
|
if _, err := svc.ListStates(context.Background()); !errors.Is(err, ErrStoreUnset) {
|
|
t.Fatalf("ListStates error = %v, want %v", err, ErrStoreUnset)
|
|
}
|
|
if _, err := svc.SetOverride(context.Background(), "features.office", nil); !errors.Is(err, ErrStoreUnset) {
|
|
t.Fatalf("SetOverride error = %v, want %v", err, ErrStoreUnset)
|
|
}
|
|
}
|
|
|
|
func stateByKey(t *testing.T, states []RuntimeFlagState, key string) RuntimeFlagState {
|
|
t.Helper()
|
|
for _, state := range states {
|
|
if state.Key == key {
|
|
return state
|
|
}
|
|
}
|
|
t.Fatalf("state %q missing", key)
|
|
return RuntimeFlagState{}
|
|
}
|