From c7a80d7460ad20d1d4967a68429e7c54ad0df820 Mon Sep 17 00:00:00 2001 From: gthea Date: Wed, 7 Aug 2024 11:33:19 -0300 Subject: [PATCH] NONE fetch algorithm support (#686) --- .github/workflows/instrumented.yml | 2 +- .../client/dtos/MyLargeSegmentsResponse.java | 8 +-- .../notifications/HashingAlgorithm.java | 4 +- ...argeSegmentsNotificationProcessorImpl.java | 9 ++- .../mysegments/SyncDelayCalculator.java | 5 +- .../mysegments/SyncDelayCalculatorImpl.java | 10 +++- .../sseclient/RetryBackoffCounterTimer.java | 2 +- .../storage/TelemetryConfigProviderImpl.java | 20 +++++++ .../storage/TelemetryStatsProviderImpl.java | 16 ++++++ .../client/service/SplitTaskExecutorTest.java | 27 ++++----- .../sseclient/NotificationParserTest.java | 4 +- ...SegmentsNotificationProcessorImplTest.java | 11 ++-- .../mysegments/SyncDelayCalculatorTest.java | 57 ++++++++++++++++++- 13 files changed, 143 insertions(+), 32 deletions(-) diff --git a/.github/workflows/instrumented.yml b/.github/workflows/instrumented.yml index 65e760879..ace72e277 100644 --- a/.github/workflows/instrumented.yml +++ b/.github/workflows/instrumented.yml @@ -5,7 +5,7 @@ on: branches: - 'development' - 'master' - - '*_baseline' +# - '*_baseline' temporary disabled jobs: test: diff --git a/src/main/java/io/split/android/client/dtos/MyLargeSegmentsResponse.java b/src/main/java/io/split/android/client/dtos/MyLargeSegmentsResponse.java index 4b3fced4d..2365ad881 100644 --- a/src/main/java/io/split/android/client/dtos/MyLargeSegmentsResponse.java +++ b/src/main/java/io/split/android/client/dtos/MyLargeSegmentsResponse.java @@ -13,8 +13,8 @@ public class MyLargeSegmentsResponse { @SerializedName("myLargeSegments") private List myLargeSegments; - @SerializedName("changeNumber") - private Long changeNumber; + @SerializedName("till") + private Long till; @NonNull public List getMyLargeSegments() { @@ -23,7 +23,7 @@ public List getMyLargeSegments() { } @Nullable - public Long getChangeNumber() { - return changeNumber; + public Long getTill() { + return till; } } diff --git a/src/main/java/io/split/android/client/service/sseclient/notifications/HashingAlgorithm.java b/src/main/java/io/split/android/client/service/sseclient/notifications/HashingAlgorithm.java index 910e162b7..1b8049233 100644 --- a/src/main/java/io/split/android/client/service/sseclient/notifications/HashingAlgorithm.java +++ b/src/main/java/io/split/android/client/service/sseclient/notifications/HashingAlgorithm.java @@ -4,7 +4,9 @@ public enum HashingAlgorithm { @SerializedName("0") - MURMUR3_32, + NONE, @SerializedName("1") + MURMUR3_32, + @SerializedName("2") MURMUR3_64 } diff --git a/src/main/java/io/split/android/client/service/sseclient/notifications/mysegments/MyLargeSegmentsNotificationProcessorImpl.java b/src/main/java/io/split/android/client/service/sseclient/notifications/mysegments/MyLargeSegmentsNotificationProcessorImpl.java index 3b87a4a7d..e56c10536 100644 --- a/src/main/java/io/split/android/client/service/sseclient/notifications/mysegments/MyLargeSegmentsNotificationProcessorImpl.java +++ b/src/main/java/io/split/android/client/service/sseclient/notifications/mysegments/MyLargeSegmentsNotificationProcessorImpl.java @@ -40,8 +40,13 @@ public MyLargeSegmentsNotificationProcessorImpl(@NonNull NotificationParser noti } @Override - public void process(MyLargeSegmentChangeNotification notification) { - long syncDelay = mSyncDelayCalculator.calculateSyncDelay(mUserKey, notification.getUpdateIntervalMs(), notification.getAlgorithmSeed()); + public void process(@NonNull MyLargeSegmentChangeNotification notification) { + long syncDelay = mSyncDelayCalculator.calculateSyncDelay(mUserKey, + notification.getUpdateIntervalMs(), + notification.getAlgorithmSeed(), + notification.getUpdateStrategy(), + notification.getHashingAlgorithm()); + mProcessorHelper.processUpdate(notification.getUpdateStrategy(), notification.getData(), notification.getCompression(), diff --git a/src/main/java/io/split/android/client/service/sseclient/notifications/mysegments/SyncDelayCalculator.java b/src/main/java/io/split/android/client/service/sseclient/notifications/mysegments/SyncDelayCalculator.java index 677568c66..277da8178 100644 --- a/src/main/java/io/split/android/client/service/sseclient/notifications/mysegments/SyncDelayCalculator.java +++ b/src/main/java/io/split/android/client/service/sseclient/notifications/mysegments/SyncDelayCalculator.java @@ -1,5 +1,8 @@ package io.split.android.client.service.sseclient.notifications.mysegments; +import io.split.android.client.service.sseclient.notifications.HashingAlgorithm; +import io.split.android.client.service.sseclient.notifications.MySegmentUpdateStrategy; + interface SyncDelayCalculator { - long calculateSyncDelay(String mUserKey, Long updateIntervalMs, Integer algorithmSeed); + long calculateSyncDelay(String key, Long updateIntervalMs, Integer algorithmSeed, MySegmentUpdateStrategy updateStrategy, HashingAlgorithm hashingAlgorithm); } diff --git a/src/main/java/io/split/android/client/service/sseclient/notifications/mysegments/SyncDelayCalculatorImpl.java b/src/main/java/io/split/android/client/service/sseclient/notifications/mysegments/SyncDelayCalculatorImpl.java index df8116179..a6bf148a9 100644 --- a/src/main/java/io/split/android/client/service/sseclient/notifications/mysegments/SyncDelayCalculatorImpl.java +++ b/src/main/java/io/split/android/client/service/sseclient/notifications/mysegments/SyncDelayCalculatorImpl.java @@ -2,6 +2,8 @@ import java.util.concurrent.TimeUnit; +import io.split.android.client.service.sseclient.notifications.HashingAlgorithm; +import io.split.android.client.service.sseclient.notifications.MySegmentUpdateStrategy; import io.split.android.client.utils.MurmurHash3; class SyncDelayCalculatorImpl implements SyncDelayCalculator { @@ -9,7 +11,13 @@ class SyncDelayCalculatorImpl implements SyncDelayCalculator { public static final long DEFAULT_SYNC_INTERVAL_MS = TimeUnit.SECONDS.toMillis(60); @Override - public long calculateSyncDelay(String key, Long updateIntervalMs, Integer algorithmSeed) { + public long calculateSyncDelay(String key, Long updateIntervalMs, Integer algorithmSeed, MySegmentUpdateStrategy updateStrategy, HashingAlgorithm hashingAlgorithm) { + boolean fetchNotification = updateStrategy == MySegmentUpdateStrategy.UNBOUNDED_FETCH_REQUEST || + updateStrategy == MySegmentUpdateStrategy.BOUNDED_FETCH_REQUEST; + if (!fetchNotification || hashingAlgorithm == HashingAlgorithm.NONE) { + return 0L; + } + if (updateIntervalMs == null || updateIntervalMs <= 0) { updateIntervalMs = DEFAULT_SYNC_INTERVAL_MS; } diff --git a/src/main/java/io/split/android/client/service/sseclient/sseclient/RetryBackoffCounterTimer.java b/src/main/java/io/split/android/client/service/sseclient/sseclient/RetryBackoffCounterTimer.java index 5ace36864..79c14f699 100644 --- a/src/main/java/io/split/android/client/service/sseclient/sseclient/RetryBackoffCounterTimer.java +++ b/src/main/java/io/split/android/client/service/sseclient/sseclient/RetryBackoffCounterTimer.java @@ -28,7 +28,7 @@ public class RetryBackoffCounterTimer implements SplitTaskExecutionListener { private Long mInitialDelayInSeconds; private SplitTask mTask; private SplitTaskExecutionListener mListener; - private String mTaskId; + private volatile String mTaskId; /** * Creates an instance which retries tasks indefinitely, using the strategy defined by backoffCounter. diff --git a/src/main/java/io/split/android/client/telemetry/storage/TelemetryConfigProviderImpl.java b/src/main/java/io/split/android/client/telemetry/storage/TelemetryConfigProviderImpl.java index 047201faa..f486d2076 100644 --- a/src/main/java/io/split/android/client/telemetry/storage/TelemetryConfigProviderImpl.java +++ b/src/main/java/io/split/android/client/telemetry/storage/TelemetryConfigProviderImpl.java @@ -8,6 +8,8 @@ import static io.split.android.client.ServiceEndpoints.EndpointValidator.streamingEndpointIsOverridden; import static io.split.android.client.ServiceEndpoints.EndpointValidator.telemetryEndpointIsOverridden; +import android.os.Build; + import androidx.annotation.NonNull; import io.split.android.client.SplitClientConfig; @@ -15,6 +17,7 @@ import io.split.android.client.telemetry.model.Config; import io.split.android.client.telemetry.model.RefreshRates; import io.split.android.client.telemetry.model.UrlOverrides; +import io.split.android.client.utils.logger.Logger; public class TelemetryConfigProviderImpl implements TelemetryConfigProvider { @@ -36,6 +39,7 @@ public TelemetryConfigProviderImpl(@NonNull TelemetryStorageConsumer telemetryCo @Override public Config getConfigTelemetry() { Config config = new Config(); + addDefaultTags(mSplitClientConfig); config.setStreamingEnabled(mSplitClientConfig.streamingEnabled()); config.setRefreshRates(buildRefreshRates(mSplitClientConfig)); config.setTags(mTelemetryConsumer.popTags()); @@ -87,4 +91,20 @@ private UrlOverrides buildUrlOverrides(SplitClientConfig splitClientConfig) { return urlOverrides; } + + private void addDefaultTags(SplitClientConfig mSplitClientConfig) { + try { + TelemetryRuntimeProducer producer = (TelemetryRuntimeProducer) mTelemetryConsumer; + int sdkInt = Build.VERSION.SDK_INT; + if (sdkInt > 0) { + producer.addTag("av:" + sdkInt); + } + + if (mSplitClientConfig.synchronizeInBackground()) { + producer.addTag("bgr:" + mSplitClientConfig.backgroundSyncPeriod()); + } + } catch (ClassCastException ex) { + Logger.d("Telemetry storage is not a producer"); + } + } } diff --git a/src/main/java/io/split/android/client/telemetry/storage/TelemetryStatsProviderImpl.java b/src/main/java/io/split/android/client/telemetry/storage/TelemetryStatsProviderImpl.java index 06bd2f920..a7f2a2d1b 100644 --- a/src/main/java/io/split/android/client/telemetry/storage/TelemetryStatsProviderImpl.java +++ b/src/main/java/io/split/android/client/telemetry/storage/TelemetryStatsProviderImpl.java @@ -2,6 +2,8 @@ import static io.split.android.client.utils.Utils.checkNotNull; +import android.os.Build; + import androidx.annotation.NonNull; import io.split.android.client.storage.mysegments.MySegmentsStorageContainer; @@ -9,6 +11,7 @@ import io.split.android.client.telemetry.model.EventsDataRecordsEnum; import io.split.android.client.telemetry.model.ImpressionsDataType; import io.split.android.client.telemetry.model.Stats; +import io.split.android.client.utils.logger.Logger; public class TelemetryStatsProviderImpl implements TelemetryStatsProvider { @@ -49,6 +52,7 @@ public void clearStats() { private Stats buildStats() { Stats stats = new Stats(); + addDefaultTags(); stats.setStreamingEvents(mTelemetryStorageConsumer.popStreamingEvents()); stats.setSplitCount(mSplitsStorage.getAll().size()); @@ -74,4 +78,16 @@ private Stats buildStats() { return stats; } + + private void addDefaultTags() { + try { + TelemetryRuntimeProducer producer = (TelemetryRuntimeProducer) mTelemetryStorageConsumer; + int sdkInt = Build.VERSION.SDK_INT; + if (sdkInt > 0) { + producer.addTag("av:" + sdkInt); + } + } catch (ClassCastException ex) { + Logger.d("Telemetry storage is not a producer"); + } + } } diff --git a/src/test/java/io/split/android/client/service/SplitTaskExecutorTest.java b/src/test/java/io/split/android/client/service/SplitTaskExecutorTest.java index 90157d367..341150e1c 100644 --- a/src/test/java/io/split/android/client/service/SplitTaskExecutorTest.java +++ b/src/test/java/io/split/android/client/service/SplitTaskExecutorTest.java @@ -24,6 +24,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import io.split.android.client.service.executor.SplitTask; import io.split.android.client.service.executor.SplitTaskBatchItem; @@ -130,7 +131,7 @@ public void simpleScheduled() throws InterruptedException { latch.await(10, TimeUnit.SECONDS); Assert.assertTrue(task.taskHasBeenCalled); - Assert.assertEquals(4, task.callCount); + Assert.assertEquals(4, task.callCount.get()); } @Test @@ -152,7 +153,7 @@ public void multipleScheduled() throws InterruptedException { for (int i = 0; i < taskCount; i++) { Assert.assertTrue(taskList.get(i).taskHasBeenCalled); } - Assert.assertTrue(4 < taskList.get(0).callCount); + Assert.assertTrue(4 < taskList.get(0).callCount.get()); } @Test @@ -192,8 +193,8 @@ public void pauseScheduled() throws InterruptedException { mTaskExecutor.schedule( task1, 6L, 20, mock(SplitTaskExecutionListener.class)); latch.await(5, TimeUnit.SECONDS); - int countBeforePause = task.callCount; - int count1BeforePause = task1.callCount; + int countBeforePause = task.callCount.get(); + int count1BeforePause = task1.callCount.get(); mTaskExecutor.pause(); @@ -201,13 +202,13 @@ public void pauseScheduled() throws InterruptedException { // then resumes task executor // and wait for task 1 latch sleep(3); - int countAfterPause = task.callCount; - int count1AfterPause = task1.callCount; + int countAfterPause = task.callCount.get(); + int count1AfterPause = task1.callCount.get(); mTaskExecutor.resume(); latch1.await(5, TimeUnit.SECONDS); - int count1AfterResume = task1.callCount; + int count1AfterResume = task1.callCount.get(); Assert.assertEquals(3, countBeforePause); Assert.assertEquals(0, count1BeforePause); @@ -250,7 +251,7 @@ public void exceptionInScheduled() throws InterruptedException { latch.await(10, TimeUnit.SECONDS); Assert.assertTrue(task.taskHasBeenCalled); - Assert.assertEquals(4, task.callCount); + Assert.assertEquals(4, task.callCount.get()); } @Test @@ -278,7 +279,7 @@ public void stopStartedTask() throws InterruptedException { assertTrue(task.taskHasBeenCalled); assertTrue(testListener.taskExecutedCalled); - assertEquals(2, task.callCount); + assertEquals(2, task.callCount.get()); } @Test @@ -293,7 +294,7 @@ public void scheduleDelayedTask() throws InterruptedException { listenerLatch.await(2L, TimeUnit.SECONDS); assertTrue(task.taskHasBeenCalled); assertTrue(testListener.taskExecutedCalled); - assertEquals(1, task.callCount); + assertEquals(1, task.callCount.get()); } @Test @@ -314,7 +315,7 @@ public void schedulingAfterShutdown() throws InterruptedException { assertTrue(task.taskHasBeenCalled); assertTrue(testListener.taskExecutedCalled); - assertEquals(2, task.callCount); + assertEquals(2, task.callCount.get()); assertFalse(newTask.taskHasBeenCalled); } @@ -338,13 +339,13 @@ static class TestTask implements SplitTask { } public boolean shouldThrowException = false; - public int callCount = 0; + public AtomicInteger callCount = new AtomicInteger(0); public boolean taskHasBeenCalled = false; @NonNull @Override public SplitTaskExecutionInfo execute() { - callCount++; + callCount.incrementAndGet(); taskHasBeenCalled = true; latch.countDown(); if (shouldThrowException) { diff --git a/src/test/java/io/split/android/client/service/sseclient/NotificationParserTest.java b/src/test/java/io/split/android/client/service/sseclient/NotificationParserTest.java index efa24c481..7814db1db 100644 --- a/src/test/java/io/split/android/client/service/sseclient/NotificationParserTest.java +++ b/src/test/java/io/split/android/client/service/sseclient/NotificationParserTest.java @@ -46,7 +46,7 @@ public class NotificationParserTest { private final static String ERROR = "{\"id\":\"null\",\"name\":\"error\",\"comment\":\"[no comments]\",\"data\":\"{\\\"message\\\":\\\"Invalid token; capability must be a string\\\",\\\"code\\\":40144,\\\"statusCode\\\":400,\\\"href\\\":\\\"https://help.ably.io/error/40144\\\"}\"}"; - private static final String MY_LARGE_SEGMENTS_UPDATE = "{\"id\": \"diSrQttrC9:0:0\",\"clientId\": \"pri:MjcyNDE2NDUxMA==\",\"timestamp\": 1702507131100,\"encoding\": \"json\",\"channel\": \"NzM2MDI5Mzc0_MTc1MTYwODQxMQ==_mylargesegments\",\"data\": \"{\\\"type\\\":\\\"MY_LARGE_SEGMENT_UPDATE\\\",\\\"changeNumber\\\":1702507130121,\\\"largeSegments\\\":[\\\"android_test\\\"],\\\"c\\\":2,\\\"u\\\":2,\\\"d\\\":\\\"eJwEwLsRwzAMA9BdWKsg+IFBraJTkRXS5rK7388+tg+KdC8+jq4eBBQLFcUnO8FAAC36gndOSEyFqJFP32Vf2+f+3wAAAP//hUQQ9A==\\\",\\\"i\\\":100,\\\"h\\\":0,\\\"s\\\":325}\"}"; + private static final String MY_LARGE_SEGMENTS_UPDATE = "{\"id\": \"diSrQttrC9:0:0\",\"clientId\": \"pri:MjcyNDE2NDUxMA==\",\"timestamp\": 1702507131100,\"encoding\": \"json\",\"channel\": \"NzM2MDI5Mzc0_MTc1MTYwODQxMQ==_mylargesegments\",\"data\": \"{\\\"type\\\":\\\"MY_LARGE_SEGMENT_UPDATE\\\",\\\"changeNumber\\\":1702507130121,\\\"largeSegments\\\":[\\\"android_test\\\"],\\\"c\\\":2,\\\"u\\\":2,\\\"d\\\":\\\"eJwEwLsRwzAMA9BdWKsg+IFBraJTkRXS5rK7388+tg+KdC8+jq4eBBQLFcUnO8FAAC36gndOSEyFqJFP32Vf2+f+3wAAAP//hUQQ9A==\\\",\\\"i\\\":100,\\\"h\\\":1,\\\"s\\\":325}\"}"; @Before public void setup() { @@ -170,7 +170,7 @@ public void parseMyLargeSegmentsIncomingNotification() { IncomingNotification incoming = mParser.parseIncoming(MY_LARGE_SEGMENTS_UPDATE); assertEquals(MY_LARGE_SEGMENT_UPDATE, incoming.getType()); - assertEquals("{\"type\":\"MY_LARGE_SEGMENT_UPDATE\",\"changeNumber\":1702507130121,\"largeSegments\":[\"android_test\"],\"c\":2,\"u\":2,\"d\":\"eJwEwLsRwzAMA9BdWKsg+IFBraJTkRXS5rK7388+tg+KdC8+jq4eBBQLFcUnO8FAAC36gndOSEyFqJFP32Vf2+f+3wAAAP//hUQQ9A==\",\"i\":100,\"h\":0,\"s\":325}", incoming.getJsonData()); + assertEquals("{\"type\":\"MY_LARGE_SEGMENT_UPDATE\",\"changeNumber\":1702507130121,\"largeSegments\":[\"android_test\"],\"c\":2,\"u\":2,\"d\":\"eJwEwLsRwzAMA9BdWKsg+IFBraJTkRXS5rK7388+tg+KdC8+jq4eBBQLFcUnO8FAAC36gndOSEyFqJFP32Vf2+f+3wAAAP//hUQQ9A==\",\"i\":100,\"h\":1,\"s\":325}", incoming.getJsonData()); assertEquals("NzM2MDI5Mzc0_MTc1MTYwODQxMQ==_mylargesegments", incoming.getChannel()); assertEquals(1702507131100L, incoming.getTimestamp()); } diff --git a/src/test/java/io/split/android/client/service/sseclient/notifications/mysegments/MyLargeSegmentsNotificationProcessorImplTest.java b/src/test/java/io/split/android/client/service/sseclient/notifications/mysegments/MyLargeSegmentsNotificationProcessorImplTest.java index 34196a7d1..632c3a951 100644 --- a/src/test/java/io/split/android/client/service/sseclient/notifications/mysegments/MyLargeSegmentsNotificationProcessorImplTest.java +++ b/src/test/java/io/split/android/client/service/sseclient/notifications/mysegments/MyLargeSegmentsNotificationProcessorImplTest.java @@ -1,6 +1,5 @@ package io.split.android.client.service.sseclient.notifications.mysegments; -import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -13,6 +12,7 @@ import java.util.concurrent.BlockingQueue; import io.split.android.client.common.CompressionType; +import io.split.android.client.service.sseclient.notifications.HashingAlgorithm; import io.split.android.client.service.sseclient.notifications.MyLargeSegmentChangeNotification; import io.split.android.client.service.sseclient.notifications.MySegmentUpdateStrategy; @@ -40,11 +40,12 @@ public void processDelegatesToHelper() { MyLargeSegmentChangeNotification notification = mock(MyLargeSegmentChangeNotification.class); when(notification.getCompression()).thenReturn(CompressionType.GZIP); when(notification.getData()).thenReturn("dummy"); + when(notification.getHashingAlgorithm()).thenReturn(HashingAlgorithm.MURMUR3_32); when(notification.getLargeSegments()).thenReturn(new HashSet<>(Arrays.asList("segment1", "segment2"))); when(notification.getUpdateIntervalMs()).thenReturn(1000L); when(notification.getAlgorithmSeed()).thenReturn(1234); when(notification.getUpdateStrategy()).thenReturn(MySegmentUpdateStrategy.BOUNDED_FETCH_REQUEST); - when(mSyncDelayCalculator.calculateSyncDelay("key", 1000L, 1234)).thenReturn(25L); + when(mSyncDelayCalculator.calculateSyncDelay("key", 1000L, 1234, MySegmentUpdateStrategy.BOUNDED_FETCH_REQUEST, HashingAlgorithm.MURMUR3_32)).thenReturn(25L); mNotificationProcessor.process(notification); @@ -61,10 +62,12 @@ public void delayIsCalculatedWithCalculator() { MyLargeSegmentChangeNotification notification = mock(MyLargeSegmentChangeNotification.class); when(notification.getUpdateIntervalMs()).thenReturn(1000L); when(notification.getAlgorithmSeed()).thenReturn(1234); - when(mSyncDelayCalculator.calculateSyncDelay("key", 1000L, 1234)).thenReturn(25L); + when(notification.getUpdateStrategy()).thenReturn(MySegmentUpdateStrategy.UNBOUNDED_FETCH_REQUEST); + when(notification.getHashingAlgorithm()).thenReturn(HashingAlgorithm.MURMUR3_32); + when(mSyncDelayCalculator.calculateSyncDelay("key", 1000L, 1234, MySegmentUpdateStrategy.UNBOUNDED_FETCH_REQUEST, HashingAlgorithm.MURMUR3_32)).thenReturn(25L); mNotificationProcessor.process(notification); - verify(mSyncDelayCalculator).calculateSyncDelay("key", 1000L, 1234); + verify(mSyncDelayCalculator).calculateSyncDelay("key", 1000L, 1234, MySegmentUpdateStrategy.UNBOUNDED_FETCH_REQUEST, HashingAlgorithm.MURMUR3_32); } } diff --git a/src/test/java/io/split/android/client/service/sseclient/notifications/mysegments/SyncDelayCalculatorTest.java b/src/test/java/io/split/android/client/service/sseclient/notifications/mysegments/SyncDelayCalculatorTest.java index cd99d18e5..405caa988 100644 --- a/src/test/java/io/split/android/client/service/sseclient/notifications/mysegments/SyncDelayCalculatorTest.java +++ b/src/test/java/io/split/android/client/service/sseclient/notifications/mysegments/SyncDelayCalculatorTest.java @@ -1,27 +1,80 @@ package io.split.android.client.service.sseclient.notifications.mysegments; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import org.junit.Test; import java.util.Random; +import io.split.android.client.service.sseclient.notifications.HashingAlgorithm; +import io.split.android.client.service.sseclient.notifications.MySegmentUpdateStrategy; + public class SyncDelayCalculatorTest { @Test public void delayIsNotLowerThan0() { SyncDelayCalculator calculator = new SyncDelayCalculatorImpl(); - long delay = calculator.calculateSyncDelay(getRandomString(), 600L, 1525); + long delay = calculator.calculateSyncDelay(getRandomString(), 600L, 1525, MySegmentUpdateStrategy.UNBOUNDED_FETCH_REQUEST, HashingAlgorithm.MURMUR3_32); assertTrue(delay >= 0); } @Test public void delayIsNotHigherThanUpdateInterval() { SyncDelayCalculator calculator = new SyncDelayCalculatorImpl(); - long delay = calculator.calculateSyncDelay(getRandomString(), 600L, 24515); + long delay = calculator.calculateSyncDelay(getRandomString(), 600L, 24515, MySegmentUpdateStrategy.BOUNDED_FETCH_REQUEST, HashingAlgorithm.MURMUR3_32); assertTrue(delay <= 600L); } + @Test + public void delayIsZeroWhenUpdateStrategyIsKeyList() { + SyncDelayCalculator calculator = new SyncDelayCalculatorImpl(); + long delay = calculator.calculateSyncDelay(getRandomString(), 600L, 24515, MySegmentUpdateStrategy.KEY_LIST, HashingAlgorithm.MURMUR3_32); + assertEquals(0, delay); + } + + @Test + public void delayIsZeroWhenUpdateStrategyIsSegmentRemoval() { + SyncDelayCalculator calculator = new SyncDelayCalculatorImpl(); + long delay = calculator.calculateSyncDelay(getRandomString(), 600L, 24515, MySegmentUpdateStrategy.SEGMENT_REMOVAL, HashingAlgorithm.MURMUR3_32); + assertEquals(0, delay); + } + + @Test + public void delayIsZeroWhenHashingAlgorithmIsNone() { + SyncDelayCalculator calculator = new SyncDelayCalculatorImpl(); + long delay = calculator.calculateSyncDelay(getRandomString(), 600L, 24515, MySegmentUpdateStrategy.BOUNDED_FETCH_REQUEST, HashingAlgorithm.NONE); + assertEquals(0, delay); + } + + @Test + public void delayIsLessThanSixtyMsWhenUpdateIntervalIsNull() { + SyncDelayCalculator calculator = new SyncDelayCalculatorImpl(); + long delay = calculator.calculateSyncDelay(getRandomString(), null, 24515, MySegmentUpdateStrategy.BOUNDED_FETCH_REQUEST, HashingAlgorithm.MURMUR3_32); + assertTrue(delay <= 60000); + } + + @Test + public void delayIsLessThanSixtyMsWhenUpdateIntervalIsZero() { + SyncDelayCalculator calculator = new SyncDelayCalculatorImpl(); + long delay = calculator.calculateSyncDelay(getRandomString(), 0L, 24515, MySegmentUpdateStrategy.BOUNDED_FETCH_REQUEST, HashingAlgorithm.MURMUR3_32); + assertTrue(delay <= 60000); + } + + @Test + public void delayIsLessThanSixtyMsWhenUpdateIntervalIsNegative() { + SyncDelayCalculator calculator = new SyncDelayCalculatorImpl(); + long delay = calculator.calculateSyncDelay(getRandomString(), -1L, 24515, MySegmentUpdateStrategy.BOUNDED_FETCH_REQUEST, HashingAlgorithm.MURMUR3_32); + assertTrue(delay <= 60000); + } + + @Test + public void delayIsCalculatedWithNullSeed() { + SyncDelayCalculator calculator = new SyncDelayCalculatorImpl(); + long delay = calculator.calculateSyncDelay(getRandomString(), 1L, null, MySegmentUpdateStrategy.BOUNDED_FETCH_REQUEST, HashingAlgorithm.MURMUR3_32); + assertTrue(delay >= 0 && delay <= 1); + } + private String getRandomString() { return String.valueOf(new Random().nextInt()); }