Thu, 25 Jul 2013 11:02:27 +0200
8007961: javax.lang.model tests for repeating annotations fail in getAnnotationsByType
Reviewed-by: jjg
1 /*
2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
24 import java.lang.annotation.Annotation;
25 import java.util.Arrays;
26 import java.util.EnumSet;
27 import java.util.List;
28 import java.util.Set;
29 import javax.annotation.processing.*;
30 import javax.lang.model.element.*;
31 import javax.lang.model.type.MirroredTypeException;
32 import javax.lang.model.type.TypeMirror;
33 import javax.lang.model.util.Elements;
35 public class ElementRepAnnoTester extends JavacTestingAbstractProcessor {
36 // All methods to test.
37 final EnumSet<TestMethod> ALL_TEST_METHODS = EnumSet.allOf(TestMethod.class);
38 int count = 0;
39 int error = 0;
41 public boolean process(Set<? extends TypeElement> annotations,
42 RoundEnvironment roundEnv) {
43 if (!roundEnv.processingOver()) {
44 List<String> superClass = Arrays.asList("A", "B", "C", "D", "E",
45 "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P");
46 // Go through all test classes
47 for (Element element : roundEnv.getRootElements()) {
48 // For now, no testing super classes (TODO)
49 if (element.getKind() == ElementKind.CLASS
50 && !superClass.contains(element.getSimpleName().toString())) {
51 // Compare expected and actual values from methods.
52 checkAnnoValues(element, ALL_TEST_METHODS);
53 // Now, look for enclosed elements in test classes.
54 for (Element elements : element.getEnclosedElements()) {
55 // Look for Methods annotations.
56 if (elements.getKind() == ElementKind.METHOD
57 && elements.getSimpleName().toString().equals("testMethod")) {
58 checkAnnoValues(elements, ALL_TEST_METHODS);
59 }
60 // Look for Field annotations.
61 if (elements.getKind() == ElementKind.FIELD
62 && elements.getSimpleName().toString().equals("testField")) {
63 checkAnnoValues(elements, ALL_TEST_METHODS);
64 }
65 }
66 }
67 }
69 if (error != 0) {
70 System.out.println("Total tests : " + count);
71 System.out.println("Total test failures : " + error);
72 throw new RuntimeException();
73 } else {
74 System.out.println("ALL TESTS PASSED. " + count);
75 }
76 }
77 return true;
78 }
80 enum TestMethod {
81 getAnnotation,
82 getAnnotationsByType,
83 getAllAnnotationMirrors,
84 getAnnotationMirrors
85 }
87 protected void checkAnnoValues(Element element, EnumSet<TestMethod> testMethods) {
88 boolean baseAnnoPresent = false;
89 boolean conAnnoPresent = false;
90 ExpectedBase eb = null;
91 ExpectedContainer ec = null;
92 // Getting the expected values to compare with.
93 eb = element.getAnnotation(ExpectedBase.class);
94 ec = element.getAnnotation(ExpectedContainer.class);
96 if (eb == null) {
97 System.out.println("Did not find ExpectedBase Annotation in "
98 + element.getSimpleName().toString() + ", Test will exit");
99 throw new RuntimeException();
100 }
101 if (ec == null) {
102 System.out.println("Did not find ExpectedContainer Annotation in "
103 + element.getSimpleName().toString() + " Test will exit");
104 throw new RuntimeException();
105 }
106 // Look if all test cases have ExpectedBase and ExpectedContainer values().
107 TypeMirror valueBase = null;
108 TypeMirror valueCon = null;
110 try {
111 eb.value();
112 } catch (MirroredTypeException mte) {
113 valueBase = mte.getTypeMirror();
114 }
116 try {
117 ec.value();
118 } catch (MirroredTypeException mte1) {
119 valueCon = mte1.getTypeMirror();
120 }
122 String expectedBaseAnno = valueBase.toString();
123 String expectedConAnno = valueCon.toString();
125 if (!expectedBaseAnno.equals("java.lang.annotation.Annotation")) {
126 baseAnnoPresent = true;
127 }
128 if (!expectedConAnno.equalsIgnoreCase("java.lang.annotation.Annotation")) {
129 conAnnoPresent = true;
130 }
132 // Look into TestMethod and compare method's output with expected values.
133 for (TestMethod testMethod : testMethods) {
134 boolean isBasePass = true;
135 boolean isConPass = true;
137 switch (testMethod) {
138 case getAnnotation:
139 if (baseAnnoPresent) {
140 count++;
141 Annotation actualAnno = getAnnotationBase(element);
142 String expectedAnno = eb.getAnnotation();
143 isBasePass = compareAnnotation(actualAnno, expectedAnno);
144 }
145 if (conAnnoPresent) {
146 count++;
147 Annotation actualAnno = getAnnotationContainer(element);
148 String expectedAnno = ec.getAnnotation();
149 isConPass = compareAnnotation(actualAnno, expectedAnno);
150 }
151 if (!isBasePass || !isConPass) {
152 System.out.println("FAIL in " + element.getSimpleName()
153 + "-" + element.getKind()
154 + " method: getAnnotation(class <T>)");
155 error++;
156 }
157 break;
159 case getAnnotationMirrors:
160 if (baseAnnoPresent) {
161 count++;
162 List<? extends AnnotationMirror> actualDeclAnnos =
163 element.getAnnotationMirrors();
164 String[] expectedAnnos = eb.getAnnotationMirrors();
165 isBasePass = compareArrVals(actualDeclAnnos, expectedAnnos);
166 }
167 if (conAnnoPresent) {
168 isConPass = true;
169 }
170 if (!isBasePass || !isConPass) {
171 System.out.println("FAIL in " + element.getSimpleName()
172 + "-" + element.getKind()
173 + " method: getAnnotationMirrors()");
174 error++;
175 }
176 break;
178 case getAnnotationsByType:
179 if (baseAnnoPresent) {
180 count++;
181 Annotation[] actualAnnosArgs = getAnnotationsBase(element);
182 String[] expectedAnnos = eb.getAnnotationsByType();
183 isBasePass = compareArrVals(actualAnnosArgs, expectedAnnos);
184 }
185 if (conAnnoPresent) {
186 count++;
187 Annotation[] actualAnnosArgs = getAnnotationsContainer(element);
188 String[] expectedAnnos = ec.getAnnotationsByType();
189 isConPass = compareArrVals(actualAnnosArgs, expectedAnnos);
190 }
191 if (!isBasePass || !isConPass) {
192 System.out.println("FAIL in " + element.getSimpleName()
193 + "-" + element.getKind()
194 + " method: getAnnotationsByType(class <T>)");
195 error++;
196 }
197 break;
199 case getAllAnnotationMirrors:
200 if (baseAnnoPresent) {
201 count++;
202 Elements elements = processingEnv.getElementUtils();
203 List<? extends AnnotationMirror> actualAnnosMirrors =
204 elements.getAllAnnotationMirrors(element);
205 String[] expectedAnnos = eb.getAllAnnotationMirrors();
206 isBasePass = compareArrVals(actualAnnosMirrors, expectedAnnos);
207 }
208 if (conAnnoPresent) {
209 isConPass = true;
210 }
211 if (!isBasePass || !isConPass) {
212 System.out.println("FAIL in " + element.getSimpleName()
213 + "-" + element.getKind()
214 + " method: getAllAnnotationMirrors(e)");
215 error++;
216 }
217 break;
218 }
219 }
220 }
221 // Sort tests to be run with different anno processors.
222 final List<String> singularAnno = Arrays.asList(
223 "SingularBasicTest"
224 );
225 final List<String> singularInheritedAnno = Arrays.asList(
226 "SingularInheritedATest"
227 );
228 final List<String> repeatableAnno = Arrays.asList(
229 "RepeatableBasicTest",
230 "MixRepeatableAndOfficialContainerBasicTest",
231 "OfficialContainerBasicTest",
232 "RepeatableOfficialContainerBasicTest"
233 );
234 final List<String> repeatableInheritedAnno = Arrays.asList(
235 "RepeatableInheritedTest",
236 "RepeatableOverrideATest",
237 "RepeatableOverrideBTest",
238 "OfficialContainerInheritedTest",
239 "MixRepeatableAndOfficialContainerInheritedA1Test",
240 "MixRepeatableAndOfficialContainerInheritedB1Test",
241 "MixRepeatableAndOfficialContainerInheritedA2Test",
242 "MixRepeatableAndOfficialContainerInheritedB2Test"
243 );
244 final List<String> repeatableContainerInheritedAnno = Arrays.asList(
245 "RepeatableOfficialContainerInheritedTest"
246 );
247 final List<String> unofficialAnno = Arrays.asList(
248 "UnofficialContainerBasicTest",
249 "MixSingularAndUnofficialContainerBasicTest"
250 );
251 final List<String> unofficialInheritedAnno = Arrays.asList(
252 "UnofficialContainerInheritedTest",
253 "SingularInheritedBTest",
254 "MixSingularAndUnofficialContainerInheritedA1Test",
255 "MixSingularAndUnofficialContainerInheritedB1Test",
256 "MixSingularAndUnofficialContainerInheritedA2Test",
257 "MixSingularAndUnofficialContainerInheritedB2Test"
258 );
259 // Respective container annotation for the different test cases to test.
260 final List<String> repeatableAnnoContainer = repeatableAnno;
261 final List<String> repeatableInheritedAnnoContainer = repeatableInheritedAnno;
262 final List<String> repeatableContainerInheritedAnnoContainer =
263 repeatableContainerInheritedAnno;
264 final List<String> unofficialAnnoContainer = unofficialAnno;
265 final List<String> unofficialInheritedAnnoContainer = unofficialInheritedAnno;
267 // Variables to verify if all test cases have been run.
268 private Annotation specialAnno = new Annotation() {
269 @Override
270 public Class annotationType() {
271 return null;
272 }
273 };
274 private Annotation[] specialAnnoArray = new Annotation[1];
275 private List<AnnotationMirror> specialAnnoMirrors =
276 new java.util.ArrayList<AnnotationMirror>(2);
278 private Annotation getAnnotationBase(Element e) {
279 Annotation actualAnno = specialAnno;
281 if (singularAnno.contains(
282 e.getEnclosingElement().toString())
283 || singularAnno.contains(
284 e.getSimpleName().toString())
285 || unofficialAnno.contains(
286 e.getEnclosingElement().toString())
287 || unofficialAnno.contains(
288 e.getSimpleName().toString())) {
289 actualAnno = e.getAnnotation(Foo.class);
290 }
291 if (singularInheritedAnno.contains(
292 e.getEnclosingElement().toString())
293 || singularInheritedAnno.contains(
294 e.getSimpleName().toString())
295 || unofficialInheritedAnno.contains(
296 e.getEnclosingElement().toString())
297 || unofficialInheritedAnno.contains(
298 e.getSimpleName().toString())) {
299 actualAnno = e.getAnnotation(FooInherited.class);
300 }
301 if (repeatableAnno.contains(
302 e.getEnclosingElement().toString())
303 || repeatableAnno.contains(
304 e.getSimpleName().toString())) {
305 actualAnno = e.getAnnotation(Bar.class);
306 }
307 if (repeatableInheritedAnno.contains(
308 e.getEnclosingElement().toString())
309 || repeatableInheritedAnno.contains(
310 e.getSimpleName().toString())) {
311 actualAnno = e.getAnnotation(BarInherited.class);
312 }
313 if (repeatableContainerInheritedAnno.contains(
314 e.getEnclosingElement().toString())
315 || repeatableContainerInheritedAnno.contains(
316 e.getSimpleName().toString())) {
317 actualAnno = e.getAnnotation(BarInheritedContainer.class);
318 }
319 return actualAnno;
320 }
322 private Annotation getAnnotationContainer(Element e) {
323 Annotation actualAnno = specialAnno;
325 if (repeatableAnnoContainer.contains(
326 e.getEnclosingElement().toString())
327 || repeatableAnnoContainer.contains(
328 e.getSimpleName().toString())) {
329 actualAnno = e.getAnnotation(BarContainer.class);
330 }
331 if (repeatableInheritedAnnoContainer.contains(
332 e.getEnclosingElement().toString())
333 || repeatableInheritedAnnoContainer.contains(
334 e.getSimpleName().toString())) {
335 actualAnno = e.getAnnotation(BarInheritedContainer.class);
336 }
337 if (repeatableContainerInheritedAnnoContainer.contains(
338 e.getEnclosingElement().toString())
339 || repeatableContainerInheritedAnnoContainer.contains(
340 e.getSimpleName().toString())) {
341 actualAnno = e.getAnnotation(BarInheritedContainerContainer.class);
342 }
343 if (unofficialAnnoContainer.contains(
344 e.getEnclosingElement().toString())
345 || unofficialAnnoContainer.contains(
346 e.getSimpleName().toString())) {
347 actualAnno = e.getAnnotation(UnofficialContainer.class);
348 }
349 if (unofficialInheritedAnnoContainer.contains(
350 e.getEnclosingElement().toString())
351 || unofficialInheritedAnnoContainer.contains(
352 e.getSimpleName().toString())) {
353 actualAnno = e.getAnnotation(UnofficialInheritedContainer.class);
354 }
355 return actualAnno;
356 }
358 private Annotation[] getAnnotationsBase(Element e) {
359 Annotation[] actualAnnosArgs = specialAnnoArray;
361 if (singularAnno.contains(
362 e.getEnclosingElement().toString())
363 || singularAnno.contains(
364 e.getSimpleName().toString())
365 || unofficialAnno.contains(
366 e.getEnclosingElement().toString())
367 || unofficialAnno.contains(
368 e.getSimpleName().toString())) {
369 actualAnnosArgs = e.getAnnotationsByType(Foo.class);
370 }
371 if (singularInheritedAnno.contains(
372 e.getEnclosingElement().toString())
373 || singularInheritedAnno.contains(
374 e.getSimpleName().toString())
375 || unofficialInheritedAnno.contains(
376 e.getEnclosingElement().toString())
377 || unofficialInheritedAnno.contains(
378 e.getSimpleName().toString())) {
379 actualAnnosArgs = e.getAnnotationsByType(FooInherited.class);
380 }
381 if (repeatableAnno.contains(
382 e.getEnclosingElement().toString())
383 || repeatableAnno.contains(
384 e.getSimpleName().toString())) {
385 actualAnnosArgs = e.getAnnotationsByType(Bar.class);
386 }
387 if (repeatableInheritedAnno.contains(
388 e.getEnclosingElement().toString())
389 || repeatableInheritedAnno.contains(
390 e.getSimpleName().toString())) {
391 actualAnnosArgs = e.getAnnotationsByType(BarInherited.class);
392 }
393 if (repeatableContainerInheritedAnno.contains(
394 e.getEnclosingElement().toString())
395 || repeatableContainerInheritedAnno.contains(
396 e.getSimpleName().toString())) {
397 actualAnnosArgs = e.getAnnotationsByType(BarInheritedContainer.class);
398 }
399 return actualAnnosArgs;
400 }
402 private Annotation[] getAnnotationsContainer(Element e) {
403 Annotation[] actualAnnosArgs = specialAnnoArray;
405 if (repeatableAnnoContainer.contains(
406 e.getEnclosingElement().toString())
407 || repeatableAnnoContainer.contains(
408 e.getSimpleName().toString())) {
409 actualAnnosArgs = e.getAnnotationsByType(BarContainer.class);
410 }
411 if (repeatableInheritedAnnoContainer.contains(
412 e.getEnclosingElement().toString())
413 || repeatableInheritedAnnoContainer.contains(
414 e.getSimpleName().toString())) {
415 actualAnnosArgs = e.getAnnotationsByType(BarInheritedContainer.class);
416 }
417 if (repeatableContainerInheritedAnnoContainer.contains(
418 e.getEnclosingElement().toString())
419 || repeatableContainerInheritedAnnoContainer.contains(
420 e.getSimpleName().toString())) {
421 actualAnnosArgs = e.getAnnotationsByType(BarInheritedContainerContainer.class);
422 }
423 if (unofficialAnnoContainer.contains(
424 e.getEnclosingElement().toString())
425 || unofficialAnnoContainer.contains(
426 e.getSimpleName().toString())) {
427 actualAnnosArgs = e.getAnnotationsByType(UnofficialContainer.class);
428 }
429 if (unofficialInheritedAnnoContainer.contains(
430 e.getEnclosingElement().toString())
431 || unofficialInheritedAnnoContainer.contains(
432 e.getSimpleName().toString())) {
433 actualAnnosArgs = e.getAnnotationsByType(UnofficialInheritedContainer.class);
434 }
435 return actualAnnosArgs;
436 }
438 // Array comparison: Length should be same and all expected values
439 // should be present in actualAnnos[].
440 private boolean compareArrVals(Annotation[] actualAnnos, String[] expectedAnnos) {
441 // Look if test case was run.
442 if (actualAnnos == specialAnnoArray) {
443 return false; // no testcase matches
444 }
445 if (actualAnnos.length != expectedAnnos.length) {
446 System.out.println("Length not same. "
447 + " actualAnnos length = " + actualAnnos.length
448 + " expectedAnnos length = " + expectedAnnos.length);
449 printArrContents(actualAnnos);
450 printArrContents(expectedAnnos);
451 return false;
452 } else {
453 int i = 0;
454 String[] actualArr = new String[actualAnnos.length];
455 for (Annotation a : actualAnnos) {
456 actualArr[i++] = a.toString();
457 }
458 List<String> actualList = Arrays.asList(actualArr);
459 List<String> expectedList = Arrays.asList(expectedAnnos);
461 if (!actualList.containsAll(expectedList)) {
462 System.out.println("Array values are not same");
463 printArrContents(actualAnnos);
464 printArrContents(expectedAnnos);
465 return false;
466 }
467 }
468 return true;
469 }
471 // Array comparison: Length should be same and all expected values
472 // should be present in actualAnnos List<?>.
473 private boolean compareArrVals(List<? extends AnnotationMirror> actualAnnos,
474 String[] expectedAnnos) {
475 // Look if test case was run.
476 if (actualAnnos == specialAnnoMirrors) {
477 return false; //no testcase run
478 }
479 if (actualAnnos.size() != expectedAnnos.length) {
480 System.out.println("Length not same. "
481 + " actualAnnos length = " + actualAnnos.size()
482 + " expectedAnnos length = " + expectedAnnos.length);
483 printArrContents(actualAnnos);
484 printArrContents(expectedAnnos);
485 return false;
486 } else {
487 int i = 0;
488 String[] actualArr = new String[actualAnnos.size()];
489 String annoTypeName = "";
490 for (AnnotationMirror annotationMirror : actualAnnos) {
491 if (annotationMirror.getAnnotationType().toString().contains("Expected")) {
492 annoTypeName = annotationMirror.getAnnotationType().toString();
493 } else {
494 annoTypeName = annotationMirror.toString();
495 }
496 actualArr[i++] = annoTypeName;
497 }
498 List<String> actualList = Arrays.asList(actualArr);
499 List<String> expectedList = Arrays.asList(expectedAnnos);
501 if (!actualList.containsAll(expectedList)) {
502 System.out.println("Array values are not same");
503 printArrContents(actualAnnos);
504 printArrContents(expectedAnnos);
505 return false;
506 }
507 }
508 return true;
509 }
511 private void printArrContents(Annotation[] actualAnnos) {
512 for (Annotation a : actualAnnos) {
513 System.out.println("actualAnnos values = " + a);
514 }
515 }
517 private void printArrContents(String[] expectedAnnos) {
518 for (String s : expectedAnnos) {
519 System.out.println("expectedAnnos values = " + s);
520 }
521 }
523 private void printArrContents(List<? extends AnnotationMirror> actualAnnos) {
524 for (AnnotationMirror annotationMirror : actualAnnos) {
525 System.out.println("actualAnnos values = " + annotationMirror);
526 }
527 }
529 private boolean compareAnnotation(Annotation actualAnno, String expectedAnno) {
530 //String actualAnnoName = "";
531 boolean isSame = true;
532 // Look if test case was run.
533 if (actualAnno == specialAnno) {
534 return false; //no testcase run
535 }
536 if (actualAnno != null) {
537 if (!actualAnno.toString().equalsIgnoreCase(expectedAnno)) {
538 System.out.println("Anno did not match. "
539 + " expectedAnno = " + expectedAnno
540 + " actualAnno = " + actualAnno);
541 isSame = false;
542 } else {
543 isSame = true;
544 }
545 } else {
546 if (expectedAnno.compareToIgnoreCase("null") == 0) {
547 isSame = true;
548 } else {
549 System.out.println("Actual anno is null");
550 isSame = false;
551 }
552 }
553 return isSame;
554 }
555 }