1515#include " openfeature/memory_provider/flag.h"
1616#include " openfeature/reason.h"
1717#include " openfeature/resolution_details.h"
18+ #include " openfeature/value.h"
1819
1920namespace openfeature {
2021
@@ -25,13 +26,14 @@ class InMemoryProviderTest : public ::testing::Test {
2526 protected:
2627 EvaluationContext empty_ctx_ = EvaluationContext::Builder().build();
2728
28- // Helper method to create a basic boolean flag for testing.
29- Flag<bool > CreateBoolFlag (std::unordered_map<std::string, bool > variants,
30- std::optional<std::string> default_variant_opt,
31- Flag<bool >::ContextEvaluator evaluator = nullptr ,
32- bool disabled = false ) {
33- return Flag<bool >(std::move (variants), std::move (default_variant_opt),
34- std::move (evaluator), FlagMetadata{}, disabled);
29+ // Helper method to create a generic flag for testing.
30+ template <typename T>
31+ Flag<T> CreateFlag (std::unordered_map<std::string, T> variants,
32+ std::optional<std::string> default_variant_opt,
33+ typename Flag<T>::ContextEvaluator evaluator = nullptr ,
34+ bool disabled = false ) {
35+ return Flag<T>(std::move (variants), std::move (default_variant_opt),
36+ std::move (evaluator), FlagMetadata{}, disabled);
3537 }
3638};
3739
@@ -101,7 +103,7 @@ TEST_F(InMemoryProviderTest, FlagTypeMismatch) {
101103TEST_F (InMemoryProviderTest, DisabledFlagReturnsDisabledReason) {
102104 InMemoryProvider provider ({});
103105 provider.UpdateFlag (" disabled_flag" ,
104- CreateBoolFlag ({{" on" , true }}, " on" , nullptr , true ));
106+ CreateFlag< bool > ({{" on" , true }}, " on" , nullptr , true ));
105107 EXPECT_TRUE (provider.Init (empty_ctx_).ok ());
106108
107109 std::unique_ptr<BoolResolutionDetails> res =
@@ -115,7 +117,7 @@ TEST_F(InMemoryProviderTest, DisabledFlagReturnsDisabledReason) {
115117TEST_F (InMemoryProviderTest, StaticEvaluationSuccess) {
116118 InMemoryProvider provider ({});
117119 provider.UpdateFlag (" static_flag" ,
118- CreateBoolFlag ({{" on" , true }, {" off" , false }}, " on" ));
120+ CreateFlag< bool > ({{" on" , true }, {" off" , false }}, " on" ));
119121 EXPECT_TRUE (provider.Init (empty_ctx_).ok ());
120122
121123 std::unique_ptr<BoolResolutionDetails> res =
@@ -133,8 +135,9 @@ TEST_F(InMemoryProviderTest, ContextEvaluatorSuccess) {
133135 };
134136
135137 InMemoryProvider provider ({});
136- provider.UpdateFlag (" dyn_flag" , CreateBoolFlag ({{" on" , true }, {" off" , false }},
137- " on" , evaluator));
138+ provider.UpdateFlag (
139+ " dyn_flag" ,
140+ CreateFlag<bool >({{" on" , true }, {" off" , false }}, " on" , evaluator));
138141 EXPECT_TRUE (provider.Init (empty_ctx_).ok ());
139142
140143 std::unique_ptr<BoolResolutionDetails> res =
@@ -151,8 +154,9 @@ TEST_F(InMemoryProviderTest, ContextEvaluatorFailureFallsBackToDefaultVariant) {
151154 };
152155
153156 InMemoryProvider provider ({});
154- provider.UpdateFlag (" dyn_flag" , CreateBoolFlag ({{" on" , true }, {" off" , false }},
155- " off" , evaluator));
157+ provider.UpdateFlag (
158+ " dyn_flag" ,
159+ CreateFlag<bool >({{" on" , true }, {" off" , false }}, " off" , evaluator));
156160 EXPECT_TRUE (provider.Init (empty_ctx_).ok ());
157161
158162 std::unique_ptr<BoolResolutionDetails> res =
@@ -201,23 +205,23 @@ TEST_F(InMemoryProviderTest, UpdateFlagReplacesAndAddsNew) {
201205 InMemoryProvider provider ({});
202206 EXPECT_TRUE (provider.Init (empty_ctx_).ok ());
203207
204- provider.UpdateFlag (" flag1" , CreateBoolFlag ({{" on" , true }}, " on" ));
208+ provider.UpdateFlag (" flag1" , CreateFlag< bool > ({{" on" , true }}, " on" ));
205209 EXPECT_TRUE (
206210 provider.GetBooleanEvaluation (" flag1" , false , empty_ctx_)->GetValue ());
207211
208- provider.UpdateFlag (" flag1" , CreateBoolFlag ({{" off" , false }}, " off" ));
212+ provider.UpdateFlag (" flag1" , CreateFlag< bool > ({{" off" , false }}, " off" ));
209213 EXPECT_FALSE (
210214 provider.GetBooleanEvaluation (" flag1" , true , empty_ctx_)->GetValue ());
211215
212- provider.UpdateFlag (" new_flag" , CreateBoolFlag ({{" added" , true }}, " added" ));
216+ provider.UpdateFlag (" new_flag" , CreateFlag< bool > ({{" added" , true }}, " added" ));
213217 EXPECT_TRUE (
214218 provider.GetBooleanEvaluation (" new_flag" , false , empty_ctx_)->GetValue ());
215219}
216220
217221TEST_F (InMemoryProviderTest, UpdateFlagsAddsAndOverwritesExisting) {
218222 std::unordered_map<std::string, std::any> initial;
219- initial[" flag1" ] = CreateBoolFlag ({{" on" , true }}, " on" );
220- initial[" common_flag" ] = CreateBoolFlag ({{" initial" , false }}, " initial" );
223+ initial[" flag1" ] = CreateFlag< bool > ({{" on" , true }}, " on" );
224+ initial[" common_flag" ] = CreateFlag< bool > ({{" initial" , false }}, " initial" );
221225
222226 InMemoryProvider provider (std::move (initial));
223227 EXPECT_TRUE (provider.Init (empty_ctx_).ok ());
@@ -227,8 +231,8 @@ TEST_F(InMemoryProviderTest, UpdateFlagsAddsAndOverwritesExisting) {
227231 ->GetValue ());
228232
229233 std::unordered_map<std::string, std::any> updated;
230- updated[" flag2" ] = CreateBoolFlag ({{" off" , false }}, " off" );
231- updated[" common_flag" ] = CreateBoolFlag ({{" updated" , true }}, " updated" );
234+ updated[" flag2" ] = CreateFlag< bool > ({{" off" , false }}, " off" );
235+ updated[" common_flag" ] = CreateFlag< bool > ({{" updated" , true }}, " updated" );
232236
233237 provider.UpdateFlags (std::move (updated));
234238
@@ -258,7 +262,7 @@ TEST_F(InMemoryProviderTest, UpdateFlagsAddsAndOverwritesExisting) {
258262TEST_F (InMemoryProviderTest, NoDefaultVariantAndEvaluatorFailsOrMissing) {
259263 InMemoryProvider provider1 ({});
260264 provider1.UpdateFlag (" no_default_no_evaluator" ,
261- CreateBoolFlag ({{" v1" , true }}, std::nullopt , nullptr ));
265+ CreateFlag< bool > ({{" v1" , true }}, std::nullopt , nullptr ));
262266 EXPECT_TRUE (provider1.Init (empty_ctx_).ok ());
263267 std::unique_ptr<BoolResolutionDetails> res1 = provider1.GetBooleanEvaluation (
264268 " no_default_no_evaluator" , true , empty_ctx_);
@@ -273,7 +277,7 @@ TEST_F(InMemoryProviderTest, NoDefaultVariantAndEvaluatorFailsOrMissing) {
273277 InMemoryProvider provider2 ({});
274278 provider2.UpdateFlag (
275279 " no_default_failing_evaluator" ,
276- CreateBoolFlag ({{" v1" , true }}, std::nullopt , failing_evaluator));
280+ CreateFlag< bool > ({{" v1" , true }}, std::nullopt , failing_evaluator));
277281 EXPECT_TRUE (provider2.Init (empty_ctx_).ok ());
278282 std::unique_ptr<BoolResolutionDetails> res2 = provider2.GetBooleanEvaluation (
279283 " no_default_failing_evaluator" , false , empty_ctx_);
@@ -300,8 +304,8 @@ TEST_F(InMemoryProviderTest, ContextEvaluatorUsesContext) {
300304
301305 InMemoryProvider provider ({});
302306 provider.UpdateFlag (" admin_flag" ,
303- CreateBoolFlag ({{" on" , true }, {" off" , false }}, " off" ,
304- context_aware_evaluator));
307+ CreateFlag< bool > ({{" on" , true }, {" off" , false }}, " off" ,
308+ context_aware_evaluator));
305309 EXPECT_TRUE (provider.Init (empty_ctx_).ok ());
306310
307311 EvaluationContext admin_ctx =
@@ -342,4 +346,65 @@ TEST_F(InMemoryProviderTest, ContextEvaluatorUsesContext) {
342346 EXPECT_THAT (res_wrong_type->GetVariant (), Optional (std::string (" off" )));
343347 EXPECT_FALSE (res_wrong_type->GetErrorCode ().has_value ());
344348}
349+
350+ TEST_F (InMemoryProviderTest, StringEvaluationSuccess) {
351+ InMemoryProvider provider ({});
352+ provider.UpdateFlag (
353+ " string_flag" ,
354+ CreateFlag<std::string>({{" v1" , " hello" }, {" v2" , " world" }}, " v2" ));
355+ EXPECT_TRUE (provider.Init (empty_ctx_).ok ());
356+
357+ std::unique_ptr<StringResolutionDetails> res =
358+ provider.GetStringEvaluation (" string_flag" , " default" , empty_ctx_);
359+
360+ ASSERT_NE (res, nullptr );
361+ EXPECT_EQ (res->GetValue (), " world" );
362+ EXPECT_EQ (res->GetReason (), Reason::kStatic );
363+ EXPECT_THAT (res->GetVariant (), Optional (std::string (" v2" )));
364+ }
365+
366+ TEST_F (InMemoryProviderTest, IntegerEvaluationSuccess) {
367+ InMemoryProvider provider ({});
368+ provider.UpdateFlag (" int_flag" ,
369+ CreateFlag<int64_t >({{" v1" , 100 }, {" v2" , 200 }}, " v1" ));
370+ EXPECT_TRUE (provider.Init (empty_ctx_).ok ());
371+
372+ std::unique_ptr<IntResolutionDetails> res =
373+ provider.GetIntegerEvaluation (" int_flag" , 0 , empty_ctx_);
374+
375+ ASSERT_NE (res, nullptr );
376+ EXPECT_EQ (res->GetValue (), 100 );
377+ EXPECT_EQ (res->GetReason (), Reason::kStatic );
378+ EXPECT_THAT (res->GetVariant (), Optional (std::string (" v1" )));
379+ }
380+
381+ TEST_F (InMemoryProviderTest, DoubleEvaluationSuccess) {
382+ InMemoryProvider provider ({});
383+ provider.UpdateFlag (" double_flag" ,
384+ CreateFlag<double >({{" v1" , 3.14 }, {" v2" , 2.71 }}, " v2" ));
385+ EXPECT_TRUE (provider.Init (empty_ctx_).ok ());
386+
387+ std::unique_ptr<DoubleResolutionDetails> res =
388+ provider.GetDoubleEvaluation (" double_flag" , 0.0 , empty_ctx_);
389+
390+ ASSERT_NE (res, nullptr );
391+ EXPECT_DOUBLE_EQ (res->GetValue (), 2.71 );
392+ EXPECT_EQ (res->GetReason (), Reason::kStatic );
393+ EXPECT_THAT (res->GetVariant (), Optional (std::string (" v2" )));
394+ }
395+
396+ TEST_F (InMemoryProviderTest, ObjectEvaluationSuccess) {
397+ InMemoryProvider provider ({});
398+ provider.UpdateFlag (" object_flag" ,
399+ CreateFlag<Value>({{" v1" , Value ()}}, " v1" ));
400+ EXPECT_TRUE (provider.Init (empty_ctx_).ok ());
401+
402+ std::unique_ptr<ObjectResolutionDetails> res =
403+ provider.GetObjectEvaluation (" object_flag" , Value (), empty_ctx_);
404+
405+ ASSERT_NE (res, nullptr );
406+ EXPECT_EQ (res->GetReason (), Reason::kStatic );
407+ EXPECT_THAT (res->GetVariant (), Optional (std::string (" v1" )));
408+ }
409+
345410} // namespace openfeature
0 commit comments