14c0c8eed8
Reviewed-by: darcy, abuckley
556 lines
24 KiB
Java
556 lines
24 KiB
Java
/*
|
|
* 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;
|
|
}
|
|
}
|