From 6afd6a65ec4d442b99719af757ecc4244f1f4d74 Mon Sep 17 00:00:00 2001 From: wangjoshuah Date: Thu, 5 Oct 2017 17:22:19 -0700 Subject: [PATCH 1/3] if no live variable usage exists for the variable in the variation, return the default value --- core-api/src/main/java/com/optimizely/ab/Optimizely.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core-api/src/main/java/com/optimizely/ab/Optimizely.java b/core-api/src/main/java/com/optimizely/ab/Optimizely.java index 1ee6d498e..08a527a62 100644 --- a/core-api/src/main/java/com/optimizely/ab/Optimizely.java +++ b/core-api/src/main/java/com/optimizely/ab/Optimizely.java @@ -556,7 +556,12 @@ else if (!variable.getType().equals(variableType)) { if (variation != null) { LiveVariableUsageInstance liveVariableUsageInstance = variation.getVariableIdToLiveVariableUsageInstanceMap().get(variable.getId()); - variableValue = liveVariableUsageInstance.getValue(); + if (liveVariableUsageInstance != null) { + variableValue = liveVariableUsageInstance.getValue(); + } + else { + variableValue = variable.getDefaultValue(); + } } else { logger.info("User \"" + userId + From b5182b144710ee685e84178463d2976e9cae8424 Mon Sep 17 00:00:00 2001 From: wangjoshuah Date: Thu, 5 Oct 2017 17:40:56 -0700 Subject: [PATCH 2/3] add rollout with variation that does not change variable value in rollout rule. This means no live variable usage will be in datafile. need to fallback on default value --- .../ab/config/ValidProjectConfigV4.java | 52 +++++++++++++++---- .../config/valid-project-config-v4.json | 28 +++++++++- 2 files changed, 69 insertions(+), 11 deletions(-) diff --git a/core-api/src/test/java/com/optimizely/ab/config/ValidProjectConfigV4.java b/core-api/src/test/java/com/optimizely/ab/config/ValidProjectConfigV4.java index bc0dab271..6b4d418f0 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/ValidProjectConfigV4.java +++ b/core-api/src/test/java/com/optimizely/ab/config/ValidProjectConfigV4.java @@ -118,15 +118,6 @@ public class ValidProjectConfigV4 { null, LiveVariable.VariableType.INTEGER ); - private static final FeatureFlag FEATURE_FLAG_SINGLE_VARIABLE_INTEGER = new FeatureFlag( - FEATURE_SINGLE_VARIABLE_INTEGER_ID, - FEATURE_SINGLE_VARIABLE_INTEGER_KEY, - "", - Collections.emptyList(), - Collections.singletonList( - VARIABLE_INTEGER_VARIABLE - ) - ); private static final String FEATURE_SINGLE_VARIABLE_BOOLEAN_ID = "2591051011"; public static final String FEATURE_SINGLE_VARIABLE_BOOLEAN_KEY = "boolean_single_variable_feature"; private static final String VARIABLE_BOOLEAN_VARIABLE_ID = "3974680341"; @@ -206,6 +197,38 @@ public class ValidProjectConfigV4 { VARIABLE_STRING_VARIABLE ) ); + private static final String ROLLOUT_3_ID = "2048875663"; + private static final String ROLLOUT_3_EVERYONE_ELSE_EXPERIMENT_ID = "3794675122"; + private static final String ROLLOUT_3_EVERYONE_ELSE_RULE_ENABLED_VARIATION_ID = "589640735"; + private static final Variation ROLLOUT_3_EVERYONE_ELSE_RULE_ENABLED_VARIATION = new Variation( + ROLLOUT_3_EVERYONE_ELSE_RULE_ENABLED_VARIATION_ID, + ROLLOUT_3_EVERYONE_ELSE_RULE_ENABLED_VARIATION_ID, + Collections.emptyList() + ); + private static final Experiment ROLLOUT_3_EVERYONE_ELSE_RULE = new Experiment( + ROLLOUT_3_EVERYONE_ELSE_EXPERIMENT_ID, + ROLLOUT_3_EVERYONE_ELSE_EXPERIMENT_ID, + Experiment.ExperimentStatus.RUNNING.toString(), + ROLLOUT_3_ID, + Collections.emptyList(), + Collections.singletonList( + ROLLOUT_3_EVERYONE_ELSE_RULE_ENABLED_VARIATION + ), + Collections.emptyMap(), + Collections.singletonList( + new TrafficAllocation( + ROLLOUT_3_EVERYONE_ELSE_RULE_ENABLED_VARIATION_ID, + 10000 + ) + ) + ); + public static final Rollout ROLLOUT_3 = new Rollout( + ROLLOUT_3_ID, + Collections.singletonList( + ROLLOUT_3_EVERYONE_ELSE_RULE + ) + ); + private static final String FEATURE_MULTI_VARIATE_FEATURE_ID = "3263342226"; public static final String FEATURE_MULTI_VARIATE_FEATURE_KEY = "multi_variate_feature"; private static final String VARIABLE_FIRST_LETTER_ID = "675244127"; @@ -917,7 +940,15 @@ public class ValidProjectConfigV4 { VARIABLE_DOUBLE_VARIABLE ) ); - + private static final FeatureFlag FEATURE_FLAG_SINGLE_VARIABLE_INTEGER = new FeatureFlag( + FEATURE_SINGLE_VARIABLE_INTEGER_ID, + FEATURE_SINGLE_VARIABLE_INTEGER_KEY, + ROLLOUT_3_ID, + Collections.emptyList(), + Collections.singletonList( + VARIABLE_INTEGER_VARIABLE + ) + ); public static ProjectConfig generateValidProjectConfigV4() { @@ -964,6 +995,7 @@ public static ProjectConfig generateValidProjectConfigV4() { List rollouts = new ArrayList(); rollouts.add(ROLLOUT_1); rollouts.add(ROLLOUT_2); + rollouts.add(ROLLOUT_3); return new ProjectConfig( ACCOUNT_ID, diff --git a/core-api/src/test/resources/config/valid-project-config-v4.json b/core-api/src/test/resources/config/valid-project-config-v4.json index 9ef2e682f..fed802474 100644 --- a/core-api/src/test/resources/config/valid-project-config-v4.json +++ b/core-api/src/test/resources/config/valid-project-config-v4.json @@ -449,7 +449,7 @@ { "id": "3281420120", "key": "integer_single_variable_feature", - "rolloutId": "", + "rolloutId": "2048875663", "experimentIds": [], "variables": [ { @@ -679,6 +679,32 @@ ] } ] + }, + { + "id": "2048875663", + "experiments": [ + { + "id": "3794675122", + "key": "3794675122", + "status": "Running", + "layerId": "2048875663", + "audienceIds": [], + "forcedVariations": {}, + "variations": [ + { + "id": "589640735", + "key": "589640735", + "variables": [] + } + ], + "trafficAllocation": [ + { + "entityId": "589640735", + "endOfRange": 10000 + } + ] + } + ] } ], "variables": [] From 55c94ac65c8cfaee21aa5c12fbe5e31379e6c66f Mon Sep 17 00:00:00 2001 From: wangjoshuah Date: Thu, 5 Oct 2017 18:00:04 -0700 Subject: [PATCH 3/3] add test to make sure we fall back on default value when variable usage not found in datafile --- .../com/optimizely/ab/OptimizelyTest.java | 33 +++++++++++++++++++ .../ab/config/ValidProjectConfigV4.java | 6 ++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/core-api/src/test/java/com/optimizely/ab/OptimizelyTest.java b/core-api/src/test/java/com/optimizely/ab/OptimizelyTest.java index e40e5eb1c..2bef5266e 100644 --- a/core-api/src/test/java/com/optimizely/ab/OptimizelyTest.java +++ b/core-api/src/test/java/com/optimizely/ab/OptimizelyTest.java @@ -80,9 +80,11 @@ import static com.optimizely.ab.config.ValidProjectConfigV4.EXPERIMENT_PAUSED_EXPERIMENT_KEY; import static com.optimizely.ab.config.ValidProjectConfigV4.FEATURE_FLAG_MULTI_VARIATE_FEATURE; import static com.optimizely.ab.config.ValidProjectConfigV4.FEATURE_FLAG_SINGLE_VARIABLE_DOUBLE; +import static com.optimizely.ab.config.ValidProjectConfigV4.FEATURE_FLAG_SINGLE_VARIABLE_INTEGER; import static com.optimizely.ab.config.ValidProjectConfigV4.FEATURE_MULTI_VARIATE_FEATURE_KEY; import static com.optimizely.ab.config.ValidProjectConfigV4.FEATURE_SINGLE_VARIABLE_BOOLEAN_KEY; import static com.optimizely.ab.config.ValidProjectConfigV4.FEATURE_SINGLE_VARIABLE_DOUBLE_KEY; +import static com.optimizely.ab.config.ValidProjectConfigV4.FEATURE_SINGLE_VARIABLE_INTEGER_KEY; import static com.optimizely.ab.config.ValidProjectConfigV4.MULTIVARIATE_EXPERIMENT_FORCED_VARIATION_USER_ID_GRED; import static com.optimizely.ab.config.ValidProjectConfigV4.PAUSED_EXPERIMENT_FORCED_VARIATION_USER_ID_CONTROL; import static com.optimizely.ab.config.ValidProjectConfigV4.VARIABLE_BOOLEAN_VARIABLE_DEFAULT_VALUE; @@ -90,6 +92,7 @@ import static com.optimizely.ab.config.ValidProjectConfigV4.VARIABLE_DOUBLE_DEFAULT_VALUE; import static com.optimizely.ab.config.ValidProjectConfigV4.VARIABLE_DOUBLE_VARIABLE_KEY; import static com.optimizely.ab.config.ValidProjectConfigV4.VARIABLE_FIRST_LETTER_KEY; +import static com.optimizely.ab.config.ValidProjectConfigV4.VARIABLE_INTEGER_VARIABLE_KEY; import static com.optimizely.ab.config.ValidProjectConfigV4.VARIATION_MULTIVARIATE_EXPERIMENT_GRED; import static com.optimizely.ab.config.ValidProjectConfigV4.VARIATION_MULTIVARIATE_EXPERIMENT_GRED_KEY; import static com.optimizely.ab.event.LogEvent.RequestMethod; @@ -2631,6 +2634,36 @@ public void getFeatureVariableValueReturnsVariationValueWhenUserGetsBucketedToVa assertEquals(expectedValue, value); } + /** + * Verify {@link Optimizely#getFeatureVariableValueForType(String, String, String, Map, LiveVariable.VariableType)} + * returns the default value for the feature variable + * when there is no variable usage present for the variation the user is bucketed into. + * @throws ConfigParseException + */ + @Test + public void getFeatureVariableValueReturnsDefaultValueWhenNoVariationUsageIsPresent() throws ConfigParseException { + assumeTrue(datafileVersion >= Integer.parseInt(ProjectConfig.Version.V4.toString())); + + String validFeatureKey = FEATURE_SINGLE_VARIABLE_INTEGER_KEY; + String validVariableKey = VARIABLE_INTEGER_VARIABLE_KEY; + LiveVariable variable = FEATURE_FLAG_SINGLE_VARIABLE_INTEGER.getVariableKeyToLiveVariableMap().get(validVariableKey); + String expectedValue = variable.getDefaultValue(); + + Optimizely optimizely = Optimizely.builder(validDatafile, mockEventHandler) + .withConfig(validProjectConfig) + .build(); + + String value = optimizely.getFeatureVariableValueForType( + validFeatureKey, + validVariableKey, + genericUserId, + Collections.emptyMap(), + LiveVariable.VariableType.INTEGER + ); + + assertEquals(expectedValue, value); + } + /** * Verify {@link Optimizely#isFeatureEnabled(String, String)} calls into * {@link Optimizely#isFeatureEnabled(String, String, Map)} and they both diff --git a/core-api/src/test/java/com/optimizely/ab/config/ValidProjectConfigV4.java b/core-api/src/test/java/com/optimizely/ab/config/ValidProjectConfigV4.java index 6b4d418f0..d8932db01 100644 --- a/core-api/src/test/java/com/optimizely/ab/config/ValidProjectConfigV4.java +++ b/core-api/src/test/java/com/optimizely/ab/config/ValidProjectConfigV4.java @@ -107,9 +107,9 @@ public class ValidProjectConfigV4 { LiveVariable.VariableType.DOUBLE ); private static final String FEATURE_SINGLE_VARIABLE_INTEGER_ID = "3281420120"; - private static final String FEATURE_SINGLE_VARIABLE_INTEGER_KEY = "integer_single_variable_feature"; + public static final String FEATURE_SINGLE_VARIABLE_INTEGER_KEY = "integer_single_variable_feature"; private static final String VARIABLE_INTEGER_VARIABLE_ID = "593964691"; - private static final String VARIABLE_INTEGER_VARIABLE_KEY = "integer_variable"; + public static final String VARIABLE_INTEGER_VARIABLE_KEY = "integer_variable"; private static final String VARIABLE_INTEGER_DEFAULT_VALUE = "7"; private static final LiveVariable VARIABLE_INTEGER_VARIABLE = new LiveVariable( VARIABLE_INTEGER_VARIABLE_ID, @@ -940,7 +940,7 @@ public class ValidProjectConfigV4 { VARIABLE_DOUBLE_VARIABLE ) ); - private static final FeatureFlag FEATURE_FLAG_SINGLE_VARIABLE_INTEGER = new FeatureFlag( + public static final FeatureFlag FEATURE_FLAG_SINGLE_VARIABLE_INTEGER = new FeatureFlag( FEATURE_SINGLE_VARIABLE_INTEGER_ID, FEATURE_SINGLE_VARIABLE_INTEGER_KEY, ROLLOUT_3_ID,