Skip to content

Commit 2e75298

Browse files
authored
Refactor cipher creation (#501)
1 parent 22007d0 commit 2e75298

File tree

6 files changed

+38
-149
lines changed

6 files changed

+38
-149
lines changed

README.md

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# Split SDK for Android
2-
![Build Status](https://github.com/splitio/android-client/actions/workflows/sonar.yml/badge.svg?branch=master)
32

43
## Overview
54
This SDK is designed to work with Split, the platform for controlled rollouts, which serves features to your users via feature flags to manage your complete customer experience.

src/main/java/io/split/android/client/SplitFactoryHelper.java

+7-14
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@
6565
import io.split.android.client.shared.UserConsent;
6666
import io.split.android.client.storage.cipher.EncryptionMigrationTask;
6767
import io.split.android.client.storage.cipher.SplitCipher;
68+
import io.split.android.client.storage.cipher.SplitCipherFactory;
69+
import io.split.android.client.storage.cipher.SplitEncryptionLevel;
6870
import io.split.android.client.storage.common.SplitStorageContainer;
6971
import io.split.android.client.storage.attributes.PersistentAttributesStorage;
7072
import io.split.android.client.storage.db.SplitRoomDatabase;
@@ -135,7 +137,6 @@ Map<String, String> buildStreamingHeaders(String apiToken) {
135137

136138
SplitStorageContainer buildStorageContainer(UserConsent userConsentStatus,
137139
SplitRoomDatabase splitRoomDatabase,
138-
Key key,
139140
boolean shouldRecordTelemetry,
140141
SplitCipher splitCipher,
141142
TelemetryStorage telemetryStorage) {
@@ -370,34 +371,26 @@ public ProcessStrategy getImpressionStrategy(SplitTaskExecutor splitTaskExecutor
370371
config.userConsent() == UserConsent.GRANTED).getStrategy(config.impressionsMode());
371372
}
372373

373-
@NonNull
374374
SplitCipher migrateEncryption(String apiKey,
375375
SplitRoomDatabase splitDatabase,
376376
SplitTaskExecutor splitTaskExecutor,
377377
ISplitEventsManager eventsManager,
378378
final boolean encryptionEnabled) {
379-
AtomicReference<SplitCipher> splitCipher = new AtomicReference<>(null);
380-
CountDownLatch cipherLatch = new CountDownLatch(1);
381379

380+
SplitCipher toCipher = SplitCipherFactory.create(apiKey, encryptionEnabled ? SplitEncryptionLevel.AES_128_CBC :
381+
SplitEncryptionLevel.NONE);
382382
splitTaskExecutor.submit(new EncryptionMigrationTask(apiKey,
383383
splitDatabase,
384-
splitCipher,
385-
cipherLatch,
386-
encryptionEnabled),
384+
encryptionEnabled,
385+
toCipher),
387386
new SplitTaskExecutionListener() {
388387
@Override
389388
public void taskExecuted(@NonNull SplitTaskExecutionInfo taskInfo) {
390389
eventsManager.notifyInternalEvent(SplitInternalEvent.ENCRYPTION_MIGRATION_DONE);
391390
}
392391
});
393392

394-
try {
395-
cipherLatch.await(2, TimeUnit.SECONDS);
396-
} catch (InterruptedException ignored) {
397-
398-
}
399-
400-
return splitCipher.get();
393+
return toCipher;
401394
}
402395

403396
private TelemetryStorage getTelemetryStorage(boolean shouldRecordTelemetry, TelemetryStorage telemetryStorage) {

src/main/java/io/split/android/client/SplitFactoryImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ private SplitFactoryImpl(String apiToken, Key key, SplitClientConfig config,
152152
config.encryptionEnabled());
153153

154154
mStorageContainer = factoryHelper.buildStorageContainer(config.userConsent(),
155-
splitDatabase, key, config.shouldRecordTelemetry(), splitCipher, telemetryStorage);
155+
splitDatabase, config.shouldRecordTelemetry(), splitCipher, telemetryStorage);
156156

157157
String splitsFilterQueryString = factoryHelper.buildSplitsFilterQueryString(config);
158158

src/main/java/io/split/android/client/storage/cipher/EncryptionMigrationTask.java

+5-15
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,17 @@ public class EncryptionMigrationTask implements SplitTask {
1919

2020
private final String mApiKey;
2121
private final SplitRoomDatabase mSplitDatabase;
22-
private final AtomicReference<SplitCipher> mSplitCipher;
2322
private final boolean mEncryptionEnabled;
24-
private final CountDownLatch mCountDownLatch;
23+
private final SplitCipher mToCipher;
2524

2625
public EncryptionMigrationTask(String apiKey,
2726
SplitRoomDatabase splitDatabase,
28-
AtomicReference<SplitCipher> splitCipher,
29-
CountDownLatch countDownLatch,
30-
boolean encryptionEnabled) {
27+
boolean encryptionEnabled,
28+
SplitCipher toCipher) {
3129
mApiKey = checkNotNull(apiKey);
3230
mSplitDatabase = checkNotNull(splitDatabase);
33-
mSplitCipher = checkNotNull(splitCipher);
34-
mCountDownLatch = checkNotNull(countDownLatch);
3531
mEncryptionEnabled = encryptionEnabled;
32+
mToCipher = checkNotNull(toCipher);
3633
}
3734

3835
@NonNull
@@ -45,15 +42,8 @@ public SplitTaskExecutionInfo execute() {
4542
// Determine target encryption level
4643
SplitEncryptionLevel toLevel = getLevel(mEncryptionEnabled);
4744

48-
// Create target level cipher
49-
SplitCipher toCipher = SplitCipherFactory.create(mApiKey, toLevel);
50-
51-
// Return cipher to be used by the SDK
52-
mSplitCipher.set(toCipher);
53-
mCountDownLatch.countDown();
54-
5545
// Apply encryption
56-
new DBCipher(mApiKey, mSplitDatabase, fromLevel, toLevel, toCipher).apply();
46+
new DBCipher(mApiKey, mSplitDatabase, fromLevel, toLevel, mToCipher).apply();
5747

5848
// Update encryption level
5949
updateCurrentLevel(toLevel);

src/main/java/io/split/android/client/storage/cipher/SplitEncryptionLevel.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import androidx.annotation.NonNull;
44

5-
enum SplitEncryptionLevel {
5+
public enum SplitEncryptionLevel {
66

77
/**
88
* AES 128 CBC.

src/test/java/io/split/android/client/storage/cipher/EncryptionMigrationTaskTest.kt

+24-117
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,28 @@ import org.junit.Before
1010
import org.junit.Test
1111
import org.mockito.ArgumentMatchers.any
1212
import org.mockito.ArgumentMatchers.argThat
13-
import org.mockito.ArgumentMatchers.eq
1413
import org.mockito.Mock
15-
import org.mockito.Mockito.mockStatic
1614
import org.mockito.Mockito.verify
1715
import org.mockito.Mockito.`when`
1816
import org.mockito.MockitoAnnotations
19-
import java.util.concurrent.CountDownLatch
20-
import java.util.concurrent.atomic.AtomicReference
2117

2218

2319
class EncryptionMigrationTaskTest {
2420

2521
private val mApiKey: String = "abcdedfghijklmnopqrstuvwxyz"
22+
2623
@Mock
2724
private lateinit var mSplitDatabase: SplitRoomDatabase
25+
2826
@Mock
2927
private lateinit var mGeneralInfoDao: GeneralInfoDao
30-
@Mock
31-
private lateinit var mSplitCipherReference: AtomicReference<SplitCipher>
32-
@Mock
33-
private lateinit var mFromCipher: SplitCipher
28+
3429
@Mock
3530
private lateinit var mToCipher: SplitCipher
36-
private lateinit var mCountDownLatch: CountDownLatch
3731

3832
@Before
3933
fun setUp() {
4034
MockitoAnnotations.openMocks(this)
41-
mCountDownLatch = CountDownLatch(1)
4235
`when`(mSplitDatabase.generalInfoDao()).thenReturn(mGeneralInfoDao)
4336
}
4437

@@ -47,9 +40,8 @@ class EncryptionMigrationTaskTest {
4740
val encryptionMigrationTask = EncryptionMigrationTask(
4841
mApiKey,
4942
mSplitDatabase,
50-
mSplitCipherReference,
51-
mCountDownLatch,
52-
false
43+
false,
44+
mToCipher
5345
)
5446
`when`(mGeneralInfoDao.getByName("databaseEncryptionMode")).thenReturn(
5547
GeneralInfoEntity(
@@ -68,106 +60,30 @@ class EncryptionMigrationTaskTest {
6860
val encryptionMigrationTask = EncryptionMigrationTask(
6961
mApiKey,
7062
mSplitDatabase,
71-
mSplitCipherReference,
72-
mCountDownLatch,
73-
true
63+
true,
64+
mToCipher
7465
)
7566

76-
mockStatic(SplitCipherFactory::class.java).use { mock ->
77-
mock.`when`<Any> {
78-
SplitCipherFactory.create(
79-
any(), eq(SplitEncryptionLevel.AES_128_CBC)
80-
)
81-
}.thenReturn(mToCipher)
82-
83-
encryptionMigrationTask.execute()
67+
encryptionMigrationTask.execute()
8468

85-
mock.verify { SplitCipherFactory.create(mApiKey, SplitEncryptionLevel.AES_128_CBC) }
86-
}
69+
verify(mGeneralInfoDao).update(argThat { entity ->
70+
entity.name == "databaseEncryptionMode" && entity.stringValue == "AES_128_CBC"
71+
})
8772
}
8873

8974
@Test
9075
fun targetEncryptionLevelIsDeterminedWithEncryptionDisabledProperty() {
9176
val encryptionMigrationTask = EncryptionMigrationTask(
9277
mApiKey,
9378
mSplitDatabase,
94-
mSplitCipherReference,
95-
mCountDownLatch,
96-
false
97-
)
98-
99-
mockStatic(SplitCipherFactory::class.java).use { mock ->
100-
mock.`when`<Any> {
101-
SplitCipherFactory.create(
102-
any(), eq(SplitEncryptionLevel.NONE)
103-
)
104-
}.thenReturn(mToCipher)
105-
106-
encryptionMigrationTask.execute()
107-
108-
mock.verify { SplitCipherFactory.create(mApiKey, SplitEncryptionLevel.NONE) }
109-
}
110-
}
111-
112-
@Test
113-
fun toCipherIsSetToCipherReference() {
114-
val encryptionMigrationTask = EncryptionMigrationTask(
115-
mApiKey,
116-
mSplitDatabase,
117-
mSplitCipherReference,
118-
mCountDownLatch,
119-
false
79+
false,
80+
mToCipher
12081
)
12182

122-
mockStatic(SplitCipherFactory::class.java).use { mock ->
123-
mock.`when`<Any> {
124-
SplitCipherFactory.create(
125-
any(), eq(SplitEncryptionLevel.NONE)
126-
)
127-
}.thenReturn(mToCipher)
128-
129-
encryptionMigrationTask.execute()
130-
131-
verify(mSplitCipherReference).set(mToCipher)
132-
}
133-
}
134-
135-
@Test
136-
fun countDownLatchIsCountedDownAfterReferenceIsSet() {
137-
val encryptionMigrationTask = EncryptionMigrationTask(
138-
mApiKey,
139-
mSplitDatabase,
140-
mSplitCipherReference,
141-
mCountDownLatch,
142-
true
143-
)
144-
145-
mockStatic(SplitCipherFactory::class.java).use { mock ->
146-
mock.`when`<Any> {
147-
SplitCipherFactory.create(
148-
any(), eq(SplitEncryptionLevel.AES_128_CBC)
149-
)
150-
}.thenReturn(mToCipher)
151-
152-
encryptionMigrationTask.execute()
153-
154-
verify(mSplitCipherReference).set(mToCipher)
155-
assertEquals(0L, mCountDownLatch.count)
156-
}
157-
}
158-
159-
@Test
160-
fun levelIsUpdatedInGeneralInfo() {
161-
EncryptionMigrationTask(
162-
mApiKey,
163-
mSplitDatabase,
164-
mSplitCipherReference,
165-
mCountDownLatch,
166-
true
167-
).execute()
83+
encryptionMigrationTask.execute()
16884

169-
verify(mGeneralInfoDao).update(argThat {
170-
it.name == "databaseEncryptionMode" && it.stringValue == "AES_128_CBC"
85+
verify(mGeneralInfoDao).update(argThat { entity ->
86+
entity.name == "databaseEncryptionMode" && entity.stringValue == "NONE"
17187
})
17288
}
17389

@@ -176,9 +92,8 @@ class EncryptionMigrationTaskTest {
17692
val encryptionMigrationTask = EncryptionMigrationTask(
17793
mApiKey,
17894
mSplitDatabase,
179-
mSplitCipherReference,
180-
mCountDownLatch,
181-
true
95+
true,
96+
mToCipher
18297
)
18398

18499
val taskInfo = encryptionMigrationTask.execute()
@@ -192,22 +107,14 @@ class EncryptionMigrationTaskTest {
192107
val encryptionMigrationTask = EncryptionMigrationTask(
193108
mApiKey,
194109
mSplitDatabase,
195-
mSplitCipherReference,
196-
mCountDownLatch,
197-
true
110+
true,
111+
mToCipher
198112
)
113+
`when`(mGeneralInfoDao.update(any())).thenThrow(RuntimeException())
199114

200-
mockStatic(SplitCipherFactory::class.java).use { mock ->
201-
mock.`when`<Any> {
202-
SplitCipherFactory.create(
203-
any(), eq(SplitEncryptionLevel.AES_128_CBC)
204-
)
205-
}.thenThrow(RuntimeException("Test exception"))
206-
207-
val taskInfo = encryptionMigrationTask.execute()
115+
val taskInfo = encryptionMigrationTask.execute()
208116

209-
assertEquals(SplitTaskExecutionStatus.ERROR, taskInfo.status)
210-
assertEquals(SplitTaskType.GENERIC_TASK, taskInfo.taskType)
211-
}
117+
assertEquals(SplitTaskExecutionStatus.ERROR, taskInfo.status)
118+
assertEquals(SplitTaskType.GENERIC_TASK, taskInfo.taskType)
212119
}
213120
}

0 commit comments

Comments
 (0)