Skip to content

Commit 4798072

Browse files
authored
Implemented tests on @KeepGeneratedSerializer annotation (#2758)
1 parent 85b3294 commit 4798072

File tree

1 file changed

+247
-0
lines changed

1 file changed

+247
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
/*
2+
* Copyright 2017-2024 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.serialization
6+
7+
import kotlinx.serialization.descriptors.*
8+
import kotlinx.serialization.encoding.*
9+
import kotlinx.serialization.json.*
10+
import kotlin.jvm.*
11+
import kotlin.test.*
12+
13+
class KeepGeneratedSerializerTest {
14+
@Serializable(with = ValueSerializer::class)
15+
@KeepGeneratedSerializer
16+
@JvmInline
17+
value class Value(val i: Int)
18+
19+
object ValueSerializer: KSerializer<Value> {
20+
override val descriptor = PrimitiveSerialDescriptor("ValueSerializer", PrimitiveKind.INT)
21+
override fun deserialize(decoder: Decoder): Value {
22+
val value = decoder.decodeInt()
23+
return Value(value - 42)
24+
}
25+
override fun serialize(encoder: Encoder, value: Value) {
26+
encoder.encodeInt(value.i + 42)
27+
}
28+
}
29+
30+
@Test
31+
fun testValueClass() {
32+
test(Value(1), "43", "1", Value.serializer(), Value.generatedSerializer())
33+
}
34+
35+
36+
37+
@Serializable(with = DataSerializer::class)
38+
@KeepGeneratedSerializer
39+
data class Data(val i: Int)
40+
41+
object DataSerializer: KSerializer<Data> {
42+
override val descriptor = PrimitiveSerialDescriptor("DataSerializer", PrimitiveKind.INT)
43+
override fun deserialize(decoder: Decoder): Data {
44+
val value = decoder.decodeInt()
45+
return Data(value)
46+
}
47+
override fun serialize(encoder: Encoder, value: Data) {
48+
encoder.encodeInt(value.i)
49+
}
50+
}
51+
52+
@Test
53+
fun testDataClass() {
54+
test(Data(2), "2", "{\"i\":2}", Data.serializer(), Data.generatedSerializer())
55+
}
56+
57+
58+
@Serializable(with = ParentSerializer::class)
59+
@KeepGeneratedSerializer
60+
open class Parent(val p: Int) {
61+
override fun equals(other: Any?): Boolean {
62+
if (this === other) return true
63+
if (other !is Parent) return false
64+
65+
if (p != other.p) return false
66+
67+
return true
68+
}
69+
70+
override fun hashCode(): Int {
71+
return p
72+
}
73+
}
74+
75+
object ParentSerializer: KSerializer<Parent> {
76+
override val descriptor = PrimitiveSerialDescriptor("ParentSerializer", PrimitiveKind.INT)
77+
override fun deserialize(decoder: Decoder): Parent {
78+
val value = decoder.decodeInt()
79+
return Parent(value - 1)
80+
}
81+
override fun serialize(encoder: Encoder, value: Parent) {
82+
encoder.encodeInt(value.p + 1)
83+
}
84+
}
85+
86+
@Serializable
87+
data class Child(val c: Int): Parent(0)
88+
89+
@Serializable(with = ChildSerializer::class)
90+
@KeepGeneratedSerializer
91+
data class ChildWithCustom(val c: Int): Parent(0)
92+
93+
object ChildSerializer: KSerializer<ChildWithCustom> {
94+
override val descriptor = PrimitiveSerialDescriptor("ChildSerializer", PrimitiveKind.INT)
95+
override fun deserialize(decoder: Decoder): ChildWithCustom {
96+
val value = decoder.decodeInt()
97+
return ChildWithCustom(value - 2)
98+
}
99+
100+
override fun serialize(encoder: Encoder, value: ChildWithCustom) {
101+
encoder.encodeInt(value.c + 2)
102+
}
103+
}
104+
105+
@Test
106+
fun testInheritance() {
107+
test(Parent(3), "4", "{\"p\":3}", Parent.serializer(), Parent.generatedSerializer())
108+
test(Child(4), "{\"p\":0,\"c\":4}", "", Child.serializer(), null)
109+
test(ChildWithCustom(5), "7", "{\"p\":0,\"c\":5}", ChildWithCustom.serializer(), ChildWithCustom.generatedSerializer())
110+
}
111+
112+
113+
@Serializable(with = MyEnumSerializer::class)
114+
@KeepGeneratedSerializer
115+
enum class MyEnum {
116+
A,
117+
B,
118+
FALLBACK
119+
}
120+
121+
@Serializable
122+
data class EnumHolder(val e: MyEnum)
123+
124+
object MyEnumSerializer: KSerializer<MyEnum> {
125+
val defaultSerializer = MyEnum.generatedSerializer()
126+
127+
override val descriptor = PrimitiveSerialDescriptor("MyEnumSerializer", PrimitiveKind.INT)
128+
129+
override fun deserialize(decoder: Decoder): MyEnum {
130+
decoder.decodeString()
131+
return MyEnum.A
132+
}
133+
134+
override fun serialize(encoder: Encoder, value: MyEnum) {
135+
// always encode FALLBACK entry by generated serializer
136+
defaultSerializer.serialize(encoder, MyEnum.FALLBACK)
137+
}
138+
}
139+
140+
@Test
141+
fun testEnum() {
142+
test(MyEnum.A, "\"FALLBACK\"", "\"A\"", MyEnum.serializer(), MyEnum.generatedSerializer())
143+
assertTrue(serializer<MyEnum>() is MyEnumSerializer, "serializer<MyEnum> illegal = " + serializer<MyEnum>())
144+
assertTrue(MyEnum.serializer() is MyEnumSerializer, "MyEnum.serializer() illegal = " + MyEnum.serializer())
145+
assertEquals("kotlinx.serialization.internal.EnumSerializer<kotlinx.serialization.KeepGeneratedSerializerTest.MyEnum>", MyEnum.generatedSerializer().toString(), "MyEnum.generatedSerializer() illegal")
146+
assertSame(MyEnum.generatedSerializer(), MyEnum.generatedSerializer(), "MyEnum.generatedSerializer() instance differs")
147+
}
148+
149+
150+
@Serializable(with = ParametrizedSerializer::class)
151+
@KeepGeneratedSerializer
152+
data class ParametrizedData<T>(val t: T)
153+
154+
class ParametrizedSerializer(val serializer: KSerializer<Any>): KSerializer<ParametrizedData<Any>> {
155+
override val descriptor = PrimitiveSerialDescriptor("ParametrizedSerializer", PrimitiveKind.INT)
156+
157+
override fun deserialize(decoder: Decoder): ParametrizedData<Any> {
158+
val value = serializer.deserialize(decoder)
159+
return ParametrizedData(value)
160+
}
161+
162+
override fun serialize(encoder: Encoder, value: ParametrizedData<Any>) {
163+
serializer.serialize(encoder, value.t)
164+
}
165+
}
166+
167+
@Test
168+
fun testParametrized() {
169+
test(
170+
ParametrizedData<Data>(Data(6)), "6", "{\"t\":6}", ParametrizedData.serializer(Data.serializer()), ParametrizedData.generatedSerializer(
171+
Data.serializer()))
172+
}
173+
174+
175+
@Serializable(WithCompanion.Companion::class)
176+
@KeepGeneratedSerializer
177+
data class WithCompanion(val value: Int) {
178+
@Serializer(WithCompanion::class)
179+
companion object {
180+
override val descriptor = PrimitiveSerialDescriptor("WithCompanionDesc", PrimitiveKind.INT)
181+
override fun deserialize(decoder: Decoder): WithCompanion {
182+
val value = decoder.decodeInt()
183+
return WithCompanion(value)
184+
}
185+
186+
override fun serialize(encoder: Encoder, value: WithCompanion) {
187+
encoder.encodeInt(value.value)
188+
}
189+
}
190+
}
191+
192+
@Test
193+
fun testCompanion() {
194+
test(WithCompanion(7), "7", "{\"value\":7}", WithCompanion.serializer(), WithCompanion.generatedSerializer())
195+
}
196+
197+
198+
@Serializable(with = ObjectSerializer::class)
199+
@KeepGeneratedSerializer
200+
object Object
201+
202+
object ObjectSerializer: KSerializer<Object> {
203+
override val descriptor = PrimitiveSerialDescriptor("ObjectSerializer", PrimitiveKind.INT)
204+
205+
override fun deserialize(decoder: Decoder): Object {
206+
decoder.decodeInt()
207+
return Object
208+
}
209+
override fun serialize(encoder: Encoder, value: Object) {
210+
encoder.encodeInt(8)
211+
}
212+
}
213+
214+
@Test
215+
fun testObject() {
216+
test(Object, "8", "{}", Object.serializer(), Object.generatedSerializer())
217+
assertEquals("kotlinx.serialization.KeepGeneratedSerializerTest.Object()", Object.generatedSerializer().descriptor.toString(), "Object.generatedSerializer() illegal")
218+
assertSame(Object.generatedSerializer(), Object.generatedSerializer(), "Object.generatedSerializer() instance differs")
219+
}
220+
221+
222+
223+
inline fun <reified T : Any> test(
224+
value: T,
225+
customJson: String,
226+
keepJson: String,
227+
serializer: KSerializer<T>,
228+
generatedSerializer: KSerializer<T>?
229+
) {
230+
val implicitJson = Json.encodeToString(value)
231+
assertEquals(customJson, implicitJson, "Json.encodeToString(value: ${T::class.simpleName})")
232+
val implicitDecoded = Json.decodeFromString<T>(implicitJson)
233+
assertEquals(value, implicitDecoded, "Json.decodeFromString(json): ${T::class.simpleName}")
234+
235+
val exlicitJson = Json.encodeToString(serializer, value)
236+
assertEquals(customJson, exlicitJson, "Json.encodeToString(${T::class.simpleName}.serializer(), value)")
237+
val explicitDecoded = Json.decodeFromString(serializer, exlicitJson)
238+
assertEquals(value, explicitDecoded, "Json.decodeFromString(${T::class.simpleName}.serializer(), json)")
239+
240+
if (generatedSerializer == null) return
241+
val keep = Json.encodeToString(generatedSerializer, value)
242+
assertEquals(keepJson, keep, "Json.encodeToString(${T::class.simpleName}.generatedSerializer(), value)")
243+
val keepDecoded = Json.decodeFromString(generatedSerializer, keep)
244+
assertEquals(value, keepDecoded, "Json.decodeFromString(${T::class.simpleName}.generatedSerializer(), json)")
245+
}
246+
247+
}

0 commit comments

Comments
 (0)