diff options
author | Leonid Startsev <sandwwraith@users.noreply.github.com> | 2022-06-21 13:44:21 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-21 14:44:21 +0300 |
commit | bb18d6243a524a1512da48f897804564e147af1f (patch) | |
tree | e17436be6866b8ec4f0f2835c05bb87832ee6825 | |
parent | 6a5ebd555017dad02ab5c085fde68f98c25415b3 (diff) | |
download | kotlinx.serialization-bb18d6243a524a1512da48f897804564e147af1f.tar.gz |
Tests for serializable sealed interfaces (#1754)
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"}]""" + ) + } +} |