| /* |
| * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| import java.lang.annotation.Annotation; |
| import java.util.Arrays; |
| import java.util.EnumSet; |
| import java.util.List; |
| import java.util.Set; |
| import javax.annotation.processing.*; |
| import javax.lang.model.element.*; |
| import javax.lang.model.type.MirroredTypeException; |
| import javax.lang.model.type.TypeMirror; |
| import javax.lang.model.util.Elements; |
| |
| public class ElementRepAnnoTester extends JavacTestingAbstractProcessor { |
| // All methods to test. |
| final EnumSet<TestMethod> ALL_TEST_METHODS = EnumSet.allOf(TestMethod.class); |
| int count = 0; |
| int error = 0; |
| |
| public boolean process(Set<? extends TypeElement> annotations, |
| RoundEnvironment roundEnv) { |
| if (!roundEnv.processingOver()) { |
| List<String> superClass = Arrays.asList("A", "B", "C", "D", "E", |
| "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P"); |
| // Go through all test classes |
| for (Element element : roundEnv.getRootElements()) { |
| // For now, no testing super classes (TODO) |
| if (element.getKind() == ElementKind.CLASS |
| && !superClass.contains(element.getSimpleName().toString())) { |
| // Compare expected and actual values from methods. |
| checkAnnoValues(element, ALL_TEST_METHODS); |
| // Now, look for enclosed elements in test classes. |
| for (Element elements : element.getEnclosedElements()) { |
| // Look for Methods annotations. |
| if (elements.getKind() == ElementKind.METHOD |
| && elements.getSimpleName().toString().equals("testMethod")) { |
| checkAnnoValues(elements, ALL_TEST_METHODS); |
| } |
| // Look for Field annotations. |
| if (elements.getKind() == ElementKind.FIELD |
| && elements.getSimpleName().toString().equals("testField")) { |
| checkAnnoValues(elements, ALL_TEST_METHODS); |
| } |
| } |
| } |
| } |
| |
| if (error != 0) { |
| System.out.println("Total tests : " + count); |
| System.out.println("Total test failures : " + error); |
| throw new RuntimeException(); |
| } else { |
| System.out.println("ALL TESTS PASSED. " + count); |
| } |
| } |
| return true; |
| } |
| |
| enum TestMethod { |
| getAnnotation, |
| getAnnotationsByType, |
| getAllAnnotationMirrors, |
| getAnnotationMirrors |
| } |
| |
| protected void checkAnnoValues(Element element, EnumSet<TestMethod> testMethods) { |
| boolean baseAnnoPresent = false; |
| boolean conAnnoPresent = false; |
| ExpectedBase eb = null; |
| ExpectedContainer ec = null; |
| // Getting the expected values to compare with. |
| eb = element.getAnnotation(ExpectedBase.class); |
| ec = element.getAnnotation(ExpectedContainer.class); |
| |
| if (eb == null) { |
| System.out.println("Did not find ExpectedBase Annotation in " |
| + element.getSimpleName().toString() + ", Test will exit"); |
| throw new RuntimeException(); |
| } |
| if (ec == null) { |
| System.out.println("Did not find ExpectedContainer Annotation in " |
| + element.getSimpleName().toString() + " Test will exit"); |
| throw new RuntimeException(); |
| } |
| // Look if all test cases have ExpectedBase and ExpectedContainer values(). |
| TypeMirror valueBase = null; |
| TypeMirror valueCon = null; |
| |
| try { |
| eb.value(); |
| } catch (MirroredTypeException mte) { |
| valueBase = mte.getTypeMirror(); |
| } |
| |
| try { |
| ec.value(); |
| } catch (MirroredTypeException mte1) { |
| valueCon = mte1.getTypeMirror(); |
| } |
| |
| String expectedBaseAnno = valueBase.toString(); |
| String expectedConAnno = valueCon.toString(); |
| |
| if (!expectedBaseAnno.equals("java.lang.annotation.Annotation")) { |
| baseAnnoPresent = true; |
| } |
| if (!expectedConAnno.equalsIgnoreCase("java.lang.annotation.Annotation")) { |
| conAnnoPresent = true; |
| } |
| |
| // Look into TestMethod and compare method's output with expected values. |
| for (TestMethod testMethod : testMethods) { |
| boolean isBasePass = true; |
| boolean isConPass = true; |
| |
| switch (testMethod) { |
| case getAnnotation: |
| if (baseAnnoPresent) { |
| count++; |
| Annotation actualAnno = getAnnotationBase(element); |
| String expectedAnno = eb.getAnnotation(); |
| isBasePass = compareAnnotation(actualAnno, expectedAnno); |
| } |
| if (conAnnoPresent) { |
| count++; |
| Annotation actualAnno = getAnnotationContainer(element); |
| String expectedAnno = ec.getAnnotation(); |
| isConPass = compareAnnotation(actualAnno, expectedAnno); |
| } |
| if (!isBasePass || !isConPass) { |
| System.out.println("FAIL in " + element.getSimpleName() |
| + "-" + element.getKind() |
| + " method: getAnnotation(class <T>)"); |
| error++; |
| } |
| break; |
| |
| case getAnnotationMirrors: |
| if (baseAnnoPresent) { |
| count++; |
| List<? extends AnnotationMirror> actualDeclAnnos = |
| element.getAnnotationMirrors(); |
| String[] expectedAnnos = eb.getAnnotationMirrors(); |
| isBasePass = compareArrVals(actualDeclAnnos, expectedAnnos); |
| } |
| if (conAnnoPresent) { |
| isConPass = true; |
| } |
| if (!isBasePass || !isConPass) { |
| System.out.println("FAIL in " + element.getSimpleName() |
| + "-" + element.getKind() |
| + " method: getAnnotationMirrors()"); |
| error++; |
| } |
| break; |
| |
| case getAnnotationsByType: |
| if (baseAnnoPresent) { |
| count++; |
| Annotation[] actualAnnosArgs = getAnnotationsBase(element); |
| String[] expectedAnnos = eb.getAnnotationsByType(); |
| isBasePass = compareArrVals(actualAnnosArgs, expectedAnnos); |
| } |
| if (conAnnoPresent) { |
| count++; |
| Annotation[] actualAnnosArgs = getAnnotationsContainer(element); |
| String[] expectedAnnos = ec.getAnnotationsByType(); |
| isConPass = compareArrVals(actualAnnosArgs, expectedAnnos); |
| } |
| if (!isBasePass || !isConPass) { |
| System.out.println("FAIL in " + element.getSimpleName() |
| + "-" + element.getKind() |
| + " method: getAnnotationsByType(class <T>)"); |
| error++; |
| } |
| break; |
| |
| case getAllAnnotationMirrors: |
| if (baseAnnoPresent) { |
| count++; |
| Elements elements = processingEnv.getElementUtils(); |
| List<? extends AnnotationMirror> actualAnnosMirrors = |
| elements.getAllAnnotationMirrors(element); |
| String[] expectedAnnos = eb.getAllAnnotationMirrors(); |
| isBasePass = compareArrVals(actualAnnosMirrors, expectedAnnos); |
| } |
| if (conAnnoPresent) { |
| isConPass = true; |
| } |
| if (!isBasePass || !isConPass) { |
| System.out.println("FAIL in " + element.getSimpleName() |
| + "-" + element.getKind() |
| + " method: getAllAnnotationMirrors(e)"); |
| error++; |
| } |
| break; |
| } |
| } |
| } |
| // Sort tests to be run with different anno processors. |
| final List<String> singularAnno = Arrays.asList( |
| "SingularBasicTest" |
| ); |
| final List<String> singularInheritedAnno = Arrays.asList( |
| "SingularInheritedATest" |
| ); |
| final List<String> repeatableAnno = Arrays.asList( |
| "RepeatableBasicTest", |
| "MixRepeatableAndOfficialContainerBasicTest", |
| "OfficialContainerBasicTest", |
| "RepeatableOfficialContainerBasicTest" |
| ); |
| final List<String> repeatableInheritedAnno = Arrays.asList( |
| "RepeatableInheritedTest", |
| "RepeatableOverrideATest", |
| "RepeatableOverrideBTest", |
| "OfficialContainerInheritedTest", |
| "MixRepeatableAndOfficialContainerInheritedA1Test", |
| "MixRepeatableAndOfficialContainerInheritedB1Test", |
| "MixRepeatableAndOfficialContainerInheritedA2Test", |
| "MixRepeatableAndOfficialContainerInheritedB2Test" |
| ); |
| final List<String> repeatableContainerInheritedAnno = Arrays.asList( |
| "RepeatableOfficialContainerInheritedTest" |
| ); |
| final List<String> unofficialAnno = Arrays.asList( |
| "UnofficialContainerBasicTest", |
| "MixSingularAndUnofficialContainerBasicTest" |
| ); |
| final List<String> unofficialInheritedAnno = Arrays.asList( |
| "UnofficialContainerInheritedTest", |
| "SingularInheritedBTest", |
| "MixSingularAndUnofficialContainerInheritedA1Test", |
| "MixSingularAndUnofficialContainerInheritedB1Test", |
| "MixSingularAndUnofficialContainerInheritedA2Test", |
| "MixSingularAndUnofficialContainerInheritedB2Test" |
| ); |
| // Respective container annotation for the different test cases to test. |
| final List<String> repeatableAnnoContainer = repeatableAnno; |
| final List<String> repeatableInheritedAnnoContainer = repeatableInheritedAnno; |
| final List<String> repeatableContainerInheritedAnnoContainer = |
| repeatableContainerInheritedAnno; |
| final List<String> unofficialAnnoContainer = unofficialAnno; |
| final List<String> unofficialInheritedAnnoContainer = unofficialInheritedAnno; |
| |
| // Variables to verify if all test cases have been run. |
| private Annotation specialAnno = new Annotation() { |
| @Override |
| public Class annotationType() { |
| return null; |
| } |
| }; |
| private Annotation[] specialAnnoArray = new Annotation[1]; |
| private List<AnnotationMirror> specialAnnoMirrors = |
| new java.util.ArrayList<AnnotationMirror>(2); |
| |
| private Annotation getAnnotationBase(Element e) { |
| Annotation actualAnno = specialAnno; |
| |
| if (singularAnno.contains( |
| e.getEnclosingElement().toString()) |
| || singularAnno.contains( |
| e.getSimpleName().toString()) |
| || unofficialAnno.contains( |
| e.getEnclosingElement().toString()) |
| || unofficialAnno.contains( |
| e.getSimpleName().toString())) { |
| actualAnno = e.getAnnotation(Foo.class); |
| } |
| if (singularInheritedAnno.contains( |
| e.getEnclosingElement().toString()) |
| || singularInheritedAnno.contains( |
| e.getSimpleName().toString()) |
| || unofficialInheritedAnno.contains( |
| e.getEnclosingElement().toString()) |
| || unofficialInheritedAnno.contains( |
| e.getSimpleName().toString())) { |
| actualAnno = e.getAnnotation(FooInherited.class); |
| } |
| if (repeatableAnno.contains( |
| e.getEnclosingElement().toString()) |
| || repeatableAnno.contains( |
| e.getSimpleName().toString())) { |
| actualAnno = e.getAnnotation(Bar.class); |
| } |
| if (repeatableInheritedAnno.contains( |
| e.getEnclosingElement().toString()) |
| || repeatableInheritedAnno.contains( |
| e.getSimpleName().toString())) { |
| actualAnno = e.getAnnotation(BarInherited.class); |
| } |
| if (repeatableContainerInheritedAnno.contains( |
| e.getEnclosingElement().toString()) |
| || repeatableContainerInheritedAnno.contains( |
| e.getSimpleName().toString())) { |
| actualAnno = e.getAnnotation(BarInheritedContainer.class); |
| } |
| return actualAnno; |
| } |
| |
| private Annotation getAnnotationContainer(Element e) { |
| Annotation actualAnno = specialAnno; |
| |
| if (repeatableAnnoContainer.contains( |
| e.getEnclosingElement().toString()) |
| || repeatableAnnoContainer.contains( |
| e.getSimpleName().toString())) { |
| actualAnno = e.getAnnotation(BarContainer.class); |
| } |
| if (repeatableInheritedAnnoContainer.contains( |
| e.getEnclosingElement().toString()) |
| || repeatableInheritedAnnoContainer.contains( |
| e.getSimpleName().toString())) { |
| actualAnno = e.getAnnotation(BarInheritedContainer.class); |
| } |
| if (repeatableContainerInheritedAnnoContainer.contains( |
| e.getEnclosingElement().toString()) |
| || repeatableContainerInheritedAnnoContainer.contains( |
| e.getSimpleName().toString())) { |
| actualAnno = e.getAnnotation(BarInheritedContainerContainer.class); |
| } |
| if (unofficialAnnoContainer.contains( |
| e.getEnclosingElement().toString()) |
| || unofficialAnnoContainer.contains( |
| e.getSimpleName().toString())) { |
| actualAnno = e.getAnnotation(UnofficialContainer.class); |
| } |
| if (unofficialInheritedAnnoContainer.contains( |
| e.getEnclosingElement().toString()) |
| || unofficialInheritedAnnoContainer.contains( |
| e.getSimpleName().toString())) { |
| actualAnno = e.getAnnotation(UnofficialInheritedContainer.class); |
| } |
| return actualAnno; |
| } |
| |
| private Annotation[] getAnnotationsBase(Element e) { |
| Annotation[] actualAnnosArgs = specialAnnoArray; |
| |
| if (singularAnno.contains( |
| e.getEnclosingElement().toString()) |
| || singularAnno.contains( |
| e.getSimpleName().toString()) |
| || unofficialAnno.contains( |
| e.getEnclosingElement().toString()) |
| || unofficialAnno.contains( |
| e.getSimpleName().toString())) { |
| actualAnnosArgs = e.getAnnotationsByType(Foo.class); |
| } |
| if (singularInheritedAnno.contains( |
| e.getEnclosingElement().toString()) |
| || singularInheritedAnno.contains( |
| e.getSimpleName().toString()) |
| || unofficialInheritedAnno.contains( |
| e.getEnclosingElement().toString()) |
| || unofficialInheritedAnno.contains( |
| e.getSimpleName().toString())) { |
| actualAnnosArgs = e.getAnnotationsByType(FooInherited.class); |
| } |
| if (repeatableAnno.contains( |
| e.getEnclosingElement().toString()) |
| || repeatableAnno.contains( |
| e.getSimpleName().toString())) { |
| actualAnnosArgs = e.getAnnotationsByType(Bar.class); |
| } |
| if (repeatableInheritedAnno.contains( |
| e.getEnclosingElement().toString()) |
| || repeatableInheritedAnno.contains( |
| e.getSimpleName().toString())) { |
| actualAnnosArgs = e.getAnnotationsByType(BarInherited.class); |
| } |
| if (repeatableContainerInheritedAnno.contains( |
| e.getEnclosingElement().toString()) |
| || repeatableContainerInheritedAnno.contains( |
| e.getSimpleName().toString())) { |
| actualAnnosArgs = e.getAnnotationsByType(BarInheritedContainer.class); |
| } |
| return actualAnnosArgs; |
| } |
| |
| private Annotation[] getAnnotationsContainer(Element e) { |
| Annotation[] actualAnnosArgs = specialAnnoArray; |
| |
| if (repeatableAnnoContainer.contains( |
| e.getEnclosingElement().toString()) |
| || repeatableAnnoContainer.contains( |
| e.getSimpleName().toString())) { |
| actualAnnosArgs = e.getAnnotationsByType(BarContainer.class); |
| } |
| if (repeatableInheritedAnnoContainer.contains( |
| e.getEnclosingElement().toString()) |
| || repeatableInheritedAnnoContainer.contains( |
| e.getSimpleName().toString())) { |
| actualAnnosArgs = e.getAnnotationsByType(BarInheritedContainer.class); |
| } |
| if (repeatableContainerInheritedAnnoContainer.contains( |
| e.getEnclosingElement().toString()) |
| || repeatableContainerInheritedAnnoContainer.contains( |
| e.getSimpleName().toString())) { |
| actualAnnosArgs = e.getAnnotationsByType(BarInheritedContainerContainer.class); |
| } |
| if (unofficialAnnoContainer.contains( |
| e.getEnclosingElement().toString()) |
| || unofficialAnnoContainer.contains( |
| e.getSimpleName().toString())) { |
| actualAnnosArgs = e.getAnnotationsByType(UnofficialContainer.class); |
| } |
| if (unofficialInheritedAnnoContainer.contains( |
| e.getEnclosingElement().toString()) |
| || unofficialInheritedAnnoContainer.contains( |
| e.getSimpleName().toString())) { |
| actualAnnosArgs = e.getAnnotationsByType(UnofficialInheritedContainer.class); |
| } |
| return actualAnnosArgs; |
| } |
| |
| // Array comparison: Length should be same and all expected values |
| // should be present in actualAnnos[]. |
| private boolean compareArrVals(Annotation[] actualAnnos, String[] expectedAnnos) { |
| // Look if test case was run. |
| if (actualAnnos == specialAnnoArray) { |
| return false; // no testcase matches |
| } |
| if (actualAnnos.length != expectedAnnos.length) { |
| System.out.println("Length not same. " |
| + " actualAnnos length = " + actualAnnos.length |
| + " expectedAnnos length = " + expectedAnnos.length); |
| printArrContents(actualAnnos); |
| printArrContents(expectedAnnos); |
| return false; |
| } else { |
| int i = 0; |
| String[] actualArr = new String[actualAnnos.length]; |
| for (Annotation a : actualAnnos) { |
| actualArr[i++] = a.toString(); |
| } |
| List<String> actualList = Arrays.asList(actualArr); |
| List<String> expectedList = Arrays.asList(expectedAnnos); |
| |
| if (!actualList.containsAll(expectedList)) { |
| System.out.println("Array values are not same"); |
| printArrContents(actualAnnos); |
| printArrContents(expectedAnnos); |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| // Array comparison: Length should be same and all expected values |
| // should be present in actualAnnos List<?>. |
| private boolean compareArrVals(List<? extends AnnotationMirror> actualAnnos, |
| String[] expectedAnnos) { |
| // Look if test case was run. |
| if (actualAnnos == specialAnnoMirrors) { |
| return false; //no testcase run |
| } |
| if (actualAnnos.size() != expectedAnnos.length) { |
| System.out.println("Length not same. " |
| + " actualAnnos length = " + actualAnnos.size() |
| + " expectedAnnos length = " + expectedAnnos.length); |
| printArrContents(actualAnnos); |
| printArrContents(expectedAnnos); |
| return false; |
| } else { |
| int i = 0; |
| String[] actualArr = new String[actualAnnos.size()]; |
| String annoTypeName = ""; |
| for (AnnotationMirror annotationMirror : actualAnnos) { |
| if (annotationMirror.getAnnotationType().toString().contains("Expected")) { |
| annoTypeName = annotationMirror.getAnnotationType().toString(); |
| } else { |
| annoTypeName = annotationMirror.toString(); |
| } |
| actualArr[i++] = annoTypeName; |
| } |
| List<String> actualList = Arrays.asList(actualArr); |
| List<String> expectedList = Arrays.asList(expectedAnnos); |
| |
| if (!actualList.containsAll(expectedList)) { |
| System.out.println("Array values are not same"); |
| printArrContents(actualAnnos); |
| printArrContents(expectedAnnos); |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| private void printArrContents(Annotation[] actualAnnos) { |
| for (Annotation a : actualAnnos) { |
| System.out.println("actualAnnos values = " + a); |
| } |
| } |
| |
| private void printArrContents(String[] expectedAnnos) { |
| for (String s : expectedAnnos) { |
| System.out.println("expectedAnnos values = " + s); |
| } |
| } |
| |
| private void printArrContents(List<? extends AnnotationMirror> actualAnnos) { |
| for (AnnotationMirror annotationMirror : actualAnnos) { |
| System.out.println("actualAnnos values = " + annotationMirror); |
| } |
| } |
| |
| private boolean compareAnnotation(Annotation actualAnno, String expectedAnno) { |
| //String actualAnnoName = ""; |
| boolean isSame = true; |
| // Look if test case was run. |
| if (actualAnno == specialAnno) { |
| return false; //no testcase run |
| } |
| if (actualAnno != null) { |
| if (!actualAnno.toString().equalsIgnoreCase(expectedAnno)) { |
| System.out.println("Anno did not match. " |
| + " expectedAnno = " + expectedAnno |
| + " actualAnno = " + actualAnno); |
| isSame = false; |
| } else { |
| isSame = true; |
| } |
| } else { |
| if (expectedAnno.compareToIgnoreCase("null") == 0) { |
| isSame = true; |
| } else { |
| System.out.println("Actual anno is null"); |
| isSame = false; |
| } |
| } |
| return isSame; |
| } |
| } |