summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeonid Startsev <sandwwraith@users.noreply.github.com>2022-06-21 13:44:21 +0200
committerGitHub <noreply@github.com>2022-06-21 14:44:21 +0300
commitbb18d6243a524a1512da48f897804564e147af1f (patch)
treee17436be6866b8ec4f0f2835c05bb87832ee6825
parent6a5ebd555017dad02ab5c085fde68f98c25415b3 (diff)
downloadkotlinx.serialization-bb18d6243a524a1512da48f897804564e147af1f.tar.gz
Tests for serializable sealed interfaces (#1754)
-rw-r--r--buildSrc/build.gradle.kts21
-rw-r--r--core/commonTest/src/kotlinx/serialization/features/SealedInterfacesSerializationTest.kt100
-rw-r--r--core/jvmMain/src/kotlinx/serialization/internal/Platform.kt2
-rw-r--r--formats/json/commonTest/src/kotlinx/serialization/features/sealed/SealedInterfacesJsonSerializationTest.kt40
4 files changed, 158 insertions, 5 deletions
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 994e674d..801d06a6 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -1,3 +1,7 @@
+/*
+ * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
import java.util.*
import java.io.FileInputStream
@@ -7,12 +11,21 @@ plugins {
repositories {
mavenCentral()
+ mavenLocal()
}
-val kotlinVersion = FileInputStream(file("../gradle.properties")).use { propFile ->
- val ver = Properties().apply { load(propFile) }["kotlin.version"]
- require(ver is String) { "kotlin.version must be string in ../gradle.properties, got $ver instead" }
- ver
+val kotlinVersion = run {
+ if (project.hasProperty("build_snapshot_train")) {
+ val ver = project.properties["kotlin_snapshot_version"] as? String
+ require(!ver.isNullOrBlank()) {"kotlin_snapshot_version must be present if build_snapshot_train is used" }
+ return@run ver
+ }
+ val targetProp = if (project.hasProperty("bootstrap")) "kotlin.version.snapshot" else "kotlin.version"
+ FileInputStream(file("../gradle.properties")).use { propFile ->
+ val ver = Properties().apply { load(propFile) }[targetProp]
+ require(ver is String) { "$targetProp must be string in ../gradle.properties, got $ver instead" }
+ ver
+ }
}
dependencies {
diff --git a/core/commonTest/src/kotlinx/serialization/features/SealedInterfacesSerializationTest.kt b/core/commonTest/src/kotlinx/serialization/features/SealedInterfacesSerializationTest.kt
new file mode 100644
index 00000000..008706dc
--- /dev/null
+++ b/core/commonTest/src/kotlinx/serialization/features/SealedInterfacesSerializationTest.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+@file:Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
+
+package kotlinx.serialization.features
+
+import kotlinx.serialization.*
+import kotlinx.serialization.descriptors.*
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
+import kotlinx.serialization.test.*
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+
+class SealedInterfacesSerializationTest {
+ interface A
+
+ sealed interface B
+
+ @Serializable
+ sealed interface C
+
+ @Serializable(DummySerializer::class)
+ sealed interface D
+
+ @Serializable(DummySerializer::class)
+ interface E
+
+ @Serializable
+ @Polymorphic
+ sealed interface F
+
+ @Serializable
+ class ImplA : A, B, C, D, E, F
+
+ @Serializable
+ class ImplB : A, B, C, D, E, F
+
+ @Serializable
+ class Holder(
+ val a: A,
+ val b: B,
+ val c: C,
+ val d: D,
+ val e: E,
+ @Polymorphic val polyC: C,
+ val f: F
+ )
+
+ class DummySerializer : KSerializer<Any> {
+ override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Dummy")
+
+ override fun serialize(encoder: Encoder, value: Any) {
+ error("serialize")
+ }
+
+ override fun deserialize(decoder: Decoder): Any {
+ error("deserialize")
+ }
+ }
+
+ private fun SerialDescriptor.haveSealedSubclasses() {
+ assertEquals(PolymorphicKind.SEALED, kind)
+ val subclasses = getElementDescriptor(1).elementDescriptors.map { it.serialName.substringAfterLast('.') }
+ assertEquals(listOf("ImplA", "ImplB"), subclasses)
+ }
+
+ private fun SerialDescriptor.isDummy() = serialName == "Dummy"
+
+ private fun SerialDescriptor.isPolymorphic() = kind == PolymorphicKind.OPEN
+
+ operator fun SerialDescriptor.get(i: Int) = getElementDescriptor(i)
+
+ @Test
+ fun testInHolder() {
+ val desc = Holder.serializer().descriptor
+ desc[0].isPolymorphic()
+ desc[1].isPolymorphic()
+ desc[2].haveSealedSubclasses()
+ desc[3].isDummy()
+ desc[4].isDummy()
+ desc[5].isPolymorphic()
+ desc[6].isPolymorphic()
+ }
+
+ @Test
+ fun testGenerated() {
+ C.serializer().descriptor.haveSealedSubclasses()
+ }
+
+ @Test
+ fun testResolved() = noJsLegacy {
+ serializer<C>().descriptor.haveSealedSubclasses()
+ }
+
+
+}
diff --git a/core/jvmMain/src/kotlinx/serialization/internal/Platform.kt b/core/jvmMain/src/kotlinx/serialization/internal/Platform.kt
index 0c770c93..7c16650b 100644
--- a/core/jvmMain/src/kotlinx/serialization/internal/Platform.kt
+++ b/core/jvmMain/src/kotlinx/serialization/internal/Platform.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.serialization.internal
diff --git a/formats/json/commonTest/src/kotlinx/serialization/features/sealed/SealedInterfacesJsonSerializationTest.kt b/formats/json/commonTest/src/kotlinx/serialization/features/sealed/SealedInterfacesJsonSerializationTest.kt
new file mode 100644
index 00000000..da05cc0e
--- /dev/null
+++ b/formats/json/commonTest/src/kotlinx/serialization/features/sealed/SealedInterfacesJsonSerializationTest.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization.features.sealed
+
+import kotlinx.serialization.*
+import kotlinx.serialization.json.*
+import kotlinx.serialization.test.*
+import kotlin.test.*
+
+class SealedInterfacesJsonSerializationTest : JsonTestBase() {
+ @Serializable
+ sealed interface I
+
+ @Serializable
+ sealed class Response: I {
+ @Serializable
+ @SerialName("ResponseInt")
+ data class ResponseInt(val i: Int): Response()
+
+ @Serializable
+ @SerialName("ResponseString")
+ data class ResponseString(val s: String): Response()
+ }
+
+ @Serializable
+ @SerialName("NoResponse")
+ object NoResponse: I
+
+ @Test
+ fun testSealedInterfaceJson() = noLegacyJs {
+ val messages = listOf(Response.ResponseInt(10), NoResponse, Response.ResponseString("foo"))
+ assertJsonFormAndRestored(
+ serializer(),
+ messages,
+ """[{"type":"ResponseInt","i":10},{"type":"NoResponse"},{"type":"ResponseString","s":"foo"}]"""
+ )
+ }
+}