8042931: Implement classfile tests for EnclosingMethod attribute.
Reviewed-by: jjg, shurailine, anazarov
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/EnclosingMethod/EnclosingMethodTest.java Wed Nov 12 15:16:35 2014 +0200
@@ -0,0 +1,537 @@
+/*
+ * 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 8042931
+ * @summary Checking EnclosingMethod attribute of anonymous/local class.
+ * @library /tools/lib /tools/javac/lib ../lib
+ * @build EnclosingMethodTest TestBase TestResult InMemoryFileManager ToolBox
+ * @run main EnclosingMethodTest
+ */
+
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.EnclosingMethod_attribute;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Stream;
+
+/**
+ * The test checks the enclosing method attribute of anonymous/local classes.
+ * The top-level class contains the anonymous and local classes to be tested. The test examines
+ * each inner class and determine whether the class should have the EnclosingMethod attribute or not.
+ * Golden information about enclosing methods are held in annotation {@code ExpectedEnclosingMethod}.
+ *
+ * The test assumes that a class must have the EnclosingMethod attribute if the class is annotated or
+ * if its parent class is annotated in case of anonymous class. In addition, classes
+ * named {@code VariableInitializer} are introduced to test variable initializer cases. These classes
+ * must not have the enclosing method attribute, but its anonymous derived class must.
+ * After classification of classes, the test checks whether classes contain the correct enclosing
+ * method attribute in case of anonymous/local class, or checks whether classes do not contain
+ * the EnclosingMethod attribute, otherwise.
+ *
+ * Test cases:
+ * top-level class as enclosing class:
+ * 1. anonymous and local classes in static initializer;
+ * 2. anonymous and local classes in instance initializer;
+ * 3. anonymous and local classes in lambda;
+ * 4. anonymous and local classes in constructor;
+ * 5. anonymous and local classes in method;
+ * 6. static and instance variable initializer.
+ *
+ * inner class as enclosing class:
+ * 1. anonymous and local classes in static initializer;
+ * 2. anonymous and local classes in instance initializer;
+ * 3. anonymous and local classes in lambda;
+ * 4. anonymous and local classes in constructor;
+ * 5. anonymous and local classes in method;
+ * 6. static and instance variable initializer.
+ *
+ * enum as enclosing class:
+ * 1. anonymous and local classes in static initializer;
+ * 2. anonymous and local classes in instance initializer;
+ * 3. anonymous and local classes in lambda;
+ * 4. anonymous and local classes in constructor;
+ * 5. anonymous and local classes in method;
+ * 6. static and instance variable initializer.
+ *
+ * interface as enclosing class:
+ * 1. anonymous and local classes in lambda;
+ * 2. anonymous and local classes in static method;
+ * 3. anonymous and local classes in default method;
+ * 4. static variable initializer.
+ *
+ * annotation as enclosing class:
+ * 1. anonymous and local classes in lambda;
+ * 2. static variable initializer.
+ */
+public class EnclosingMethodTest extends TestResult {
+
+ private final Map<Class<?>, ExpectedEnclosingMethod> class2EnclosingMethod = new HashMap<>();
+ private final Set<Class<?>> noEnclosingMethod = new HashSet<>();
+
+ public EnclosingMethodTest() throws ClassNotFoundException {
+ Class<EnclosingMethodTest> outerClass = EnclosingMethodTest.class;
+ String outerClassName = outerClass.getSimpleName();
+ File testClasses = getClassDir();
+ FilenameFilter filter = (dir, name) -> name.matches(outerClassName + ".*\\.class");
+
+ for (File file : testClasses.listFiles(filter)) {
+ Class<?> clazz = Class.forName(file.getName().replace(".class", ""));
+ if (clazz.isAnonymousClass()) {
+ // anonymous class cannot be annotated, information is in its parent class.
+ ExpectedEnclosingMethod declaredAnnotation =
+ clazz.getSuperclass().getDeclaredAnnotation(ExpectedEnclosingMethod.class);
+ class2EnclosingMethod.put(clazz, declaredAnnotation);
+ } else {
+ ExpectedEnclosingMethod enclosingMethod = clazz.getDeclaredAnnotation(ExpectedEnclosingMethod.class);
+ // if class is annotated and it does not contain information for variable initializer cases,
+ // then it must have the enclosing method attribute.
+ if (enclosingMethod != null && !clazz.getSimpleName().contains("VariableInitializer")) {
+ class2EnclosingMethod.put(clazz, enclosingMethod);
+ } else {
+ noEnclosingMethod.add(clazz);
+ }
+ }
+ }
+ }
+
+ public void test() throws TestFailedException {
+ try {
+ testEnclosingMethodAttribute();
+ testLackOfEnclosingMethodAttribute();
+ } finally {
+ checkStatus();
+ }
+ }
+
+ private void testLackOfEnclosingMethodAttribute() {
+ for (Class<?> clazz : noEnclosingMethod) {
+ try {
+ addTestCase("Class should not have EnclosingMethod attribute : " + clazz);
+ ClassFile classFile = readClassFile(clazz);
+ checkEquals(countEnclosingMethodAttributes(classFile),
+ 0l, "number of the EnclosingMethod attribute in the class is zero : "
+ + classFile.getName());
+ } catch (Exception e) {
+ addFailure(e);
+ }
+ }
+ }
+
+ private void testEnclosingMethodAttribute() {
+ class2EnclosingMethod.forEach((clazz, enclosingMethod) -> {
+ try {
+ String info = enclosingMethod.info() + " "
+ + (clazz.isAnonymousClass() ? "anonymous" : "local");
+ addTestCase(info);
+ printf("Testing test case : %s\n", info);
+ ClassFile classFile = readClassFile(clazz);
+ String className = clazz.getName();
+ checkEquals(countEnclosingMethodAttributes(classFile), 1l,
+ "number of the EnclosingMethod attribute in the class is one : "
+ + clazz);
+ EnclosingMethod_attribute attr = (EnclosingMethod_attribute)
+ classFile.getAttribute(Attribute.EnclosingMethod);
+
+ if (!checkNotNull(attr, "the EnclosingMethod attribute is not null : " + className)) {
+ // stop checking, attr is null. test case failed
+ return;
+ }
+ checkEquals(classFile.constant_pool.getUTF8Value(attr.attribute_name_index),
+ "EnclosingMethod",
+ "attribute_name_index of EnclosingMethod attribute in the class : " + className);
+ checkEquals(attr.attribute_length, 4,
+ "attribute_length of EnclosingMethod attribute in the class : " + className);
+ String expectedClassName = enclosingMethod.enclosingClazz().getName();
+ checkEquals(classFile.constant_pool.getClassInfo(attr.class_index).getName(),
+ expectedClassName, String.format(
+ "enclosing class of EnclosingMethod attribute in the class %s is %s",
+ className, expectedClassName));
+
+ String expectedMethodName = enclosingMethod.enclosingMethod();
+ if (expectedMethodName.isEmpty()) {
+ // class does not have an enclosing method
+ checkEquals(attr.method_index, 0, String.format(
+ "enclosing method of EnclosingMethod attribute in the class %s is null", className));
+ } else {
+ String methodName = classFile.constant_pool.getNameAndTypeInfo(attr.method_index).getName();
+ checkTrue(methodName.startsWith(expectedMethodName), String.format(
+ "enclosing method of EnclosingMethod attribute in the class %s" +
+ " is method name %s" +
+ ", actual method name is %s",
+ className, expectedMethodName, methodName));
+ }
+ } catch (Exception e) {
+ addFailure(e);
+ }
+ });
+ }
+
+ private long countEnclosingMethodAttributes(ClassFile classFile) {
+ return Stream.of(classFile.attributes.attrs)
+ .filter(x -> x instanceof EnclosingMethod_attribute)
+ .count();
+ }
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface ExpectedEnclosingMethod {
+ String info();
+ Class<?> enclosingClazz();
+ String enclosingMethod() default "";
+ }
+
+ public static void main(String[] args) throws ClassNotFoundException, TestFailedException {
+ new EnclosingMethodTest().test();
+ }
+
+ // Test cases: enclosing class is a top-level class
+ static {
+ // anonymous and local classes in static initializer
+ @ExpectedEnclosingMethod(
+ info = "EnclosingStaticInitialization in EnclosingMethodTest",
+ enclosingClazz = EnclosingMethodTest.class
+ )
+ class EnclosingStaticInitialization {
+ }
+ new EnclosingStaticInitialization() {
+ };
+ }
+
+ {
+ // anonymous and local classes in instance initializer
+ @ExpectedEnclosingMethod(
+ info = "EnclosingInitialization in EnclosingMethodTest",
+ enclosingClazz = EnclosingMethodTest.class
+ )
+ class EnclosingInitialization {
+ }
+ new EnclosingInitialization() {
+ };
+ }
+
+ Runnable lambda = () -> {
+ // anonymous and local classes in lambda
+ @ExpectedEnclosingMethod(
+ info = "EnclosingLambda in EnclosingMethodTest",
+ enclosingMethod = "lambda",
+ enclosingClazz = EnclosingMethodTest.class
+ )
+ class EnclosingLambda {
+ }
+ new EnclosingLambda() {
+ };
+ };
+
+ EnclosingMethodTest(int i) {
+ // anonymous and local classes in constructor
+ @ExpectedEnclosingMethod(
+ info = "EnclosingConstructor in EnclosingMethodTest",
+ enclosingMethod = "<init>",
+ enclosingClazz = EnclosingMethodTest.class
+ )
+ class EnclosingConstructor {
+ }
+ new EnclosingConstructor() {
+ };
+ }
+
+ void method() {
+ // anonymous and local classes in method
+ @ExpectedEnclosingMethod(
+ info = "EnclosingMethod in EnclosingMethodTest",
+ enclosingMethod = "method",
+ enclosingClazz = EnclosingMethodTest.class
+ )
+ class EnclosingMethod {
+ }
+ new EnclosingMethod() {
+ };
+ }
+
+ @ExpectedEnclosingMethod(
+ info = "VariableInitializer in EnclosingMethodTest",
+ enclosingClazz = EnclosingMethodTest.class
+ )
+ static class VariableInitializer {
+ }
+
+ // static variable initializer
+ private static final VariableInitializer cvi = new VariableInitializer() {
+ };
+
+ // instance variable initializer
+ private final VariableInitializer ivi = new VariableInitializer() {
+ };
+
+ // Test cases: enclosing class is an inner class
+ public static class notEnclosing01 {
+ static {
+ // anonymous and local classes in static initializer
+ @ExpectedEnclosingMethod(
+ info = "EnclosingStaticInitialization in notEnclosing01",
+ enclosingClazz = notEnclosing01.class
+ )
+ class EnclosingStaticInitialization {
+ }
+ new EnclosingStaticInitialization() {
+ };
+ }
+
+ {
+ // anonymous and local classes in instance initializer
+ @ExpectedEnclosingMethod(
+ info = "EnclosingInitialization in notEnclosing01",
+ enclosingClazz = notEnclosing01.class
+ )
+ class EnclosingInitialization {
+ }
+ new EnclosingInitialization() {
+ };
+ }
+
+ Runnable lambda = () -> {
+ // anonymous and local classes in lambda
+ @ExpectedEnclosingMethod(
+ info = "EnclosingLambda in notEnclosing01",
+ enclosingMethod = "lambda",
+ enclosingClazz = notEnclosing01.class
+ )
+ class EnclosingLambda {
+ }
+ new EnclosingLambda() {
+ };
+ };
+
+ notEnclosing01() {
+ // anonymous and local classes in constructor
+ @ExpectedEnclosingMethod(
+ info = "EnclosingConstructor in notEnclosing01",
+ enclosingMethod = "<init>",
+ enclosingClazz = notEnclosing01.class
+ )
+ class EnclosingConstructor {
+ }
+ new EnclosingConstructor() {
+ };
+ }
+
+ void method() {
+ // anonymous and local classes in method
+ @ExpectedEnclosingMethod(
+ info = "EnclosingMethod in notEnclosing01",
+ enclosingMethod = "method",
+ enclosingClazz = notEnclosing01.class
+ )
+ class EnclosingMethod {
+ }
+ new EnclosingMethod() {
+ };
+ }
+
+ @ExpectedEnclosingMethod(
+ info = "VariableInitializer in notEnclosing01",
+ enclosingClazz = notEnclosing01.class
+ )
+ static class VariableInitializer {
+ }
+
+ // static variable initializer
+ private static final VariableInitializer cvi = new VariableInitializer() {
+ };
+
+ // instance variable initializer
+ private final VariableInitializer ivi = new VariableInitializer() {
+ };
+ }
+
+ // Test cases: enclosing class is an interface
+ public interface notEnclosing02 {
+ Runnable lambda = () -> {
+ // anonymous and local classes in lambda
+ @ExpectedEnclosingMethod(
+ info = "EnclosingLambda in notEnclosing02",
+ enclosingMethod = "lambda",
+ enclosingClazz = notEnclosing02.class
+ )
+ class EnclosingLambda {
+ }
+ new EnclosingLambda() {
+ };
+ };
+
+ static void staticMethod() {
+ // anonymous and local classes in static method
+ @ExpectedEnclosingMethod(
+ info = "EnclosingMethod in notEnclosing02",
+ enclosingMethod = "staticMethod",
+ enclosingClazz = notEnclosing02.class
+ )
+ class EnclosingMethod {
+ }
+ new EnclosingMethod() {
+ };
+ }
+
+ default void defaultMethod() {
+ // anonymous and local classes in default method
+ @ExpectedEnclosingMethod(
+ info = "EnclosingMethod in notEnclosing02",
+ enclosingMethod = "defaultMethod",
+ enclosingClazz = notEnclosing02.class
+ )
+ class EnclosingMethod {
+ }
+ new EnclosingMethod() {
+ };
+ }
+
+ @ExpectedEnclosingMethod(
+ info = "VariableInitializer in notEnclosing02",
+ enclosingClazz = notEnclosing02.class
+ )
+ static class VariableInitializer {
+ }
+
+ // static variable initializer
+ VariableInitializer cvi = new VariableInitializer() {
+ };
+ }
+
+ // Test cases: enclosing class is an enum
+ public enum notEnclosing03 {;
+
+ static {
+ // anonymous and local classes in static initializer
+ @ExpectedEnclosingMethod(
+ info = "EnclosingStaticInitialization in notEnclosing03",
+ enclosingClazz = notEnclosing03.class
+ )
+ class EnclosingStaticInitialization {
+ }
+ new EnclosingStaticInitialization() {
+ };
+ }
+
+ {
+ // anonymous and local classes in instance initializer
+ @ExpectedEnclosingMethod(
+ info = "EnclosingInitialization in notEnclosing03",
+ enclosingClazz = notEnclosing03.class
+ )
+ class EnclosingInitialization {
+ }
+ new EnclosingInitialization() {
+ };
+ }
+
+ Runnable lambda = () -> {
+ // anonymous and local classes in lambda
+ @ExpectedEnclosingMethod(
+ info = "EnclosingLambda in notEnclosing03",
+ enclosingMethod = "lambda",
+ enclosingClazz = notEnclosing03.class
+ )
+ class EnclosingLambda {
+ }
+ new EnclosingLambda() {
+ };
+ };
+
+ notEnclosing03() {
+ // anonymous and local classes in constructor
+ @ExpectedEnclosingMethod(
+ info = "EnclosingConstructor in notEnclosing03",
+ enclosingMethod = "<init>",
+ enclosingClazz = notEnclosing03.class
+ )
+ class EnclosingConstructor {
+ }
+ new EnclosingConstructor() {
+ };
+ }
+
+ void method() {
+ // anonymous and local classes in method
+ @ExpectedEnclosingMethod(
+ info = "EnclosingMethod in notEnclosing03",
+ enclosingMethod = "method",
+ enclosingClazz = notEnclosing03.class
+ )
+ class EnclosingMethod {
+ }
+ new EnclosingMethod() {
+ };
+ }
+
+ @ExpectedEnclosingMethod(
+ info = "VariableInitializer in notEnclosing03",
+ enclosingClazz = notEnclosing03.class
+ )
+ static class VariableInitializer {
+ }
+
+ // static variable initializer
+ private static final VariableInitializer cvi = new VariableInitializer() {
+ };
+
+ // instance variable initializer
+ private final VariableInitializer ivi = new VariableInitializer() {
+ };
+ }
+
+ // Test cases: enclosing class is an annotation
+ public @interface notEnclosing04 {
+ Runnable lambda = () -> {
+ // anonymous and local classes in lambda
+ @ExpectedEnclosingMethod(
+ info = "EnclosingLambda in notEnclosing04",
+ enclosingMethod = "lambda",
+ enclosingClazz = notEnclosing04.class
+ )
+ class EnclosingLambda {
+ }
+ new EnclosingLambda() {
+ };
+ };
+
+ @ExpectedEnclosingMethod(
+ info = "VariableInitializer in notEnclosing04",
+ enclosingClazz = notEnclosing04.class
+ )
+ static class VariableInitializer {
+ }
+
+ // static variable initializer
+ VariableInitializer cvi = new VariableInitializer() {
+ };
+ }
+}
--- a/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java Wed Nov 12 12:41:32 2014 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java Wed Nov 12 15:16:35 2014 +0200
@@ -74,13 +74,13 @@
addTestCase(src);
printf("Testing test case: \n%s\n", src);
try {
- ClassFile cf = ClassFile.read(compile(
+ ClassFile cf = readClassFile(compile(
new String[]{"package-info.java", package_info},
new String[]{"notDeprecated.java", src})
- .getClasses().get(CLASS_NAME).openInputStream());
+ .getClasses().get(CLASS_NAME));
Deprecated_attribute attr =
(Deprecated_attribute) cf.getAttribute(Attribute.Deprecated);
- assertNull(attr, "Class can not have deprecated attribute : " + CLASS_NAME);
+ checkNull(attr, "Class can not have deprecated attribute : " + CLASS_NAME);
} catch (Exception e) {
addFailure(e);
}
--- a/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java Wed Nov 12 12:41:32 2014 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java Wed Nov 12 15:16:35 2014 +0200
@@ -240,7 +240,7 @@
? "deprecated"
: "notDeprecated";
echo("Testing outer class : " + outerClassName);
- ClassFile cf = ClassFile.read(classes.get(outerClassName).openInputStream());
+ ClassFile cf = readClassFile(classes.get(outerClassName));
Deprecated_attribute attr = (Deprecated_attribute)
cf.getAttribute(Attribute.Deprecated);
testAttribute(outerClassName, attr, cf);
@@ -260,7 +260,7 @@
String innerClassName = cf.constant_pool.
getClassInfo(innerClass.inner_class_info_index).getName();
echo("Testing inner class : " + innerClassName);
- ClassFile innerCf = ClassFile.read(classes.get(innerClassName).openInputStream());
+ ClassFile innerCf = readClassFile(classes.get(innerClassName));
Deprecated_attribute attr = (Deprecated_attribute)
innerCf.getAttribute(Attribute.Deprecated);
String innerClassSimpleName = innerClass.getInnerName(cf.constant_pool);
@@ -298,17 +298,18 @@
if (name.contains("deprecated")) {
testDeprecatedAttribute(name, attr, cf);
} else {
- assertNull(attr, name + " should not have deprecated attribute");
+ checkNull(attr, name + " should not have deprecated attribute");
}
}
private void testDeprecatedAttribute(String name, Deprecated_attribute attr, ClassFile cf)
throws ConstantPoolException {
- assertNotNull(attr, name + " must have deprecated attribute");
- assertEquals(0, attr.attribute_length,
- "attribute_length should equal to 0");
- assertEquals("Deprecated",
- cf.constant_pool.getUTF8Value(attr.attribute_name_index),
- name + " attribute_name_index");
+ if (checkNotNull(attr, name + " must have deprecated attribute")) {
+ checkEquals(0, attr.attribute_length,
+ "attribute_length should equal to 0");
+ checkEquals("Deprecated",
+ cf.constant_pool.getUTF8Value(attr.attribute_name_index),
+ name + " attribute_name_index");
+ }
}
}
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java Wed Nov 12 12:41:32 2014 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java Wed Nov 12 15:16:35 2014 +0200
@@ -96,21 +96,21 @@
ClassFile cf = readClassFile(currentClassName);
InnerClasses_attribute attr = (InnerClasses_attribute)
cf.getAttribute(Attribute.InnerClasses);
- assertNotNull(attr, "Class should not contain "
+ checkNotNull(attr, "Class should not contain "
+ "inner classes attribute : " + currentClassName);
- assertTrue(innerClasses.containsKey(currentClassName),
+ checkTrue(innerClasses.containsKey(currentClassName),
"map contains class name : " + currentClassName);
Set<String> setClasses = innerClasses.get(currentClassName);
if (setClasses == null) {
continue;
}
- assertEquals(attr.number_of_classes,
+ checkEquals(attr.number_of_classes,
setClasses.size(),
"Check number of inner classes : " + setClasses);
for (Info info : attr.classes) {
String innerClassName = info
.getInnerClassInfo(cf.constant_pool).getBaseName();
- assertTrue(setClasses.contains(innerClassName),
+ checkTrue(setClasses.contains(innerClassName),
currentClassName + " contains inner class : "
+ innerClassName);
if (visitedClasses.add(innerClassName)) {
@@ -124,10 +124,10 @@
Set<String> a_b = removeAll(visitedClasses, allClasses);
Set<String> b_a = removeAll(allClasses, visitedClasses);
- assertEquals(visitedClasses, allClasses,
+ checkEquals(visitedClasses, allClasses,
"All classes are found\n"
- + "visited - all classes : " + a_b
- + "\nall classes - visited : " + b_a);
+ + "visited - all classes : " + a_b
+ + "\nall classes - visited : " + b_a);
} catch (Exception e) {
addFailure(e);
} finally {
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java Wed Nov 12 12:41:32 2014 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java Wed Nov 12 15:16:35 2014 +0200
@@ -78,16 +78,16 @@
continue;
}
foundClasses.add(innerName);
- assertEquals(info.outer_class_info_index, 0,
+ checkEquals(info.outer_class_info_index, 0,
"outer_class_info_index of " + innerName);
if (innerName.matches("\\$\\d+")) {
- assertEquals(info.inner_name_index, 0,
+ checkEquals(info.inner_name_index, 0,
"inner_name_index of anonymous class");
}
}
Set<String> expectedClasses = getInnerClasses();
expectedClasses.remove("InnerClassesIndexTest$Inner");
- assertEquals(foundClasses, expectedClasses, "All classes are found");
+ checkEquals(foundClasses, expectedClasses, "All classes are found");
} catch (Exception e) {
addFailure(e);
} finally {
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java Wed Nov 12 12:41:32 2014 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java Wed Nov 12 15:16:35 2014 +0200
@@ -202,44 +202,44 @@
++count;
}
}
- assertEquals(1, count, "Number of inner classes attribute");
- if (innerClasses == null) {
+ checkEquals(1, count, "Number of inner classes attribute");
+ if (!checkNotNull(innerClasses, "InnerClasses attribute should not be null")) {
return;
}
- assertEquals(cf.constant_pool.
+ checkEquals(cf.constant_pool.
getUTF8Info(innerClasses.attribute_name_index).value, "InnerClasses",
"innerClasses.attribute_name_index");
// Inner Classes attribute consists of length (2 bytes)
// and 8 bytes for each inner class's entry.
- assertEquals(innerClasses.attribute_length,
+ checkEquals(innerClasses.attribute_length,
2 + 8 * class2Flags.size(), "innerClasses.attribute_length");
- assertEquals(innerClasses.number_of_classes,
+ checkEquals(innerClasses.number_of_classes,
class2Flags.size(), "innerClasses.number_of_classes");
Set<String> visitedClasses = new HashSet<>();
for (Info e : innerClasses.classes) {
String baseName = cf.constant_pool.getClassInfo(
e.inner_class_info_index).getBaseName();
if (cf.major_version >= 51 && e.inner_name_index == 0) {
- assertEquals(e.outer_class_info_index, 0,
- "outer_class_info_index "
- + "in case of inner_name_index is zero : "
- + baseName);
+ checkEquals(e.outer_class_info_index, 0,
+ "outer_class_info_index "
+ + "in case of inner_name_index is zero : "
+ + baseName);
}
String className = baseName.replaceFirst(".*\\$", "");
- assertTrue(class2Flags.containsKey(className),
+ checkTrue(class2Flags.containsKey(className),
className);
- assertTrue(visitedClasses.add(className),
+ checkTrue(visitedClasses.add(className),
"there are no duplicates in attribute : " + className);
- assertEquals(e.inner_class_access_flags.getInnerClassFlags(),
+ checkEquals(e.inner_class_access_flags.getInnerClassFlags(),
class2Flags.get(className),
"inner_class_access_flags " + className);
if (!Arrays.asList(skipClasses).contains(className)) {
- assertEquals(
- cf.constant_pool.getClassInfo(e.inner_class_info_index).getBaseName(),
- classToTest + "$" + className,
- "inner_class_info_index of " + className);
+ checkEquals(
+ cf.constant_pool.getClassInfo(e.inner_class_info_index).getBaseName(),
+ classToTest + "$" + className,
+ "inner_class_info_index of " + className);
if (e.outer_class_info_index > 0) {
- assertEquals(
+ checkEquals(
cf.constant_pool.getClassInfo(e.outer_class_info_index).getName(),
classToTest,
"outer_class_info_index of " + className);
--- a/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java Wed Nov 12 12:41:32 2014 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java Wed Nov 12 15:16:35 2014 +0200
@@ -25,10 +25,7 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -78,8 +75,8 @@
/**
* Compiles sources in memory.
*
- * @param sources to compile.
- * @return memory file manager which contains class files and class loader.
+ * @param sources to compile
+ * @return in-memory file manager which contains class files and class loader
*/
public InMemoryFileManager compile(String... sources)
throws IOException, CompilationException {
@@ -91,7 +88,7 @@
*
* @param options compiler options.
* @param sources sources to compile.
- * @return map where key is className, value is corresponding ClassFile.
+ * @return in-memory file manager which contains class files and class loader.
*/
public InMemoryFileManager compile(List<String> options, String... sources)
throws IOException, CompilationException {
@@ -102,7 +99,7 @@
* Compiles sources in memory.
*
* @param sources sources[i][0] - name of file, sources[i][1] - sources.
- * @return map where key is className, value is corresponding ClassFile.
+ * @return in-memory file manager which contains class files and class loader.
*/
public InMemoryFileManager compile(String[]... sources) throws IOException,
CompilationException {
@@ -114,7 +111,7 @@
*
* @param options compiler options
* @param sources sources[i][0] - name of file, sources[i][1] - sources.
- * @return map where key is className, value is corresponding ClassFile.
+ * @return in-memory file manager which contains class files and class loader.
*/
public InMemoryFileManager compile(List<String> options, String[]... sources)
throws IOException, CompilationException {
@@ -142,7 +139,9 @@
* @throws ConstantPoolException if constant pool error occurs
*/
public ClassFile readClassFile(JavaFileObject fileObject) throws IOException, ConstantPoolException {
- return readClassFile(fileObject.openInputStream());
+ try (InputStream is = fileObject.openInputStream()) {
+ return readClassFile(is);
+ }
}
/**
@@ -205,6 +204,12 @@
assertEquals(actual, false, message);
}
+ public void assertContains(Set<?> found, Set<?> expected, String message) {
+ Set<?> copy = new HashSet<>(expected);
+ copy.removeAll(found);
+ assertTrue(found.containsAll(expected), message + " : " + copy);
+ }
+
public File getSourceDir() {
return new File(System.getProperty("test.src", "."));
}
--- a/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java Wed Nov 12 12:41:32 2014 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java Wed Nov 12 15:16:35 2014 +0200
@@ -24,10 +24,7 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
-import java.util.stream.Stream;
-
-import static java.lang.String.format;
-import static java.util.stream.Collectors.joining;
+import java.util.stream.Collectors;
/**
* This class accumulates test results. Test results can be checked with method @{code checkStatus}.
@@ -52,39 +49,46 @@
private String errorMessage() {
return testCases.stream().filter(Info::isFailed)
- .map(tc -> format("Failure in test case:\n%s\n%s", tc.info(), tc.getMessage()))
- .collect(joining("\n"));
+ .map(tc -> String.format("Failure in test case:\n%s\n%s", tc.info(), tc.getMessage()))
+ .collect(Collectors.joining("\n"));
}
- @Override
- public void assertEquals(Object actual, Object expected, String message) {
- getLastTestCase().assertEquals(actual, expected, message);
+ public boolean checkEquals(Object actual, Object expected, String message) {
+ echo("Testing : " + message);
+ if (!Objects.equals(actual, expected)) {
+ getLastTestCase().addAssert(new AssertionFailedException(
+ String.format("%s%nGot: %s, Expected: %s", message, actual, expected)));
+ return false;
+ }
+ return true;
}
- @Override
- public void assertNull(Object actual, String message) {
- getLastTestCase().assertEquals(actual, null, message);
+ public boolean checkNull(Object actual, String message) {
+ return checkEquals(actual, null, message);
}
- @Override
- public void assertNotNull(Object actual, String message) {
- getLastTestCase().assertNotNull(actual, message);
- }
-
- @Override
- public void assertFalse(boolean actual, String message) {
- getLastTestCase().assertEquals(actual, false, message);
+ public boolean checkNotNull(Object actual, String message) {
+ echo("Testing : " + message);
+ if (Objects.isNull(actual)) {
+ getLastTestCase().addAssert(new AssertionFailedException(
+ message + " : Expected not null value"));
+ return false;
+ }
+ return true;
}
- @Override
- public void assertTrue(boolean actual, String message) {
- getLastTestCase().assertEquals(actual, true, message);
+ public boolean checkFalse(boolean actual, String message) {
+ return checkEquals(actual, false, message);
}
- public void assertContains(Set<?> found, Set<?> expected, String message) {
+ public boolean checkTrue(boolean actual, String message) {
+ return checkEquals(actual, true, message);
+ }
+
+ public boolean checkContains(Set<?> found, Set<?> expected, String message) {
Set<?> copy = new HashSet<>(expected);
copy.removeAll(found);
- assertTrue(found.containsAll(expected), message + " : " + copy);
+ return checkTrue(found.containsAll(expected), message + " : " + copy);
}
public void addFailure(Throwable th) {
@@ -99,10 +103,10 @@
}
/**
- * Throws {@code TestFailedException} if one of the asserts are failed
+ * Throws {@code TestFailedException} if one of the checks are failed
* or an exception occurs. Prints error message of failed test cases.
*
- * @throws TestFailedException if one of the asserts are failed
+ * @throws TestFailedException if one of the checks are failed
* or an exception occurs
*/
public void checkStatus() throws TestFailedException {
@@ -115,7 +119,7 @@
private class Info {
private final String info;
- private final List<String> asserts;
+ private final List<AssertionFailedException> asserts;
private final List<Throwable> errors;
private Info(String info) {
@@ -137,45 +141,20 @@
printf("[ERROR] : %s\n", getStackTrace(th));
}
- public void addFailure(String message) {
- String stackTrace = Stream.of(Thread.currentThread().getStackTrace())
- // just to get stack trace without TestResult and Thread
- .filter(e -> !"TestResult.java".equals(e.getFileName()) &&
- !"java.lang.Thread".equals(e.getClassName()))
- .map(e -> "\tat " + e)
- .collect(joining("\n"));
- asserts.add(format("%s\n%s", message, stackTrace));
- printf("[ASSERT] : %s\n", message);
- }
-
- public void assertEquals(Object actual, Object expected, String message) {
- echo("Testing : " + message);
- if (!Objects.equals(actual, expected)) {
- addFailure(message + ": Got: " + actual + ", " + "Expected: " + expected);
- }
- }
-
- public void assertNotNull(Object actual, String message) {
- echo("Testing : " + message);
- if (actual == null) {
- addFailure(message + " : Expected not null value");
- }
+ public void addAssert(AssertionFailedException e) {
+ asserts.add(e);
+ printf("[ASSERT] : %s\n", getStackTrace(e));
}
public String getMessage() {
- return (asserts.size() > 0 ? getAssertMessage() + "\n" : "") + getErrorMessage();
+ return (asserts.size() > 0 ? getErrorMessage("[ASSERT]", asserts) + "\n" : "")
+ + getErrorMessage("[ERROR]", errors);
}
- public String getAssertMessage() {
- return asserts.stream()
- .map(failure -> "[ASSERT] : " + failure)
- .collect(joining("\n"));
- }
-
- public String getErrorMessage() {
- return errors.stream()
- .map(throwable -> format("[ERROR] : %s", getStackTrace(throwable)))
- .collect(joining("\n"));
+ public String getErrorMessage(String header, List<? extends Throwable> list) {
+ return list.stream()
+ .map(throwable -> String.format("%s : %s", header, getStackTrace(throwable)))
+ .collect(Collectors.joining("\n"));
}
public String getStackTrace(Throwable throwable) {