1 /*
2  * Copyright 2017-2019 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 kotlin.test.*
9 
10 class SerialDescriptorAnnotationsTest {
11 
12     @SerialInfo
13     @Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS)
14     annotation class CustomAnnotation(val value: String)
15 
16     @Serializable
17     @SerialName("MyClass")
18     @CustomAnnotation("onClass")
19     data class WithNames(
20         val a: Int,
21         @CustomAnnotationWithDefault @CustomAnnotation("onProperty") val veryLongName: String
22     )
23 
24     @SerialInfo
25     @Target(AnnotationTarget.PROPERTY, AnnotationTarget.CLASS)
26     annotation class CustomAnnotationWithDefault(val value: String = "default_annotation_value")
27 
28     @SerialInfo
29     @Target(AnnotationTarget.PROPERTY)
30     public annotation class JShort(val order: SByteOrder = SByteOrder.BE, val mod: SByteMod = SByteMod.Add)
31 
32     public enum class SByteOrder {
33         BE, LE
34     }
35 
36     public enum class SByteMod {
37         None, Add
38     }
39 
40     @Serializable
41     public class Foo(
42         @JShort(SByteOrder.LE, SByteMod.None) public val bar: Short,
43         @JShort public val baz: Short
44     )
45 
46 
47     @Test
testSerialNameOnClassnull48     fun testSerialNameOnClass() {
49         val desc = WithNames.serializer().descriptor
50         val name = desc.serialName
51         assertEquals("MyClass", name)
52     }
53 
54     @Test
testCustomSerialAnnotationOnPropertynull55     fun testCustomSerialAnnotationOnProperty() {
56         val desc: SerialDescriptor = WithNames.serializer().descriptor
57         val b = desc.getElementAnnotations(1).getCustom()
58         assertEquals("onProperty", b)
59     }
60 
61     @Test
testCustomSerialAnnotationOnClassnull62     fun testCustomSerialAnnotationOnClass() {
63         val desc: SerialDescriptor = WithNames.serializer().descriptor
64         val name = desc.annotations.getCustom()
65         assertEquals("onClass", name)
66     }
67 
68     @Test
testCustomAnnotationWithDefaultValuenull69     fun testCustomAnnotationWithDefaultValue() {
70         val value =
71             WithNames.serializer().descriptor
72                 .getElementAnnotations(1).filterIsInstance<CustomAnnotationWithDefault>().single()
73         assertEquals("default_annotation_value", value.value)
74     }
75 
76     @Test
testAnnotationWithMultipleArgsnull77     fun testAnnotationWithMultipleArgs() {
78         fun SerialDescriptor.getValues(i: Int) = getElementAnnotations(i).filterIsInstance<JShort>().single().run { order to mod }
79         assertEquals(SByteOrder.LE to SByteMod.None, Foo.serializer().descriptor.getValues(0))
80         assertEquals(SByteOrder.BE to SByteMod.Add, Foo.serializer().descriptor.getValues(1))
81     }
82 
Listnull83     private fun List<Annotation>.getCustom() = filterIsInstance<CustomAnnotation>().single().value
84 
85     @Serializable
86     @CustomAnnotation("sealed")
87     sealed class Result {
88         @Serializable class OK(val s: String): Result()
89     }
90 
91     @Serializable
92     @CustomAnnotation("abstract")
93     abstract class AbstractResult {
94         var result: String = ""
95     }
96 
97     @Serializable
98     @CustomAnnotation("object")
99     object ObjectResult {}
100 
101     @Serializable
102     class Holder(val r: Result, val a: AbstractResult, val o: ObjectResult, @Contextual val names: WithNames)
103 
doTestnull104     private fun doTest(position: Int, expected: String) {
105         val desc = Holder.serializer().descriptor.getElementDescriptor(position)
106         assertEquals(expected, desc.annotations.getCustom())
107     }
108 
109     @Test
testCustomAnnotationOnSealedClassnull110     fun testCustomAnnotationOnSealedClass() = doTest(0, "sealed")
111 
112     @Test
113     fun testCustomAnnotationOnPolymorphicClass() = doTest(1, "abstract")
114 
115     @Test
116     fun testCustomAnnotationOnObject() = doTest(2, "object")
117 
118     @Test
119     fun testCustomAnnotationTransparentForContextual() = doTest(3, "onClass")
120 }
121