From 6ecc1a5f82c6f32a4d45371eade2361c2ca2417c Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Tue, 12 Sep 2023 15:47:17 -0300 Subject: [PATCH] Sets evaluation test --- .../sets/FlagSetsEvaluationTest.java | 172 ++++++++++++++++++ .../integration/sets/FlagSetsPollingTest.java | 11 +- 2 files changed, 175 insertions(+), 8 deletions(-) create mode 100644 src/androidTest/java/tests/integration/sets/FlagSetsEvaluationTest.java diff --git a/src/androidTest/java/tests/integration/sets/FlagSetsEvaluationTest.java b/src/androidTest/java/tests/integration/sets/FlagSetsEvaluationTest.java new file mode 100644 index 000000000..55864f291 --- /dev/null +++ b/src/androidTest/java/tests/integration/sets/FlagSetsEvaluationTest.java @@ -0,0 +1,172 @@ +package tests.integration.sets; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static helper.IntegrationHelper.ResponseClosure.getSinceFromUri; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; + +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import fake.HttpClientMock; +import fake.HttpResponseMock; +import fake.HttpResponseMockDispatcher; +import helper.DatabaseHelper; +import helper.FileHelper; +import helper.IntegrationHelper; +import helper.TestableSplitConfigBuilder; +import io.split.android.client.SplitClient; +import io.split.android.client.SplitClientConfig; +import io.split.android.client.SplitFactory; +import io.split.android.client.SplitFilter; +import io.split.android.client.SplitResult; +import io.split.android.client.SyncConfig; +import io.split.android.client.dtos.SplitChange; +import io.split.android.client.events.SplitEvent; +import io.split.android.client.storage.db.SplitRoomDatabase; +import io.split.android.client.utils.Json; +import tests.integration.shared.TestingHelper; + +public class FlagSetsEvaluationTest { + + private final FileHelper fileHelper = new FileHelper(); + private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext(); + + @Test + public void sdkWithSetsCanOnlyEvaluateSetsConfigured() throws IOException, InterruptedException { + /* + Initialize with set_1 configured. Changes contains 1 flag in set_1 & set_2, and one in set_3. + + Only the flag in set_1 can be evaluated. + */ + SplitClient client = getClient(mContext, DatabaseHelper.getTestDatabase(mContext), "set_1"); + + Map set1Treatments = client.getTreatmentsByFlagSet("set_1", null); + Map set2Treatments = client.getTreatmentsByFlagSet("set_2", null); + Map set3Treatments = client.getTreatmentsByFlagSet("set_3", null); + Map set1Results = client.getTreatmentsWithConfigByFlagSet("set_1", null); + Map set2Results = client.getTreatmentsWithConfigByFlagSet("set_2", null); + Map set3Results = client.getTreatmentsWithConfigByFlagSet("set_3", null); + Map allTreatments = client.getTreatmentsByFlagSets(Arrays.asList("set_1", "set_2", "set_3"), null); + Map allTreatmentsWithConfig = client.getTreatmentsWithConfigByFlagSets(Arrays.asList("set_1", "set_2", "set_3"), null); + + assertEquals(1, set1Treatments.size()); + assertEquals(0, set2Treatments.size()); + assertEquals(0, set3Treatments.size()); + assertEquals(1, set1Results.size()); + assertEquals(0, set2Results.size()); + assertEquals(0, set3Results.size()); + assertEquals(1, allTreatments.size()); + assertEquals(1, allTreatmentsWithConfig.size()); + assertTrue(set1Treatments.values().stream().noneMatch(t -> t.equals("control"))); + assertTrue(set1Results.values().stream().noneMatch(t -> t.treatment().equals("control"))); + assertTrue(allTreatments.values().stream().noneMatch(t -> t.equals("control"))); + assertTrue(allTreatmentsWithConfig.values().stream().noneMatch(t -> t.treatment().equals("control"))); + } + + @Test + public void sdkWithoutSetsCanEvaluateAnySet() throws IOException, InterruptedException { + /* + Initialize with no sets configured. Changes contains 1 flag in set_1 & set_2, and one in set_3. + + All flags can be evaluated by sets. + */ + SplitClient client = getClient(mContext, DatabaseHelper.getTestDatabase(mContext)); + + Map set1Treatments = client.getTreatmentsByFlagSet("set_1", null); + Map set2Treatments = client.getTreatmentsByFlagSet("set_2", null); + Map set3Treatments = client.getTreatmentsByFlagSet("set_3", null); + Map set1Results = client.getTreatmentsWithConfigByFlagSet("set_1", null); + Map set2Results = client.getTreatmentsWithConfigByFlagSet("set_2", null); + Map set3Results = client.getTreatmentsWithConfigByFlagSet("set_3", null); + Map allTreatments = client.getTreatmentsByFlagSets(Arrays.asList("set_1", "set_2", "set_3"), null); + Map allTreatmentsWithConfig = client.getTreatmentsWithConfigByFlagSets(Arrays.asList("set_1", "set_2", "set_3"), null); + + assertEquals(1, set1Treatments.size()); + assertEquals(1, set2Treatments.size()); + assertEquals(1, set3Treatments.size()); + assertEquals(1, set1Results.size()); + assertEquals(1, set2Results.size()); + assertEquals(1, set3Results.size()); + assertTrue(set1Treatments.values().stream().noneMatch(t -> t.equals("control"))); + assertTrue(set2Treatments.values().stream().noneMatch(t -> t.equals("control"))); + assertTrue(set3Treatments.values().stream().noneMatch(t -> t.equals("control"))); + assertTrue(set1Results.values().stream().noneMatch(t -> t.treatment().equals("control"))); + assertTrue(set2Results.values().stream().noneMatch(t -> t.treatment().equals("control"))); + assertTrue(set3Results.values().stream().noneMatch(t -> t.treatment().equals("control"))); + assertTrue(allTreatments.values().stream().noneMatch(t -> t.equals("control"))); + assertTrue(allTreatmentsWithConfig.values().stream().noneMatch(t -> t.treatment().equals("control"))); + } + + private SplitClient getClient( + Context mContext, + SplitRoomDatabase splitRoomDatabase, + String... sets) throws IOException, InterruptedException { + SplitClientConfig config = new TestableSplitConfigBuilder() + .ready(30000) + .trafficType("client") + .enableDebug() + .impressionsRefreshRate(1000) + .impressionsCountersRefreshRate(1000) + .syncConfig(SyncConfig.builder() + .addSplitFilter(SplitFilter.bySet(Arrays.asList(sets))) + .build()) + .featuresRefreshRate(2) + .streamingEnabled(false) + .eventFlushInterval(1000) + .build(); + + Map responses = new HashMap<>(); + responses.put("splitChanges", (uri, httpMethod, body) -> { + String since = getSinceFromUri(uri); + + if (since.equals("-1")) { + return new HttpResponseMock(200, loadSplitChangeWithSet(2)); + } else { + return new HttpResponseMock(200, IntegrationHelper.emptySplitChanges(1602796638344L, 1602796638344L)); + } + }); + + responses.put("mySegments/CUSTOMER_ID", (uri, httpMethod, body) -> new HttpResponseMock(200, IntegrationHelper.emptyMySegments())); + + HttpResponseMockDispatcher httpResponseMockDispatcher = IntegrationHelper.buildDispatcher(responses); + + SplitFactory factory = IntegrationHelper.buildFactory( + IntegrationHelper.dummyApiKey(), + IntegrationHelper.dummyUserKey(), + config, + mContext, + new HttpClientMock(httpResponseMockDispatcher), + splitRoomDatabase, null, null, null); + + CountDownLatch readyLatch = new CountDownLatch(1); + SplitClient client = factory.client(); + client.on(SplitEvent.SDK_READY, TestingHelper.testTask(readyLatch)); + + boolean readyAwait = readyLatch.await(5, TimeUnit.SECONDS); + + if (readyAwait) { + return client; + } else { + return null; + } + } + + private String loadSplitChangeWithSet(int setsCount) { + String change = fileHelper.loadFileContent(mContext, "split_changes_flag_set-" + setsCount + ".json"); + SplitChange parsedChange = Json.fromJson(change, SplitChange.class); + parsedChange.since = parsedChange.till; + + return Json.toJson(parsedChange); + } +} diff --git a/src/androidTest/java/tests/integration/sets/FlagSetsPollingTest.java b/src/androidTest/java/tests/integration/sets/FlagSetsPollingTest.java index dfc0a8b98..202fdf463 100644 --- a/src/androidTest/java/tests/integration/sets/FlagSetsPollingTest.java +++ b/src/androidTest/java/tests/integration/sets/FlagSetsPollingTest.java @@ -19,7 +19,6 @@ import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; import fake.HttpClientMock; import fake.HttpResponseMock; @@ -28,14 +27,11 @@ import helper.FileHelper; import helper.IntegrationHelper; import helper.TestableSplitConfigBuilder; -import io.split.android.client.SplitClient; import io.split.android.client.SplitClientConfig; import io.split.android.client.SplitFactory; import io.split.android.client.SplitFilter; import io.split.android.client.SyncConfig; import io.split.android.client.dtos.SplitChange; -import io.split.android.client.events.SplitEvent; -import io.split.android.client.events.SplitEventTask; import io.split.android.client.storage.db.SplitEntity; import io.split.android.client.storage.db.SplitRoomDatabase; import io.split.android.client.utils.Json; @@ -77,7 +73,7 @@ public void featureFlagIsUpdatedAccordingToSetsWhenTheyAreConfigured() throws IO -> it should be removed from storage */ - createFactory(mContext, mRoomDb, false, "set_1", "set_2"); + createFactory(mContext, mRoomDb, "set_1", "set_2"); boolean awaitFirst = firstChangeLatch.await(5, TimeUnit.SECONDS); Thread.sleep(200); @@ -122,7 +118,7 @@ public void featureFlagSetsAreIgnoredWhenSetsAreNotConfigured() throws IOExcepti -> that split should be updated. */ - createFactory(mContext, mRoomDb, false); + createFactory(mContext, mRoomDb); boolean awaitFirst = firstChangeLatch.await(5, TimeUnit.SECONDS); Thread.sleep(500); @@ -174,7 +170,6 @@ public void featureFlagSetsAreIgnoredWhenSetsAreNotConfigured() throws IOExcepti private SplitFactory createFactory( Context mContext, SplitRoomDatabase splitRoomDatabase, - boolean streamingEnabled, String... sets) throws IOException { SplitClientConfig config = new TestableSplitConfigBuilder() .ready(30000) @@ -186,7 +181,7 @@ private SplitFactory createFactory( .addSplitFilter(SplitFilter.bySet(Arrays.asList(sets))) .build()) .featuresRefreshRate(2) - .streamingEnabled(streamingEnabled) + .streamingEnabled(false) .eventFlushInterval(1000) .build();