diff --git a/benchmark/build.gradle.kts b/benchmark/build.gradle.kts index 8f140925b26..cf4a29178e9 100644 --- a/benchmark/build.gradle.kts +++ b/benchmark/build.gradle.kts @@ -21,6 +21,7 @@ import flavor.ProductFlavors plugins { id("com.android.test") alias(libs.plugins.androidx.baselineprofile) + alias(libs.plugins.kotlin.serialization) } android { @@ -81,7 +82,7 @@ dependencies { implementation(libs.androidx.test.uiAutomator) implementation(libs.androidx.benchmark.macro.junit4) implementation(libs.datafaker) - implementation(libs.gson) + implementation(libs.ktx.serialization) implementation(libs.junit4) implementation(libs.zxing.android.embedded) implementation(libs.zxing.core) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 25522fc91ce..c8a29788dda 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -116,7 +116,6 @@ hamcrest = "3.0" rules = "1.7.0" zxing = "3.5.2" zxingAndroid = "4.3.0" -gson = "2.13.2" allureKotlin = "2.4.0" androidx-test-services = "1.6.0" @@ -305,7 +304,6 @@ androidx-test-work = { module = "androidx.work:work-testing", version.ref = "and androidx-benchmark-macro-junit4 = { group = "androidx.benchmark", name = "benchmark-macro-junit4", version.ref = "benchmark-macro-junit4" } zxing-core = { module = "com.google.zxing:core", version.ref = "zxing" } zxing-android-embedded = { module = "com.journeyapps:zxing-android-embedded", version.ref = "zxingAndroid" } -gson = { module = "com.google.code.gson:gson", version.ref = "gson" } # Test androidx-espresso-accessibility = { module = "androidx.test.espresso:espresso-accessibility", version.ref = "androidx-espresso" } diff --git a/tests/testsCore/build.gradle.kts b/tests/testsCore/build.gradle.kts index 406f6af537e..de228a44fad 100644 --- a/tests/testsCore/build.gradle.kts +++ b/tests/testsCore/build.gradle.kts @@ -1,5 +1,6 @@ plugins { id(libs.plugins.wire.android.test.library.get().pluginId) + alias(libs.plugins.kotlin.serialization) id(libs.plugins.wire.compose.compiler.get().pluginId) } @@ -36,7 +37,7 @@ dependencies { implementation(libs.datafaker) androidTestImplementation(libs.zxing.core) androidTestImplementation(libs.zxing.android.embedded) - androidTestImplementation(libs.gson) + androidTestImplementation(libs.ktx.serialization) androidTestImplementation(libs.allure.kotlin.android) androidTestUtil(libs.androidx.test.orchestrator) androidTestUtil(libs.androidx.test.services) diff --git a/tests/testsSupport/build.gradle.kts b/tests/testsSupport/build.gradle.kts index 1bc38c3f157..ff825cdb44f 100644 --- a/tests/testsSupport/build.gradle.kts +++ b/tests/testsSupport/build.gradle.kts @@ -5,6 +5,7 @@ import java.util.Properties // Apply your test library plugin plugins { id(libs.plugins.wire.android.test.library.get().pluginId) + alias(libs.plugins.kotlin.serialization) id(libs.plugins.wire.compose.compiler.get().pluginId) } @@ -83,7 +84,7 @@ dependencies { androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(libs.androidx.test.uiAutomator) implementation(libs.datafaker) - androidTestImplementation(libs.gson) + implementation(libs.ktx.serialization) } // Register a custom Gradle task 'fetchSecrets' to fetch secrets from 1Password CLI and generate secrets.json diff --git a/tests/testsSupport/src/main/call/CallingService.kt b/tests/testsSupport/src/main/call/CallingService.kt index 77c40a83d4d..71a67f93c49 100644 --- a/tests/testsSupport/src/main/call/CallingService.kt +++ b/tests/testsSupport/src/main/call/CallingService.kt @@ -17,9 +17,11 @@ import call.models.CallFlow import call.models.CallRequest import call.models.Instance import call.models.InstanceRequest -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken import com.wire.android.testSupport.BuildConfig +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json import network.HttpRequestException import java.io.IOException import java.net.HttpCookie @@ -37,7 +39,13 @@ class CallingService( val applicationJson = "application/json" val contentTypeString = "Content-Type" - private val gson = Gson() + @OptIn(ExperimentalSerializationApi::class) + private val json = Json { + coerceInputValues = true + encodeDefaults = true + explicitNulls = false + ignoreUnknownKeys = true + } private val cookies = ConcurrentHashMap() private var basicAuthUser: String? = null private var basicAuthPassword: String? = null @@ -100,8 +108,8 @@ class CallingService( conn.setRequestProperty(contentTypeString, applicationJson) conn.setRequestProperty("Accept", applicationJson) - val response = httpPost(conn, gson.toJson(request), intArrayOf(HttpURLConnection.HTTP_OK)) - val instance = gson.fromJson(response, Instance::class.java) + val response = httpPost(conn, json.encodeToString(request), intArrayOf(HttpURLConnection.HTTP_OK)) + val instance = json.decodeFromString(response) conn.getHeaderField("Set-Cookie")?.let { cookieHeader -> HttpCookie.parse(cookieHeader) @@ -120,7 +128,7 @@ class CallingService( return try { val response = httpPut(conn, "", intArrayOf(HttpURLConnection.HTTP_OK)) cookies.remove(instance.id) - gson.fromJson(response, Instance::class.java) + json.decodeFromString(response) } catch (ex: Exception) { throw HttpRequestException("destroyInstance failed: ${ex.message}", 500) } @@ -131,7 +139,7 @@ class CallingService( val conn = buildRequestForInstance(instance.id, target) return try { val response = httpGet(conn, intArrayOf(HttpURLConnection.HTTP_OK)) - gson.fromJson(response, Instance::class.java) + json.decodeFromString(response) } catch (ex: Exception) { throw HttpRequestException("getInstance failed: ${ex.message}", 500) } @@ -142,8 +150,7 @@ class CallingService( val conn = buildRequestForInstance(instance.id, target) return try { val response = httpGet(conn, intArrayOf(HttpURLConnection.HTTP_OK)) - val type = object : TypeToken>() {}.type - gson.fromJson(response, type) + json.decodeFromString>(response) } catch (ex: Exception) { throw HttpRequestException("getFlows failed: ${ex.message}", 500) } @@ -190,8 +197,7 @@ class CallingService( val conn = buildRequestForCertainInstance(serverId, target) try { val response = httpGet(conn, intArrayOf(HttpURLConnection.HTTP_OK)) - val type = object : TypeToken>() {}.type - val serverInstances: List = gson.fromJson(response, type) + val serverInstances = json.decodeFromString>(response) serverInstances.forEach { if (!cookies.containsKey(it.id)) { cookies[it.id!!] = HttpCookie("SERVERID", serverId) @@ -273,22 +279,22 @@ class CallingService( // region CALL HELPERS - private fun performCall(instance: Instance, path: String, request: Any): Call { + private fun performCall(instance: Instance, path: String, request: CallRequest): Call { val conn = buildRequestForInstance(instance.id, "/api/v1/instance/${instance.id}$path") - val response = httpPost(conn, gson.toJson(request), intArrayOf(HttpURLConnection.HTTP_OK)) - return gson.fromJson(response, Call::class.java) + val response = httpPost(conn, json.encodeToString(request), intArrayOf(HttpURLConnection.HTTP_OK)) + return json.decodeFromString(response) } private fun performCallPut(instance: Instance, path: String): Call { val conn = buildRequestForInstance(instance.id, "/api/v1/instance/${instance.id}$path") val response = httpPut(conn, "", intArrayOf(HttpURLConnection.HTTP_OK)) - return gson.fromJson(response, Call::class.java) + return json.decodeFromString(response) } private fun performCallGet(instance: Instance, path: String): Call { val conn = buildRequestForInstance(instance.id, "/api/v1/instance/${instance.id}$path") val response = httpGet(conn, intArrayOf(HttpURLConnection.HTTP_OK)) - return gson.fromJson(response, Call::class.java) + return json.decodeFromString(response) } // endregion diff --git a/tests/testsSupport/src/main/call/models/BackendDTO.kt b/tests/testsSupport/src/main/call/models/BackendDTO.kt index 4d4c32e5a65..4f3331af79a 100644 --- a/tests/testsSupport/src/main/call/models/BackendDTO.kt +++ b/tests/testsSupport/src/main/call/models/BackendDTO.kt @@ -18,7 +18,9 @@ package call.models import backendUtils.BackendClient +import kotlinx.serialization.Serializable +@Serializable data class BackendDTO( var name: String, val webappUrl: String, diff --git a/tests/testsSupport/src/main/call/models/Call.kt b/tests/testsSupport/src/main/call/models/Call.kt index d194fb5f9a2..038c7534c52 100644 --- a/tests/testsSupport/src/main/call/models/Call.kt +++ b/tests/testsSupport/src/main/call/models/Call.kt @@ -17,6 +17,9 @@ */ package call.models +import kotlinx.serialization.Serializable + +@Serializable data class Call( var id: String? = null, var status: CallStatus? = null, diff --git a/tests/testsSupport/src/main/call/models/CallFlow.kt b/tests/testsSupport/src/main/call/models/CallFlow.kt index 06f5849e4c1..5de650d6dc4 100644 --- a/tests/testsSupport/src/main/call/models/CallFlow.kt +++ b/tests/testsSupport/src/main/call/models/CallFlow.kt @@ -17,22 +17,24 @@ */ package call.models -import com.google.gson.annotations.SerializedName +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +@Serializable data class CallFlow( - @SerializedName("audioPacketsReceived") + @SerialName("audioPacketsReceived") val audioPacketsReceived: Long, - @SerializedName("audioPacketsSent") + @SerialName("audioPacketsSent") val audioPacketsSent: Long, - @SerializedName("videoPacketsReceived") + @SerialName("videoPacketsReceived") val videoPacketsReceived: Long, - @SerializedName("videoPacketsSent") + @SerialName("videoPacketsSent") val videoPacketsSent: Long, - @SerializedName("remoteUserId") + @SerialName("remoteUserId") val remoteUserId: String ) { diff --git a/tests/testsSupport/src/main/call/models/CallRequest.kt b/tests/testsSupport/src/main/call/models/CallRequest.kt index 4bfc26f62b8..8c8a7c14fca 100644 --- a/tests/testsSupport/src/main/call/models/CallRequest.kt +++ b/tests/testsSupport/src/main/call/models/CallRequest.kt @@ -17,13 +17,15 @@ */ package call.models -import com.google.gson.annotations.SerializedName +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +@Serializable data class CallRequest( - @SerializedName("conversationId") + @SerialName("conversationId") val conversationId: String = "", - @SerializedName("timeout") + @SerialName("timeout") val timeout: Long = DEFAULT_CALL_TIMEOUT ) { companion object { diff --git a/tests/testsSupport/src/main/call/models/CallStatus.kt b/tests/testsSupport/src/main/call/models/CallStatus.kt index 3b05fb88d1d..09999d78e7e 100644 --- a/tests/testsSupport/src/main/call/models/CallStatus.kt +++ b/tests/testsSupport/src/main/call/models/CallStatus.kt @@ -17,6 +17,9 @@ */ package call.models +import kotlinx.serialization.Serializable + +@Serializable enum class CallStatus { NON_EXISTENT, WAITING, diff --git a/tests/testsSupport/src/main/call/models/Instance.kt b/tests/testsSupport/src/main/call/models/Instance.kt index e70d45c713e..27a808dfcb7 100644 --- a/tests/testsSupport/src/main/call/models/Instance.kt +++ b/tests/testsSupport/src/main/call/models/Instance.kt @@ -17,6 +17,9 @@ */ package call.models +import kotlinx.serialization.Serializable + +@Serializable data class Instance( val id: String?, val instanceStatus: InstanceStatus?, diff --git a/tests/testsSupport/src/main/call/models/InstanceRequest.kt b/tests/testsSupport/src/main/call/models/InstanceRequest.kt index edc1ce0aa62..7025656f9b3 100644 --- a/tests/testsSupport/src/main/call/models/InstanceRequest.kt +++ b/tests/testsSupport/src/main/call/models/InstanceRequest.kt @@ -17,6 +17,9 @@ */ package call.models +import kotlinx.serialization.Serializable + +@Serializable data class InstanceRequest( val email: String, val password: String, diff --git a/tests/testsSupport/src/main/call/models/InstanceStatus.kt b/tests/testsSupport/src/main/call/models/InstanceStatus.kt index d969957bb74..ffeb56ad30c 100644 --- a/tests/testsSupport/src/main/call/models/InstanceStatus.kt +++ b/tests/testsSupport/src/main/call/models/InstanceStatus.kt @@ -18,6 +18,9 @@ package call.models +import kotlinx.serialization.Serializable + +@Serializable enum class InstanceStatus { NON_EXISTENT, STARTING, diff --git a/tests/testsSupport/src/main/call/models/Metrics.kt b/tests/testsSupport/src/main/call/models/Metrics.kt index 790612af581..e907dbef2fa 100644 --- a/tests/testsSupport/src/main/call/models/Metrics.kt +++ b/tests/testsSupport/src/main/call/models/Metrics.kt @@ -20,6 +20,9 @@ ) package call.models +import kotlinx.serialization.Serializable + +@Serializable data class Metrics( val success: Boolean, val estabTimeMs: Long, diff --git a/tests/testsSupport/src/main/call/models/VersionedInstanceType.kt b/tests/testsSupport/src/main/call/models/VersionedInstanceType.kt index fcdb9f403c3..1e23f59e9de 100644 --- a/tests/testsSupport/src/main/call/models/VersionedInstanceType.kt +++ b/tests/testsSupport/src/main/call/models/VersionedInstanceType.kt @@ -17,6 +17,9 @@ */ package call.models +import kotlinx.serialization.Serializable + +@Serializable data class VersionedInstanceType( val name: String, val version: String