diff options
Diffstat (limited to 'runtime/jvmTest/src/kotlinx/serialization/SerializeFlatTest.kt')
-rw-r--r-- | runtime/jvmTest/src/kotlinx/serialization/SerializeFlatTest.kt | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/runtime/jvmTest/src/kotlinx/serialization/SerializeFlatTest.kt b/runtime/jvmTest/src/kotlinx/serialization/SerializeFlatTest.kt new file mode 100644 index 00000000..7a51bb2b --- /dev/null +++ b/runtime/jvmTest/src/kotlinx/serialization/SerializeFlatTest.kt @@ -0,0 +1,285 @@ +/* + * Copyright 2018 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package kotlinx.serialization + +import org.junit.Test + +// Serializable data class + +@Serializable +data class Data( + val value1: String, + val value2: Int +) + +// Serializable data class with explicit companion object + +@Serializable +data class DataExplicit( + val value1: String, + val value2: Int +) { + companion object +} + +// Regular (non-data) class with var properties + +@Serializable +class Reg { + var value1: String = "" + var value2: Int = 0 +} + +// Specify serializable names + +@Serializable +data class Names( + @SerialName("value1") + val custom1: String, + @SerialName("value2") + val custom2: Int +) + +// Custom serializer + +@Serializable(with= CustomSerializer::class) +data class Custom( + val _value1: String, + val _value2: Int +) + +@Suppress("NAME_SHADOWING") +object CustomSerializer : KSerializer<Custom> { + override val descriptor = object : SerialDescriptor { + override val name = "kotlinx.serialization.Custom" + override val kind: SerialKind = StructureKind.CLASS + override fun getElementName(index: Int) = when(index) { + 0 -> "value1" + 1 -> "value2" + else -> "" + } + override fun getElementIndex(name: String) = when(name) { + "value1" -> 0 + "value2" -> 1 + else -> -1 + } + } + + override fun serialize(encoder: Encoder, obj : Custom) { + val encoder = encoder.beginStructure(descriptor) + encoder.encodeStringElement(descriptor, 0, obj._value1) + encoder.encodeIntElement(descriptor, 1, obj._value2) + encoder.endStructure(descriptor) + } + + override fun deserialize(decoder: Decoder): Custom { + val decoder = decoder.beginStructure(descriptor) + if (decoder.decodeElementIndex(descriptor) != 0) throw java.lang.IllegalStateException() + val value1 = decoder.decodeStringElement(descriptor, 0) + if (decoder.decodeElementIndex(descriptor) != 1) throw java.lang.IllegalStateException() + val value2 = decoder.decodeIntElement(descriptor, 1) + if (decoder.decodeElementIndex(descriptor) != CompositeDecoder.READ_DONE) throw java.lang.IllegalStateException() + decoder.endStructure(descriptor) + return Custom(value1, value2) + } +} + +// External serializer + +// not Serializable !!! +data class ExternalData( + val value1: String, + val value2: Int +) + +@Serializer(forClass= ExternalData::class) +object ExternalSerializer + +// --------- tests and utils --------- + +class SerializeFlatTest() { + @Test + fun testData() { + val out = Out("Data") + out.encode(Data::class.serializer(), Data("s1", 42)) + out.done() + + val inp = Inp("Data") + val data = inp.decode(Data::class.serializer()) + inp.done() + assert(data.value1 == "s1" && data.value2 == 42) + } + + @Test + fun testDataExplicit() { + val out = Out("DataExplicit") + out.encode(DataExplicit::class.serializer(), DataExplicit("s1", 42)) + out.done() + + val inp = Inp("DataExplicit") + val data = inp.decode(DataExplicit::class.serializer()) + inp.done() + assert(data.value1 == "s1" && data.value2 == 42) + } + + @Test + fun testReg() { + val out = Out("Reg") + val reg = Reg(); + reg.value1 = "s1" + reg.value2 = 42 + out.encode(Reg::class.serializer(), reg) + out.done() + + val inp = Inp("Reg") + val data = inp.decode(Reg::class.serializer()) + inp.done() + assert(data.value1 == "s1" && data.value2 == 42) + } + + @Test + fun testNames() { + val out = Out("Names") + out.encode(Names::class.serializer(), Names("s1", 42)) + out.done() + + val inp = Inp("Names") + val data = inp.decode(Names::class.serializer()) + inp.done() + assert(data.custom1 == "s1" && data.custom2 == 42) + } + + @Test + fun testCustom() { + val out = Out("Custom") + out.encode(CustomSerializer, Custom("s1", 42)) + out.done() + + val inp = Inp("Custom") + val data = inp.decode(CustomSerializer) + inp.done() + assert(data._value1 == "s1" && data._value2 == 42) + } + + @Test + fun testExternalData() { + val out = Out("ExternalData") + out.encode(ExternalSerializer, ExternalData("s1", 42)) + out.done() + + val inp = Inp("ExternalData") + val data = inp.decode(ExternalSerializer) + inp.done() + assert(data.value1 == "s1" && data.value2 == 42) + } + + companion object { + fun fail(msg: String): Nothing = throw RuntimeException(msg) + + fun checkDesc(name: String, desc: SerialDescriptor) { + if (desc.name != "kotlinx.serialization." + name) fail("checkDesc name $desc") + if (desc.kind != StructureKind.CLASS) fail("checkDesc kind ${desc.kind}") + if (desc.getElementName(0) != "value1") fail("checkDesc[0] $desc") + if (desc.getElementName(1) != "value2") fail("checkDesc[1] $desc") + } + } + + class Out(private val name: String) : ElementValueEncoder() { + var step = 0 + + override fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeEncoder { + checkDesc(name, desc) + if (step == 0) step++ else fail("@$step: beginStructure($desc)") + return this + } + + override fun encodeElement(desc: SerialDescriptor, index: Int): Boolean { + checkDesc(name, desc) + when (step) { + 1 -> if (index == 0) { step++; return true } + 3 -> if (index == 1) { step++; return true } + } + fail("@$step: encodeElement($desc, $index)") + } + + override fun encodeString(value: String) { + when (step) { + 2 -> if (value == "s1") { step++; return } + } + fail("@$step: encodeString($value)") + } + + override fun encodeInt(value: Int) { + when (step) { + 4 -> if (value == 42) { step++; return } + } + fail("@$step: decodeInt($value)") + } + + override fun endStructure(desc: SerialDescriptor) { + checkDesc(name, desc) + if (step == 5) step++ else fail("@$step: endStructure($desc)") + } + + fun done() { + if (step != 6) fail("@$step: OUT FAIL") + } + } + + class Inp(private val name: String) : ElementValueDecoder() { + var step = 0 + + override fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeDecoder { + checkDesc(name, desc) + if (step == 0) step++ else fail("@$step: beginStructure($desc)") + return this + } + + override fun decodeElementIndex(desc: SerialDescriptor): Int { + checkDesc(name, desc) + when (step) { + 1 -> { step++; return 0 } + 3 -> { step++; return 1 } + 5 -> { step++; return -1 } + } + fail("@$step: decodeElementIndex($desc)") + } + + override fun decodeString(): String { + when (step) { + 2 -> { step++; return "s1" } + } + fail("@$step: decodeString()") + } + + override fun decodeInt(): Int { + when (step) { + 4 -> { step++; return 42 } + } + fail("@$step: decodeInt()") + } + + override fun endStructure(desc: SerialDescriptor) { + checkDesc(name, desc) + if (step == 6) step++ else fail("@$step: endStructure($desc)") + } + + fun done() { + if (step != 7) fail("@$step: INP FAIL") + } + } +} |