From 98f848c45fde0d3f26b2d3f322b0d02fe5404635 Mon Sep 17 00:00:00 2001 From: Erdi Rowlands Date: Wed, 2 Aug 2023 16:53:07 +0100 Subject: [PATCH] FFM-8890 Add optional hashing on flag ID --- src/cfclient_evaluator.erl | 4 +- test/cfclient_evaluator_tests.erl | 205 +++++++++++++++++++++++++++--- 2 files changed, 187 insertions(+), 22 deletions(-) diff --git a/src/cfclient_evaluator.erl b/src/cfclient_evaluator.erl index 55ea1ed..dba7eaa 100644 --- a/src/cfclient_evaluator.erl +++ b/src/cfclient_evaluator.erl @@ -270,7 +270,7 @@ evaluate_flag(group_rules, #{rules := []} = Flag, Target, Config) -> evaluate_flag(default_on, Flag, Target, Config); evaluate_flag(group_rules, #{rules := Rules} = Flag, Target, Config) when Rules /= null -> - case search_rules_for_inclusion(sort_by_priority(Rules), Target, Config, maps:get(identifier, Flag)) of + case search_rules_for_inclusion(sort_by_priority(Rules), Target, Config, maps:get(feature, Flag)) of false -> #{verbose_evaluation_logs := IsVerboseLogging} = Config, ?LOG_EVALUATION_STATE( @@ -400,7 +400,7 @@ search_rules_for_inclusion([Rule | Tail], Target, Config, FlagIdentifier) -> apply_percentage_rollout(Variations, BucketBy, FinalTargetAttributeValue, 0) end; - _ -> search_rules_for_inclusion(Tail, Target, Config) + _ -> search_rules_for_inclusion(Tail, Target, Config, FlagIdentifier) end. diff --git a/test/cfclient_evaluator_tests.erl b/test/cfclient_evaluator_tests.erl index 52bb6dd..fe8096b 100644 --- a/test/cfclient_evaluator_tests.erl +++ b/test/cfclient_evaluator_tests.erl @@ -6,38 +6,57 @@ config() -> cfclient_config:defaults(). -setup() -> +setup(UseHashFlag) -> Modules = [cfclient_config, cfclient_ets], - % ?debugFmt("Running setup for ~p", [Modules]), - Config = cfclient_config:defaults(), + InitialConfig = cfclient_config:defaults(), + Config = if + UseHashFlag -> maps:put(hash_flag_and_target_ids, true, InitialConfig); + true -> InitialConfig + end, meck:new(Modules), meck:expect(cfclient_config, get_config, fun () -> Config end), meck:expect(cfclient_config, get_config, fun (_) -> Config end), meck:expect(cfclient_config, defaults, fun () -> Config end), Modules. +setup_without_hash_flag() -> + setup(false). + +setup_with_hash_flag() -> + setup(true). cleanup(Modules) -> % ?debugFmt("Running cleanup ~p)", [Modules]), meck:unload(Modules). - top_test_() -> - { - setup, - fun setup/0, - fun cleanup/1, - [ - {generator, fun variations_bool/0}, - {generator, fun variations_string/0}, - {generator, fun variations_number/0}, - {generator, fun variations_json/0}, - {generator, fun percentage_rollout_boolean_flag/0}, - {generator, fun percentage_rollout_multivariate_string_flag/0}, - {generator, fun search_prerequisites/0}, - {generator, fun check_prerequisite/0} - ] - }. + [ + { + setup, + fun setup_without_hash_flag/0, + fun cleanup/1, + [ + {generator, fun variations_bool/0}, + {generator, fun variations_string/0}, + {generator, fun variations_number/0}, + {generator, fun variations_json/0}, + {generator, fun percentage_rollout_boolean_flag/0}, + {generator, fun percentage_rollout_multivariate_string_flag/0}, + {generator, fun search_prerequisites/0}, + {generator, fun check_prerequisite/0} + ] + }, + { + setup, + fun setup_with_hash_flag/0, + fun cleanup/1, + [ + {generator, fun percentage_rollout_multivariate_string_flag_hash_enabled/0} + ] + } + ]. + + % Target Sample Data existing_target_a() -> @@ -1057,7 +1076,6 @@ search_variation_map_test() -> is_rule_included_or_excluded_test_() -> { setup, - fun setup/0, fun cleanup/1, fun () -> @@ -1980,6 +1998,153 @@ percentage_rollout_multivariate_string_flag() -> ] }. +percentage_rollout_multivariate_string_flag_hash_enabled() -> + { + "Percentage Rollout Multivariate String Flag", + [ + { + "34/33/33", + setup, + fun + () -> + meck:expect( + cfclient_ets, + get, + fun + (_, <<"segments/target_group_1">>) -> + cfclient_evaluator_test_data:target_group_for_percentage_rollout(); + + (_, <<"flags/My_string_flag">>) -> + cfclient_evaluator_test_data:percentage_rollout_multi_variate(34, 33, 33) + end + ) + end, + fun + (_) -> + [ + { + timeout, + 100, + ?_assertEqual({68181, 65967, 65852}, do_string_variation_200k_times({0, 0, 0}, 0)) + } + ] + end + }, + { + "100/0/0", + setup, + fun + () -> + meck:expect( + cfclient_ets, + get, + fun + (_, <<"segments/target_group_1">>) -> + cfclient_evaluator_test_data:target_group_for_percentage_rollout(); + + (_, <<"flags/My_string_flag">>) -> + cfclient_evaluator_test_data:percentage_rollout_multi_variate(100, 0, 0) + end + ) + end, + fun + (_) -> + [ + { + timeout, + 100, + ?_assertEqual({200000, 0, 0}, do_string_variation_200k_times({0, 0, 0}, 0)) + } + ] + end + }, + { + "0/0/100", + setup, + fun + () -> + meck:expect( + cfclient_ets, + get, + fun + (_, <<"segments/target_group_1">>) -> + cfclient_evaluator_test_data:target_group_for_percentage_rollout(); + + (_, <<"flags/My_string_flag">>) -> + cfclient_evaluator_test_data:percentage_rollout_multi_variate(0, 0, 100) + end + ) + end, + fun + (_) -> + [ + { + timeout, + 100, + ?_assertEqual({0, 0, 200000}, do_string_variation_200k_times({0, 0, 0}, 0)) + } + ] + end + }, + { + "0/50/50", + setup, + fun + () -> + meck:expect( + cfclient_ets, + get, + fun + (_, <<"segments/target_group_1">>) -> + cfclient_evaluator_test_data:target_group_for_percentage_rollout(); + + (_, <<"flags/My_string_flag">>) -> + cfclient_evaluator_test_data:percentage_rollout_multi_variate(0, 50, 50) + end + ) + end, + fun + (_) -> + [ + { + timeout, + 100, + ?_assertEqual({0, 100124, 99876}, do_string_variation_200k_times({0, 0, 0}, 0)) + } + ] + end + }, + { + "80/10/10", + setup, + fun + () -> + meck:expect( + cfclient_ets, + get, + fun + (_, <<"segments/target_group_1">>) -> + cfclient_evaluator_test_data:target_group_for_percentage_rollout(); + + (_, <<"flags/My_string_flag">>) -> + cfclient_evaluator_test_data:percentage_rollout_multi_variate(80, 10, 10) + end + ) + end, + fun + (_) -> + [ + { + timeout, + 100, + ?_assertEqual({159978, 19995, 20027}, do_string_variation_200k_times({0, 0, 0}, 0)) + } + ] + end + } + ] + }. + do_bool_variation_200k_times({TrueCounter, FalseCounter}, 200000) -> {TrueCounter, FalseCounter}; do_bool_variation_200k_times({TrueCounter, FalseCounter}, AccuIn) ->