-
Notifications
You must be signed in to change notification settings - Fork 37
(chore): Use the project config manager in java sdk with android. Also add listener. #276
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
Changes from 19 commits
e729d75
61e7459
d7aaa17
0f58881
289dab7
30258fd
8034458
27d3202
cccaf11
eb6bba3
a295664
c619ce6
253ba75
07db97b
9999cd7
802c514
2ae390e
fe2d2d9
eaab9a4
435681e
0847b7b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,8 @@ | |
| import com.optimizely.ab.android.shared.ServiceScheduler; | ||
| import com.optimizely.ab.android.user_profile.DefaultUserProfileService; | ||
| import com.optimizely.ab.bucketing.UserProfileService; | ||
| import com.optimizely.ab.config.DatafileProjectConfig; | ||
| import com.optimizely.ab.config.ProjectConfig; | ||
| import com.optimizely.ab.config.Variation; | ||
| import com.optimizely.ab.event.EventHandler; | ||
|
|
||
|
|
@@ -74,6 +76,7 @@ public class OptimizelyManagerTest { | |
| private ListeningExecutorService executor; | ||
| private Logger logger; | ||
| private OptimizelyManager optimizelyManager; | ||
| private DefaultDatafileHandler defaultDatafileHandler; | ||
|
|
||
| private String minDatafile = "{\n" + | ||
| "experiments: [ ],\n" + | ||
|
|
@@ -88,19 +91,24 @@ public class OptimizelyManagerTest { | |
| "}"; | ||
|
|
||
| @Before | ||
| public void setup() { | ||
| public void setup() throws Exception { | ||
| logger = mock(Logger.class); | ||
| executor = MoreExecutors.newDirectExecutorService(); | ||
| DatafileHandler datafileHandler = mock(DefaultDatafileHandler.class); | ||
| defaultDatafileHandler = mock(DefaultDatafileHandler.class); | ||
| EventHandler eventHandler = mock(DefaultEventHandler.class); | ||
| optimizelyManager = new OptimizelyManager(testProjectId, null, null, logger, 3600L, datafileHandler, null, 3600L, | ||
| optimizelyManager = new OptimizelyManager(testProjectId, null, null, logger, 3600L, defaultDatafileHandler, null, 3600L, | ||
| eventHandler, null); | ||
| String datafile = optimizelyManager.getDatafile(InstrumentationRegistry.getTargetContext(), R.raw.datafile); | ||
| ProjectConfig config = new DatafileProjectConfig.Builder().withDatafile(datafile).build(); | ||
|
|
||
| when(defaultDatafileHandler.getConfig()).thenReturn(config); | ||
| } | ||
|
|
||
| @Test | ||
| public void initializeIntUseForcedVariation() { | ||
| optimizelyManager.initialize(InstrumentationRegistry.getTargetContext(), R.raw.datafile); | ||
|
|
||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems extraneous. Remove. |
||
| assertTrue(optimizelyManager.getOptimizely().setForcedVariation("android_experiment_key", "1", "var_1")); | ||
| Variation variation = optimizelyManager.getOptimizely().getForcedVariation("android_experiment_key", "1"); | ||
| assertEquals(variation.getKey(), "var_1"); | ||
|
|
@@ -116,7 +124,7 @@ public void initializeInt() { | |
|
|
||
| assertEquals(optimizelyManager.getDatafileUrl(), "https://cdn.optimizely.com/json/7595190003.json" ); | ||
|
|
||
| verify(optimizelyManager.getDatafileHandler()).startBackgroundUpdates(eq(InstrumentationRegistry.getTargetContext()), eq(new DatafileConfig(testProjectId, null)), eq(3600L)); | ||
| verify(optimizelyManager.getDatafileHandler()).startBackgroundUpdates(eq(InstrumentationRegistry.getTargetContext()), eq(new DatafileConfig(testProjectId, null)), eq(3600L), any(DatafileLoadedListener.class)); | ||
| assertNotNull(optimizelyManager.getOptimizely()); | ||
| assertNotNull(optimizelyManager.getDatafileHandler()); | ||
|
|
||
|
|
@@ -169,6 +177,7 @@ public void initializeSyncWithEmptyDatafile() { | |
| Context appContext = mock(Context.class); | ||
| when(context.getApplicationContext()).thenReturn(appContext); | ||
| when(appContext.getPackageName()).thenReturn("com.optly"); | ||
| when(defaultDatafileHandler.getConfig()).thenReturn(null); | ||
| optimizelyManager.initialize(InstrumentationRegistry.getTargetContext(), R.raw.emptydatafile); | ||
| assertFalse(optimizelyManager.getOptimizely().isValid()); | ||
| } | ||
|
|
@@ -227,7 +236,7 @@ public void onStart(OptimizelyClient optimizely) { | |
| }; | ||
| optimizelyManager.initialize(InstrumentationRegistry.getContext(), R.raw.datafile, listener); | ||
|
|
||
| verify(optimizelyManager.getDatafileHandler()).startBackgroundUpdates(any(Context.class), eq(new DatafileConfig(testProjectId, testSdkKey)), eq(3600L)); | ||
| verify(optimizelyManager.getDatafileHandler()).startBackgroundUpdates(any(Context.class), eq(new DatafileConfig(testProjectId, testSdkKey)), eq(3600L), any(DatafileLoadedListener.class)); | ||
|
|
||
|
|
||
| assertEquals(optimizelyManager.isDatafileCached(InstrumentationRegistry.getTargetContext()), false); | ||
|
|
@@ -261,6 +270,7 @@ public void initializeWithEmptyDatafile() { | |
| Context appContext = mock(Context.class); | ||
| when(context.getApplicationContext()).thenReturn(appContext); | ||
| when(appContext.getPackageName()).thenReturn("com.optly"); | ||
| when(defaultDatafileHandler.getConfig()).thenReturn(null); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Surprised this mock works since we already mocked with: in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the when override works fine. these are unit tests. however, it might also be possible to just include the default datafile handler instead of a mock and achieve the same thing. |
||
|
|
||
| String emptyString = ""; | ||
|
|
||
|
|
@@ -274,6 +284,7 @@ public void initializeWithMalformedDatafile() { | |
| Context appContext = mock(Context.class); | ||
| when(context.getApplicationContext()).thenReturn(appContext); | ||
| when(appContext.getPackageName()).thenReturn("com.optly"); | ||
| when(defaultDatafileHandler.getConfig()).thenReturn(null); | ||
|
|
||
| String emptyString = "malformed data"; | ||
|
|
||
|
|
@@ -347,7 +358,7 @@ public void injectOptimizely() { | |
|
|
||
| verify(logger).info("Sending Optimizely instance to listener"); | ||
| verify(startListener).onStart(any(OptimizelyClient.class)); | ||
| verify(optimizelyManager.getDatafileHandler()).startBackgroundUpdates(eq(context), eq(new DatafileConfig(testProjectId, null)), eq(3600L)); | ||
| verify(optimizelyManager.getDatafileHandler()).startBackgroundUpdates(eq(context), eq(new DatafileConfig(testProjectId, null)), eq(3600L), any(DatafileLoadedListener.class)); | ||
|
|
||
| } | ||
|
|
||
|
|
@@ -366,7 +377,7 @@ public void injectOptimizelyWithDatafileLisener() { | |
| fail("Timed out"); | ||
| } | ||
|
|
||
| verify(optimizelyManager.getDatafileHandler()).startBackgroundUpdates(eq(context), eq(new DatafileConfig(testProjectId, null)), eq(3600L)); | ||
| verify(optimizelyManager.getDatafileHandler()).startBackgroundUpdates(eq(context), eq(new DatafileConfig(testProjectId, null)), eq(3600L), any(DatafileLoadedListener.class)); | ||
| verify(logger).info("Sending Optimizely instance to listener"); | ||
| verify(startListener).onStart(any(OptimizelyClient.class)); | ||
| } | ||
|
|
@@ -435,6 +446,7 @@ public void injectOptimizelyHandlesInvalidDatafile() { | |
| ArgumentCaptor<DefaultUserProfileService.StartCallback> callbackArgumentCaptor = | ||
| ArgumentCaptor.forClass(DefaultUserProfileService.StartCallback.class); | ||
|
|
||
| when(defaultDatafileHandler.getConfig()).thenReturn(null); | ||
| optimizelyManager.setOptimizelyStartListener(null); | ||
| optimizelyManager.injectOptimizely(context, userProfileService, "{}"); | ||
| try { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,6 +44,8 @@ | |
| import com.optimizely.ab.error.ErrorHandler; | ||
| import com.optimizely.ab.event.EventHandler; | ||
| import com.optimizely.ab.event.internal.payload.EventBatch; | ||
| import com.optimizely.ab.notification.NotificationCenter; | ||
| import com.optimizely.ab.notification.UpdateConfigNotification; | ||
|
|
||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
@@ -184,11 +186,7 @@ protected OptimizelyClient initialize(@NonNull Context context, @Nullable String | |
| defaultUserProfileService.start(); | ||
| } | ||
| optimizelyClient = buildOptimizely(context, datafile); | ||
|
|
||
| if (datafileDownloadInterval > 0 && datafileHandler != null) { | ||
| datafileHandler.startBackgroundUpdates(context, datafileConfig, datafileDownloadInterval); | ||
| } | ||
|
|
||
| startDatafileHandler(context); | ||
| } | ||
| else { | ||
| logger.error("Invalid datafile"); | ||
|
|
@@ -343,9 +341,6 @@ public void onDatafileLoaded(@Nullable String datafile) { | |
| injectOptimizely(context, userProfileService, getDatafile(context,datafileRes)); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public void onStop(Context context) {} | ||
| }; | ||
| } | ||
|
|
||
|
|
@@ -434,17 +429,32 @@ public DatafileHandler getDatafileHandler() { | |
| return datafileHandler; | ||
| } | ||
|
|
||
| private void startDatafileHandler(Context context) { | ||
| if (datafileDownloadInterval <= 0) { | ||
| logger.debug("Invalid download interval, ignoring background updates."); | ||
| return; | ||
| } | ||
|
|
||
| datafileHandler.startBackgroundUpdates(context, datafileConfig, datafileDownloadInterval, datafile1 -> { | ||
| NotificationCenter notificationCenter = getOptimizely().getNotificationCenter(); | ||
| if (notificationCenter == null) { | ||
| logger.debug("NotificationCenter null, not sending notification"); | ||
| return; | ||
| } | ||
| notificationCenter.send(new UpdateConfigNotification()); | ||
| }); | ||
| } | ||
|
|
||
| @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) | ||
| void injectOptimizely(@NonNull final Context context, final @NonNull UserProfileService userProfileService, | ||
| @NonNull final String datafile) { | ||
|
|
||
| if (datafileDownloadInterval > 0 && datafileHandler != null) { | ||
| datafileHandler.startBackgroundUpdates(context, datafileConfig, datafileDownloadInterval); | ||
| } | ||
| try { | ||
| optimizelyClient = buildOptimizely(context, datafile); | ||
| optimizelyClient.setDefaultAttributes(OptimizelyDefaultAttributes.buildDefaultAttributesMap(context, logger)); | ||
|
|
||
| startDatafileHandler(context); | ||
|
|
||
| if (userProfileService instanceof DefaultUserProfileService) { | ||
| ((DefaultUserProfileService) userProfileService).startInBackground(new DefaultUserProfileService.StartCallback() { | ||
| @Override | ||
|
|
@@ -483,20 +493,26 @@ private OptimizelyClient buildOptimizely(@NonNull Context context, @NonNull Stri | |
|
|
||
| EventBatch.ClientEngine clientEngine = OptimizelyClientEngine.getClientEngineFromContext(context); | ||
|
|
||
| Optimizely.Builder builder = Optimizely.builder(datafile, eventHandler) | ||
| .withClientEngine(clientEngine) | ||
| Optimizely.Builder builder = Optimizely.builder(); | ||
|
|
||
| if (datafileHandler instanceof DefaultDatafileHandler) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this logic should be part of the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At build time the developer has not called an initialize/start. It was decided that there would be explicit ways to initialize sync and async. So, moving it would break backward compatibility. However, this does bring up the point on whether we should also be be deprecating the initialize methods. |
||
| DefaultDatafileHandler handler = (DefaultDatafileHandler)datafileHandler; | ||
| handler.setDatafile(datafile); | ||
| builder.withConfigManager(handler); | ||
| builder.withEventHandler(eventHandler); | ||
| } | ||
| else { | ||
| builder = Optimizely.builder(datafile, eventHandler); | ||
| } | ||
|
|
||
| builder.withClientEngine(clientEngine) | ||
| .withClientVersion(BuildConfig.CLIENT_VERSION); | ||
|
|
||
| if (errorHandler != null) { | ||
| builder.withErrorHandler(errorHandler); | ||
| } | ||
| if (userProfileService != null) { | ||
| builder.withUserProfileService(userProfileService); | ||
| } | ||
| else { | ||
| // the builder creates the default user profile service. So, this should never happen. | ||
| userProfileService = DefaultUserProfileService.newInstance(datafileConfig.getKey(), context); | ||
| builder.withUserProfileService(userProfileService); | ||
| } | ||
|
|
||
| builder.withUserProfileService(userProfileService); | ||
|
|
||
| Optimizely optimizely = builder.build(); | ||
| return new OptimizelyClient(optimizely, LoggerFactory.getLogger(OptimizelyClient.class)); | ||
|
|
@@ -752,6 +768,10 @@ public OptimizelyManager build(Context context) { | |
| } | ||
| } | ||
|
|
||
| if (datafileConfig == null) { | ||
| datafileConfig = new DatafileConfig(projectId, sdkKey); | ||
| } | ||
|
|
||
| if (datafileHandler == null) { | ||
| datafileHandler = new DefaultDatafileHandler(); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This import seems unnecessary.