Skip to content

Commit 971761e

Browse files
authored
feat(ATS): add vuid manager (#431)
1 parent 9d43ce0 commit 971761e

File tree

16 files changed

+330
-25
lines changed

16 files changed

+330
-25
lines changed

android-sdk/build.gradle

+1-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
apply plugin: 'com.android.library'
1818
apply plugin: 'kotlin-android'
19-
apply plugin: 'kotlin-android-extensions'
2019

2120
android {
2221
compileSdkVersion compile_sdk_version
@@ -28,6 +27,7 @@ android {
2827
multiDexEnabled true
2928
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
3029
buildConfigField "String", "CLIENT_VERSION", "\"$version_name\""
30+
multiDexEnabled true
3131

3232
// these rules will be merged to app's proguard rules
3333
consumerProguardFiles '../proguard-rules.txt'
@@ -48,10 +48,6 @@ android {
4848
sourceCompatibility JavaVersion.VERSION_1_8
4949
targetCompatibility JavaVersion.VERSION_1_8
5050
}
51-
52-
dexOptions {
53-
javaMaxHeapSize "4g"
54-
}
5551
}
5652

5753
dependencies {

build.gradle

+23-10
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ buildscript {
3030
google()
3131
}
3232
dependencies {
33-
classpath 'com.android.tools.build:gradle:7.2.1'
33+
classpath 'com.android.tools.build:gradle:7.2.2'
3434
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
3535

3636
// NOTE: Do not place your application dependencies here; they belong
@@ -86,7 +86,7 @@ task clean(type: Delete) {
8686
task cleanAllModules () {
8787
logger.info("Running clean for all modules")
8888
dependsOn(':android-sdk:clean', ':event-handler:clean',
89-
':user-profile:clean', ':shared:clean', ':datafile-handler:clean')
89+
':user-profile:clean', ':shared:clean', ':datafile-handler:clean', ':odp:clean')
9090
}
9191

9292
task testAllModules () {
@@ -100,20 +100,21 @@ task testAllModulesTravis () {
100100
':event-handler:connectedAndroidTest', ':event-handler:test',
101101
':datafile-handler:connectedAndroidTest', ':datafile-handler:test',
102102
':user-profile:connectedAndroidTest',
103-
':shared:connectedAndroidTest')
103+
':shared:connectedAndroidTest',
104+
':odp:connectedAndroidTest', ':odp:test'
105+
)
104106
}
105107

106108
// Publish to MavenCentral
107109

108110
task ship() {
109-
dependsOn(':android-sdk:ship', ':shared:ship', ':event-handler:ship', ':user-profile:ship', ':datafile-handler:ship')
111+
dependsOn(':android-sdk:ship', ':shared:ship', ':event-handler:ship', ':user-profile:ship', ':datafile-handler:ship', ':odp:ship')
110112
}
111113

112114
def publishedProjects = subprojects.findAll { it.name != 'test-app' }
113115
configure(publishedProjects) {
114116
apply plugin: 'com.android.library'
115117
apply plugin: 'kotlin-android'
116-
apply plugin: 'kotlin-android-extensions'
117118
apply plugin: 'maven-publish'
118119
apply plugin: 'signing'
119120

@@ -140,13 +141,17 @@ configure(publishedProjects) {
140141
artifactName = 'android-sdk-user-profile'
141142
docTitle = 'Optimizely X Android SDK: User Profile'
142143
break
144+
case 'odp':
145+
artifactName = 'android-sdk-odp'
146+
docTitle = 'Optimizely X Android SDK: ODP'
147+
break
143148
default:
144149
return
145150
}
146151

147152
android.libraryVariants.all { variant ->
148153
task("${variant.name}Javadoc", type: Javadoc, dependsOn: "assemble${variant.name.capitalize()}") {
149-
source = variant.javaCompile.source
154+
source = variant.javaCompileProvider.get().source
150155

151156
title = docTitle
152157

@@ -178,11 +183,20 @@ configure(publishedProjects) {
178183
android.libraryVariants.all { variant ->
179184
task("${variant.name}SourcesJar", type: Jar) {
180185
classifier = 'sources'
181-
from variant.javaCompile.source
186+
from variant.javaCompileProvider.get().source
182187
}
183188
project.artifacts.add("archives", tasks["${variant.name}SourcesJar"]);
184189
}
185190

191+
android {
192+
publishing {
193+
singleVariant("release") {
194+
withSourcesJar()
195+
withJavadocJar()
196+
}
197+
}
198+
}
199+
186200
afterEvaluate {
187201
publishing {
188202
publications {
@@ -196,8 +210,6 @@ configure(publishedProjects) {
196210
pom.description = 'The Android SDK for Optimizely Full Stack (feature flag management for product development teams)'
197211

198212
from components.release
199-
artifact releaseSourcesJar
200-
artifact releaseJavadocJar
201213
}
202214
}
203215
repositories {
@@ -232,11 +244,12 @@ configure(publishedProjects) {
232244
}
233245
}
234246

235-
project(':android-sdk').ship.shouldRunAfter = [':android-sdk:clean', ':datafile-handler:ship', ':event-handler:ship', ':user-profile:ship']
247+
project(':android-sdk').ship.shouldRunAfter = [':android-sdk:clean', ':datafile-handler:ship', ':event-handler:ship', ':user-profile:ship', ':odp:ship']
236248
project(':datafile-handler').ship.shouldRunAfter = [':datafile-handler:clean', ':shared:ship']
237249
project(':event-handler').ship.shouldRunAfter = [':event-handler:clean', ':shared:ship']
238250
project(':shared').ship.shouldRunAfter = [':shared:clean']
239251
project(':user-profile').ship.shouldRunAfter = [':user-profile:clean', ':shared:ship']
252+
project(':odp').ship.shouldRunAfter = [':odp:clean', ':shared:ship']
240253

241254
// standard POM format required by MavenCentral
242255

datafile-handler/build.gradle

-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
apply plugin: 'com.android.library'
1818
apply plugin: 'kotlin-android'
19-
apply plugin: 'kotlin-android-extensions'
2019

2120
android {
2221
compileSdkVersion compile_sdk_version

event-handler/build.gradle

-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
apply plugin: 'com.android.library'
1818
apply plugin: 'kotlin-android'
19-
apply plugin: 'kotlin-android-extensions'
2019

2120
android {
2221
compileSdkVersion compile_sdk_version

event-handler/src/androidTest/java/com/optimizely/ab/android/event_handler/EventDAOTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public void setupEventDAO() {
5959

6060
@After
6161
public void tearDownEventDAO() {
62-
assertTrue(context.deleteDatabase(String.format(EventSQLiteOpenHelper.DB_NAME , "1")));
62+
context.deleteDatabase(String.format(EventSQLiteOpenHelper.DB_NAME , "1"));
6363
}
6464

6565
@Test
@@ -80,7 +80,7 @@ public void getEvents() throws MalformedURLException {
8080
assertTrue(eventDAO.storeEvent(event3));
8181

8282
List<Pair<Long,Event>> events = eventDAO.getEvents();
83-
assertTrue(events.size() == 3);
83+
assertEquals(events.size(), 3);
8484

8585
Pair<Long,Event> pair1 = events.get(0);
8686
Pair<Long,Event> pair2 = events.get(1);

gradle.properties

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
android.enableJetifier=true
22
android.useAndroidX=true
33
org.gradle.jvmargs=-Xmx1g
4+
android.disableAutomaticComponentCreation=true

odp/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

odp/build.gradle

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//
2+
// Copyright 2022, Optimizely, Inc. and contributors
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// https://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
apply plugin: 'com.android.library'
18+
apply plugin: 'kotlin-android'
19+
20+
android {
21+
compileSdkVersion compile_sdk_version
22+
buildToolsVersion build_tools_version
23+
24+
defaultConfig {
25+
minSdkVersion min_sdk_version
26+
targetSdkVersion target_sdk_version
27+
versionCode 1
28+
versionName "1.0"
29+
multiDexEnabled true
30+
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
31+
}
32+
testOptions {
33+
unitTests.returnDefaultValues = true
34+
}
35+
buildTypes {
36+
release {
37+
minifyEnabled false
38+
}
39+
debug {
40+
testCoverageEnabled true
41+
}
42+
}
43+
compileOptions {
44+
sourceCompatibility JavaVersion.VERSION_1_8
45+
targetCompatibility JavaVersion.VERSION_1_8
46+
}
47+
buildToolsVersion build_tools_version
48+
49+
kotlinOptions {
50+
jvmTarget = '1.8'
51+
}
52+
}
53+
54+
dependencies {
55+
api project(':shared')
56+
implementation "androidx.annotation:annotation:$annotations_ver"
57+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
58+
implementation 'androidx.test.ext:junit-ktx:1.1.3'
59+
60+
testImplementation "junit:junit:$junit_ver"
61+
testImplementation "org.mockito:mockito-core:$mockito_ver"
62+
63+
compileOnly "com.noveogroup.android:android-logger:$android_logger_ver"
64+
65+
androidTestImplementation "androidx.test.ext:junit:$androidx_test_junit"
66+
androidTestImplementation "androidx.test.espresso:espresso-core:$espresso_ver"
67+
// Set this dependency to use JUnit 4 rules
68+
androidTestImplementation "androidx.test:rules:$androidx_test_rules"
69+
androidTestImplementation "androidx.test:core:$androidx_test_core"
70+
androidTestImplementation "androidx.test:core-ktx:$androidx_test_core"
71+
72+
androidTestImplementation "org.mockito:mockito-core:$mockito_ver"
73+
androidTestImplementation "com.crittercism.dexmaker:dexmaker:$dexmaker_ver"
74+
androidTestImplementation "com.crittercism.dexmaker:dexmaker-dx:$dexmaker_ver"
75+
androidTestImplementation "com.crittercism.dexmaker:dexmaker-mockito:$dexmaker_ver"
76+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Copyright 2022, Optimizely, Inc. and contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.optimizely.ab.android.odp
16+
17+
import android.content.Context
18+
import android.content.SharedPreferences
19+
import androidx.test.ext.junit.runners.AndroidJUnit4
20+
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
21+
import org.junit.After
22+
import org.junit.Assert.*
23+
import org.junit.Before
24+
import org.junit.Test
25+
import org.junit.runner.RunWith
26+
27+
@RunWith(AndroidJUnit4::class)
28+
class VuidManagerTest {
29+
lateinit var vuidManager: VuidManager
30+
val context = getInstrumentation().getTargetContext()
31+
32+
@Before
33+
fun setUp() {
34+
// remove vuid storage
35+
cleanSharedPrefs()
36+
// remove a singlton instance
37+
VuidManager.removeSharedForTesting()
38+
39+
vuidManager = VuidManager.getShared(context)
40+
}
41+
42+
@After
43+
fun cleanSharedPrefs() {
44+
val sharedPreferences: SharedPreferences = context.getSharedPreferences("optly", Context.MODE_PRIVATE)
45+
val editor = sharedPreferences.edit()
46+
editor.clear()
47+
editor.commit()
48+
}
49+
50+
@Test
51+
fun makeVuid() {
52+
val vuid = vuidManager.makeVuid()
53+
assertTrue(vuid.length == 32)
54+
assertTrue(vuid.startsWith("vuid_", ignoreCase = false))
55+
assertTrue("generated vuids should be all lowercased", vuid.toLowerCase().equals(vuid, ignoreCase = false))
56+
}
57+
58+
@Test
59+
fun isVuid() {
60+
assertTrue(VuidManager.isVuid("vuid_1234"))
61+
assertTrue(VuidManager.isVuid("VUID_1234"))
62+
assertFalse(VuidManager.isVuid("vuid1234"))
63+
assertFalse(VuidManager.isVuid("1234"))
64+
assertFalse(VuidManager.isVuid(""))
65+
}
66+
67+
@Test
68+
fun loadBeforeSave() {
69+
val vuid1 = vuidManager.load(context)
70+
assertTrue("new vuid is created", VuidManager.isVuid(vuid1))
71+
val vuid2 = vuidManager.load(context)
72+
assertEquals("old vuid should be returned since load will save a created vuid", vuid1, vuid2)
73+
}
74+
75+
@Test
76+
fun loadAfterSave() {
77+
vuidManager.save(context,"vuid_1234")
78+
val vuidLoaded = vuidManager.load(context)
79+
assertEquals("saved vuid should be returned", vuidLoaded, "vuid_1234")
80+
val vuidLoaded2 = vuidManager.load(context)
81+
assertEquals("the same vuid should be returned", vuidLoaded2, "vuid_1234")
82+
}
83+
84+
@Test
85+
fun autoLoaded() {
86+
val vuid1 = VuidManager.getShared(context).vuid
87+
assertTrue("vuid should be auto loaded when constructed", vuid1.startsWith("vuid_"))
88+
89+
val vuid2 = VuidManager.getShared(context).vuid
90+
assertEquals("the same vuid should be returned when getting a singleton", vuid1, vuid2)
91+
92+
// remove shared instance, so will be re-instantiated
93+
VuidManager.removeSharedForTesting()
94+
95+
val vuid3 = VuidManager.getShared(context).vuid
96+
assertEquals("the saved vuid should be returned when instantiated again", vuid2, vuid3)
97+
98+
// remove saved vuid
99+
cleanSharedPrefs()
100+
// remove shared instance, so will be re-instantiated
101+
VuidManager.removeSharedForTesting()
102+
103+
val vuid4 = VuidManager.getShared(context).vuid
104+
assertNotEquals("a new vuid should be returned when storage cleared and re-instantiated", vuid3, vuid4)
105+
assertTrue(vuid4.startsWith("vuid_"))
106+
}
107+
}

odp/src/main/AndroidManifest.xml

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
//
4+
// Copyright 2022, Optimizely, Inc. and contributors
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// https://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
-->
19+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
20+
package="com.optimizely.ab.android.odp">
21+
22+
</manifest>

0 commit comments

Comments
 (0)