Skip to content

Commit c118cb7

Browse files
fix: serialization for onDeviceEval (#399)
I think the real issue is android-local-eval expecting type of array, but we define as map on server side
1 parent ebf46f4 commit c118cb7

File tree

2 files changed

+27
-54
lines changed

2 files changed

+27
-54
lines changed

src/main/kotlin/com/statsig/sdk/OnDeviceEvalClientIntializeFormatter.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ internal data class OnDeviceEvalClientIntializeResponse(
1212
) {
1313
fun toMap(): Map<String, Any> {
1414
val map = mutableMapOf<String, Any>()
15-
map["feature_gates"] = feature_gates
16-
map["dynamic_configs"] = dynamic_configs
17-
map["layer_configs"] = layer_configs
15+
map["feature_gates"] = feature_gates.values.toTypedArray()
16+
map["dynamic_configs"] = dynamic_configs.values.toTypedArray()
17+
map["layer_configs"] = layer_configs.values.toTypedArray()
1818
map["has_updates"] = has_updates
1919
map["time"] = time
2020
map["sdkInfo"] = sdkInfo

src/test/java/com/statsig/sdk/OnDeviceEvalClientInitializeFormatterTest.kt

+24-51
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
package com.statsig.sdk
22

33
import com.google.gson.*
4+
import com.google.gson.annotations.SerializedName
45
import org.junit.Assert.*
56
import org.junit.Before
67
import org.junit.Test
78

9+
internal data class APIDownloadedConfigsFromLocalEval(
10+
@SerializedName("dynamic_configs") val dynamicConfigs: Array<APIConfig>,
11+
@SerializedName("feature_gates") val featureGates: Array<APIConfig>,
12+
@SerializedName("layer_configs") val layerConfigs: Array<APIConfig>,
13+
@SerializedName("layers") val layers: Map<String, Array<String>>?,
14+
@SerializedName("time") val time: Long = 0,
15+
@SerializedName("has_updates") val hasUpdates: Boolean,
16+
@SerializedName("diagnostics") val diagnostics: Map<String, Int>? = null,
17+
)
18+
819
class OnDeviceEvalClientInitializeFormatterTest {
920
private lateinit var driver: StatsigServer
1021
private lateinit var gson: Gson
@@ -25,62 +36,24 @@ class OnDeviceEvalClientInitializeFormatterTest {
2536
gson.fromJson(dcs, APIDownloadedConfigs::class.java)
2637
specStore.setDownloadedConfigs(configs)
2738

28-
val formatter = OnDeviceEvalClientInitializeFormatter(specStore, clientSDKKey = "client-sdk")
29-
val response = formatter.getFormattedResponse()
39+
val formatter = OnDeviceEvalClientInitializeFormatter(specStore, null)
40+
val response = formatter.getFormattedResponse().toMap()
3041
val serializedResponse = gson.toJson(response)
3142
assertNotNull(serializedResponse)
3243
assertTrue(serializedResponse is String)
3344
assertTrue(serializedResponse.isNotEmpty())
3445

35-
val actualJson = gson.fromJson(serializedResponse, Map::class.java) as Map<String, Any>
36-
val expectedJson = gson.fromJson(dcs, Map::class.java) as Map<String, Any>
37-
38-
val actualFeatureGatesMap = actualJson["feature_gates"] as Map<String, Any>
39-
val expectedFeatureGatesList = expectedJson["feature_gates"] as List<Map<String, Any>>
40-
val expectedFeatureGatesMap = expectedFeatureGatesList.associateBy { it["name"] as String }
41-
42-
val gateName = "always_on_gate"
43-
val actualGate = actualFeatureGatesMap[gateName] as Map<String, Any>
44-
val expectedGate = expectedFeatureGatesMap[gateName] as Map<String, Any>
45-
46-
val actualRules = actualGate["rules"] as List<Map<String, Any>>
47-
val expectedRules = expectedGate["rules"] as List<Map<String, Any>>
48-
49-
assertEquals(expectedGate["name"], actualGate["name"])
50-
assertEquals(expectedGate["type"], actualGate["type"])
51-
assertEquals(expectedGate["salt"], actualGate["salt"])
52-
assertEquals(expectedGate["enabled"], actualGate["enabled"])
53-
assertEquals(expectedGate["defaultValue"], actualGate["defaultValue"])
54-
55-
assertEquals(expectedRules.size, actualRules.size)
56-
57-
for (i in expectedRules.indices) {
58-
val expectedRule = expectedRules[i]
59-
val actualRule = actualRules[i]
60-
61-
assertEquals(expectedRule["name"], actualRule["name"])
62-
assertEquals(expectedRule["groupName"], actualRule["groupName"])
63-
assertEquals(expectedRule["passPercentage"], actualRule["passPercentage"])
64-
assertEquals(expectedRule["returnValue"], actualRule["returnValue"])
65-
assertEquals(expectedRule["id"], actualRule["id"])
66-
assertEquals(expectedRule["salt"], actualRule["salt"])
67-
68-
val actualConditions = actualRule["conditions"] as List<Map<String, Any>>
69-
val expectedConditions = expectedRule["conditions"] as List<Map<String, Any>>
70-
71-
assertEquals(expectedConditions.size, actualConditions.size)
72-
73-
for (j in expectedConditions.indices) {
74-
val expectedCondition = expectedConditions[j]
75-
val actualCondition = actualConditions[j]
76-
77-
assertEquals(expectedCondition["type"], actualCondition["type"])
78-
assertEquals(expectedCondition["targetValue"], actualCondition["targetValue"])
79-
assertEquals(expectedCondition["operator"], actualCondition["operator"])
80-
assertEquals(expectedCondition["field"], actualCondition["field"])
81-
assertEquals(expectedCondition["additionalValues"], actualCondition["additionalValues"])
82-
}
83-
}
46+
val actualJson = gson.fromJson(serializedResponse, APIDownloadedConfigsFromLocalEval::class.java)
47+
val expectedJson = configs
48+
49+
// Compare the seven fields ( since local eval only have below fields)
50+
assertEquals(gson.toJson(expectedJson.dynamicConfigs), gson.toJson(actualJson.dynamicConfigs))
51+
assertEquals(gson.toJson(expectedJson.featureGates), gson.toJson(actualJson.featureGates))
52+
assertEquals(gson.toJson(expectedJson.layerConfigs), gson.toJson(actualJson.layerConfigs))
53+
assertEquals(gson.toJson(expectedJson.layers), gson.toJson(actualJson.layers))
54+
assertEquals(gson.toJson(expectedJson.time), gson.toJson(actualJson.time))
55+
assertEquals(gson.toJson(expectedJson.hasUpdates), gson.toJson(actualJson.hasUpdates))
56+
assertEquals(gson.toJson(expectedJson.diagnostics), gson.toJson(actualJson.diagnostics))
8457
}
8558

8659
@Test

0 commit comments

Comments
 (0)