
commonTest.kotlinx.serialization.modules.ModuleBuildersTest.kt Maven / Gradle / Ivy
/*
* Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
@file:Suppress("UNCHECKED_CAST")
package kotlinx.serialization.modules
import kotlinx.serialization.*
import kotlinx.serialization.builtins.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlin.reflect.*
import kotlin.test.*
class ModuleBuildersTest {
@Serializable
class A(val i: Int)
@Serializable
class B(val b: String)
@Serializer(forClass = A::class)
object ASerializer : KSerializer
@Serializer(forClass = B::class)
object BSerializer : KSerializer
private fun SerializersModule.assertModuleHas(aSerializer: Boolean = false, bSerializer: Boolean = false) {
with(this) {
assertSame(if (aSerializer) ASerializer else null, getContextual(A::class))
assertSame(if (bSerializer) BSerializer else null, getContextual(B::class))
}
}
@Test
fun testSingletonModule() {
val module = serializersModuleOf(A::class, ASerializer)
module.assertModuleHas(
aSerializer = true,
bSerializer = false
)
}
@Test
fun testMapModule() {
val module1 = serializersModuleOf(BSerializer)
module1.assertModuleHas(
aSerializer = false,
bSerializer = true
)
SerializersModule {
contextual(ASerializer)
contextual(BSerializer)
}.assertModuleHas(
aSerializer = true,
bSerializer = true
)
(module1 + serializersModuleOf(A::class, ASerializer)).assertModuleHas(
aSerializer = true,
bSerializer = true
)
}
@Test
fun testCompositeModule() {
val moduleA = serializersModuleOf(ASerializer)
val moduleB = serializersModuleOf(BSerializer)
(moduleA + moduleB).assertModuleHas(
aSerializer = true,
bSerializer = true
)
var composite = SerializersModule { }
composite.assertModuleHas(
aSerializer = false,
bSerializer = false
)
composite += moduleA
composite.assertModuleHas(
aSerializer = true,
bSerializer = false
)
composite += moduleB
composite.assertModuleHas(
aSerializer = true,
bSerializer = true
)
}
@Test
fun testDSL() {
val module = SerializersModule {
contextual(A::class, ASerializer)
}
module.assertModuleHas(aSerializer = true, bSerializer = false)
}
@Test
fun testPolymorphicDSL() {
val module1 = SerializersModule {
polymorphic(PolyBase::class, PolyBase.serializer()) {
subclass(PolyDerived.serializer())
}
polymorphic(Any::class, baseSerializer = null) {
subclass(PolyBase.serializer())
subclass(PolyDerived.serializer())
}
}
val module2 = SerializersModule {
polymorphic(Any::class) {
subclass(PolyBase::class)
subclass(PolyDerived.serializer())
}
polymorphic(PolyBase::class) {
subclass(PolyBase.serializer())
subclass(PolyDerived::class)
}
}
val base = PolyBase(10)
val derived = PolyDerived("foo")
listOf(module1, module2).forEachIndexed { index, module ->
fun assertPoly(serializer: KSerializer, base: KClass , obj: T) =
assertEquals(
serializer,
module.getPolymorphic(base, obj),
"No serializer for ${obj::class} with base $base in module ${index + 1}:"
)
assertPoly(PolyBase.serializer(), PolyBase::class, base)
assertPoly(PolyDerived.serializer(), PolyBase::class, derived)
assertPoly(PolyBase.serializer(), Any::class, base)
assertPoly(PolyDerived.serializer(), Any::class, derived)
}
}
@Test
fun testOverwriteSerializer() {
val moduleA = SerializersModule {
contextual(A::class, ASerializer)
assertFailsWith {
contextual(A::class, object : KSerializer by A.serializer() {})
}
}
moduleA.assertModuleHas(aSerializer = true, bSerializer = false)
}
@Test
fun testOverwriteIsRightBiased() {
val incorrect = serializersModuleOf(A::class as KClass, BSerializer as KSerializer)
val correct = serializersModuleOf(ASerializer)
correct.assertModuleHas(aSerializer = true, bSerializer = false)
val sum = incorrect overwriteWith correct
sum.assertModuleHas(aSerializer = true, bSerializer = false)
}
@Test
fun testPlusThrowsExceptionOnDuplication() {
val incorrect = serializersModuleOf(A::class as KClass, BSerializer as KSerializer)
val correct = serializersModuleOf(ASerializer)
correct.assertModuleHas(aSerializer = true, bSerializer = false)
assertFailsWith {
incorrect + correct
}
}
@Serializable
@SerialName("C")
class C
@Serializer(forClass = C::class)
object CSerializer : KSerializer {
override val descriptor: SerialDescriptor = buildSerialDescriptor("AnotherName", StructureKind.OBJECT)
}
@Serializer(forClass = C::class)
object CSerializer2 : KSerializer {
override val descriptor: SerialDescriptor = buildSerialDescriptor("C", StructureKind.OBJECT)
}
@Test
fun testOverwriteWithDifferentSerialName() {
val m1 = SerializersModule {
polymorphic(Any::class) {
subclass(C::class, CSerializer)
}
}
val m2 = SerializersModule {
polymorphic(Any::class) {
subclass(C::class, C.serializer())
}
}
assertEquals(CSerializer, m1.getPolymorphic(Any::class, serializedClassName = "AnotherName"))
assertFailsWith { m1 + m2 }
val result = m1 overwriteWith m2
assertEquals(C.serializer(), result.getPolymorphic(Any::class, C()))
assertEquals(C.serializer(), result.getPolymorphic(Any::class, serializedClassName = "C"))
assertNull(result.getPolymorphic(Any::class, serializedClassName = "AnotherName"))
}
@Test
fun testOverwriteWithSameSerialName() {
val m1 = SerializersModule {
polymorphic(Any::class) {
subclass(C::class, C.serializer())
}
}
val m2 = SerializersModule {
polymorphic(Any::class) {
subclass(C::class, CSerializer2)
}
}
assertEquals(C.serializer(), m1.getPolymorphic(Any::class, serializedClassName = "C"))
assertEquals(CSerializer2, m2.getPolymorphic(Any::class, serializedClassName = "C"))
assertFailsWith { m1 + m2 }
val result = m1 overwriteWith m2
assertEquals(CSerializer2, result.getPolymorphic(Any::class, C()))
assertEquals(CSerializer2, result.getPolymorphic(Any::class, serializedClassName = "C"))
}
@Test
fun testDoesntThrowOnTheSameSerializer() {
val m1 = serializersModuleOf(A::class, A.serializer())
val m2 = serializersModuleOf(A::class, A.serializer())
val aggregate = m1 + m2
assertEquals(A.serializer(), aggregate.getContextual(A::class))
}
@Test
fun testDoesntThrowOnTheEqualSerializers() {
val delegate = object : KSerializer by Unit.serializer() {
override fun equals(other: Any?): Boolean = (other is KSerializer<*>) && other.descriptor == descriptor
}
val delegate2 = object : KSerializer by Unit.serializer() {
override fun equals(other: Any?): Boolean = (other is KSerializer<*>) && other.descriptor == descriptor
}
val m1 = serializersModuleOf(Unit::class, delegate)
val m2 = serializersModuleOf(Unit::class, delegate2)
val aggregate = m1 + m2
assertEquals(delegate2, aggregate.getContextual(Unit::class))
assertEquals(delegate, aggregate.getContextual(Unit::class))
}
@Test
fun testThrowOnTheSamePolymorphicSerializer() {
val m1 = SerializersModule { polymorphic(Any::class) { subclass(A.serializer()) } }
val m2 = SerializersModule { polymorphic(Any::class) { subclass(ASerializer) } }
assertFailsWith { m1 + m2 }
}
@Test
fun testDoesntThrowOnEqualPolymorphicSerializer() {
val delegate = object : KSerializer by Unit.serializer() {
override fun equals(other: Any?): Boolean = (other is KSerializer<*>) && other.descriptor == descriptor
}
val delegate2 = object : KSerializer by Unit.serializer() {
override fun equals(other: Any?): Boolean = (other is KSerializer<*>) && other.descriptor == descriptor
}
assertEquals(delegate as Any, delegate2 as Any)
val m1 = SerializersModule { polymorphic(Any::class) { subclass(delegate) } }
val m2 = SerializersModule { polymorphic(Any::class) { subclass(delegate2) } }
val aggregate = m1 + m2
assertEquals(delegate2, aggregate.getPolymorphic(Any::class, Unit))
assertEquals(delegate, aggregate.getPolymorphic(Any::class, Unit))
}
@Test
fun testPolymorphicCollision() {
val m1 = SerializersModule {
polymorphic(Any::class) {
defaultDeserializer { _ -> Unit.serializer() }
}
}
val m2 = SerializersModule {
polymorphic(Any::class) {
defaultDeserializer { _ -> Unit.serializer() }
}
}
assertFailsWith { m1 + m2 }
}
@Test
fun testNoPolymorphicCollision() {
val defaultSerializerProvider = { _: String? -> Unit.serializer() }
val m1 = SerializersModule {
polymorphic(Any::class) {
defaultDeserializer(defaultSerializerProvider)
}
}
val m2 = m1 + m1
assertEquals(Unit.serializer(), m2.getPolymorphic(Any::class, serializedClassName = "foo"))
}
@Test
fun testBothPolymorphicDefaults() {
val anySerializer = object : KSerializer {
override val descriptor: SerialDescriptor get() = error("descriptor")
override fun serialize(encoder: Encoder, value: Any): Unit = error("serialize")
override fun deserialize(decoder: Decoder): Any = error("deserialize")
}
val module = SerializersModule {
polymorphicDefaultDeserializer(Any::class) { _ -> anySerializer }
polymorphicDefaultSerializer(Any::class) { _ -> anySerializer }
}
assertEquals(anySerializer, module.getPolymorphic(Any::class, 42))
assertEquals(anySerializer, module.getPolymorphic(Any::class, serializedClassName = "42"))
}
@Test
fun testPolymorphicForStandardSubtypesOfAny() {
val serializer = object : KSerializer by Int.serializer() {}
val module = SerializersModule {
polymorphic(Any::class) {
subclass(serializer)
}
}
assertSame(serializer, module.getPolymorphic(Any::class, 42))
assertSame(serializer, module.getPolymorphic(Any::class, serializedClassName = "kotlin.Int"))
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy