1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.processor
17 
18 import android.processor.IntDefProcessor.IntDefMapping
19 import com.google.common.collect.ObjectArrays.concat
20 import com.google.testing.compile.CompilationSubject.assertThat
21 import com.google.testing.compile.Compiler.javac
22 import com.google.testing.compile.JavaFileObjects
23 import junit.framework.Assert.assertEquals
24 import org.junit.Test
25 import java.io.StringWriter
26 import javax.tools.JavaFileObject
27 import javax.tools.StandardLocation.SOURCE_OUTPUT
28 
29 /**
30  * Tests for [IntDefProcessor]
31  */
32 class IntDefProcessorTest {
33     private val mAnnotations = arrayOf<JavaFileObject>(
34             JavaFileObjects.forSourceLines("android.annotation.IntDef",
35                     "package android.annotation;",
36                     "import java.lang.annotation.Retention;",
37                     "import java.lang.annotation.Target;",
38                     "import static java.lang.annotation.ElementType.ANNOTATION_TYPE;",
39                     "import static java.lang.annotation.RetentionPolicy.SOURCE;",
40                     "@Retention(SOURCE)",
41                     "@Target({ANNOTATION_TYPE})",
42                     "public @interface IntDef {",
43                     "    String[] prefix() default {};",
44                     "    String[] suffix() default {};",
45                     "    int[] value() default {};",
46                     "    boolean flag() default false;",
47                     "}")
48     )
49 
50     @Test
annotationProcessorGeneratesMappingnull51     public fun annotationProcessorGeneratesMapping() {
52         val sources: Array<JavaFileObject> = arrayOf(
53                 JavaFileObjects.forSourceLines(
54                         "com.android.server.accessibility.magnification.MagnificationGestureMatcher",
55                         "package com.android.server.accessibility.magnification;",
56                         "import android.annotation.IntDef;",
57                         "import java.lang.annotation.Retention;",
58                         "import java.lang.annotation.RetentionPolicy;",
59                         "class MagnificationGestureMatcher {",
60                         "    private static final int GESTURE_BASE = 100;",
61                         "    public static final int GESTURE_TWO_FINGER_DOWN = GESTURE_BASE + 1;",
62                         "    public static final int GESTURE_SWIPE = GESTURE_BASE + 2;",
63                         "    @IntDef(prefix = {\"GESTURE_MAGNIFICATION_\"}, value = {",
64                         "            GESTURE_TWO_FINGER_DOWN,",
65                         "            GESTURE_SWIPE",
66                         "    })",
67                         "    @Retention(RetentionPolicy.SOURCE)",
68                         "    @interface GestureId {}",
69                         "}"
70                 ),
71                 JavaFileObjects.forSourceLines(
72                         "android.service.storage.ExternalStorageService",
73                         "package android.service.storage;",
74                         "import android.annotation.IntDef;",
75                         "import java.lang.annotation.Retention;",
76                         "import java.lang.annotation.RetentionPolicy;",
77                         "class MagnificationGestureMatcher {",
78                         "    public static final int FLAG_SESSION_TYPE_FUSE = 1 << 0;",
79                         "    public static final int FLAG_SESSION_ATTRIBUTE_INDEXABLE = 1 << 1;",
80                         "    @IntDef(flag = true, prefix = {\"FLAG_SESSION_\"},",
81                         "        value = {FLAG_SESSION_TYPE_FUSE, FLAG_SESSION_ATTRIBUTE_INDEXABLE})",
82                         "    @Retention(RetentionPolicy.SOURCE)",
83                         "    public @interface SessionFlag {}",
84                         "}"
85                 )
86         )
87 
88         val expectedFile = """
89             {
90               "com.android.server.accessibility.magnification.MagnificationGestureMatcher.GestureId": {
91                 "flag": false,
92                 "values": {
93                   "101": "GESTURE_TWO_FINGER_DOWN",
94                   "102": "GESTURE_SWIPE"
95                 }
96               },
97               "android.service.storage.MagnificationGestureMatcher.SessionFlag": {
98                 "flag": true,
99                 "values": {
100                   "1": "FLAG_SESSION_TYPE_FUSE",
101                   "2": "FLAG_SESSION_ATTRIBUTE_INDEXABLE"
102                 }
103               }
104             }
105 
106         """.trimIndent()
107 
108         val filesToCompile = concat(mAnnotations, sources, JavaFileObject::class.java)
109 
110         val compilation = javac()
111                 .withProcessors(IntDefProcessor())
112                 .compile(filesToCompile.toMutableList())
113 
114         assertThat(compilation).succeeded()
115         assertThat(compilation).generatedFile(SOURCE_OUTPUT, "com.android.winscope",
116                 "intDefMapping.json").contentsAsUtf8String().isEqualTo(expectedFile)
117     }
118 
119     @Test
serializesMappingCorrectlynull120     public fun serializesMappingCorrectly() {
121         val map = linkedMapOf(
122             "SimpleIntDef" to IntDefMapping(linkedMapOf(
123                 0x0001 to "VAL_1",
124                 0x0002 to "VAL_2",
125                 0x0003 to "VAL_3"
126             ), flag = false),
127             "Flags" to IntDefMapping(linkedMapOf(
128                 0b0001 to "PRIVATE_FLAG_1",
129                 0b0010 to "PRIVATE_FLAG_2",
130                 0b0100 to "PRIVATE_FLAG_3"
131             ), flag = true)
132         )
133 
134         val writer = StringWriter()
135         IntDefProcessor.serializeTo(map, writer)
136 
137         val actualOutput = writer.toString()
138         val expectedOutput = """
139             {
140               "SimpleIntDef": {
141                 "flag": false,
142                 "values": {
143                   "1": "VAL_1",
144                   "2": "VAL_2",
145                   "3": "VAL_3"
146                 }
147               },
148               "Flags": {
149                 "flag": true,
150                 "values": {
151                   "1": "PRIVATE_FLAG_1",
152                   "2": "PRIVATE_FLAG_2",
153                   "4": "PRIVATE_FLAG_3"
154                 }
155               }
156             }
157 
158         """.trimIndent()
159 
160         assertEquals(actualOutput, expectedOutput)
161     }
162 }