diff options
Diffstat (limited to 'formats/json-tests/commonTest/src/kotlinx/serialization/features/PolymorphismWithAnyTest.kt')
-rw-r--r-- | formats/json-tests/commonTest/src/kotlinx/serialization/features/PolymorphismWithAnyTest.kt | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/formats/json-tests/commonTest/src/kotlinx/serialization/features/PolymorphismWithAnyTest.kt b/formats/json-tests/commonTest/src/kotlinx/serialization/features/PolymorphismWithAnyTest.kt new file mode 100644 index 00000000..07b6e31a --- /dev/null +++ b/formats/json-tests/commonTest/src/kotlinx/serialization/features/PolymorphismWithAnyTest.kt @@ -0,0 +1,149 @@ +/* + * Copyright 2017-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.serialization.features + +import kotlinx.serialization.* +import kotlinx.serialization.json.* +import kotlinx.serialization.modules.* +import kotlinx.serialization.modules.plus +import kotlinx.serialization.test.assertStringFormAndRestored +import kotlin.test.* + +class PolymorphismWithAnyTest: JsonTestBase() { + + @Serializable + data class MyPolyData(val data: Map<String, @Polymorphic Any>) + + @Serializable + data class MyPolyDataWithPolyBase( + val data: Map<String, @Polymorphic Any>, + @Polymorphic val polyBase: PolyBase + ) + + // KClass.toString() on JS prints simple name, not FQ one + @Suppress("NAME_SHADOWING") + private fun checkNotRegisteredMessage(className: String, scopeName: String, exception: SerializationException) { + val className = className.substringAfterLast('.') + val scopeName = scopeName.substringAfterLast('.') + val expectedText = + "Serializer for subclass '$className' is not found in the polymorphic scope of '$scopeName'" + assertTrue(exception.message!!.startsWith(expectedText), + "Found $exception, but expected to start with: $expectedText") + } + + @Test + fun testFailWithoutModulesWithCustomClass() = parametrizedTest { mode -> + checkNotRegisteredMessage( + "kotlinx.serialization.IntData", "kotlin.Any", + assertFailsWith<SerializationException>("not registered") { + Json.encodeToString( + MyPolyData.serializer(), + MyPolyData(mapOf("a" to IntData(42))), + mode + ) + } + ) + } + + @Test + fun testWithModules() { + val json = Json { + serializersModule = SerializersModule { polymorphic(Any::class) { subclass(IntData.serializer()) } } + } + assertJsonFormAndRestored( + expected = """{"data":{"a":{"type":"kotlinx.serialization.IntData","intV":42}}}""", + data = MyPolyData(mapOf("a" to IntData(42))), + serializer = MyPolyData.serializer(), + json = json + ) + } + + /** + * This test should fail because PolyDerived registered in the scope of PolyBase, not kotlin.Any + */ + @Test + fun testFailWithModulesNotInAnyScope() = parametrizedTest { mode -> + val json = Json { serializersModule = BaseAndDerivedModule } + checkNotRegisteredMessage( + "kotlinx.serialization.PolyDerived", "kotlin.Any", + assertFailsWith<SerializationException> { + json.encodeToString( + MyPolyData.serializer(), + MyPolyData(mapOf("a" to PolyDerived("foo"))), + mode + ) + } + ) + } + + private val baseAndDerivedModuleAtAny = SerializersModule { + polymorphic(Any::class) { + subclass(PolyDerived.serializer()) + } + } + + + @Test + fun testRebindModules() { + val json = Json { serializersModule = baseAndDerivedModuleAtAny } + assertJsonFormAndRestored( + expected = """{"data":{"a":{"type":"kotlinx.serialization.PolyDerived","id":1,"s":"foo"}}}""", + data = MyPolyData(mapOf("a" to PolyDerived("foo"))), + serializer = MyPolyData.serializer(), + json = json + ) + } + + /** + * This test should fail because PolyDerived registered in the scope of kotlin.Any, not PolyBase + */ + @Test + fun testFailWithModulesNotInParticularScope() = parametrizedTest { mode -> + val json = Json { serializersModule = baseAndDerivedModuleAtAny } + checkNotRegisteredMessage( + "kotlinx.serialization.PolyDerived", "kotlinx.serialization.PolyBase", + assertFailsWith { + json.encodeToString( + MyPolyDataWithPolyBase.serializer(), + MyPolyDataWithPolyBase( + mapOf("a" to PolyDerived("foo")), + PolyDerived("foo") + ), + mode + ) + } + ) + } + + @Test + fun testBindModules() { + val json = Json { serializersModule = (baseAndDerivedModuleAtAny + BaseAndDerivedModule) } + assertJsonFormAndRestored( + expected = """{"data":{"a":{"type":"kotlinx.serialization.PolyDerived","id":1,"s":"foo"}}, + |"polyBase":{"type":"kotlinx.serialization.PolyDerived","id":1,"s":"foo"}}""".trimMargin().lines().joinToString( + "" + ), + data = MyPolyDataWithPolyBase( + mapOf("a" to PolyDerived("foo")), + PolyDerived("foo") + ), + serializer = MyPolyDataWithPolyBase.serializer(), + json = json + ) + } + + @Test + fun testTypeKeyLastInInput() = parametrizedTest { mode -> + val json = Json { serializersModule = (baseAndDerivedModuleAtAny + BaseAndDerivedModule) } + val input = """{"data":{"a":{"id":1,"s":"foo","type":"kotlinx.serialization.PolyDerived"}}, + |"polyBase":{"id":1,"s":"foo","type":"kotlinx.serialization.PolyDerived"}}""".trimMargin().lines().joinToString( + "") + val data = MyPolyDataWithPolyBase( + mapOf("a" to PolyDerived("foo")), + PolyDerived("foo") + ) + assertEquals(data, json.decodeFromString(MyPolyDataWithPolyBase.serializer(), input, mode)) + } +} |