blob: 3de12e641601cbed44cca67877bc0cb6a86c6ed9 [file] [log] [blame]
/*
* 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;
}
}