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