From 831227cc999394fd1d0ca48b15c0375293728046 Mon Sep 17 00:00:00 2001 From: wangjoshuah Date: Wed, 5 Jul 2017 22:05:46 -0700 Subject: [PATCH] remove live variable APIs --- .../java/com/optimizely/ab/Optimizely.java | 167 ------------- .../com/optimizely/ab/OptimizelyTest.java | 231 +----------------- 2 files changed, 1 insertion(+), 397 deletions(-) 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 a329cdb98..347c27d64 100644 --- a/core-api/src/main/java/com/optimizely/ab/Optimizely.java +++ b/core-api/src/main/java/com/optimizely/ab/Optimizely.java @@ -22,8 +22,6 @@ import com.optimizely.ab.config.Attribute; import com.optimizely.ab.config.EventType; import com.optimizely.ab.config.Experiment; -import com.optimizely.ab.config.LiveVariable; -import com.optimizely.ab.config.LiveVariableUsageInstance; import com.optimizely.ab.config.ProjectConfig; import com.optimizely.ab.config.Variation; import com.optimizely.ab.config.parser.ConfigParseException; @@ -38,7 +36,6 @@ import com.optimizely.ab.event.internal.EventBuilderV2; import com.optimizely.ab.event.internal.payload.Event.ClientEngine; import com.optimizely.ab.internal.EventTagUtils; -import com.optimizely.ab.internal.ReservedEventKey; import com.optimizely.ab.notification.NotificationBroadcaster; import com.optimizely.ab.notification.NotificationListener; import org.slf4j.Logger; @@ -283,139 +280,6 @@ public void track(@Nonnull String eventName, conversionEvent); } - //======== live variable getters ========// - - @Deprecated - public @Nullable - String getVariableString(@Nonnull String variableKey, - @Nonnull String userId, - boolean activateExperiment) throws UnknownLiveVariableException { - return getVariableString(variableKey, userId, Collections.emptyMap(), activateExperiment); - } - - @Deprecated - public @Nullable - String getVariableString(@Nonnull String variableKey, - @Nonnull String userId, - @Nonnull Map attributes, - boolean activateExperiment) - throws UnknownLiveVariableException { - - LiveVariable variable = getLiveVariableOrThrow(projectConfig, variableKey); - if (variable == null) { - return null; - } - - List experimentsUsingLiveVariable = - projectConfig.getLiveVariableIdToExperimentsMapping().get(variable.getId()); - Map> variationToLiveVariableUsageInstanceMapping = - projectConfig.getVariationToLiveVariableUsageInstanceMapping(); - - if (experimentsUsingLiveVariable == null) { - logger.warn("No experiment is using variable \"{}\".", variable.getKey()); - return variable.getDefaultValue(); - } - - for (Experiment experiment : experimentsUsingLiveVariable) { - Variation variation; - if (activateExperiment) { - variation = activate(experiment, userId, attributes); - } else { - variation = getVariation(experiment, userId, attributes); - } - - if (variation != null) { - LiveVariableUsageInstance usageInstance = - variationToLiveVariableUsageInstanceMapping.get(variation.getId()).get(variable.getId()); - return usageInstance.getValue(); - } - } - - return variable.getDefaultValue(); - } - - @Deprecated - public @Nullable - Boolean getVariableBoolean(@Nonnull String variableKey, - @Nonnull String userId, - boolean activateExperiment) throws UnknownLiveVariableException { - return getVariableBoolean(variableKey, userId, Collections.emptyMap(), activateExperiment); - } - - @Deprecated - public @Nullable - Boolean getVariableBoolean(@Nonnull String variableKey, - @Nonnull String userId, - @Nonnull Map attributes, - boolean activateExperiment) - throws UnknownLiveVariableException { - - String variableValueString = getVariableString(variableKey, userId, attributes, activateExperiment); - if (variableValueString != null) { - return Boolean.parseBoolean(variableValueString); - } - - return null; - } - - @Deprecated - public @Nullable - Integer getVariableInteger(@Nonnull String variableKey, - @Nonnull String userId, - boolean activateExperiment) throws UnknownLiveVariableException { - return getVariableInteger(variableKey, userId, Collections.emptyMap(), activateExperiment); - } - - @Deprecated - public @Nullable - Integer getVariableInteger(@Nonnull String variableKey, - @Nonnull String userId, - @Nonnull Map attributes, - boolean activateExperiment) - throws UnknownLiveVariableException { - - String variableValueString = getVariableString(variableKey, userId, attributes, activateExperiment); - if (variableValueString != null) { - try { - return Integer.parseInt(variableValueString); - } catch (NumberFormatException e) { - logger.error("Variable value \"{}\" for live variable \"{}\" is not an integer.", variableValueString, - variableKey); - } - } - - return null; - } - - @Deprecated - public @Nullable - Double getVariableDouble(@Nonnull String variableKey, - @Nonnull String userId, - boolean activateExperiment) throws UnknownLiveVariableException { - return getVariableDouble(variableKey, userId, Collections.emptyMap(), activateExperiment); - } - - @Deprecated - public @Nullable - Double getVariableDouble(@Nonnull String variableKey, - @Nonnull String userId, - @Nonnull Map attributes, - boolean activateExperiment) - throws UnknownLiveVariableException { - - String variableValueString = getVariableString(variableKey, userId, attributes, activateExperiment); - if (variableValueString != null) { - try { - return Double.parseDouble(variableValueString); - } catch (NumberFormatException e) { - logger.error("Variable value \"{}\" for live variable \"{}\" is not a double.", variableValueString, - variableKey); - } - } - - return null; - } - //======== FeatureFlag APIs ========// /** @@ -739,37 +603,6 @@ private EventType getEventTypeOrThrow(ProjectConfig projectConfig, String eventN return eventType; } - /** - * Helper method to retrieve the {@link LiveVariable} for the given variable key. - * If {@link RaiseExceptionErrorHandler} is provided, either a live variable is returned, or an exception is - * thrown. - * If {@link NoOpErrorHandler} is used, either a live variable or {@code null} is returned. - * - * @param projectConfig the current project config - * @param variableKey the key for the live variable being retrieved from the current project config - * @return the live variable to retrieve for the given variable key - * - * @throws UnknownLiveVariableException if there are no event types in the current project config with the given - * name - */ - @Deprecated - private LiveVariable getLiveVariableOrThrow(ProjectConfig projectConfig, String variableKey) - throws UnknownLiveVariableException { - - LiveVariable liveVariable = projectConfig - .getLiveVariableKeyMapping() - .get(variableKey); - - if (liveVariable == null) { - String unknownLiveVariableKeyError = - String.format("Live variable \"%s\" is not in the datafile.", variableKey); - logger.error(unknownLiveVariableKeyError); - errorHandler.handleError(new UnknownLiveVariableException(unknownLiveVariableKeyError)); - } - - return liveVariable; - } - /** * Helper method to verify that the given attributes map contains only keys that are present in the * {@link ProjectConfig}. 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 400a60cec..d557cc7dd 100644 --- a/core-api/src/test/java/com/optimizely/ab/OptimizelyTest.java +++ b/core-api/src/test/java/com/optimizely/ab/OptimizelyTest.java @@ -35,7 +35,6 @@ import com.optimizely.ab.event.internal.EventBuilderV2; import com.optimizely.ab.internal.ExperimentUtils; import com.optimizely.ab.internal.LogbackVerifier; -import com.optimizely.ab.internal.ReservedEventKey; import com.optimizely.ab.notification.NotificationListener; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.junit.Rule; @@ -75,8 +74,6 @@ import static org.hamcrest.Matchers.hasKey; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assume.assumeTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyMapOf; import static org.mockito.Matchers.anyString; @@ -1439,217 +1436,6 @@ public void trackDoesNotSendEventWhenUserDoesNotSatisfyAudiences() throws Except verify(mockEventHandler, never()).dispatchEvent(any(LogEvent.class)); } - //======== live variable getters tests ========// - - /** - * Verify that {@link Optimizely#getVariableString(String, String, boolean)} returns null and logs properly when - * an invalid live variable key is provided and the {@link NoOpErrorHandler} is used. - */ - @Test - public void getVariableInvalidVariableKeyNoOpErrorHandler() throws Exception { - - Optimizely optimizely = Optimizely.builder(validDatafile, mockEventHandler) - .withConfig(validProjectConfig) - .build(); - - logbackVerifier.expectMessage(Level.ERROR, "Live variable \"invalid_key\" is not in the datafile."); - assertNull(optimizely.getVariableString("invalid_key", "userId", false)); - } - - /** - * Verify that {@link Optimizely#getVariableString(String, String, boolean)} returns throws an - * {@link UnknownLiveVariableException} when an invalid live variable key is provided and the - * {@link RaiseExceptionErrorHandler} is used. - */ - @Test - public void getVariableInvalidVariableKeyRaiseExceptionErrorHandler() throws Exception { - thrown.expect(UnknownLiveVariableException.class); - - - Optimizely optimizely = Optimizely.builder(validDatafile, mockEventHandler) - .withConfig(validProjectConfig) - .withErrorHandler(new RaiseExceptionErrorHandler()) - .build(); - - optimizely.getVariableString("invalid_key", "userId", false); - } - - /** - * Verify that {@link Optimizely#getVariableString(String, String, Map, boolean)} returns a string live variable - * value when an proper variable key is provided and dispatches an impression when activateExperiment is true. - */ - @Test - public void getVariableStringActivateExperimentTrue() throws Exception { - - assumeTrue(datafileVersion >= 3); - - Experiment activatedExperiment = validProjectConfig.getExperiments().get(0); - Variation bucketedVariation = activatedExperiment.getVariations().get(0); - - when(mockBucketer.bucket(activatedExperiment, genericUserId)) - .thenReturn(bucketedVariation); - - Optimizely optimizely = Optimizely.builder(validDatafile, mockEventHandler) - .withConfig(validProjectConfig) - .withBucketing(mockBucketer) - .withErrorHandler(new RaiseExceptionErrorHandler()) - .build(); - - String variableKey = "string_variable"; - Map attributes = Collections.singletonMap("browser_type", "chrome"); - - assertThat(optimizely.getVariableString(variableKey, genericUserId, - attributes, true), - is("string_var_vtag1")); - - verify(mockEventHandler).dispatchEvent(any(LogEvent.class)); - } - - /** - * Verify that {@link Optimizely#getVariableString(String, String, Map, boolean)} returns a string live variable - * value when an proper variable key is provided and doesn't dispatch an impression when activateExperiment is - * false. - */ - @Test - public void getVariableStringActivateExperimentFalse() throws Exception { - - assumeTrue(datafileVersion >= 3); - - Experiment activatedExperiment = validProjectConfig.getExperiments().get(0); - Variation bucketedVariation = activatedExperiment.getVariations().get(0); - - when(mockBucketer.bucket(activatedExperiment, "userId")) - .thenReturn(bucketedVariation); - - Optimizely optimizely = Optimizely.builder(validDatafile, mockEventHandler) - .withConfig(validProjectConfig) - .withBucketing(mockBucketer) - .withErrorHandler(new RaiseExceptionErrorHandler()) - .build(); - - assertThat(optimizely.getVariableString("string_variable", "userId", - Collections.singletonMap("browser_type", "chrome"), false), - is("string_var_vtag1")); - verify(mockEventHandler, never()).dispatchEvent(any(LogEvent.class)); - } - - /** - * Verify that {@link Optimizely#getVariableString(String, String, boolean)} returns the default value of - * a live variable when no experiments are using the live variable. - */ - @Test - public void getVariableStringReturnsDefaultValueNoExperimentsUsingLiveVariable() throws Exception { - - assumeTrue(datafileVersion >= 3); - - Optimizely optimizely = Optimizely.builder(validDatafile, mockEventHandler) - .withConfig(validProjectConfig) - .build(); - - logbackVerifier.expectMessage(Level.WARN, "No experiment is using variable \"unused_string_variable\"."); - assertThat(optimizely.getVariableString("unused_string_variable", - "userId", true), is("unused_variable")); - } - - /** - * Verify that {@link Optimizely#getVariableString(String, String, Map, boolean)} returns the default value when - * a user isn't bucketed into a variation in the experiment. - */ - @Test - public void getVariableStringReturnsDefaultValueUserNotInVariation() throws Exception { - - assumeTrue(datafileVersion >= 3); - - // user isn't bucketed into a variation in any experiment - when(mockBucketer.bucket(any(Experiment.class), any(String.class))) - .thenReturn(null); - - Optimizely optimizely = Optimizely.builder(validDatafile, mockEventHandler) - .withConfig(validProjectConfig) - .withBucketing(mockBucketer) - .build(); - - assertThat(optimizely.getVariableString("string_variable", "userId", - Collections.singletonMap("browser_type", "chrome"), true), - is("string_live_variable")); - } - - /** - * Verify that {@link Optimizely#getVariableBoolean(String, String, Map, boolean)} returns a boolean live variable - * value when an proper variable key is provided and dispatches an impression when activateExperiment is true. - */ - @Test - public void getVariableBoolean() throws Exception { - - assumeTrue(datafileVersion >= 3); - - Experiment activatedExperiment = validProjectConfig.getExperiments().get(0); - Variation bucketedVariation = activatedExperiment.getVariations().get(0); - - when(mockBucketer.bucket(activatedExperiment, "userId")) - .thenReturn(bucketedVariation); - - Optimizely optimizely = Optimizely.builder(validDatafile, mockEventHandler) - .withConfig(validProjectConfig) - .withBucketing(mockBucketer) - .build(); - - assertTrue(optimizely.getVariableBoolean("etag1_variable", "userId", - Collections.singletonMap("browser_type", "chrome"), true)); - } - - /** - * Verify that {@link Optimizely#getVariableDouble(String, String, Map, boolean)} returns a double live variable - * value when an proper variable key is provided and dispatches an impression when activateExperiment is true. - */ - @Test - public void getVariableDouble() throws Exception { - - assumeTrue(datafileVersion >= 3); - - Experiment activatedExperiment = validProjectConfig.getExperiments().get(0); - Variation bucketedVariation = activatedExperiment.getVariations().get(0); - - when(mockBucketer.bucket(activatedExperiment, "userId")) - .thenReturn(bucketedVariation); - - Optimizely optimizely = Optimizely.builder(validDatafile, mockEventHandler) - .withConfig(validProjectConfig) - .withBucketing(mockBucketer) - .build(); - - assertThat(optimizely.getVariableDouble("double_variable", "userId", - Collections.singletonMap("browser_type", "chrome"), true), - is(5.3)); - verify(mockEventHandler).dispatchEvent(any(LogEvent.class)); - } - - /** - * Verify that {@link Optimizely#getVariableInteger(String, String, Map, boolean)} returns a integer live variable - * value when an proper variable key is provided and dispatches an impression when activateExperiment is true. - */ - @Test - public void getVariableInteger() throws Exception { - - assumeTrue(datafileVersion >= 3); - - Experiment activatedExperiment = validProjectConfig.getExperiments().get(0); - Variation bucketedVariation = activatedExperiment.getVariations().get(0); - - when(mockBucketer.bucket(activatedExperiment, "userId")) - .thenReturn(bucketedVariation); - - Optimizely optimizely = Optimizely.builder(validDatafile, mockEventHandler) - .withConfig(validProjectConfig) - .withBucketing(mockBucketer) - .build(); - - assertThat(optimizely.getVariableInteger("integer_variable", "userId", - Collections.singletonMap("browser_type", "chrome"), true), - is(10)); - verify(mockEventHandler).dispatchEvent(any(LogEvent.class)); - } - //======== getVariation tests ========// /** @@ -1938,17 +1724,8 @@ public void addNotificationListener() throws Exception { // Check if listener is notified when experiment is activated Variation actualVariation = optimizely.activate(activatedExperiment, genericUserId, attributes); - verify(listener, times(1)) - .onExperimentActivated(activatedExperiment, genericUserId, attributes, actualVariation); - // Check if listener is notified when live variable is accessed - boolean activateExperiment = true; - optimizely.getVariableString("string_variable", genericUserId, attributes, activateExperiment); - - if (datafileVersion >= 3) { - verify(listener, times(2)) - .onExperimentActivated(activatedExperiment, genericUserId, attributes, actualVariation); - } else { + if (datafileVersion == 3 || datafileVersion == 2) { verify(listener, times(1)) .onExperimentActivated(activatedExperiment, genericUserId, attributes, actualVariation); } @@ -2022,9 +1799,6 @@ public void removeNotificationListener() throws Exception { verify(listener, never()) .onExperimentActivated(activatedExperiment, genericUserId, attributes, actualVariation); - // Check if listener is notified after a live variable is accessed - boolean activateExperiment = true; - optimizely.getVariableString("string_variable", genericUserId, attributes, activateExperiment); verify(listener, never()) .onExperimentActivated(activatedExperiment, genericUserId, attributes, actualVariation); @@ -2096,9 +1870,6 @@ public void clearNotificationListeners() throws Exception { verify(listener, never()) .onExperimentActivated(activatedExperiment, genericUserId, attributes, actualVariation); - // Check if listener is notified after a live variable is accessed - boolean activateExperiment = true; - optimizely.getVariableString("string_variable", genericUserId, attributes, activateExperiment); verify(listener, never()) .onExperimentActivated(activatedExperiment, genericUserId, attributes, actualVariation);