8042931: Implement classfile tests for EnclosingMethod attribute.
authoraeremeev
Wed, 12 Nov 2014 15:16:35 +0200
changeset 27552 8a4b2d3639c1
parent 27551 14a74a56c4a0
child 27553 75321debd020
8042931: Implement classfile tests for EnclosingMethod attribute. Reviewed-by: jjg, shurailine, anazarov
langtools/test/tools/javac/classfiles/attributes/EnclosingMethod/EnclosingMethodTest.java
langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java
langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java
langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java
langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java
langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java
langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java
langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java
--- /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) {