mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-07 22:50:49 +00:00
8042947: Implement classfile tests for AnnotationDefault attribute
Reviewed-by: jjg, shurailine, anazarov
This commit is contained in:
parent
7cbdcf978d
commit
56c8f87b08
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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.*;
|
||||
|
||||
%REPEATABLE%
|
||||
@Retention(RetentionPolicy.%POLICY%)
|
||||
public @interface AnnotationDefault {
|
||||
@ExpectedValues(tag = 'Z', name = "booleanDefault", values = "1")
|
||||
boolean booleanDefault() default true;
|
||||
|
||||
@ExpectedValues(tag = 'C', name = "charDefault", values = "1")
|
||||
char charDefault() default 1;
|
||||
|
||||
@ExpectedValues(tag = 'B', name = "byteDefault", values = "1")
|
||||
byte byteDefault() default 1;
|
||||
|
||||
@ExpectedValues(tag = 'S', name = "shortDefault", values = "1")
|
||||
short shortDefault() default 1;
|
||||
|
||||
@ExpectedValues(tag = 'I', name = "intDefault", values = "1")
|
||||
int intDefault() default 1;
|
||||
|
||||
@ExpectedValues(tag = 'J', name = "longDefault", values = "1")
|
||||
long longDefault() default 1;
|
||||
|
||||
@ExpectedValues(tag = 'F', name = "floatDefault", values = "1.0")
|
||||
float floatDefault() default 1.0f;
|
||||
|
||||
@ExpectedValues(tag = 'D', name = "doubleDefault", values = "1.0")
|
||||
double doubleDefault() default 1.0;
|
||||
|
||||
@ExpectedValues(tag = 's', name = "stringDefault", values = "DEFAULT_VALUE")
|
||||
String stringDefault() default "DEFAULT_VALUE";
|
||||
|
||||
@ExpectedValues(tag = 'e', name = "enumDefault", values = {"LAnnotationDefault$DefaultValues;", "VALUE1"})
|
||||
DefaultValues enumDefault() default DefaultValues.VALUE1;
|
||||
|
||||
@ExpectedValues(tag = 'c', name = "clazzDefault1", values = "V")
|
||||
Class<?> clazzDefault1() default void.class;
|
||||
|
||||
@ExpectedValues(tag = 'c', name = "clazzDefault2", values = "Ljava/lang/Void;")
|
||||
Class<?> clazzDefault2() default Void.class;
|
||||
|
||||
@ExpectedValues(tag = '[', name = "arrayDefault1", values = {"1", "2", "3"})
|
||||
int[] arrayDefault1() default {1, 2, 3};
|
||||
|
||||
@ExpectedValues(tag = '[', name = "arrayDefault2", values = {"DEFAULT_VALUE_1", "DEFAULT_VALUE_2", "DEFAULT_VALUE_3"})
|
||||
String[] arrayDefault2() default {"DEFAULT_VALUE_1", "DEFAULT_VALUE_2", "DEFAULT_VALUE_3"};
|
||||
|
||||
@ExpectedValues(tag = '[', name = "arrayOfEnums", values = {"LAnnotationDefault$DefaultValues;", "VALUE2",
|
||||
"LAnnotationDefault$DefaultValues;", "VALUE3"})
|
||||
DefaultValues[] arrayOfEnums() default {DefaultValues.VALUE2, DefaultValues.VALUE3};
|
||||
|
||||
@ExpectedValues(tag = '[', name = "arrayOfAnno", values = {"LAnnotationDefault$DefaultAnnotation;", "value", "DEFAULT_VALUE1",
|
||||
"LAnnotationDefault$DefaultAnnotation;", "value", "DEFAULT_VALUE2"})
|
||||
DefaultAnnotation[] arrayOfAnno() default {@DefaultAnnotation(value = "DEFAULT_VALUE1"), @DefaultAnnotation(value = "DEFAULT_VALUE2")};
|
||||
|
||||
@ExpectedValues(tag = '@', name = "annoDefault", values = {"LAnnotationDefault$DefaultAnnotation;", "value", "DEFAULT_VALUE"})
|
||||
DefaultAnnotation annoDefault() default @DefaultAnnotation(value = "DEFAULT_VALUE");
|
||||
|
||||
@interface DefaultAnnotation {
|
||||
String value() default "NOT_DEFAULT_VALUE";
|
||||
}
|
||||
|
||||
enum DefaultValues {
|
||||
VALUE1, VALUE2, VALUE3
|
||||
}
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.%POLICY%)
|
||||
@interface Container {
|
||||
AnnotationDefault[] value();
|
||||
}
|
||||
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8042947
|
||||
* @summary Checking AnnotationDefault attribute.
|
||||
* @library /tools/lib /tools/javac/lib ../lib
|
||||
* @build AnnotationDefaultTest TestBase TestResult InMemoryFileManager ToolBox AnnotationDefaultVerifier
|
||||
* @run main AnnotationDefaultTest
|
||||
*/
|
||||
|
||||
import com.sun.tools.classfile.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class AnnotationDefaultTest extends TestResult {
|
||||
|
||||
private final static String templateFileName = "AnnotationDefault.java.template";
|
||||
|
||||
private final AnnotationDefaultVerifier verifier;
|
||||
|
||||
public AnnotationDefaultTest() {
|
||||
verifier = new AnnotationDefaultVerifier();
|
||||
}
|
||||
|
||||
private void test(String template, Map<String, String> replacements, boolean hasDefault) {
|
||||
String source = replace(template, replacements);
|
||||
addTestCase(source);
|
||||
try {
|
||||
printf("Testing source:\n%s\n", source);
|
||||
String className = "AnnotationDefault";
|
||||
InMemoryFileManager fileManager = compile(source);
|
||||
|
||||
// Map <method-name, expected-annotation-default-values>
|
||||
Map<String, ExpectedValues> expectedValues =
|
||||
getExpectedValues(forName(className, fileManager));
|
||||
ClassFile classFile = readClassFile(fileManager.getClasses().get(className));
|
||||
|
||||
for (Method method : classFile.methods) {
|
||||
String methodName = method.getName(classFile.constant_pool);
|
||||
printf("Testing method : %s\n", methodName);
|
||||
AnnotationDefault_attribute attr =
|
||||
(AnnotationDefault_attribute) method.attributes
|
||||
.get(Attribute.AnnotationDefault);
|
||||
|
||||
if (hasDefault && !checkNotNull(attr, "Attribute is not null")
|
||||
|| !hasDefault && checkNull(attr, "Attribute is null")) {
|
||||
// stop checking, attr is null
|
||||
continue;
|
||||
}
|
||||
|
||||
checkEquals(countNumberOfAttributes(method.attributes.attrs),
|
||||
1l,
|
||||
"Number of AnnotationDefault attribute");
|
||||
checkEquals(classFile.constant_pool
|
||||
.getUTF8Value(attr.attribute_name_index),
|
||||
"AnnotationDefault", "attribute_name_index");
|
||||
|
||||
ExpectedValues expectedValue = expectedValues.get(methodName);
|
||||
checkEquals((char) attr.default_value.tag, expectedValue.tag(),
|
||||
String.format("check tag : %c %s", expectedValue.tag(), expectedValue.name()));
|
||||
verifier.testElementValue(attr.default_value.tag,
|
||||
this, classFile, attr.default_value,
|
||||
expectedValue.values());
|
||||
verifier.testLength(attr.default_value.tag, this, attr);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
addFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> forName(String className, InMemoryFileManager fileManager) throws ClassNotFoundException {
|
||||
return fileManager.getClassLoader(null).loadClass(className);
|
||||
}
|
||||
|
||||
private Map<String, ExpectedValues> getExpectedValues(Class<?> clazz) {
|
||||
return Stream.of(clazz.getMethods())
|
||||
.map(method -> method.getAnnotation(ExpectedValues.class))
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toMap(
|
||||
ExpectedValues::name,
|
||||
Function.identity()));
|
||||
}
|
||||
|
||||
private String replace(String template, Map<String, String> replacements) {
|
||||
String ans = template;
|
||||
for (Map.Entry<String, String> replace : replacements.entrySet()) {
|
||||
ans = ans.replaceAll(replace.getKey(), replace.getValue());
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
private long countNumberOfAttributes(Attribute[] attrs) {
|
||||
return Stream.of(attrs)
|
||||
.filter(x -> x instanceof AnnotationDefault_attribute)
|
||||
.count();
|
||||
}
|
||||
|
||||
public String getSource(File templateFileName) throws IOException {
|
||||
return Files.lines(templateFileName.toPath())
|
||||
.filter(str -> !str.startsWith("/*") && !str.startsWith(" *"))
|
||||
.collect(Collectors.joining("\n"));
|
||||
}
|
||||
|
||||
public void test() throws TestFailedException {
|
||||
try {
|
||||
String template = getSource(getSourceFile(templateFileName));
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
for (String repeatable : new String[] {"", "@Repeatable(Container.class)"}) {
|
||||
for (RetentionPolicy policy : RetentionPolicy.values()) {
|
||||
final int finalI = i;
|
||||
Map<String, String> replacements = new HashMap<String, String>(){{
|
||||
put("%POLICY%", policy.toString());
|
||||
if (finalI != 0) {
|
||||
put("default.*\n", ";\n");
|
||||
}
|
||||
put("%REPEATABLE%", repeatable);
|
||||
}};
|
||||
test(template, replacements, i == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
addFailure(e);
|
||||
} finally {
|
||||
checkStatus();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws TestFailedException {
|
||||
new AnnotationDefaultTest().test();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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.AnnotationDefault_attribute;
|
||||
import com.sun.tools.classfile.ClassFile;
|
||||
import com.sun.tools.classfile.ConstantPool;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AnnotationDefaultVerifier {
|
||||
|
||||
private final Map<Integer, TestElementValue> verifiers;
|
||||
|
||||
public AnnotationDefaultVerifier() {
|
||||
this.verifiers = new HashMap<>();
|
||||
verifiers.put((int) 'B', new TestIntegerElementValue());
|
||||
verifiers.put((int) 'C', new TestIntegerElementValue());
|
||||
verifiers.put((int) 'D', new TestDoubleElementValue());
|
||||
verifiers.put((int) 'F', new TestFloatElementValue());
|
||||
verifiers.put((int) 'I', new TestIntegerElementValue());
|
||||
verifiers.put((int) 'J', new TestLongElementValue());
|
||||
verifiers.put((int) 'S', new TestIntegerElementValue());
|
||||
verifiers.put((int) 'Z', new TestIntegerElementValue());
|
||||
verifiers.put((int) 's', new TestStringElementValue());
|
||||
verifiers.put((int) 'e', new TestEnumElementValue());
|
||||
verifiers.put((int) 'c', new TestClassElementValue());
|
||||
verifiers.put((int) '[', new TestArrayElementValue());
|
||||
verifiers.put((int) '@', new TestAnnotationElementValue());
|
||||
}
|
||||
|
||||
public void testLength(int tag, TestResult testResult, AnnotationDefault_attribute attr) {
|
||||
verifiers.get(tag).testLength(testResult, attr);
|
||||
}
|
||||
|
||||
public void testElementValue(int tag, TestResult testResult, ClassFile classFile,
|
||||
Annotation.element_value element_value, String[] values)
|
||||
throws ConstantPool.UnexpectedEntry, ConstantPool.InvalidIndex {
|
||||
get(tag).testElementValue(testResult, classFile, element_value, values);
|
||||
}
|
||||
|
||||
private TestElementValue get(int tag) {
|
||||
TestElementValue ev = verifiers.get(tag);
|
||||
if (ev == null) {
|
||||
throw new IllegalArgumentException("Unknown tag : " + (char) tag);
|
||||
}
|
||||
return ev;
|
||||
}
|
||||
|
||||
private abstract class TestElementValue {
|
||||
public void testLength(TestResult testCase, AnnotationDefault_attribute attr) {
|
||||
testCase.checkEquals(attr.attribute_length, 1 + attr.default_value.length(),
|
||||
"attribute_length");
|
||||
}
|
||||
|
||||
public String[] getValues(String[] values, int index, int length) {
|
||||
return Arrays.copyOfRange(values, index, index + length);
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public abstract void testElementValue(
|
||||
TestResult testCase,
|
||||
ClassFile classFile,
|
||||
Annotation.element_value element_value,
|
||||
String[] values)
|
||||
throws ConstantPool.InvalidIndex, ConstantPool.UnexpectedEntry;
|
||||
}
|
||||
|
||||
private class TestIntegerElementValue extends TestElementValue {
|
||||
|
||||
@Override
|
||||
public void testElementValue(
|
||||
TestResult testCase,
|
||||
ClassFile classFile,
|
||||
Annotation.element_value element_value,
|
||||
String[] values) throws ConstantPool.InvalidIndex {
|
||||
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);
|
||||
testCase.checkEquals(info.value, Integer.parseInt(values[0]), "const_value_index");
|
||||
}
|
||||
}
|
||||
|
||||
private class TestLongElementValue extends TestElementValue {
|
||||
@Override
|
||||
public void testElementValue(
|
||||
TestResult testCase,
|
||||
ClassFile classFile,
|
||||
Annotation.element_value element_value,
|
||||
String[] values) throws ConstantPool.InvalidIndex {
|
||||
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);
|
||||
testCase.checkEquals(info.value, Long.parseLong(values[0]), "const_value_index");
|
||||
}
|
||||
}
|
||||
|
||||
private class TestFloatElementValue extends TestElementValue {
|
||||
@Override
|
||||
public void testElementValue(
|
||||
TestResult testCase,
|
||||
ClassFile classFile,
|
||||
Annotation.element_value element_value,
|
||||
String[] values) throws ConstantPool.InvalidIndex {
|
||||
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);
|
||||
testCase.checkEquals(info.value, Float.parseFloat(values[0]), "const_value_index");
|
||||
}
|
||||
}
|
||||
|
||||
private class TestDoubleElementValue extends TestElementValue {
|
||||
@Override
|
||||
public void testElementValue(
|
||||
TestResult testCase,
|
||||
ClassFile classFile,
|
||||
Annotation.element_value element_value,
|
||||
String[] values) throws ConstantPool.InvalidIndex {
|
||||
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);
|
||||
testCase.checkEquals(info.value, Double.parseDouble(values[0]), "const_value_index");
|
||||
}
|
||||
}
|
||||
|
||||
private class TestStringElementValue extends TestElementValue {
|
||||
@Override
|
||||
public void testElementValue(
|
||||
TestResult testCase,
|
||||
ClassFile classFile,
|
||||
Annotation.element_value element_value,
|
||||
String[] values) throws ConstantPool.InvalidIndex {
|
||||
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);
|
||||
testCase.checkEquals(info.value, values[0], "const_value_index");
|
||||
}
|
||||
}
|
||||
|
||||
private class TestEnumElementValue extends TestElementValue {
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testElementValue(
|
||||
TestResult testCase,
|
||||
ClassFile classFile,
|
||||
Annotation.element_value element_value,
|
||||
String[] values)
|
||||
throws ConstantPool.InvalidIndex, ConstantPool.UnexpectedEntry {
|
||||
Annotation.Enum_element_value ev = (Annotation.Enum_element_value) element_value;
|
||||
testCase.checkEquals(classFile.constant_pool.getUTF8Info(ev.type_name_index).value,
|
||||
values[0], "type_name_index");
|
||||
testCase.checkEquals(classFile.constant_pool.getUTF8Info(ev.const_name_index).value,
|
||||
values[1], "const_name_index");
|
||||
}
|
||||
}
|
||||
|
||||
private class TestClassElementValue extends TestElementValue {
|
||||
@Override
|
||||
public void testElementValue(
|
||||
TestResult testCase,
|
||||
ClassFile classFile,
|
||||
Annotation.element_value element_value,
|
||||
String[] values)
|
||||
throws ConstantPool.InvalidIndex, ConstantPool.UnexpectedEntry {
|
||||
Annotation.Class_element_value ev = (Annotation.Class_element_value) element_value;
|
||||
testCase.checkEquals(
|
||||
classFile.constant_pool.getUTF8Info(ev.class_info_index).value,
|
||||
values[0], "class_info_index");
|
||||
}
|
||||
}
|
||||
|
||||
private class TestAnnotationElementValue extends TestElementValue {
|
||||
@Override
|
||||
public void testLength(TestResult testCase, AnnotationDefault_attribute attr) {
|
||||
// Suppress, since it is hard to test the length of this kind of element values.
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
// Expected that the test uses DefaultAnnotation
|
||||
// tag (1 byte) + annotation_value (2 bytes) which contains const_value
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testElementValue(
|
||||
TestResult testCase,
|
||||
ClassFile classFile,
|
||||
Annotation.element_value element_value,
|
||||
String[] values)
|
||||
throws ConstantPool.InvalidIndex, ConstantPool.UnexpectedEntry {
|
||||
Annotation ev = ((Annotation.Annotation_element_value) element_value)
|
||||
.annotation_value;
|
||||
testCase.checkEquals(
|
||||
classFile.constant_pool.getUTF8Info(ev.type_index).value,
|
||||
values[0],
|
||||
"type_index");
|
||||
for (int i = 0; i < ev.num_element_value_pairs; ++i) {
|
||||
Annotation.element_value_pair pair = ev.element_value_pairs[i];
|
||||
testCase.checkEquals(
|
||||
classFile.constant_pool.getUTF8Info(pair.element_name_index).value,
|
||||
values[2 * i + 1],
|
||||
"element_name_index");
|
||||
TestElementValue testElementValue = verifiers.get(pair.value.tag);
|
||||
testElementValue.testElementValue(
|
||||
testCase,
|
||||
classFile,
|
||||
pair.value,
|
||||
new String[]{values[2 * i + 2]});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class TestArrayElementValue extends TestElementValue {
|
||||
@Override
|
||||
public void testLength(TestResult testCase, AnnotationDefault_attribute attr) {
|
||||
Annotation.Array_element_value ev =
|
||||
(Annotation.Array_element_value) attr.default_value;
|
||||
int sizeOfTag = ev.values[0].tag == 'e' ? 0 : 1;
|
||||
// tag (1 byte) + array header (2 byte) + length of entries
|
||||
testCase.checkEquals(attr.attribute_length, 1 + 2 +
|
||||
(sizeOfTag + ev.length() / ev.num_values) * ev.num_values, "attribute_length");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testElementValue(
|
||||
TestResult testCase,
|
||||
ClassFile classFile,
|
||||
Annotation.element_value element_value,
|
||||
String[] values)
|
||||
throws ConstantPool.InvalidIndex, ConstantPool.UnexpectedEntry {
|
||||
Annotation.Array_element_value ev =
|
||||
(Annotation.Array_element_value) element_value;
|
||||
int index = 0;
|
||||
for (int i = 0; i < ev.num_values; ++i) {
|
||||
TestElementValue testElementValue = verifiers.get(ev.values[i].tag);
|
||||
int length = testElementValue.getLength();
|
||||
testElementValue.testElementValue(
|
||||
testCase,
|
||||
classFile,
|
||||
ev.values[i],
|
||||
testElementValue.getValues(values, index, length));
|
||||
index += length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ExpectedValues {
|
||||
char tag();
|
||||
String name();
|
||||
String[] values();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user