From 85474a9187a25971d34151e05fcc01ad04d07a1d Mon Sep 17 00:00:00 2001 From: Gaston Thea Date: Mon, 13 Nov 2023 17:32:30 -0300 Subject: [PATCH] Prefix config & prefix in db name --- .../helper/TestableSplitConfigBuilder.java | 10 +- .../android/client/SplitClientConfig.java | 19 +++- .../android/client/SplitFactoryHelper.java | 13 ++- .../android/client/SplitFactoryHelperTest.kt | 94 ++++++++++++++++++- 4 files changed, 128 insertions(+), 8 deletions(-) diff --git a/src/androidTest/java/helper/TestableSplitConfigBuilder.java b/src/androidTest/java/helper/TestableSplitConfigBuilder.java index ac73eaaee..2493b7d67 100644 --- a/src/androidTest/java/helper/TestableSplitConfigBuilder.java +++ b/src/androidTest/java/helper/TestableSplitConfigBuilder.java @@ -60,6 +60,8 @@ public class TestableSplitConfigBuilder { private long mDefaultSSEConnectionDelayInSecs = ServiceConstants.DEFAULT_SSE_CONNECTION_DELAY_SECS; private long mSSEDisconnectionDelayInSecs = 60L; + private String mPrefix = ""; + public TestableSplitConfigBuilder() { mServiceEndpoints = ServiceEndpoints.builder().build(); } @@ -249,6 +251,11 @@ public TestableSplitConfigBuilder sseDisconnectionDelayInSecs(long seconds) { return this; } + public TestableSplitConfigBuilder prefix(String prefix) { + this.mPrefix = prefix; + return this; + } + public SplitClientConfig build() { Constructor constructor = SplitClientConfig.class.getDeclaredConstructors()[0]; constructor.setAccessible(true); @@ -300,7 +307,8 @@ public SplitClientConfig build() { mUserConsent, mEncryptionEnabled, mDefaultSSEConnectionDelayInSecs, - mSSEDisconnectionDelayInSecs); + mSSEDisconnectionDelayInSecs, + mPrefix); return config; } catch (Exception e) { Logger.e("Error creating Testable Split client builder: " diff --git a/src/main/java/io/split/android/client/SplitClientConfig.java b/src/main/java/io/split/android/client/SplitClientConfig.java index 22f79f417..62ab1c577 100644 --- a/src/main/java/io/split/android/client/SplitClientConfig.java +++ b/src/main/java/io/split/android/client/SplitClientConfig.java @@ -117,6 +117,7 @@ public class SplitClientConfig { private int mLogLevel = SplitLogLevel.NONE; private UserConsent mUserConsent; private boolean mEncryptionEnabled = false; + private final String mPrefix; private final long mDefaultSSEConnectionDelayInSecs; private final long mSSEDisconnectionDelayInSecs; @@ -172,7 +173,8 @@ private SplitClientConfig(String endpoint, UserConsent userConsent, boolean encryptionEnabled, long defaultSSEConnectionDelayInSecs, - long sseDisconnectionDelayInSecs) { + long sseDisconnectionDelayInSecs, + String prefix) { mEndpoint = endpoint; mEventsEndpoint = eventsEndpoint; mTelemetryEndpoint = telemetryEndpoint; @@ -226,6 +228,7 @@ private SplitClientConfig(String endpoint, mEncryptionEnabled = encryptionEnabled; mDefaultSSEConnectionDelayInSecs = defaultSSEConnectionDelayInSecs; mSSEDisconnectionDelayInSecs = sseDisconnectionDelayInSecs; + mPrefix = prefix; Logger.instance().setLevel(mLogLevel); } @@ -350,6 +353,10 @@ String defaultDataFolder() { return DEFAULT_DATA_FOLDER; } + String prefix() { + return mPrefix; + } + public String ip() { return mIp; } @@ -521,6 +528,8 @@ public static final class Builder { private final long mSSEDisconnectionDelayInSecs = 60L; + private String mPrefix = ""; + public Builder() { mServiceEndpoints = ServiceEndpoints.builder().build(); } @@ -1022,6 +1031,11 @@ public Builder encryptionEnabled(boolean enabled) { return this; } + public Builder prefix(String prefix) { + mPrefix = (prefix == null) ? "" : prefix.trim(); + return this; + } + public SplitClientConfig build() { @@ -1127,7 +1141,8 @@ public SplitClientConfig build() { mUserConsent, mEncryptionEnabled, mDefaultSSEConnectionDelayInSecs, - mSSEDisconnectionDelayInSecs); + mSSEDisconnectionDelayInSecs, + mPrefix); } private HttpProxy parseProxyHost(String proxyUri) { diff --git a/src/main/java/io/split/android/client/SplitFactoryHelper.java b/src/main/java/io/split/android/client/SplitFactoryHelper.java index 4550db1ab..386876c3b 100644 --- a/src/main/java/io/split/android/client/SplitFactoryHelper.java +++ b/src/main/java/io/split/android/client/SplitFactoryHelper.java @@ -99,13 +99,20 @@ String getDatabaseName(SplitClientConfig config, String apiToken, Context contex } private String buildDatabaseName(SplitClientConfig config, String apiToken) { - int apiTokenLength = apiToken.length(); + if (apiToken == null) { + throw new IllegalArgumentException("SDK key cannot be null"); + } + + final int apiTokenLength = apiToken.length(); + final String prefix = (config.prefix() == null) ? "" : config.prefix(); + if (apiTokenLength > DB_MAGIC_CHARS_COUNT) { String begin = apiToken.substring(0, DB_MAGIC_CHARS_COUNT); String end = apiToken.substring(apiTokenLength - DB_MAGIC_CHARS_COUNT); - return begin + end; + return prefix + begin + end; } - return config.defaultDataFolder(); + + return prefix + config.defaultDataFolder(); } private String buildLegacyDatabaseName(SplitClientConfig splitClientConfig, String apiToken) { diff --git a/src/test/java/io/split/android/client/SplitFactoryHelperTest.kt b/src/test/java/io/split/android/client/SplitFactoryHelperTest.kt index e79858464..c1c55d395 100644 --- a/src/test/java/io/split/android/client/SplitFactoryHelperTest.kt +++ b/src/test/java/io/split/android/client/SplitFactoryHelperTest.kt @@ -1,35 +1,52 @@ package io.split.android.client +import android.content.Context import io.split.android.client.service.executor.SplitTaskExecutionListener import io.split.android.client.service.executor.SplitTaskExecutor import io.split.android.client.storage.cipher.EncryptionMigrationTask import io.split.android.client.storage.db.SplitRoomDatabase +import junit.framework.TestCase.assertEquals +import org.junit.After import org.junit.Before import org.junit.Test import org.mockito.Mock +import org.mockito.Mockito import org.mockito.Mockito.argThat +import org.mockito.Mockito.mock import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations +import java.io.File +import java.lang.IllegalArgumentException class SplitFactoryHelperTest { + private lateinit var mocks: AutoCloseable + @Mock private lateinit var splitRoomDatabase: SplitRoomDatabase @Mock private lateinit var splitTaskExecutor: SplitTaskExecutor @Mock private lateinit var taskListener: SplitTaskExecutionListener + @Mock + private lateinit var context: Context private lateinit var helper: SplitFactoryHelper @Before fun setup() { - MockitoAnnotations.openMocks(this) + mocks = MockitoAnnotations.openMocks(this) helper = SplitFactoryHelper() } + @After + fun tearDown() { + mocks.close() + } + @Test - fun testMigrateEncryption() { + fun migrateEncryption() { helper.migrateEncryption( "abcdedfghijklmnopqrstuvwxyz", @@ -43,4 +60,77 @@ class SplitFactoryHelperTest { argThat { it is EncryptionMigrationTask }, argThat { it?.equals(taskListener) == true }) } + + @Test + fun generateDatabaseNameWithoutPrefixAndKeyLongerThan4() { + val path = mock(File::class.java) + `when`(path.exists()).thenReturn(true) + `when`(context.getDatabasePath(Mockito.anyString())).thenReturn(path) + val databaseName = helper.getDatabaseName( + SplitClientConfig.builder().build(), + "abcdedfghijklmnopqrstuvwxyz", + context + ) + + assertEquals("abcdwxyz", databaseName) + } + + @Test + fun generateDatabaseNameWithoutPrefixAndKeyShorterThan4() { + val path = mock(File::class.java) + `when`(path.exists()).thenReturn(true) + `when`(context.getDatabasePath(Mockito.anyString())).thenReturn(path) + val databaseName = helper.getDatabaseName( + SplitClientConfig.builder().build(), + "abc", + context + ) + + assertEquals("split_data", databaseName) + } + + @Test + fun generateDatabaseNameWithPrefixAndKeyLongerThan4() { + val path = mock(File::class.java) + `when`(path.exists()).thenReturn(true) + `when`(context.getDatabasePath(Mockito.anyString())).thenReturn(path) + val databaseName = helper.getDatabaseName( + SplitClientConfig.builder().prefix("mydb").build(), + "abcdedfghijklmnopqrstuvwxyz", + context + ) + + assertEquals("mydbabcdwxyz", databaseName) + } + + @Test + fun generateDatabaseNameWithPrefixAndKeyShorterThan4() { + val path = mock(File::class.java) + `when`(path.exists()).thenReturn(true) + `when`(context.getDatabasePath(Mockito.anyString())).thenReturn(path) + val databaseName = helper.getDatabaseName( + SplitClientConfig.builder().prefix("mydb").build(), + "abc", + context + ) + + assertEquals("mydbsplit_data", databaseName) + } + + @Test + fun generateDatabaseNameWithNullKeyThrowsIllegalArgumentException() { + val path = mock(File::class.java) + `when`(path.exists()).thenReturn(true) + `when`(context.getDatabasePath(Mockito.anyString())).thenReturn(path) + + try { + helper.getDatabaseName( + SplitClientConfig.builder().build(), + null, + context + ) + } catch (e: IllegalArgumentException) { + assertEquals("SDK key cannot be null", e.message) + } + } }