From 4077d5aa048ab0978747dbf0b47a563090ba58a0 Mon Sep 17 00:00:00 2001 From: Seunghun Lee Date: Fri, 10 Jan 2025 03:58:36 +0900 Subject: [PATCH] fix: IntEvalution, FloatEvalution when disabled or missing flags (#610) Signed-off-by: Seunghun Lee --- providers/unleash/pkg/demo_app_toggles.json | 19 +++++- providers/unleash/pkg/provider.go | 16 +++++ providers/unleash/pkg/provider_test.go | 73 ++++++++++++++++----- 3 files changed, 90 insertions(+), 18 deletions(-) diff --git a/providers/unleash/pkg/demo_app_toggles.json b/providers/unleash/pkg/demo_app_toggles.json index ae56f487d..d409b2a01 100644 --- a/providers/unleash/pkg/demo_app_toggles.json +++ b/providers/unleash/pkg/demo_app_toggles.json @@ -123,7 +123,7 @@ ], "variants": [ { - "name": "aaaa", + "name": "int-flag-variant", "weight": 1000, "payload": { "type": "number", @@ -148,7 +148,7 @@ ], "variants": [ { - "name": "aaaa", + "name": "double-flag-variant", "weight": 1000, "payload": { "type": "number", @@ -160,6 +160,21 @@ } ] }, + { + "name": "disabled-flag", + "type": "release", + "enabled": false, + "variants": [ + { + "name": "disabled-flag-variant", + "weight": 1000, + "payload": { + "type": "string", + "value": "disabled flag variant value" + } + } + ] + }, { "name": "DateExample", "type": "release", diff --git a/providers/unleash/pkg/provider.go b/providers/unleash/pkg/provider.go index e8c62df91..b659c93f5 100644 --- a/providers/unleash/pkg/provider.go +++ b/providers/unleash/pkg/provider.go @@ -107,6 +107,14 @@ func (p *Provider) BooleanEvaluation(ctx context.Context, flag string, defaultVa func (p *Provider) FloatEvaluation(ctx context.Context, flag string, defaultValue float64, evalCtx of.FlattenedContext) of.FloatResolutionDetail { res := p.ObjectEvaluation(ctx, flag, defaultValue, evalCtx) + + if value, ok := res.Value.(float64); ok { + return of.FloatResolutionDetail{ + Value: value, + ProviderResolutionDetail: res.ProviderResolutionDetail, + } + } + if strValue, ok := res.Value.(string); ok { value, err := strconv.ParseFloat(strValue, 64) if err == nil { @@ -127,6 +135,14 @@ func (p *Provider) FloatEvaluation(ctx context.Context, flag string, defaultValu func (p *Provider) IntEvaluation(ctx context.Context, flag string, defaultValue int64, evalCtx of.FlattenedContext) of.IntResolutionDetail { res := p.ObjectEvaluation(ctx, flag, defaultValue, evalCtx) + + if value, ok := res.Value.(int64); ok { + return of.IntResolutionDetail{ + Value: value, + ProviderResolutionDetail: res.ProviderResolutionDetail, + } + } + if strValue, ok := res.Value.(string); ok { value, err := strconv.ParseInt(strValue, 10, 64) if err == nil { diff --git a/providers/unleash/pkg/provider_test.go b/providers/unleash/pkg/provider_test.go index 6d788f7b0..7d32f9049 100644 --- a/providers/unleash/pkg/provider_test.go +++ b/providers/unleash/pkg/provider_test.go @@ -40,27 +40,63 @@ func TestBooleanEvaluation(t *testing.T) { func TestIntEvaluation(t *testing.T) { defaultValue := int64(0) - expectedValue := int64(123) - resolution := provider.IntEvaluation(context.Background(), "int-flag", defaultValue, nil) - enabled, _ := resolution.ProviderResolutionDetail.FlagMetadata.GetBool("enabled") - if !enabled { - t.Fatalf("Expected feature to be enabled") - } - if resolution.ProviderResolutionDetail.Variant != "aaaa" { - t.Fatalf("Expected variant name") - } - if resolution.Value != expectedValue { - t.Fatalf("Expected one of the variant payloads") - } - t.Run("evalCtx empty", func(t *testing.T) { - resolution := provider.IntEvaluation(context.Background(), "non-existing-flag", defaultValue, nil) + t.Run("int-flag", func(t *testing.T) { + resolution := provider.IntEvaluation(context.Background(), "int-flag", defaultValue, nil) + enabled, _ := resolution.ProviderResolutionDetail.FlagMetadata.GetBool("enabled") + require.True(t, enabled) + require.Equal(t, "int-flag-variant", resolution.ProviderResolutionDetail.Variant) + require.Equal(t, int64(123), resolution.Value) + require.Equal(t, of.ErrorCode(""), resolution.ResolutionDetail().ErrorCode) + }) + + t.Run("disabled-flag", func(t *testing.T) { + resolution := provider.IntEvaluation(context.Background(), "disabled-flag", defaultValue, nil) + enabled, _ := resolution.ProviderResolutionDetail.FlagMetadata.GetBool("enabled") + require.False(t, enabled) + require.Equal(t, "", resolution.ProviderResolutionDetail.Variant) require.Equal(t, defaultValue, resolution.Value) + require.Equal(t, of.ErrorCode(""), resolution.ResolutionDetail().ErrorCode) }) - t.Run("evalCtx empty fallback to default", func(t *testing.T) { + t.Run("non-existing-flag", func(t *testing.T) { resolution := provider.IntEvaluation(context.Background(), "non-existing-flag", defaultValue, nil) + enabled, _ := resolution.ProviderResolutionDetail.FlagMetadata.GetBool("enabled") + require.False(t, enabled) + require.Equal(t, "", resolution.ProviderResolutionDetail.Variant) + require.Equal(t, defaultValue, resolution.Value) + require.Equal(t, of.ErrorCode(""), resolution.ResolutionDetail().ErrorCode) + }) +} + +func TestFloatEvaluation(t *testing.T) { + defaultValue := 0.0 + + t.Run("int-flag", func(t *testing.T) { + resolution := provider.FloatEvaluation(context.Background(), "double-flag", defaultValue, nil) + enabled, _ := resolution.ProviderResolutionDetail.FlagMetadata.GetBool("enabled") + require.True(t, enabled) + require.Equal(t, "double-flag-variant", resolution.ProviderResolutionDetail.Variant) + require.Equal(t, 1.23, resolution.Value) + require.Equal(t, of.ErrorCode(""), resolution.ResolutionDetail().ErrorCode) + }) + + t.Run("disabled-flag", func(t *testing.T) { + resolution := provider.FloatEvaluation(context.Background(), "disabled-flag", defaultValue, nil) + enabled, _ := resolution.ProviderResolutionDetail.FlagMetadata.GetBool("enabled") + require.False(t, enabled) + require.Equal(t, "", resolution.ProviderResolutionDetail.Variant) + require.Equal(t, defaultValue, resolution.Value) + require.Equal(t, of.ErrorCode(""), resolution.ResolutionDetail().ErrorCode) + }) + + t.Run("non-existing-flag", func(t *testing.T) { + resolution := provider.FloatEvaluation(context.Background(), "non-existing-flag", defaultValue, nil) + enabled, _ := resolution.ProviderResolutionDetail.FlagMetadata.GetBool("enabled") + require.False(t, enabled) + require.Equal(t, "", resolution.ProviderResolutionDetail.Variant) require.Equal(t, defaultValue, resolution.Value) + require.Equal(t, of.ErrorCode(""), resolution.ResolutionDetail().ErrorCode) }) } @@ -228,13 +264,17 @@ func TestMain(m *testing.M) { } defer demoReader.Close() + appName := "my-application" + backupFile := fmt.Sprintf("unleash-repo-schema-v1-%s.json", appName) + providerOptions := unleashProvider.ProviderConfig{ Options: []unleash.ConfigOption{ unleash.WithListener(&unleash.DebugListener{}), - unleash.WithAppName("my-application"), + unleash.WithAppName(appName), unleash.WithRefreshInterval(5 * time.Second), unleash.WithMetricsInterval(5 * time.Second), unleash.WithStorage(&unleash.BootstrapStorage{Reader: demoReader}), + unleash.WithBackupPath("./"), unleash.WithUrl("https://localhost:4242"), }, } @@ -258,5 +298,6 @@ func TestMain(m *testing.M) { cleanup() + os.Remove(backupFile) os.Exit(exitCode) }