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