• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package kotlinx.serialization
2 
3 import org.junit.Test
4 import kotlinx.serialization.json.Json
5 import kotlinx.serialization.modules.SerializersModule
6 import kotlinx.serialization.modules.polymorphic
7 import kotlinx.serialization.modules.subclass
8 import kotlin.test.assertEquals
9 import kotlin.test.assertFailsWith
10 import kotlin.test.assertTrue
11 
12 class JvmMissingFieldsExceptionTest {
13     @Serializable
14     data class Generic<out T1, out T2, out T3>(val f1: T1, val f2: T2, val f3: T3)
15 
16     @Serializable
17     sealed class Parent(val p1: Int, val p2: Int = 2, val p3: Int) {
18         @Serializable
19         @SerialName("child")
20         data class Child(val c1: Int = 1, val c2: Int, val c3: Int = 3) : Parent(c1 + 1, 2, 3)
21     }
22 
23     @Serializable
24     open class ShortPlaneClass(val f1: Int, val f2: Int, val f3: Int = 3, val f4: Int)
25 
26     @Serializable
27     class WithTransient(val f1: Int, @Transient val f2: Int = 2, val f3: Int, val f4: Int)
28 
29     @Serializable
30     abstract class SimpleAbstract(val p1: Int, val p2: Int)
31 
32     @Serializable
33     @SerialName("a")
34     data class ChildA(val c1: Int, val c2: Int = 2, val c3: Int) : SimpleAbstract(0, 10)
35 
36     @Serializable
37     data class PolymorphicWrapper(@Polymorphic val nested: SimpleAbstract)
38 
39     @Serializable
40     class BigPlaneClass(
41             val f0: Int,
42             val f5: Int = 5,
43             val f6: Int,
44             val f7: Int = 7,
45             val f8: Int,
46             val f9: Int,
47             val f10: Int,
48             val f11: Int,
49             val f12: Int,
50             val f13: Int,
51             val f14: Int,
52             val f15: Int,
53             val f16: Int,
54             val f17: Int,
55             val f18: Int,
56             val f19: Int,
57             val f20: Int,
58             val f21: Int,
59             val f22: Int,
60             val f23: Int,
61             val f24: Int,
62             val f25: Int,
63             val f26: Int,
64             val f27: Int,
65             val f28: Int,
66             val f29: Int,
67             val f30: Int,
68             val f31: Int,
69             val f32: Int,
70             val f33: Int,
71             val f34: Int,
72             val f35: Int,
73     ) : ShortPlaneClass(1, 2, 3, 4)
74 
75     @Test
testShortPlaneClassnull76     fun testShortPlaneClass() {
77         assertFailsWithMessages(listOf("f2", "f4")) {
78             Json.decodeFromString<ShortPlaneClass>("""{"f1":1}""")
79         }
80     }
81 
82     @Test
testBigPlaneClassnull83     fun testBigPlaneClass() {
84         val missedFields = MutableList(36) { "f$it" }
85         val definedInJsonFields = arrayOf("f1", "f15", "f34")
86         val optionalFields = arrayOf("f3", "f5", "f7")
87         missedFields.removeAll(definedInJsonFields)
88         missedFields.removeAll(optionalFields)
89         assertFailsWithMessages(missedFields) {
90             Json.decodeFromString<BigPlaneClass>("""{"f1":1, "f15": 15, "f34": 34}""")
91         }
92     }
93 
94     @Test
testAnnotatedPolymorphicnull95     fun testAnnotatedPolymorphic() {
96         val module = SerializersModule {
97             polymorphic(SimpleAbstract::class, null) {
98                 subclass(ChildA::class)
99             }
100         }
101 
102         assertFailsWithMessages(listOf("p2", "c3")) {
103             Json {
104                 serializersModule = module
105             }.decodeFromString<PolymorphicWrapper>("""{"nested": {"type": "a", "p1": 1, "c1": 11}}""")
106         }
107     }
108 
109 
110     @Test
testSealednull111     fun testSealed() {
112         assertFailsWithMessages(listOf("p3", "c2")) {
113             Json.decodeFromString<Parent>("""{"type": "child", "p1":1, "c1": 11}""")
114         }
115     }
116 
117     @Test
testTransientnull118     fun testTransient() {
119         assertFailsWithMessages(listOf("f3", "f4")) {
120             Json.decodeFromString<WithTransient>("""{"f1":1}""")
121         }
122     }
123 
124     @Test
testGenericnull125     fun testGeneric() {
126         assertFailsWithMessages(listOf("f2", "f3")) {
127             Json.decodeFromString<Generic<Int, Int, Int>>("""{"f1":1}""")
128         }
129     }
130 
131 
assertFailsWithMessagesnull132     private inline fun assertFailsWithMessages(fields: List<String>, block: () -> Unit) {
133         val exception = assertFailsWith(MissingFieldException::class, null, block)
134         val missedMessages = fields.filter { !exception.message!!.contains(it) }
135         assertEquals(exception.missingFields.sorted(), fields.sorted())
136         assertTrue(missedMessages.isEmpty(), "Expected message '${exception.message}' to contain substrings $fields")
137     }
138 }
139