-
Notifications
You must be signed in to change notification settings - Fork 2
feat: Add HookContext class #115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+335
−0
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
42a776d
base data structures fot hook implementation.
NeaguGeorgiana23 e968609
fix linter
NeaguGeorgiana23 334ec2a
fix linter
NeaguGeorgiana23 f110e5c
Merge branch 'main' into define-hook-data-structures
NeaguGeorgiana23 5cc878b
Update BUILD file.
NeaguGeorgiana23 bd66430
Correct include guards.
NeaguGeorgiana23 5332610
feat: Add HookData class.
NeaguGeorgiana23 c8fc92d
fix linter
NeaguGeorgiana23 3f5f4de
fix linter
NeaguGeorgiana23 b0f3a15
fix linter
NeaguGeorgiana23 e9e8852
fix linter
NeaguGeorgiana23 e333df0
add HookContext structure.
NeaguGeorgiana23 c59de28
fix linter
NeaguGeorgiana23 45ca64a
fix linter
NeaguGeorgiana23 756f2bf
fix BUILD.
NeaguGeorgiana23 1f3957b
Merge branch 'main' into hooks_context
NeaguGeorgiana23 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| #include "openfeature/hook_context.h" | ||
|
|
||
| #include <memory> | ||
| #include <string> | ||
|
|
||
| #include "openfeature/evaluation_context.h" | ||
| #include "openfeature/flag_metadata.h" | ||
| #include "openfeature/flag_type_value.h" | ||
| #include "openfeature/hook_data.h" | ||
| #include "openfeature/metadata.h" | ||
| #include "openfeature/value.h" | ||
|
|
||
| namespace openfeature { | ||
|
|
||
| template <typename T> | ||
| HookContext<T>::HookContext(std::string flag_key, FlagValueType type, | ||
| T default_value, EvaluationContext ctx, | ||
| Metadata client_metadata, | ||
| Metadata provider_metadata, | ||
| std::shared_ptr<HookData> hook_data) | ||
| : flag_key_(std::move(flag_key)), | ||
| type_(type), | ||
| default_value_(std::move(default_value)), | ||
| ctx_(std::move(ctx)), | ||
| client_metadata_(std::move(client_metadata)), | ||
| provider_metadata_(std::move(provider_metadata)), | ||
| hook_data_(std::move(hook_data)) {} | ||
|
|
||
| template <typename T> | ||
| const std::string& HookContext<T>::GetFlagKey() const { | ||
| return flag_key_; | ||
| } | ||
|
|
||
| template <typename T> | ||
| FlagValueType HookContext<T>::GetType() const { | ||
| return type_; | ||
| } | ||
|
|
||
| template <typename T> | ||
| const T& HookContext<T>::GetDefaultValue() const { | ||
| return default_value_; | ||
| } | ||
|
|
||
| template <typename T> | ||
| const EvaluationContext& HookContext<T>::GetEvaluationContext() const { | ||
| return ctx_; | ||
| } | ||
|
|
||
| template <typename T> | ||
| void HookContext<T>::SetEvaluationContext(EvaluationContext ctx) { | ||
| ctx_ = std::move(ctx); | ||
| } | ||
|
|
||
| template <typename T> | ||
| const Metadata& HookContext<T>::GetClientMetadata() const { | ||
| return client_metadata_; | ||
| } | ||
|
|
||
| template <typename T> | ||
| const Metadata& HookContext<T>::GetProviderMetadata() const { | ||
| return provider_metadata_; | ||
| } | ||
|
|
||
| template <typename T> | ||
| std::shared_ptr<HookData> HookContext<T>::GetHookData() const { | ||
| return hook_data_; | ||
| } | ||
|
|
||
| template class HookContext<bool>; | ||
| template class HookContext<std::string>; | ||
| template class HookContext<int64_t>; | ||
| template class HookContext<double>; | ||
| template class HookContext<Value>; | ||
|
|
||
| } // namespace openfeature |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| #ifndef CPP_SDK_INCLUDE_OPENFEATURE_HOOK_CONTEXT_H_ | ||
| #define CPP_SDK_INCLUDE_OPENFEATURE_HOOK_CONTEXT_H_ | ||
|
|
||
| #include <memory> | ||
| #include <string> | ||
|
|
||
| #include "openfeature/evaluation_context.h" | ||
| #include "openfeature/flag_metadata.h" | ||
| #include "openfeature/flag_type_value.h" | ||
| #include "openfeature/hook_data.h" | ||
| #include "openfeature/metadata.h" | ||
| #include "openfeature/value.h" | ||
|
|
||
| namespace openfeature { | ||
|
|
||
| template <typename T> | ||
| class HookContext { | ||
| public: | ||
| HookContext(std::string flag_key, FlagValueType type, T default_value, | ||
| EvaluationContext ctx, Metadata client_metadata, | ||
| Metadata provider_metadata, std::shared_ptr<HookData> hook_data); | ||
|
|
||
| const std::string& GetFlagKey() const; | ||
| FlagValueType GetType() const; | ||
| const T& GetDefaultValue() const; | ||
| const EvaluationContext& GetEvaluationContext() const; | ||
| void SetEvaluationContext(EvaluationContext ctx); | ||
| const Metadata& GetClientMetadata() const; | ||
| const Metadata& GetProviderMetadata() const; | ||
| std::shared_ptr<HookData> GetHookData() const; | ||
|
|
||
| private: | ||
| std::string flag_key_; | ||
| FlagValueType type_; | ||
| T default_value_; | ||
| EvaluationContext ctx_; | ||
| Metadata client_metadata_; | ||
| Metadata provider_metadata_; | ||
| std::shared_ptr<HookData> hook_data_; | ||
| }; | ||
|
|
||
| // Type aliases for common types. | ||
| using BoolHookContext = HookContext<bool>; | ||
| using StringHookContext = HookContext<std::string>; | ||
| using IntHookContext = HookContext<int64_t>; | ||
| using DoubleHookContext = HookContext<double>; | ||
| using ObjectHookContext = HookContext<Value>; | ||
|
|
||
| } // namespace openfeature | ||
| #endif // CPP_SDK_INCLUDE_OPENFEATURE_HOOK_CONTEXT_H_ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,180 @@ | ||
| #include "openfeature/hook_context.h" | ||
|
|
||
| #include <gtest/gtest.h> | ||
|
|
||
| #include <memory> | ||
| #include <string> | ||
|
|
||
| #include "openfeature/evaluation_context.h" | ||
| #include "openfeature/flag_metadata.h" | ||
| #include "openfeature/flag_type_value.h" | ||
| #include "openfeature/hook_data.h" | ||
| #include "openfeature/metadata.h" | ||
| #include "openfeature/value.h" | ||
|
|
||
| namespace openfeature { | ||
|
|
||
| class HookContextTest : public ::testing::Test { | ||
| protected: | ||
| HookContextTest() | ||
| : initial_ctx_(EvaluationContext::Builder() | ||
| .WithTargetingKey("initial-user") | ||
| .WithAttribute("env", std::string("test")) | ||
| .build()) {} | ||
|
|
||
| EvaluationContext initial_ctx_; | ||
| Metadata client_metadata_{"test-client"}; | ||
| Metadata provider_metadata_{"test-provider"}; | ||
| std::shared_ptr<HookData> hook_data_{std::make_shared<HookData>()}; | ||
| }; | ||
|
|
||
| TEST_F(HookContextTest, ConstructorAndAccessorsForBool) { | ||
| constexpr FlagValueType kType = FlagValueType::kBoolean; | ||
| constexpr bool kDefaultValue = true; | ||
|
|
||
| BoolHookContext hook_ctx("bool-flag", kType, kDefaultValue, initial_ctx_, | ||
| client_metadata_, provider_metadata_, hook_data_); | ||
|
|
||
| EXPECT_EQ(hook_ctx.GetFlagKey(), "bool-flag"); | ||
| EXPECT_EQ(hook_ctx.GetType(), kType); | ||
| EXPECT_EQ(hook_ctx.GetDefaultValue(), kDefaultValue); | ||
|
|
||
| ASSERT_TRUE(hook_ctx.GetEvaluationContext().GetTargetingKey().has_value()); | ||
| EXPECT_EQ(hook_ctx.GetEvaluationContext().GetTargetingKey().value(), | ||
| "initial-user"); | ||
|
|
||
| EXPECT_EQ(hook_ctx.GetClientMetadata().name, "test-client"); | ||
| EXPECT_EQ(hook_ctx.GetProviderMetadata().name, "test-provider"); | ||
| EXPECT_EQ(hook_ctx.GetHookData(), hook_data_); | ||
| } | ||
|
|
||
| TEST_F(HookContextTest, ConstructorAndAccessorsForString) { | ||
| constexpr FlagValueType kType = FlagValueType::kString; | ||
| const std::string default_value = "default-string"; | ||
|
|
||
| StringHookContext hook_ctx("string-flag", kType, default_value, initial_ctx_, | ||
| client_metadata_, provider_metadata_, hook_data_); | ||
|
|
||
| EXPECT_EQ(hook_ctx.GetFlagKey(), "string-flag"); | ||
| EXPECT_EQ(hook_ctx.GetType(), kType); | ||
| EXPECT_EQ(hook_ctx.GetDefaultValue(), default_value); | ||
|
|
||
| ASSERT_TRUE(hook_ctx.GetEvaluationContext().GetTargetingKey().has_value()); | ||
| EXPECT_EQ(hook_ctx.GetEvaluationContext().GetTargetingKey().value(), | ||
| "initial-user"); | ||
|
|
||
| EXPECT_EQ(hook_ctx.GetClientMetadata().name, "test-client"); | ||
| EXPECT_EQ(hook_ctx.GetProviderMetadata().name, "test-provider"); | ||
| EXPECT_EQ(hook_ctx.GetHookData(), hook_data_); | ||
| } | ||
|
|
||
| TEST_F(HookContextTest, ConstructorAndAccessorsForInteger) { | ||
| constexpr FlagValueType kType = FlagValueType::kInteger; | ||
| constexpr int64_t kDefaultValue = 123456789LL; | ||
|
|
||
| IntHookContext hook_ctx("int-flag", kType, kDefaultValue, initial_ctx_, | ||
| client_metadata_, provider_metadata_, hook_data_); | ||
|
|
||
| EXPECT_EQ(hook_ctx.GetFlagKey(), "int-flag"); | ||
| EXPECT_EQ(hook_ctx.GetType(), kType); | ||
| EXPECT_EQ(hook_ctx.GetDefaultValue(), kDefaultValue); | ||
|
|
||
| ASSERT_TRUE(hook_ctx.GetEvaluationContext().GetTargetingKey().has_value()); | ||
| EXPECT_EQ(hook_ctx.GetEvaluationContext().GetTargetingKey().value(), | ||
| "initial-user"); | ||
|
|
||
| EXPECT_EQ(hook_ctx.GetClientMetadata().name, "test-client"); | ||
| EXPECT_EQ(hook_ctx.GetProviderMetadata().name, "test-provider"); | ||
| EXPECT_EQ(hook_ctx.GetHookData(), hook_data_); | ||
| } | ||
|
|
||
| TEST_F(HookContextTest, ConstructorAndAccessorsForDouble) { | ||
| constexpr FlagValueType kType = FlagValueType::kDouble; | ||
| constexpr double kDefaultValue = 3.14159265359; | ||
|
|
||
| DoubleHookContext hook_ctx("double-flag", kType, kDefaultValue, initial_ctx_, | ||
| client_metadata_, provider_metadata_, hook_data_); | ||
|
|
||
| EXPECT_EQ(hook_ctx.GetFlagKey(), "double-flag"); | ||
| EXPECT_EQ(hook_ctx.GetType(), kType); | ||
| EXPECT_DOUBLE_EQ(hook_ctx.GetDefaultValue(), kDefaultValue); | ||
|
|
||
| ASSERT_TRUE(hook_ctx.GetEvaluationContext().GetTargetingKey().has_value()); | ||
| EXPECT_EQ(hook_ctx.GetEvaluationContext().GetTargetingKey().value(), | ||
| "initial-user"); | ||
|
|
||
| EXPECT_EQ(hook_ctx.GetClientMetadata().name, "test-client"); | ||
| EXPECT_EQ(hook_ctx.GetProviderMetadata().name, "test-provider"); | ||
| EXPECT_EQ(hook_ctx.GetHookData(), hook_data_); | ||
| } | ||
|
|
||
| TEST_F(HookContextTest, ConstructorAndAccessorsForObject) { | ||
| constexpr FlagValueType kType = FlagValueType::kObject; | ||
| Value default_value(std::string("json-or-structure")); | ||
|
|
||
| ObjectHookContext hook_ctx("object-flag", kType, default_value, initial_ctx_, | ||
| client_metadata_, provider_metadata_, hook_data_); | ||
|
|
||
| EXPECT_EQ(hook_ctx.GetFlagKey(), "object-flag"); | ||
| EXPECT_EQ(hook_ctx.GetType(), kType); | ||
| ASSERT_TRUE(hook_ctx.GetDefaultValue().IsString()); | ||
| EXPECT_EQ(hook_ctx.GetDefaultValue().AsString().value(), "json-or-structure"); | ||
|
|
||
| ASSERT_TRUE(hook_ctx.GetEvaluationContext().GetTargetingKey().has_value()); | ||
| EXPECT_EQ(hook_ctx.GetEvaluationContext().GetTargetingKey().value(), | ||
| "initial-user"); | ||
|
|
||
| EXPECT_EQ(hook_ctx.GetClientMetadata().name, "test-client"); | ||
| EXPECT_EQ(hook_ctx.GetProviderMetadata().name, "test-provider"); | ||
| EXPECT_EQ(hook_ctx.GetHookData(), hook_data_); | ||
| } | ||
|
|
||
| TEST_F(HookContextTest, SetEvaluationContextUpdatesContext) { | ||
| BoolHookContext hook_ctx("flag-key", FlagValueType::kBoolean, false, | ||
| initial_ctx_, client_metadata_, provider_metadata_, | ||
| hook_data_); | ||
|
|
||
| ASSERT_TRUE(hook_ctx.GetEvaluationContext().GetTargetingKey().has_value()); | ||
| EXPECT_EQ(hook_ctx.GetEvaluationContext().GetTargetingKey().value(), | ||
| "initial-user"); | ||
|
|
||
| EvaluationContext updated_ctx = EvaluationContext::Builder() | ||
| .WithTargetingKey("updated-user") | ||
| .WithAttribute("env", std::string("prod")) | ||
| .build(); | ||
|
|
||
| hook_ctx.SetEvaluationContext(std::move(updated_ctx)); | ||
|
|
||
| ASSERT_TRUE(hook_ctx.GetEvaluationContext().GetTargetingKey().has_value()); | ||
| EXPECT_EQ(hook_ctx.GetEvaluationContext().GetTargetingKey().value(), | ||
| "updated-user"); | ||
|
|
||
| const std::any* env_val = hook_ctx.GetEvaluationContext().GetValue("env"); | ||
| ASSERT_NE(env_val, nullptr); | ||
| EXPECT_EQ(std::any_cast<std::string>(*env_val), "prod"); | ||
| } | ||
|
|
||
| TEST_F(HookContextTest, HookDataSharesStateAndAllowsMutations) { | ||
| BoolHookContext hook_ctx("flag-key", FlagValueType::kBoolean, true, | ||
| initial_ctx_, client_metadata_, provider_metadata_, | ||
| hook_data_); | ||
|
|
||
| ASSERT_NE(hook_ctx.GetHookData(), nullptr); | ||
| EXPECT_EQ(hook_ctx.GetHookData()->Get("custom_key"), nullptr); | ||
|
|
||
| hook_ctx.GetHookData()->Set("custom_key", std::string("stage_before")); | ||
|
|
||
| auto* retrieved = hook_ctx.GetHookData()->GetAs<std::string>("custom_key"); | ||
| ASSERT_NE(retrieved, nullptr); | ||
| EXPECT_EQ(*retrieved, "stage_before"); | ||
| } | ||
|
|
||
| TEST_F(HookContextTest, HandlesNullptrHookData) { | ||
| BoolHookContext hook_ctx("flag-key", FlagValueType::kBoolean, false, | ||
| initial_ctx_, client_metadata_, provider_metadata_, | ||
| nullptr); | ||
|
|
||
| EXPECT_EQ(hook_ctx.GetHookData(), nullptr); | ||
| } | ||
|
|
||
| } // namespace openfeature | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.