xref: /aosp_15_r20/external/auto/common/src/test/java/com/google/auto/common/AnnotationValuesTest.java (revision 1c2bbba85eccddce6de79cbbf1645fda32e723f0)
1 /*
2  * Copyright 2019 Google LLC
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 com.google.auto.common;
17 
18 import static com.google.common.collect.ImmutableList.toImmutableList;
19 import static com.google.common.truth.Truth.assertThat;
20 import static java.util.stream.Collectors.joining;
21 
22 import com.google.common.collect.ImmutableList;
23 import com.google.common.collect.ImmutableMap;
24 import com.google.common.truth.Correspondence;
25 import com.google.testing.compile.CompilationRule;
26 import javax.lang.model.element.AnnotationMirror;
27 import javax.lang.model.element.AnnotationValue;
28 import javax.lang.model.element.Element;
29 import javax.lang.model.element.Name;
30 import javax.lang.model.element.TypeElement;
31 import javax.lang.model.element.VariableElement;
32 import javax.lang.model.type.DeclaredType;
33 import javax.lang.model.type.TypeMirror;
34 import javax.lang.model.util.Elements;
35 import javax.lang.model.util.Types;
36 import org.junit.Before;
37 import org.junit.Rule;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
40 import org.junit.runners.JUnit4;
41 
42 /** Tests {@link AnnotationValues}. */
43 @RunWith(JUnit4.class)
44 public final class AnnotationValuesTest {
45 
46   private @interface InsideAnnotation {
value()47     int value();
48   }
49 
50   private static class GenericClass<T> {}
51 
52   private static class InsideClassA {}
53 
54   private static class InsideClassB {}
55 
56   private @interface MultiValueAnnotation {
classValue()57     Class<InsideClassA> classValue();
58 
classValues()59     Class<?>[] classValues();
60 
genericClassValue()61     Class<?> genericClassValue();
62 
insideAnnotationValue()63     InsideAnnotation insideAnnotationValue();
64 
insideAnnotationValues()65     InsideAnnotation[] insideAnnotationValues();
66 
stringValue()67     String stringValue();
68 
stringValues()69     String[] stringValues();
70 
enumValue()71     Foo enumValue();
72 
enumValues()73     Foo[] enumValues();
74 
intValue()75     int intValue();
76 
intValues()77     int[] intValues();
78 
longValue()79     long longValue();
80 
longValues()81     long[] longValues();
82 
byteValue()83     byte byteValue();
84 
byteValues()85     byte[] byteValues();
86 
shortValue()87     short shortValue();
88 
shortValues()89     short[] shortValues();
90 
floatValue()91     float floatValue();
92 
floatValues()93     float[] floatValues();
94 
doubleValue()95     double doubleValue();
96 
doubleValues()97     double[] doubleValues();
98 
booleanValue()99     boolean booleanValue();
100 
booleanValues()101     boolean[] booleanValues();
102 
charValue()103     char charValue();
104 
charValues()105     char[] charValues();
106   }
107 
108   private enum Foo {
109     BAR,
110     BAZ,
111     BAH;
112   }
113 
114   @MultiValueAnnotation(
115       classValue = InsideClassA.class,
116       classValues = {InsideClassA.class, InsideClassB.class},
117       genericClassValue = GenericClass.class,
118       insideAnnotationValue = @InsideAnnotation(19),
119       insideAnnotationValues = {@InsideAnnotation(20), @InsideAnnotation(21)},
120       stringValue = "hello",
121       stringValues = {"it's", "me"},
122       enumValue = Foo.BAR,
123       enumValues = {Foo.BAZ, Foo.BAH},
124       intValue = 5,
125       intValues = {1, 2},
126       longValue = 6L,
127       longValues = {3L, 4L},
128       byteValue = (byte) 7,
129       byteValues = {(byte) 8, (byte) 9},
130       shortValue = (short) 10,
131       shortValues = {(short) 11, (short) 12},
132       floatValue = 13F,
133       floatValues = {14F, 15F},
134       doubleValue = 16D,
135       doubleValues = {17D, 18D},
136       booleanValue = true,
137       booleanValues = {true, false},
138       charValue = 'a',
139       charValues = {'b', 'c'})
140   private static class AnnotatedClass {}
141 
142   @Rule public final CompilationRule compilation = new CompilationRule();
143 
144   private Elements elements;
145   private Types types;
146   private AnnotationMirror annotationMirror;
147 
148   @Before
setUp()149   public void setUp() {
150     elements = compilation.getElements();
151     types = compilation.getTypes();
152     TypeElement annotatedClass = getTypeElement(AnnotatedClass.class);
153     annotationMirror =
154         MoreElements.getAnnotationMirror(annotatedClass, MultiValueAnnotation.class).get();
155   }
156 
157   @Test
getTypeMirror()158   public void getTypeMirror() {
159     TypeElement insideClassA = getTypeElement(InsideClassA.class);
160     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "classValue");
161     assertThat(AnnotationValues.getTypeMirror(value).asElement()).isEqualTo(insideClassA);
162   }
163 
164   @Test
getTypeMirrorGenericClass()165   public void getTypeMirrorGenericClass() {
166     TypeElement genericClass = getTypeElement(GenericClass.class);
167     AnnotationValue gvalue =
168         AnnotationMirrors.getAnnotationValue(annotationMirror, "genericClassValue");
169     assertThat(AnnotationValues.getTypeMirror(gvalue).asElement()).isEqualTo(genericClass);
170   }
171 
172   @Test
getTypeMirrors()173   public void getTypeMirrors() {
174     TypeMirror insideClassA = getTypeElement(InsideClassA.class).asType();
175     TypeMirror insideClassB = getTypeElement(InsideClassB.class).asType();
176     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "classValues");
177     ImmutableList<DeclaredType> valueElements = AnnotationValues.getTypeMirrors(value);
178     assertThat(valueElements)
179         .comparingElementsUsing(Correspondence.from(types::isSameType, "has Same Type"))
180         .containsExactly(insideClassA, insideClassB)
181         .inOrder();
182   }
183 
184   @Test
getAnnotationMirror()185   public void getAnnotationMirror() {
186     TypeElement insideAnnotation = getTypeElement(InsideAnnotation.class);
187     AnnotationValue value =
188         AnnotationMirrors.getAnnotationValue(annotationMirror, "insideAnnotationValue");
189     AnnotationMirror annotationMirror = AnnotationValues.getAnnotationMirror(value);
190     assertThat(annotationMirror.getAnnotationType().asElement()).isEqualTo(insideAnnotation);
191     assertThat(AnnotationMirrors.getAnnotationValue(annotationMirror, "value").getValue())
192         .isEqualTo(19);
193   }
194 
195   @Test
getAnnotationMirrors()196   public void getAnnotationMirrors() {
197     TypeElement insideAnnotation = getTypeElement(InsideAnnotation.class);
198     AnnotationValue value =
199         AnnotationMirrors.getAnnotationValue(annotationMirror, "insideAnnotationValues");
200     ImmutableList<AnnotationMirror> annotationMirrors =
201         AnnotationValues.getAnnotationMirrors(value);
202     ImmutableList<Element> valueElements =
203         annotationMirrors.stream()
204             .map(AnnotationMirror::getAnnotationType)
205             .map(DeclaredType::asElement)
206             .collect(toImmutableList());
207     assertThat(valueElements).containsExactly(insideAnnotation, insideAnnotation);
208     ImmutableList<Object> valuesStoredInAnnotation =
209         annotationMirrors.stream()
210             .map(
211                 annotationMirror ->
212                     AnnotationMirrors.getAnnotationValue(annotationMirror, "value").getValue())
213             .collect(toImmutableList());
214     assertThat(valuesStoredInAnnotation).containsExactly(20, 21).inOrder();
215   }
216 
217   @Test
getString()218   public void getString() {
219     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "stringValue");
220     assertThat(AnnotationValues.getString(value)).isEqualTo("hello");
221   }
222 
223   @Test
getStrings()224   public void getStrings() {
225     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "stringValues");
226     assertThat(AnnotationValues.getStrings(value)).containsExactly("it's", "me").inOrder();
227   }
228 
229   @Test
getEnum()230   public void getEnum() {
231     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "enumValue");
232     assertThat(AnnotationValues.getEnum(value)).isEqualTo(value.getValue());
233   }
234 
235   @Test
getEnums()236   public void getEnums() {
237     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "enumValues");
238     assertThat(getEnumNames(AnnotationValues.getEnums(value)))
239         .containsExactly(Foo.BAZ.name(), Foo.BAH.name())
240         .inOrder();
241   }
242 
243   @Test
getAnnotationValues()244   public void getAnnotationValues() {
245     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "intValues");
246     ImmutableList<AnnotationValue> values = AnnotationValues.getAnnotationValues(value);
247     assertThat(values)
248         .comparingElementsUsing(Correspondence.transforming(AnnotationValue::getValue, "has value"))
249         .containsExactly(1, 2)
250         .inOrder();
251   }
252 
253   @Test
getInt()254   public void getInt() {
255     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "intValue");
256     assertThat(AnnotationValues.getInt(value)).isEqualTo(5);
257   }
258 
259   @Test
getInts()260   public void getInts() {
261     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "intValues");
262     assertThat(AnnotationValues.getInts(value)).containsExactly(1, 2).inOrder();
263   }
264 
265   @Test
getLong()266   public void getLong() {
267     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "longValue");
268     assertThat(AnnotationValues.getLong(value)).isEqualTo(6L);
269   }
270 
271   @Test
getLongs()272   public void getLongs() {
273     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "longValues");
274     assertThat(AnnotationValues.getLongs(value)).containsExactly(3L, 4L).inOrder();
275   }
276 
277   @Test
getByte()278   public void getByte() {
279     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "byteValue");
280     assertThat(AnnotationValues.getByte(value)).isEqualTo((byte) 7);
281   }
282 
283   @Test
getBytes()284   public void getBytes() {
285     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "byteValues");
286     assertThat(AnnotationValues.getBytes(value)).containsExactly((byte) 8, (byte) 9).inOrder();
287   }
288 
289   @Test
getShort()290   public void getShort() {
291     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "shortValue");
292     assertThat(AnnotationValues.getShort(value)).isEqualTo((short) 10);
293   }
294 
295   @Test
getShorts()296   public void getShorts() {
297     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "shortValues");
298     assertThat(AnnotationValues.getShorts(value)).containsExactly((short) 11, (short) 12).inOrder();
299   }
300 
301   @Test
getFloat()302   public void getFloat() {
303     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "floatValue");
304     assertThat(AnnotationValues.getFloat(value)).isEqualTo(13F);
305   }
306 
307   @Test
getFloats()308   public void getFloats() {
309     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "floatValues");
310     assertThat(AnnotationValues.getFloats(value)).containsExactly(14F, 15F).inOrder();
311   }
312 
313   @Test
getDouble()314   public void getDouble() {
315     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "doubleValue");
316     assertThat(AnnotationValues.getDouble(value)).isEqualTo(16D);
317   }
318 
319   @Test
getDoubles()320   public void getDoubles() {
321     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "doubleValues");
322     assertThat(AnnotationValues.getDoubles(value)).containsExactly(17D, 18D).inOrder();
323   }
324 
325   @Test
getBoolean()326   public void getBoolean() {
327     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "booleanValue");
328     assertThat(AnnotationValues.getBoolean(value)).isTrue();
329   }
330 
331   @Test
getBooleans()332   public void getBooleans() {
333     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "booleanValues");
334     assertThat(AnnotationValues.getBooleans(value)).containsExactly(true, false).inOrder();
335   }
336 
337   @Test
getChar()338   public void getChar() {
339     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "charValue");
340     assertThat(AnnotationValues.getChar(value)).isEqualTo('a');
341   }
342 
343   @Test
getChars()344   public void getChars() {
345     AnnotationValue value = AnnotationMirrors.getAnnotationValue(annotationMirror, "charValues");
346     assertThat(AnnotationValues.getChars(value)).containsExactly('b', 'c').inOrder();
347   }
348 
349   @Test
toSourceString()350   public void toSourceString() {
351     ImmutableMap<String, String> inputs =
352         ImmutableMap.<String, String>builder()
353             .put("classValue", "com.google.auto.common.AnnotationValuesTest.InsideClassA.class")
354             .put(
355                 "classValues",
356                 "{com.google.auto.common.AnnotationValuesTest.InsideClassA.class,"
357                     + " com.google.auto.common.AnnotationValuesTest.InsideClassB.class}")
358             .put(
359                 "genericClassValue",
360                 "com.google.auto.common.AnnotationValuesTest.GenericClass.class")
361             .put(
362                 "insideAnnotationValue",
363                 "@com.google.auto.common.AnnotationValuesTest.InsideAnnotation(19)")
364             .put(
365                 "insideAnnotationValues",
366                 "{@com.google.auto.common.AnnotationValuesTest.InsideAnnotation(20),"
367                     + " @com.google.auto.common.AnnotationValuesTest.InsideAnnotation(21)}")
368             .put("stringValue", "\"hello\"")
369             .put("stringValues", "{\"it\\'s\", \"me\"}")
370             .put("enumValue", "com.google.auto.common.AnnotationValuesTest.Foo.BAR")
371             .put(
372                 "enumValues",
373                 "{com.google.auto.common.AnnotationValuesTest.Foo.BAZ,"
374                     + " com.google.auto.common.AnnotationValuesTest.Foo.BAH}")
375             .put("intValue", "5")
376             .put("intValues", "{1, 2}")
377             .put("longValue", "6L")
378             .put("longValues", "{3L, 4L}")
379             .put("byteValue", "(byte) 7")
380             .put("byteValues", "{(byte) 8, (byte) 9}")
381             .put("shortValue", "(short) 10")
382             .put("shortValues", "{(short) 11, (short) 12}")
383             .put("floatValue", "13.0F")
384             .put("floatValues", "{14.0F, 15.0F}")
385             .put("doubleValue", "16.0")
386             .put("doubleValues", "{17.0, 18.0}")
387             .put("booleanValue", "true")
388             .put("booleanValues", "{true, false}")
389             .put("charValue", "'a'")
390             .put("charValues", "{'b', 'c'}")
391             .build();
392     inputs.forEach(
393         (name, expected) ->
394             assertThat(
395                     AnnotationValues.toString(
396                         AnnotationMirrors.getAnnotationValue(annotationMirror, name)))
397                 .isEqualTo(expected));
398     assertThat(AnnotationMirrors.toString(annotationMirror))
399         .isEqualTo(
400             inputs.entrySet().stream()
401                 .map(e -> e.getKey() + " = " + e.getValue())
402                 .collect(
403                     joining(
404                         ", ",
405                         "@com.google.auto.common.AnnotationValuesTest.MultiValueAnnotation(",
406                         ")")));
407   }
408 
getTypeElement(Class<?> clazz)409   private TypeElement getTypeElement(Class<?> clazz) {
410     return elements.getTypeElement(clazz.getCanonicalName());
411   }
412 
getEnumNames(ImmutableList<VariableElement> values)413   private static ImmutableList<String> getEnumNames(ImmutableList<VariableElement> values) {
414     return values.stream()
415         .map(VariableElement::getSimpleName)
416         .map(Name::toString)
417         .collect(toImmutableList());
418   }
419 }
420