From 0af78303a5b1500612e1130d707270c728094405 Mon Sep 17 00:00:00 2001 From: Marcin Olko Date: Thu, 12 Mar 2026 15:37:58 +0000 Subject: [PATCH 1/3] Added missing provider unit tests Signed-off-by: Marcin Olko --- providers/flagd/src/provider.cpp | 16 ++- providers/flagd/src/provider.h | 5 + providers/flagd/tests/BUILD | 9 ++ providers/flagd/tests/provider_test.cpp | 139 ++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 providers/flagd/tests/provider_test.cpp diff --git a/providers/flagd/src/provider.cpp b/providers/flagd/src/provider.cpp index 96958c7..5966f2b 100644 --- a/providers/flagd/src/provider.cpp +++ b/providers/flagd/src/provider.cpp @@ -2,7 +2,6 @@ #include -#include #include #include "absl/log/log.h" @@ -28,6 +27,21 @@ FlagdProvider::FlagdProvider(FlagdProviderConfig config) evaluator_ = std::make_unique(sync_); } +FlagdProvider::FlagdProvider(std::shared_ptr sync, + FlagdProviderConfig config) + : configuration_(std::move(config)), + sync_(std::move(sync)), + evaluator_(std::make_unique(sync_)), + is_ready_(false) {} + +FlagdProvider::FlagdProvider(std::shared_ptr sync, + std::unique_ptr evaluator, + FlagdProviderConfig config) + : configuration_(std::move(config)), + sync_(std::move(sync)), + evaluator_(std::move(evaluator)), + is_ready_(false) {} + FlagdProvider::~FlagdProvider() { if (is_ready_) { absl::Status status = FlagdProvider::Shutdown(); diff --git a/providers/flagd/src/provider.h b/providers/flagd/src/provider.h index 983777c..559e2d9 100644 --- a/providers/flagd/src/provider.h +++ b/providers/flagd/src/provider.h @@ -16,6 +16,11 @@ namespace flagd { class FlagdProvider : public openfeature::FeatureProvider { public: explicit FlagdProvider(FlagdProviderConfig config = FlagdProviderConfig()); + explicit FlagdProvider(std::shared_ptr sync, + FlagdProviderConfig config = FlagdProviderConfig()); + FlagdProvider(std::shared_ptr sync, + std::unique_ptr evaluator, + FlagdProviderConfig config = FlagdProviderConfig()); ~FlagdProvider() override; diff --git a/providers/flagd/tests/BUILD b/providers/flagd/tests/BUILD index 1227f7c..fd827c6 100644 --- a/providers/flagd/tests/BUILD +++ b/providers/flagd/tests/BUILD @@ -10,3 +10,12 @@ cc_test( "@nlohmann_json//:json", ], ) + +cc_test( + name = "provider_test", + srcs = ["provider_test.cpp"], + deps = [ + "//providers/flagd/src:flagd_provider", + "@googletest//:gtest_main", + ], +) diff --git a/providers/flagd/tests/provider_test.cpp b/providers/flagd/tests/provider_test.cpp new file mode 100644 index 0000000..caedb6c --- /dev/null +++ b/providers/flagd/tests/provider_test.cpp @@ -0,0 +1,139 @@ +#include "flagd/provider.h" + +#include +#include + +#include + +#include "flagd/evaluator.h" +#include "flagd/sync.h" + +namespace flagd { + +class MockSync : public FlagSync { + public: + MOCK_METHOD(absl::Status, Init, (const openfeature::EvaluationContext& ctx), + (override)); + MOCK_METHOD(absl::Status, Shutdown, (), (override)); +}; + +class MockEvaluator : public Evaluator { + public: + MOCK_METHOD(std::unique_ptr, + ResolveBoolean, + (std::string_view flag_key, bool default_value, + const openfeature::EvaluationContext& ctx), + (override)); + MOCK_METHOD(std::unique_ptr, + ResolveString, + (std::string_view flag_key, std::string_view default_value, + const openfeature::EvaluationContext& ctx), + (override)); + MOCK_METHOD(std::unique_ptr, + ResolveInteger, + (std::string_view flag_key, int64_t default_value, + const openfeature::EvaluationContext& ctx), + (override)); + MOCK_METHOD(std::unique_ptr, + ResolveDouble, + (std::string_view flag_key, double default_value, + const openfeature::EvaluationContext& ctx), + (override)); + MOCK_METHOD(std::unique_ptr, + ResolveObject, + (std::string_view flag_key, openfeature::Value default_value, + const openfeature::EvaluationContext& ctx), + (override)); +}; + +TEST(ProviderTest, MetadataReturnsExpectedValues) { + FlagdProvider provider; + auto metadata = provider.GetMetadata(); + EXPECT_EQ(metadata.name, "flagd"); +} + +TEST(ProviderTest, ReturnsNotReadyBeforeInit) { + auto mock_sync = std::make_shared(); + auto mock_evaluator = std::make_unique(); + + // We don't expect any calls to the evaluator when not ready + EXPECT_CALL(*mock_evaluator, ResolveBoolean).Times(0); + + FlagdProvider provider(mock_sync, std::move(mock_evaluator)); + + auto result = provider.GetBooleanEvaluation( + "some-flag", false, openfeature::EvaluationContext::Builder().build()); + + EXPECT_EQ(result->GetErrorCode(), openfeature::ErrorCode::kProviderNotReady); + EXPECT_EQ(result->GetReason(), openfeature::Reason::kError); +} + +TEST(ProviderTest, ReturnsReadyAfterInit) { + auto mock_sync = std::make_shared(); + auto mock_evaluator = std::make_unique(); + + EXPECT_CALL(*mock_sync, Init).WillOnce(testing::Return(absl::OkStatus())); + + EXPECT_CALL(*mock_evaluator, ResolveBoolean) + .WillOnce([](std::string_view flag_key, bool default_value, + const openfeature::EvaluationContext& ctx) { + return std::make_unique( + true, openfeature::Reason::kStatic, "on", + openfeature::FlagMetadata()); + }); + + FlagdProvider provider(mock_sync, std::move(mock_evaluator)); + (void)provider.Init(openfeature::EvaluationContext::Builder().build()); + + auto result = provider.GetBooleanEvaluation( + "some-flag", false, openfeature::EvaluationContext::Builder().build()); + + EXPECT_EQ(result->GetValue(), true); + EXPECT_EQ(result->GetReason(), openfeature::Reason::kStatic); +} + +TEST(ProviderTest, DelegationWorks) { + auto mock_sync = std::make_shared(); + auto mock_evaluator = std::make_unique(); + + EXPECT_CALL(*mock_sync, Init).WillOnce(testing::Return(absl::OkStatus())); + + std::string expected_flag = "my-flag"; + bool expected_default = true; + + EXPECT_CALL(*mock_evaluator, + ResolveBoolean(testing::Eq(expected_flag), + testing::Eq(expected_default), testing::_)) + .WillOnce([](std::string_view flag_key, bool default_value, + const openfeature::EvaluationContext& ctx) { + return std::make_unique( + default_value, openfeature::Reason::kDefault, std::nullopt, + openfeature::FlagMetadata()); + }); + + FlagdProvider provider(mock_sync, std::move(mock_evaluator)); + (void)provider.Init(openfeature::EvaluationContext::Builder().build()); + + provider.GetBooleanEvaluation( + expected_flag, expected_default, + openfeature::EvaluationContext::Builder().build()); +} + +TEST(ProviderTest, ShutdownMakesProviderNotReady) { + auto mock_sync = std::make_shared(); + auto mock_evaluator = std::make_unique(); + + EXPECT_CALL(*mock_sync, Init).WillOnce(testing::Return(absl::OkStatus())); + EXPECT_CALL(*mock_sync, Shutdown).WillOnce(testing::Return(absl::OkStatus())); + + FlagdProvider provider(mock_sync, std::move(mock_evaluator)); + (void)provider.Init(openfeature::EvaluationContext::Builder().build()); + (void)provider.Shutdown(); + + auto result = provider.GetBooleanEvaluation( + "some-flag", false, openfeature::EvaluationContext::Builder().build()); + + EXPECT_EQ(result->GetErrorCode(), openfeature::ErrorCode::kProviderNotReady); +} + +} // namespace flagd From 0a280e033781843a2d776a9c8c59d6bda8940569 Mon Sep 17 00:00:00 2001 From: Marcin Olko Date: Fri, 13 Mar 2026 13:29:01 +0000 Subject: [PATCH 2/3] Improved tests Signed-off-by: Marcin Olko --- providers/flagd/tests/provider_test.cpp | 31 +++++++++++++++++-------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/providers/flagd/tests/provider_test.cpp b/providers/flagd/tests/provider_test.cpp index caedb6c..e2b7bbf 100644 --- a/providers/flagd/tests/provider_test.cpp +++ b/providers/flagd/tests/provider_test.cpp @@ -48,7 +48,7 @@ class MockEvaluator : public Evaluator { TEST(ProviderTest, MetadataReturnsExpectedValues) { FlagdProvider provider; - auto metadata = provider.GetMetadata(); + openfeature::Metadata metadata = provider.GetMetadata(); EXPECT_EQ(metadata.name, "flagd"); } @@ -61,8 +61,10 @@ TEST(ProviderTest, ReturnsNotReadyBeforeInit) { FlagdProvider provider(mock_sync, std::move(mock_evaluator)); - auto result = provider.GetBooleanEvaluation( - "some-flag", false, openfeature::EvaluationContext::Builder().build()); + std::unique_ptr result = + provider.GetBooleanEvaluation( + "some-flag", false, + openfeature::EvaluationContext::Builder().build()); EXPECT_EQ(result->GetErrorCode(), openfeature::ErrorCode::kProviderNotReady); EXPECT_EQ(result->GetReason(), openfeature::Reason::kError); @@ -85,8 +87,10 @@ TEST(ProviderTest, ReturnsReadyAfterInit) { FlagdProvider provider(mock_sync, std::move(mock_evaluator)); (void)provider.Init(openfeature::EvaluationContext::Builder().build()); - auto result = provider.GetBooleanEvaluation( - "some-flag", false, openfeature::EvaluationContext::Builder().build()); + std::unique_ptr result = + provider.GetBooleanEvaluation( + "some-flag", false, + openfeature::EvaluationContext::Builder().build()); EXPECT_EQ(result->GetValue(), true); EXPECT_EQ(result->GetReason(), openfeature::Reason::kStatic); @@ -114,9 +118,13 @@ TEST(ProviderTest, DelegationWorks) { FlagdProvider provider(mock_sync, std::move(mock_evaluator)); (void)provider.Init(openfeature::EvaluationContext::Builder().build()); - provider.GetBooleanEvaluation( - expected_flag, expected_default, - openfeature::EvaluationContext::Builder().build()); + std::unique_ptr result = + provider.GetBooleanEvaluation( + expected_flag, expected_default, + openfeature::EvaluationContext::Builder().build()); + + EXPECT_EQ(result->GetValue(), expected_default); + EXPECT_EQ(result->GetReason(), openfeature::Reason::kDefault); } TEST(ProviderTest, ShutdownMakesProviderNotReady) { @@ -130,10 +138,13 @@ TEST(ProviderTest, ShutdownMakesProviderNotReady) { (void)provider.Init(openfeature::EvaluationContext::Builder().build()); (void)provider.Shutdown(); - auto result = provider.GetBooleanEvaluation( - "some-flag", false, openfeature::EvaluationContext::Builder().build()); + std::unique_ptr result = + provider.GetBooleanEvaluation( + "some-flag", false, + openfeature::EvaluationContext::Builder().build()); EXPECT_EQ(result->GetErrorCode(), openfeature::ErrorCode::kProviderNotReady); + EXPECT_EQ(result->GetReason(), openfeature::Reason::kError); } } // namespace flagd From 19706320343dd28a70bf514d96f4b3874d4a8757 Mon Sep 17 00:00:00 2001 From: Marcin Olko Date: Fri, 13 Mar 2026 13:40:41 +0000 Subject: [PATCH 3/3] Fixed BUILD structure Signed-off-by: Marcin Olko --- providers/flagd/tests/BUILD | 10 ++++++++++ providers/flagd/tests/evaluator/BUILD | 11 +---------- providers/flagd/tests/provider_test.cpp | 4 ++-- 3 files changed, 13 insertions(+), 12 deletions(-) create mode 100644 providers/flagd/tests/BUILD diff --git a/providers/flagd/tests/BUILD b/providers/flagd/tests/BUILD new file mode 100644 index 0000000..5c76289 --- /dev/null +++ b/providers/flagd/tests/BUILD @@ -0,0 +1,10 @@ +load("@rules_cc//cc:defs.bzl", "cc_test") + +cc_test( + name = "provider_test", + srcs = ["provider_test.cpp"], + deps = [ + "//providers/flagd/src:flagd_provider", + "@googletest//:gtest_main", + ], +) diff --git a/providers/flagd/tests/evaluator/BUILD b/providers/flagd/tests/evaluator/BUILD index a332157..6f2ae7a 100644 --- a/providers/flagd/tests/evaluator/BUILD +++ b/providers/flagd/tests/evaluator/BUILD @@ -5,17 +5,8 @@ cc_test( srcs = ["evaluator_test.cpp"], deps = [ "//providers/flagd/src/evaluator", - "//providers/flagd/src/sync:sync", + "//providers/flagd/src/sync", "@googletest//:gtest_main", "@nlohmann_json//:json", ], ) - -cc_test( - name = "provider_test", - srcs = ["provider_test.cpp"], - deps = [ - "//providers/flagd/src:flagd_provider", - "@googletest//:gtest_main", - ], -) diff --git a/providers/flagd/tests/provider_test.cpp b/providers/flagd/tests/provider_test.cpp index e2b7bbf..f99f19c 100644 --- a/providers/flagd/tests/provider_test.cpp +++ b/providers/flagd/tests/provider_test.cpp @@ -5,8 +5,8 @@ #include -#include "flagd/evaluator.h" -#include "flagd/sync.h" +#include "flagd/evaluator/evaluator.h" +#include "flagd/sync/sync.h" namespace flagd {