Skip to content

Commit 52cdc35

Browse files
authored
Merge pull request #342 from hotwired/config-parsing-fix
Path Configuration parsing fix
2 parents e58d686 + ad43e4a commit 52cdc35

File tree

4 files changed

+51
-37
lines changed

4 files changed

+51
-37
lines changed

turbo/src/main/kotlin/dev/hotwire/turbo/config/TurboPathConfigurationLoader.kt

+9-13
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
package dev.hotwire.turbo.config
22

33
import android.content.Context
4-
import dev.hotwire.turbo.util.toObject
5-
import com.google.gson.reflect.TypeToken
4+
import dev.hotwire.turbo.config.Turbo.config
65
import dev.hotwire.turbo.util.dispatcherProvider
76
import kotlinx.coroutines.CoroutineScope
87
import kotlinx.coroutines.Job
@@ -30,29 +29,26 @@ internal class TurboPathConfigurationLoader(val context: Context) : CoroutineSco
3029
loadCachedConfigurationForUrl(url, onCompletion)
3130

3231
launch {
33-
repository.getRemoteConfiguration(url)?.let {
34-
onCompletion(load(it))
35-
cacheConfigurationForUrl(url, load(it))
32+
repository.getRemoteConfiguration(url)?.let { config ->
33+
onCompletion(config)
34+
cacheConfigurationForUrl(url, config)
3635
}
3736
}
3837
}
3938

4039
private fun loadBundledAssetConfiguration(filePath: String, onCompletion: (TurboPathConfiguration) -> Unit) {
41-
val configuration = repository.getBundledConfiguration(context, filePath)
42-
onCompletion(load(configuration))
40+
repository.getBundledConfiguration(context, filePath)?.let { config ->
41+
onCompletion(config)
42+
}
4343
}
4444

4545
private fun loadCachedConfigurationForUrl(url: String, onCompletion: (TurboPathConfiguration) -> Unit) {
46-
repository.getCachedConfigurationForUrl(context, url)?.let {
47-
onCompletion(load(it))
46+
repository.getCachedConfigurationForUrl(context, url)?.let { config ->
47+
onCompletion(config)
4848
}
4949
}
5050

5151
private fun cacheConfigurationForUrl(url: String, pathConfiguration: TurboPathConfiguration) {
5252
repository.cacheConfigurationForUrl(context, url, pathConfiguration)
5353
}
54-
55-
private fun load(json: String): TurboPathConfiguration {
56-
return json.toObject(object : TypeToken<TurboPathConfiguration>() {})
57-
}
5854
}

turbo/src/main/kotlin/dev/hotwire/turbo/config/TurboPathConfigurationRepository.kt

+21-7
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,36 @@ package dev.hotwire.turbo.config
22

33
import android.content.Context
44
import android.content.SharedPreferences
5+
import androidx.annotation.VisibleForTesting
56
import androidx.core.content.edit
7+
import com.google.gson.reflect.TypeToken
68
import dev.hotwire.turbo.http.TurboHttpClient
79
import dev.hotwire.turbo.util.dispatcherProvider
810
import dev.hotwire.turbo.util.logError
911
import dev.hotwire.turbo.util.toJson
12+
import dev.hotwire.turbo.util.toObject
1013
import kotlinx.coroutines.withContext
1114
import okhttp3.Request
12-
import java.io.IOException
1315

1416
internal class TurboPathConfigurationRepository {
1517
private val cacheFile = "turbo"
1618

17-
suspend fun getRemoteConfiguration(url: String): String? {
19+
suspend fun getRemoteConfiguration(url: String): TurboPathConfiguration? {
1820
val request = Request.Builder().url(url).build()
1921

2022
return withContext(dispatcherProvider.io) {
21-
issueRequest(request)
23+
issueRequest(request)?.let { parseFromJson(it) }
2224
}
2325
}
2426

25-
fun getBundledConfiguration(context: Context, filePath: String): String {
26-
return contentFromAsset(context, filePath)
27+
fun getBundledConfiguration(context: Context, filePath: String): TurboPathConfiguration? {
28+
val bundledConfigJson = contentFromAsset(context, filePath)
29+
return parseFromJson(bundledConfigJson)
2730
}
2831

29-
fun getCachedConfigurationForUrl(context: Context, url: String): String? {
30-
return prefs(context).getString(url, null)
32+
fun getCachedConfigurationForUrl(context: Context, url: String): TurboPathConfiguration? {
33+
val cachedConfigJson = prefs(context).getString(url, null)
34+
return cachedConfigJson?.let { parseFromJson(it) }
3135
}
3236

3337
fun cacheConfigurationForUrl(context: Context, url: String, pathConfiguration: TurboPathConfiguration) {
@@ -66,4 +70,14 @@ internal class TurboPathConfigurationRepository {
6670
String(it.readBytes())
6771
}
6872
}
73+
74+
@VisibleForTesting
75+
fun parseFromJson(json: String): TurboPathConfiguration? {
76+
return try {
77+
json.toObject(object : TypeToken<TurboPathConfiguration>() {})
78+
} catch (e: Exception) {
79+
logError("PathConfigurationLoadingException", e)
80+
null
81+
}
82+
}
6983
}

turbo/src/test/kotlin/dev/hotwire/turbo/config/TurboPathConfigurationRepositoryTest.kt

+20-17
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import android.content.Context
44
import android.os.Build
55
import androidx.test.core.app.ApplicationProvider
66
import dev.hotwire.turbo.BaseRepositoryTest
7+
import dev.hotwire.turbo.config.Turbo.config
78
import dev.hotwire.turbo.http.TurboHttpClient
8-
import dev.hotwire.turbo.util.toObject
9-
import com.google.gson.reflect.TypeToken
109
import kotlinx.coroutines.Dispatchers
1110
import kotlinx.coroutines.ExperimentalCoroutinesApi
1211
import kotlinx.coroutines.launch
@@ -36,41 +35,45 @@ class TurboPathConfigurationRepositoryTest : BaseRepositoryTest() {
3635

3736
runBlocking {
3837
launch(Dispatchers.Main) {
39-
val json = repository.getRemoteConfiguration(baseUrl())
40-
assertThat(json).isNotNull()
41-
42-
val config = load(json)
38+
val config = repository.getRemoteConfiguration(baseUrl())
39+
assertThat(config).isNotNull()
4340
assertThat(config?.rules?.size).isEqualTo(2)
4441
}
4542
}
4643
}
4744

45+
@Test
46+
fun getMalformedRemoteConfiguration() {
47+
enqueueResponse("test-configuration-malformed.json")
48+
49+
runBlocking {
50+
launch(Dispatchers.Main) {
51+
val config = repository.getRemoteConfiguration(baseUrl())
52+
assertThat(config).isNull()
53+
}
54+
}
55+
}
56+
4857
@Test
4958
fun getBundledAssetConfiguration() {
50-
val json = repository.getBundledConfiguration(context, "json/test-configuration.json")
51-
assertThat(json).isNotNull()
59+
val config = repository.getBundledConfiguration(context, "json/test-configuration.json")
60+
assertThat(config).isNotNull()
5261

53-
val config = load(json)
5462
assertThat(config?.rules?.size).isEqualTo(10)
5563
}
5664

5765
@Test
5866
fun getCachedConfiguration() {
5967
val url = "https://turbo.hotwired.dev/demo/configurations/android-v1.json"
60-
val config = requireNotNull(load(json()))
68+
val config = requireNotNull(repository.parseFromJson(json()))
6169
repository.cacheConfigurationForUrl(context, url, config)
6270

63-
val json = repository.getCachedConfigurationForUrl(context, url)
64-
assertThat(json).isNotNull()
71+
val cachedConfig = repository.getCachedConfigurationForUrl(context, url)
72+
assertThat(cachedConfig).isNotNull()
6573

66-
val cachedConfig = load(json)
6774
assertThat(cachedConfig?.rules?.size).isEqualTo(1)
6875
}
6976

70-
private fun load(json: String?): TurboPathConfiguration? {
71-
return json?.toObject(object : TypeToken<TurboPathConfiguration>() {})
72-
}
73-
7477
private fun json(): String {
7578
return """
7679
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Not a valid path configuration

0 commit comments

Comments
 (0)