From eea9d17e5892064cec9d81bb0ef452e7e1761764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Sch=C3=B6nlaub?= Date: Mon, 22 Apr 2024 20:14:39 +0200 Subject: [PATCH] feat: add integer and float specific resolver methods (#124) --- lib/open_feature/sdk/client.rb | 2 +- .../sdk/provider/in_memory_provider.rb | 12 ++- .../sdk/provider/no_op_provider.rb | 8 ++ spec/open_feature/sdk/client_spec.rb | 14 +++- .../sdk/provider/in_memory_provider_spec.rb | 81 ++++++++++++++++++- 5 files changed, 107 insertions(+), 10 deletions(-) diff --git a/lib/open_feature/sdk/client.rb b/lib/open_feature/sdk/client.rb index 9d8ca92..8f3749d 100644 --- a/lib/open_feature/sdk/client.rb +++ b/lib/open_feature/sdk/client.rb @@ -5,7 +5,7 @@ module SDK # TODO: Write documentation # class Client - RESULT_TYPE = %i[boolean string number object].freeze + RESULT_TYPE = %i[boolean string number integer float object].freeze SUFFIXES = %i[value details].freeze attr_reader :metadata, :evaluation_context diff --git a/lib/open_feature/sdk/provider/in_memory_provider.rb b/lib/open_feature/sdk/provider/in_memory_provider.rb index 5a49fab..78703a4 100644 --- a/lib/open_feature/sdk/provider/in_memory_provider.rb +++ b/lib/open_feature/sdk/provider/in_memory_provider.rb @@ -34,7 +34,15 @@ def fetch_string_value(flag_key:, default_value:, evaluation_context: nil) end def fetch_number_value(flag_key:, default_value:, evaluation_context: nil) - fetch_value(allowed_classes: [Integer, Float], flag_key:, default_value:, evaluation_context:) + fetch_value(allowed_classes: [Numeric], flag_key:, default_value:, evaluation_context:) + end + + def fetch_integer_value(flag_key:, default_value:, evaluation_context: nil) + fetch_value(allowed_classes: [Integer], flag_key:, default_value:, evaluation_context:) + end + + def fetch_float_value(flag_key:, default_value:, evaluation_context: nil) + fetch_value(allowed_classes: [Float], flag_key:, default_value:, evaluation_context:) end def fetch_object_value(flag_key:, default_value:, evaluation_context: nil) @@ -52,7 +60,7 @@ def fetch_value(allowed_classes:, flag_key:, default_value:, evaluation_context: return ResolutionDetails.new(value: default_value, error_code: ErrorCode::FLAG_NOT_FOUND, reason: Reason::ERROR) end - if allowed_classes.include?(value.class) + if allowed_classes.any? { |klass| value.is_a?(klass) } ResolutionDetails.new(value:, reason: Reason::STATIC) else ResolutionDetails.new(value: default_value, error_code: ErrorCode::TYPE_MISMATCH, reason: Reason::ERROR) diff --git a/lib/open_feature/sdk/provider/no_op_provider.rb b/lib/open_feature/sdk/provider/no_op_provider.rb index 358bd22..ab18959 100644 --- a/lib/open_feature/sdk/provider/no_op_provider.rb +++ b/lib/open_feature/sdk/provider/no_op_provider.rb @@ -44,6 +44,14 @@ def fetch_number_value(flag_key:, default_value:, evaluation_context: nil) no_op(default_value) end + def fetch_integer_value(flag_key:, default_value:, evaluation_context: nil) + no_op(default_value) + end + + def fetch_float_value(flag_key:, default_value:, evaluation_context: nil) + no_op(default_value) + end + def fetch_object_value(flag_key:, default_value:, evaluation_context: nil) no_op(default_value) end diff --git a/spec/open_feature/sdk/client_spec.rb b/spec/open_feature/sdk/client_spec.rb index 828402f..051ee4c 100644 --- a/spec/open_feature/sdk/client_spec.rb +++ b/spec/open_feature/sdk/client_spec.rb @@ -64,13 +64,21 @@ expect(client).to respond_to(:fetch_number_value) end - context "Condition 1.3.2 - The implementation language differentiates between floating-point numbers and integers." do + it do + expect(client.fetch_number_value(flag_key: flag_key, default_value: 4)).is_a?(Integer) + end + + it do + expect(client.fetch_number_value(flag_key: flag_key, default_value: 95.5)).is_a?(Float) + end + + context "Condition 1.3.3 - The implementation language differentiates between floating-point numbers and integers." do it do - expect(client.fetch_number_value(flag_key: flag_key, default_value: 4)).is_a?(Integer) + expect(client.fetch_integer_value(flag_key: flag_key, default_value: 4)).is_a?(Integer) end it do - expect(client.fetch_number_value(flag_key: flag_key, default_value: 95.5)).is_a?(Float) + expect(client.fetch_float_value(flag_key: flag_key, default_value: 95.5)).is_a?(Float) end end end diff --git a/spec/open_feature/sdk/provider/in_memory_provider_spec.rb b/spec/open_feature/sdk/provider/in_memory_provider_spec.rb index 6f96d80..e449883 100644 --- a/spec/open_feature/sdk/provider/in_memory_provider_spec.rb +++ b/spec/open_feature/sdk/provider/in_memory_provider_spec.rb @@ -6,7 +6,8 @@ { "bool" => true, "str" => "testing", - "num" => 1, + "int" => 1, + "float" => 1.0, "struct" => {"more" => "config"} } ) @@ -103,12 +104,18 @@ describe "#fetch_number_value" do context "when flag is found" do context "when type matches" do - it "returns value as static" do - fetched = provider.fetch_number_value(flag_key: "num", default_value: 0) + it "returns int as static" do + fetched = provider.fetch_number_value(flag_key: "int", default_value: 0) expect(fetched.value).to eq(1) expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::STATIC) end + it "returns float as static" do + fetched = provider.fetch_number_value(flag_key: "float", default_value: 0.0) + + expect(fetched.value).to eq(1.0) + expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::STATIC) + end end context "when type does not match" do @@ -133,6 +140,72 @@ end end + describe "#fetch_integer_value" do + context "when flag is found" do + context "when type matches" do + it "returns value as static" do + fetched = provider.fetch_integer_value(flag_key: "int", default_value: 0) + + expect(fetched.value).to eq(1) + expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::STATIC) + end + end + + context "when type does not match" do + it "returns default as type mismatch" do + fetched = provider.fetch_integer_value(flag_key: "float", default_value: 0) + + expect(fetched.value).to eq(0) + expect(fetched.error_code).to eq(OpenFeature::SDK::Provider::ErrorCode::TYPE_MISMATCH) + expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::ERROR) + end + end + end + + context "when flag is not found" do + it "returns default as flag not found" do + fetched = provider.fetch_number_value(flag_key: "not here", default_value: 0) + + expect(fetched.value).to eq(0) + expect(fetched.error_code).to eq(OpenFeature::SDK::Provider::ErrorCode::FLAG_NOT_FOUND) + expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::ERROR) + end + end + end + + describe "#fetch_integer_value" do + context "when flag is found" do + context "when type matches" do + it "returns value as static" do + fetched = provider.fetch_float_value(flag_key: "float", default_value: 0.0) + + expect(fetched.value).to eq(1.0) + expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::STATIC) + end + end + + context "when type does not match" do + it "returns default as type mismatch" do + fetched = provider.fetch_float_value(flag_key: "int", default_value: 0.0) + + expect(fetched.value).to eq(0) + expect(fetched.error_code).to eq(OpenFeature::SDK::Provider::ErrorCode::TYPE_MISMATCH) + expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::ERROR) + end + end + end + + context "when flag is not found" do + it "returns default as flag not found" do + fetched = provider.fetch_number_value(flag_key: "not here", default_value: 0) + + expect(fetched.value).to eq(0) + expect(fetched.error_code).to eq(OpenFeature::SDK::Provider::ErrorCode::FLAG_NOT_FOUND) + expect(fetched.reason).to eq(OpenFeature::SDK::Provider::Reason::ERROR) + end + end + end + describe "#fetch_object_value" do context "when flag is found" do context "when type matches" do @@ -146,7 +219,7 @@ context "when type does not match" do it "returns default as type mismatch" do - fetched = provider.fetch_object_value(flag_key: "num", default_value: {}) + fetched = provider.fetch_object_value(flag_key: "int", default_value: {}) expect(fetched.value).to eq({}) expect(fetched.error_code).to eq(OpenFeature::SDK::Provider::ErrorCode::TYPE_MISMATCH)