blob: e23a8d84bab181b3e782272db7a330a53d41195c [file] [log] [blame]
/*
* Copyright (c) 2015, 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 com.sun.tools.classfile.Annotation;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.ConstantPool;
import com.sun.tools.classfile.ConstantPoolException;
import java.lang.annotation.RetentionPolicy;
import java.util.*;
import java.util.stream.Collectors;
public class TestAnnotationInfo {
public final String annotationName;
public final RetentionPolicy policy;
public final boolean isContainer;
public final List<Pair> elementValues;
public TestAnnotationInfo(String typeIndexName, RetentionPolicy policy, Pair... values) {
this(typeIndexName, policy, false, values);
}
public TestAnnotationInfo(String typeIndexName, RetentionPolicy policy, boolean isRepeatable, Pair... values) {
this.annotationName = typeIndexName;
this.policy = policy;
this.isContainer = isRepeatable;
elementValues = Arrays.asList(values);
}
public void testAnnotation(TestResult testResult, ClassFile classFile, Annotation annotation)
throws ConstantPoolException {
testResult.checkEquals(classFile.constant_pool.getUTF8Value(annotation.type_index),
String.format("L%s;", annotationName), "Testing annotation name : " + annotationName);
testResult.checkEquals(annotation.num_element_value_pairs,
elementValues.size(), "Number of element values");
if (!testResult.checkEquals(annotation.num_element_value_pairs, elementValues.size(),
"Number of element value pairs")) {
return;
}
for (int i = 0; i < annotation.num_element_value_pairs; ++i) {
Annotation.element_value_pair pair = annotation.element_value_pairs[i];
testResult.checkEquals(classFile.constant_pool.getUTF8Value(pair.element_name_index),
elementValues.get(i).elementName, "element_name_index : " + elementValues.get(i).elementName);
elementValues.get(i).elementValue.testElementValue(testResult, classFile, pair.value);
}
}
@Override
public String toString() {
return String.format("@%s(%s)", annotationName,
elementValues.stream()
.map(Pair::toString)
.filter(s -> !s.isEmpty())
.collect(Collectors.joining(", ")));
}
public static class Pair {
public final String elementName;
public final TestElementValue elementValue;
public Pair(String elementName, TestElementValue elementValue) {
this.elementName = elementName;
this.elementValue = elementValue;
}
@Override
public String toString() {
return elementName + "=" + elementValue;
}
}
public static abstract class TestElementValue {
private final int tag;
public TestElementValue(int tag) {
this.tag = tag;
}
public void testTag(TestResult testCase, int actualTag) {
testCase.checkEquals(actualTag, tag, "tag " + (char) tag);
}
public abstract void testElementValue(TestResult testResult,
ClassFile classFile,
Annotation.element_value element_value)
throws ConstantPoolException;
}
public static class TestIntegerElementValue extends TestElementValue {
private final int value;
public TestIntegerElementValue(int tag, int value) {
super(tag);
this.value = value;
}
@Override
public void testElementValue(TestResult testResult,
ClassFile classFile,
Annotation.element_value element_value)
throws ConstantPoolException {
testTag(testResult, element_value.tag);
Annotation.Primitive_element_value ev =
(Annotation.Primitive_element_value) element_value;
ConstantPool.CONSTANT_Integer_info info =
(ConstantPool.CONSTANT_Integer_info) classFile.constant_pool.get(ev.const_value_index);
testResult.checkEquals(info.value, value, "const_value_index : " + value);
}
@Override
public String toString() {
return String.valueOf(value);
}
}
public static class TestBooleanElementValue extends TestElementValue {
private final boolean value;
public TestBooleanElementValue(boolean value) {
super('Z');
this.value = value;
}
@Override
public void testElementValue(TestResult testResult,
ClassFile classFile,
Annotation.element_value element_value)
throws ConstantPoolException {
testTag(testResult, element_value.tag);
Annotation.Primitive_element_value ev =
(Annotation.Primitive_element_value) element_value;
ConstantPool.CONSTANT_Integer_info info =
(ConstantPool.CONSTANT_Integer_info) classFile.constant_pool.get(ev.const_value_index);
testResult.checkEquals(info.value, value ? 1 : 0, "const_value_index : " + value);
}
@Override
public String toString() {
return String.valueOf(value);
}
}
public static class TestCharElementValue extends TestElementValue {
private final char value;
public TestCharElementValue(char value) {
super('C');
this.value = value;
}
@Override
public void testElementValue(TestResult testResult,
ClassFile classFile,
Annotation.element_value element_value)
throws ConstantPoolException {
testTag(testResult, element_value.tag);
Annotation.Primitive_element_value ev =
(Annotation.Primitive_element_value) element_value;
ConstantPool.CONSTANT_Integer_info info =
(ConstantPool.CONSTANT_Integer_info)
classFile.constant_pool.get(ev.const_value_index);
testResult.checkEquals(info.value, (int) value, "const_value_index : " + value);
}
@Override
public String toString() {
return String.format("\'%c\'", value);
}
}
public static class TestLongElementValue extends TestElementValue {
private final long value;
public TestLongElementValue(long value) {
super('J');
this.value = value;
}
@Override
public void testElementValue(TestResult testResult,
ClassFile classFile,
Annotation.element_value element_value)
throws ConstantPool.InvalidIndex {
testTag(testResult, element_value.tag);
Annotation.Primitive_element_value ev =
(Annotation.Primitive_element_value) element_value;
ConstantPool.CONSTANT_Long_info info =
(ConstantPool.CONSTANT_Long_info) classFile.constant_pool.get(ev.const_value_index);
testResult.checkEquals(info.value, value, "const_value_index");
}
@Override
public String toString() {
return String.valueOf(value);
}
}
public static class TestFloatElementValue extends TestElementValue {
private final float value;
public TestFloatElementValue(float value) {
super('F');
this.value = value;
}
@Override
public void testElementValue(TestResult testResult,
ClassFile classFile,
Annotation.element_value element_value)
throws ConstantPool.InvalidIndex {
testTag(testResult, element_value.tag);
Annotation.Primitive_element_value ev =
(Annotation.Primitive_element_value) element_value;
ConstantPool.CONSTANT_Float_info info =
(ConstantPool.CONSTANT_Float_info) classFile.constant_pool.get(ev.const_value_index);
testResult.checkEquals(info.value, value, "const_value_index");
}
@Override
public String toString() {
return String.valueOf(value) + "f";
}
}
public static class TestDoubleElementValue extends TestElementValue {
private final double value;
public TestDoubleElementValue(double value) {
super('D');
this.value = value;
}
@Override
public void testElementValue(TestResult testResult,
ClassFile classFile,
Annotation.element_value element_value)
throws ConstantPoolException {
testTag(testResult, element_value.tag);
Annotation.Primitive_element_value ev =
(Annotation.Primitive_element_value) element_value;
ConstantPool.CONSTANT_Double_info info = (ConstantPool.CONSTANT_Double_info)
classFile.constant_pool.get(ev.const_value_index);
testResult.checkEquals(info.value, value, "const_value_index");
}
@Override
public String toString() {
return String.valueOf(value);
}
}
public static class TestStringElementValue extends TestElementValue {
private final String value;
public TestStringElementValue(String value) {
super('s');
this.value = value;
}
@Override
public void testElementValue(TestResult testResult,
ClassFile classFile,
Annotation.element_value element_value)
throws ConstantPoolException {
testTag(testResult, element_value.tag);
Annotation.Primitive_element_value ev =
(Annotation.Primitive_element_value) element_value;
ConstantPool.CONSTANT_Utf8_info info =
(ConstantPool.CONSTANT_Utf8_info) classFile.constant_pool.get(ev.const_value_index);
testResult.checkEquals(info.value, value, "const_value_index");
}
@Override
public String toString() {
return String.format("\"%s\"", value);
}
}
public static class TestEnumElementValue extends TestElementValue {
private final String typeName;
private final String constName;
public TestEnumElementValue(String typeName, String constName) {
super('e');
this.typeName = typeName;
this.constName = constName;
}
@Override
public void testElementValue(
TestResult testResult,
ClassFile classFile,
Annotation.element_value element_value)
throws ConstantPoolException {
testTag(testResult, element_value.tag);
Annotation.Enum_element_value ev = (Annotation.Enum_element_value) element_value;
testResult.checkEquals(classFile.constant_pool.getUTF8Info(ev.type_name_index).value,
String.format("L%s;", typeName), "type_name_index");
testResult.checkEquals(classFile.constant_pool.getUTF8Info(ev.const_name_index).value,
constName, "const_name_index");
}
@Override
public String toString() {
return typeName + "." + constName;
}
}
public static class TestClassElementValue extends TestElementValue {
private final String className;
private final static Map<String, String> mappedClassName;
static {
mappedClassName = new HashMap<>();
mappedClassName.put("void", "V");
mappedClassName.put("char", "C");
mappedClassName.put("byte", "B");
mappedClassName.put("short", "S");
mappedClassName.put("int", "I");
mappedClassName.put("long", "J");
mappedClassName.put("float", "F");
mappedClassName.put("double", "D");
}
public TestClassElementValue(String className) {
super('c');
this.className = className;
}
@Override
public void testElementValue(
TestResult testResult,
ClassFile classFile,
Annotation.element_value element_value)
throws ConstantPoolException {
testTag(testResult, element_value.tag);
Annotation.Class_element_value ev = (Annotation.Class_element_value) element_value;
String expectedClassName = className.replace(".class", "");
expectedClassName = mappedClassName.getOrDefault(expectedClassName,
String.format("Ljava/lang/%s;", expectedClassName));
testResult.checkEquals(
classFile.constant_pool.getUTF8Info(ev.class_info_index).value,
expectedClassName, "class_info_index : " + expectedClassName);
}
@Override
public String toString() {
return className;
}
}
public static class TestArrayElementValue extends TestElementValue {
public final List<TestElementValue> values;
public TestArrayElementValue(TestElementValue...values) {
super('[');
this.values = new ArrayList<>(Arrays.asList(values));
}
@Override
public void testElementValue(
TestResult testResult,
ClassFile classFile,
Annotation.element_value element_value)
throws ConstantPoolException {
testTag(testResult, element_value.tag);
Annotation.Array_element_value ev = (Annotation.Array_element_value) element_value;
for (int i = 0; i < values.size(); ++i) {
values.get(i).testElementValue(testResult, classFile, ev.values[i]);
}
}
@Override
public String toString() {
return values.stream()
.map(TestElementValue::toString)
.collect(Collectors.joining(", ", "{", "}"));
}
}
public static class TestAnnotationElementValue extends TestElementValue {
private final String annotationName;
private final TestAnnotationInfo annotation;
public TestAnnotationElementValue(String className, TestAnnotationInfo annotation) {
super('@');
this.annotationName = className;
this.annotation = annotation;
}
@Override
public void testElementValue(
TestResult testResult,
ClassFile classFile,
Annotation.element_value element_value)
throws ConstantPoolException {
testTag(testResult, element_value.tag);
Annotation ev = ((Annotation.Annotation_element_value) element_value).annotation_value;
testResult.checkEquals(
classFile.constant_pool.getUTF8Info(ev.type_index).value,
String.format("L%s;", annotationName),
"type_index");
for (int i = 0; i < ev.num_element_value_pairs; ++i) {
Annotation.element_value_pair pair = ev.element_value_pairs[i];
Pair expectedPair = annotation.elementValues.get(i);
expectedPair.elementValue.testElementValue(testResult, classFile, pair.value);
testResult.checkEquals(
classFile.constant_pool.getUTF8Info(pair.element_name_index).value,
expectedPair.elementName,
"element_name_index");
}
}
@Override
public String toString() {
return annotation.toString();
}
}
}