Skip to content

Commit ac3615f

Browse files
authored
Merge b7ff899 into 5d56114
2 parents 5d56114 + b7ff899 commit ac3615f

File tree

5 files changed

+79
-52
lines changed

5 files changed

+79
-52
lines changed

firebase-sessions/src/main/kotlin/com/google/firebase/sessions/settings/RemoteSettings.kt

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ import org.json.JSONException
3535
import org.json.JSONObject
3636

3737
internal class RemoteSettings(
38-
val context: Context,
39-
val blockingDispatcher: CoroutineContext,
40-
val backgroundDispatcher: CoroutineContext,
41-
val firebaseInstallationsApi: FirebaseInstallationsApi,
42-
val appInfo: ApplicationInfo,
38+
context: Context,
39+
private val blockingDispatcher: CoroutineContext,
40+
private val backgroundDispatcher: CoroutineContext,
41+
private val firebaseInstallationsApi: FirebaseInstallationsApi,
42+
private val appInfo: ApplicationInfo,
4343
private val configsFetcher: CrashlyticsSettingsFetcher = RemoteSettingsFetcher(appInfo),
4444
dataStoreName: String = SESSION_CONFIGS_NAME
4545
) : SettingsProvider {
@@ -80,7 +80,7 @@ internal class RemoteSettings(
8080
scope.launch { settingsCache.removeConfigs() }
8181
}
8282

83-
suspend private fun fetchConfigs() {
83+
private suspend fun fetchConfigs() {
8484
// Check if a fetch is in progress. If yes, return
8585
if (fetchInProgress.get()) {
8686
return
@@ -94,7 +94,7 @@ internal class RemoteSettings(
9494
fetchInProgress.set(true)
9595

9696
// Get the installations ID before making a remote config fetch
97-
var installationId = firebaseInstallationsApi.id.await()
97+
val installationId = firebaseInstallationsApi.id.await()
9898
if (installationId == null) {
9999
fetchInProgress.set(false)
100100
return
@@ -141,7 +141,6 @@ internal class RemoteSettings(
141141
}
142142
}
143143

144-
val scope = CoroutineScope(backgroundDispatcher)
145144
sessionsEnabled?.let { settingsCache.updateSettingsEnabled(sessionsEnabled) }
146145

147146
sessionTimeoutSeconds?.let {
@@ -156,9 +155,9 @@ internal class RemoteSettings(
156155
settingsCache.updateSessionCacheUpdatedTime(System.currentTimeMillis())
157156
fetchInProgress.set(false)
158157
},
159-
onFailure = {
158+
onFailure = { msg ->
160159
// Network request failed here.
161-
Log.e(TAG, "Error failing to fetch the remote configs")
160+
Log.e(TAG, "Error failing to fetch the remote configs: $msg")
162161
fetchInProgress.set(false)
163162
}
164163
)

firebase-sessions/src/main/kotlin/com/google/firebase/sessions/settings/RemoteSettingsFetcher.kt

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package com.google.firebase.sessions.settings
1919
import android.net.Uri
2020
import com.google.firebase.sessions.ApplicationInfo
2121
import java.io.BufferedReader
22+
import java.io.IOException
2223
import java.io.InputStreamReader
2324
import java.net.URL
2425
import javax.net.ssl.HttpsURLConnection
@@ -27,46 +28,53 @@ import org.json.JSONObject
2728
internal interface CrashlyticsSettingsFetcher {
2829
suspend fun doConfigFetch(
2930
headerOptions: Map<String, String>,
30-
onSuccess: suspend ((JSONObject)) -> Unit,
31-
onFailure: suspend () -> Unit
31+
onSuccess: suspend (JSONObject) -> Unit,
32+
onFailure: suspend (msg: String) -> Unit
3233
)
3334
}
3435

35-
internal class RemoteSettingsFetcher(val appInfo: ApplicationInfo) : CrashlyticsSettingsFetcher {
36+
internal class RemoteSettingsFetcher(
37+
private val appInfo: ApplicationInfo,
38+
private val baseUrl: String = FIREBASE_SESSIONS_BASE_URL_STRING
39+
) : CrashlyticsSettingsFetcher {
3640
override suspend fun doConfigFetch(
3741
headerOptions: Map<String, String>,
38-
onSuccess: suspend ((JSONObject)) -> Unit,
39-
onFailure: suspend () -> Unit
42+
onSuccess: suspend (JSONObject) -> Unit,
43+
onFailure: suspend (String) -> Unit
4044
) {
4145
val connection = settingsUrl().openConnection() as HttpsURLConnection
4246
connection.requestMethod = "GET"
4347
connection.setRequestProperty("Accept", "application/json")
4448
headerOptions.forEach { connection.setRequestProperty(it.key, it.value) }
4549

46-
val responseCode = connection.responseCode
47-
if (responseCode == HttpsURLConnection.HTTP_OK) {
48-
val inputStream = connection.inputStream
49-
val bufferedReader = BufferedReader(InputStreamReader(inputStream))
50-
val response = StringBuilder()
51-
var inputLine: String?
52-
while (bufferedReader.readLine().also { inputLine = it } != null) {
53-
response.append(inputLine)
54-
}
55-
bufferedReader.close()
56-
inputStream.close()
50+
try {
51+
val responseCode = connection.responseCode
52+
if (responseCode == HttpsURLConnection.HTTP_OK) {
53+
val inputStream = connection.inputStream
54+
val bufferedReader = BufferedReader(InputStreamReader(inputStream))
55+
val response = StringBuilder()
56+
var inputLine: String?
57+
while (bufferedReader.readLine().also { inputLine = it } != null) {
58+
response.append(inputLine)
59+
}
60+
bufferedReader.close()
61+
inputStream.close()
5762

58-
val responseJson = JSONObject(response.toString())
59-
onSuccess(responseJson)
60-
} else {
61-
onFailure()
63+
val responseJson = JSONObject(response.toString())
64+
onSuccess(responseJson)
65+
} else {
66+
onFailure("Bad response code: $responseCode")
67+
}
68+
} catch (ex: IOException) {
69+
onFailure(ex.message ?: ex.toString())
6270
}
6371
}
6472

65-
fun settingsUrl(): URL {
66-
var uri =
73+
private fun settingsUrl(): URL {
74+
val uri =
6775
Uri.Builder()
6876
.scheme("https")
69-
.authority(FIREBASE_SESSIONS_BASE_URL_STRING)
77+
.authority(baseUrl)
7078
.appendPath("spi")
7179
.appendPath("v2")
7280
.appendPath("platforms")

firebase-sessions/src/test/kotlin/com/google/firebase/sessions/RemoteSettingsTest.kt

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,26 @@ import com.google.common.truth.Truth.assertThat
2121
import com.google.firebase.FirebaseApp
2222
import com.google.firebase.concurrent.TestOnlyExecutors
2323
import com.google.firebase.sessions.settings.RemoteSettings
24+
import com.google.firebase.sessions.settings.RemoteSettingsFetcher
2425
import com.google.firebase.sessions.testing.FakeFirebaseApp
2526
import com.google.firebase.sessions.testing.FakeFirebaseInstallations
2627
import com.google.firebase.sessions.testing.FakeRemoteConfigFetcher
28+
import com.google.firebase.sessions.testing.TestSessionEventData.TEST_APPLICATION_INFO
2729
import kotlin.time.Duration.Companion.minutes
30+
import kotlinx.coroutines.ExperimentalCoroutinesApi
2831
import kotlinx.coroutines.asCoroutineDispatcher
2932
import kotlinx.coroutines.test.runTest
3033
import org.json.JSONObject
3134
import org.junit.After
3235
import org.junit.Test
3336
import org.junit.runner.RunWith
3437

38+
@OptIn(ExperimentalCoroutinesApi::class)
3539
@RunWith(AndroidJUnit4::class)
3640
class RemoteSettingsTest {
3741

3842
@Test
39-
fun RemoteSettings_successfulFetchCachesValues() = runTest {
43+
fun remoteSettings_successfulFetchCachesValues() = runTest {
4044
val firebaseApp = FakeFirebaseApp().firebaseApp
4145
val context = firebaseApp.applicationContext
4246
val firebaseInstallations = FakeFirebaseInstallations("FaKeFiD")
@@ -67,7 +71,7 @@ class RemoteSettingsTest {
6771
}
6872

6973
@Test
70-
fun RemoteSettings_successfulFetchWithLessConfigsCachesOnlyReceivedValues() = runTest {
74+
fun remoteSettings_successfulFetchWithLessConfigsCachesOnlyReceivedValues() = runTest {
7175
val firebaseApp = FakeFirebaseApp().firebaseApp
7276
val context = firebaseApp.applicationContext
7377
val firebaseInstallations = FakeFirebaseInstallations("FaKeFiD")
@@ -100,7 +104,7 @@ class RemoteSettingsTest {
100104
}
101105

102106
@Test
103-
fun RemoteSettings_successfulRefetchUpdatesCache() = runTest {
107+
fun remoteSettings_successfulReFetchUpdatesCache() = runTest {
104108
val firebaseApp = FakeFirebaseApp().firebaseApp
105109
val context = firebaseApp.applicationContext
106110
val firebaseInstallations = FakeFirebaseInstallations("FaKeFiD")
@@ -146,7 +150,7 @@ class RemoteSettingsTest {
146150
}
147151

148152
@Test
149-
fun RemoteSettings_successfulFetchWithEmptyConfigRetainsOldConfigs() = runTest {
153+
fun remoteSettings_successfulFetchWithEmptyConfigRetainsOldConfigs() = runTest {
150154
val firebaseApp = FakeFirebaseApp().firebaseApp
151155
val context = firebaseApp.applicationContext
152156
val firebaseInstallations = FakeFirebaseInstallations("FaKeFiD")
@@ -186,6 +190,20 @@ class RemoteSettingsTest {
186190
remoteSettings.clearCachedSettings()
187191
}
188192

193+
@Test
194+
fun remoteSettingsFetcher_badFetch_callsOnFailure() = runTest {
195+
var failure: String? = null
196+
197+
RemoteSettingsFetcher(TEST_APPLICATION_INFO, baseUrl = "this.url.is.invalid")
198+
.doConfigFetch(
199+
headerOptions = emptyMap(),
200+
onSuccess = {},
201+
onFailure = { failure = it },
202+
)
203+
204+
assertThat(failure).isNotNull()
205+
}
206+
189207
@After
190208
fun cleanUp() {
191209
FirebaseApp.clearInstancesForTest()

firebase-sessions/src/test/kotlin/com/google/firebase/sessions/testing/FakeRemoteConfigFetcher.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ internal class FakeRemoteConfigFetcher(var responseJSONObject: JSONObject = JSON
2424
override suspend fun doConfigFetch(
2525
headerOptions: Map<String, String>,
2626
onSuccess: suspend (JSONObject) -> Unit,
27-
onFailure: suspend () -> Unit
27+
onFailure: suspend (String) -> Unit
2828
) {
2929
onSuccess(responseJSONObject)
3030
}

firebase-sessions/src/test/kotlin/com/google/firebase/sessions/testing/TestSessionEventData.kt

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,23 +58,25 @@ internal object TestSessionEventData {
5858
firebaseInstallationId = "",
5959
)
6060

61+
val TEST_APPLICATION_INFO =
62+
ApplicationInfo(
63+
appId = FakeFirebaseApp.MOCK_APP_ID,
64+
deviceModel = Build.MODEL,
65+
sessionSdkVersion = BuildConfig.VERSION_NAME,
66+
osVersion = Build.VERSION.RELEASE,
67+
logEnvironment = LogEnvironment.LOG_ENVIRONMENT_PROD,
68+
AndroidApplicationInfo(
69+
packageName = ApplicationProvider.getApplicationContext<Context>().packageName,
70+
versionName = FakeFirebaseApp.MOCK_APP_VERSION,
71+
appBuildVersion = FakeFirebaseApp.MOCK_APP_BUILD_VERSION,
72+
deviceManufacturer = Build.MANUFACTURER,
73+
),
74+
)
75+
6176
val TEST_SESSION_EVENT =
6277
SessionEvent(
6378
eventType = EventType.SESSION_START,
6479
sessionData = TEST_SESSION_DATA,
65-
applicationInfo =
66-
ApplicationInfo(
67-
appId = FakeFirebaseApp.MOCK_APP_ID,
68-
deviceModel = Build.MODEL,
69-
sessionSdkVersion = BuildConfig.VERSION_NAME,
70-
osVersion = Build.VERSION.RELEASE,
71-
logEnvironment = LogEnvironment.LOG_ENVIRONMENT_PROD,
72-
AndroidApplicationInfo(
73-
packageName = ApplicationProvider.getApplicationContext<Context>().packageName,
74-
versionName = FakeFirebaseApp.MOCK_APP_VERSION,
75-
appBuildVersion = FakeFirebaseApp.MOCK_APP_BUILD_VERSION,
76-
deviceManufacturer = Build.MANUFACTURER,
77-
),
78-
)
80+
applicationInfo = TEST_APPLICATION_INFO
7981
)
8082
}

0 commit comments

Comments
 (0)