8042261: Implement classfile tests for Deprecated attribute.
authorjjg
Fri, 04 Jul 2014 10:52:22 +0100
changeset 25434 823512a72660
parent 25433 b935bc56f1e4
child 25435 928866794984
8042261: Implement classfile tests for Deprecated attribute. Reviewed-by: jjg, anazarov, shurailine
langtools/test/tools/javac/classfiles/attributes/SourceFile/SourceFileTestBase.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/lib/TestBase.java
langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java
--- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/SourceFileTestBase.java	Thu Jul 03 15:48:23 2014 -0700
+++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/SourceFileTestBase.java	Fri Jul 04 10:52:22 2014 +0100
@@ -45,7 +45,7 @@
      */
     protected void compileAndTest(String sourceCode, String... classesToTest) throws Exception {
 
-        Map<String, ? extends JavaFileObject> classes = compile(sourceCode);
+        Map<String, ? extends JavaFileObject> classes = compile(sourceCode).getClasses();
         String fileName = ToolBox.getJavaFileNameFromSource(sourceCode);
         for (String className : classesToTest) {
             assertAttributePresent(ClassFile.read(classes.get(className).openInputStream()), fileName);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedPackageTest.java	Fri Jul 04 10:52:22 2014 +0100
@@ -0,0 +1,88 @@
+/*
+ * 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 8042261
+ * @summary Checking that deprecated attribute does not apply to classes of deprecated package.
+ * @library /tools/javac/lib ../lib
+ * @build DeprecatedPackageTest TestBase TestResult InMemoryFileManager ToolBox
+ * @run main DeprecatedPackageTest
+ */
+
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.Deprecated_attribute;
+
+public class DeprecatedPackageTest extends TestResult {
+
+    private static final String[] sourceTest = new String[]{
+        "package deprecated;\n"
+        + "public class notDeprecated{}",
+        "package deprecated;\n"
+        + "public interface notDeprecated{}",
+        "package deprecated;\n"
+        + "public @interface notDeprecated{}",
+        "package deprecated;\n"
+        + "public enum notDeprecated{}"
+    };
+
+    private static final String CLASS_NAME = "deprecated.notDeprecated";
+
+    private static final String PACKAGE_INFO =
+            "@Deprecated\n" +
+            "package deprecated;";
+
+    public static void main(String[] args) throws TestFailedException {
+        new DeprecatedPackageTest().test();
+    }
+
+    private void test() throws TestFailedException {
+        try {
+            for (String src : sourceTest) {
+                test(PACKAGE_INFO, src);
+                test(PACKAGE_INFO.replaceAll("@Deprecated", "/** @deprecated */"), src);
+            }
+        } catch (Exception e) {
+            addFailure(e);
+        } finally {
+            checkStatus();
+        }
+    }
+
+    private void test(String package_info, String src) {
+        addTestCase(src);
+        printf("Testing test case: \n%s\n", src);
+        try {
+            ClassFile cf = ClassFile.read(compile(
+                        new String[]{"package-info.java", package_info},
+                        new String[]{"notDeprecated.java", src})
+                    .getClasses().get(CLASS_NAME).openInputStream());
+            Deprecated_attribute attr =
+                    (Deprecated_attribute) cf.getAttribute(Attribute.Deprecated);
+            assertNull(attr, "Class can not have deprecated attribute : " + CLASS_NAME);
+        } catch (Exception e) {
+            addFailure(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/deprecated/DeprecatedTest.java	Fri Jul 04 10:52:22 2014 +0100
@@ -0,0 +1,314 @@
+/*
+ * 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 8042261
+ * @summary Checking what attribute is generated by annotation Deprecated
+ *          or javadoc deprecated for field, method, class(inner/local), interface.
+ * @library /tools/javac/lib ../lib
+ * @build DeprecatedTest TestBase TestResult InMemoryFileManager ToolBox
+ * @run main DeprecatedTest
+ */
+
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPoolException;
+import com.sun.tools.classfile.Deprecated_attribute;
+import com.sun.tools.classfile.Field;
+import com.sun.tools.classfile.InnerClasses_attribute;
+import com.sun.tools.classfile.InnerClasses_attribute.Info;
+import com.sun.tools.classfile.Method;
+
+import javax.tools.JavaFileObject;
+import java.io.IOException;
+import java.util.Map;
+
+public class DeprecatedTest extends TestResult {
+
+    private static final String[] sources = new String[]{
+            "@Deprecated public class deprecated {\n"
+            + "@Deprecated class deprecatedInner01 {}\n"
+            + "@Deprecated interface deprecatedInner02 {}\n"
+            + "@Deprecated enum deprecatedInner03 {}\n"
+            + "@Deprecated @interface deprecatedInner04 {}\n"
+            + "class notDeprecatedInner01 {}\n"
+            + "interface notDeprecatedInner02 {}\n"
+            + "enum notDeprecatedInner03 {}\n"
+            + "@interface notDeprecatedInner04 {}\n"
+            + "@Deprecated public void deprecated() {}\n"
+            + "@Deprecated public int deprecated;\n"
+            + "public void notDeprecated() {}\n"
+            + "public int notDeprecated;\n"
+            + "public void f() {\n"
+            + "    @Deprecated class deprecatedLocal {\n"
+            + "        @Deprecated int deprecated;\n"
+            + "        @Deprecated void deprecated() {}\n"
+            + "        int notDeprecated;\n"
+            + "        void notDeprecated(){}\n"
+            + "    }\n"
+            + "    class notDeprecatedLocal {\n"
+            + "        @Deprecated int deprecated;\n"
+            + "        @Deprecated void deprecated() {}\n"
+            + "        int notDeprecated;\n"
+            + "        void notDeprecated(){}\n"
+            + "    }}\n"
+            + "}",
+            "@Deprecated public interface deprecated {\n"
+            + "@Deprecated class deprecatedInner01 {}\n"
+            + "@Deprecated interface deprecatedInner02 {}\n"
+            + "@Deprecated enum deprecatedInner03 {}\n"
+            + "@Deprecated @interface deprecatedInner04 {}\n"
+            + "class notDeprecatedInner01 {}\n"
+            + "interface notDeprecatedInner02 {}\n"
+            + "enum notDeprecatedInner03 {}\n"
+            + "@interface notDeprecatedInner04 {}\n"
+            + "@Deprecated void deprecated01();\n"
+            + "void notDeprecated01();\n"
+            + "@Deprecated default void deprecated02() {}\n"
+            + "default void notDeprecated02() {}\n"
+            + "@Deprecated int deprecated = 0;\n"
+            + "int notDeprecated = 0;\n"
+            + "}",
+            "@Deprecated public enum deprecated {\n"
+            + "@Deprecated deprecated, notDeprecated;\n"
+            + "@Deprecated class deprecatedInner01 {}\n"
+            + "@Deprecated interface deprecatedInner02 {}\n"
+            + "@Deprecated enum deprecatedInner03 {}\n"
+            + "@Deprecated @interface deprecatedInner04 {}\n"
+            + "class notDeprecatedInner01 {}\n"
+            + "interface notDeprecatedInner02 {}\n"
+            + "enum notDeprecatedInner03 {}\n"
+            + "@interface notDeprecatedInner04 {}\n"
+            + "@Deprecated public void deprecated() {}\n"
+            + "public void notDeprecated() {}\n"
+            + "public void f() {\n"
+            + "    @Deprecated class deprecatedLocal {\n"
+            + "        @Deprecated int deprecated;\n"
+            + "        @Deprecated void deprecated() {}\n"
+            + "        int notDeprecated;\n"
+            + "        void notDeprecated(){}\n"
+            + "    }\n"
+            + "    class notDeprecatedLocal {\n"
+            + "        @Deprecated int deprecated;\n"
+            + "        @Deprecated void deprecated() {}\n"
+            + "        int notDeprecated;\n"
+            + "        void notDeprecated(){}\n"
+            + "    }}\n"
+            + "}",
+            "@Deprecated public @interface deprecated {\n"
+            + "@Deprecated class deprecatedInner01 {}\n"
+            + "@Deprecated interface deprecatedInner02 {}\n"
+            + "@Deprecated enum deprecatedInner03 {}\n"
+            + "@Deprecated @interface deprecatedInner04 {}\n"
+            + "class notDeprecatedInner01 {}\n"
+            + "interface notDeprecatedInner02 {}\n"
+            + "enum notDeprecatedInner03 {}\n"
+            + "@interface notDeprecatedInner04 {}\n"
+            + "@Deprecated int deprecated() default 0;\n"
+            + "int notDeprecated() default 0;\n"
+            + "@Deprecated int deprecated = 0;\n"
+            + "int notDeprecated = 0;\n"
+            + "}",
+            "public class notDeprecated {\n"
+            + "@Deprecated class deprecatedInner01 {}\n"
+            + "@Deprecated interface deprecatedInner02 {}\n"
+            + "@Deprecated enum deprecatedInner03 {}\n"
+            + "@Deprecated @interface deprecatedInner04 {}\n"
+            + "class notDeprecatedInner01 {}\n"
+            + "interface notDeprecatedInner02 {}\n"
+            + "enum notDeprecatedInner03 {}\n"
+            + "@interface notDeprecatedInner04 {}\n"
+            + "@Deprecated public void deprecated() {}\n"
+            + "@Deprecated public int deprecated;\n"
+            + "public void notDeprecated() {}\n"
+            + "public int notDeprecated;\n"
+            + "public void f() {\n"
+            + "    @Deprecated class deprecatedLocal {\n"
+            + "        @Deprecated int deprecated;\n"
+            + "        @Deprecated void deprecated() {}\n"
+            + "        int notDeprecated;\n"
+            + "        void notDeprecated(){}\n"
+            + "    }\n"
+            + "    class notDeprecatedLocal {\n"
+            + "        @Deprecated int deprecated;\n"
+            + "        @Deprecated void deprecated() {}\n"
+            + "        int notDeprecated;\n"
+            + "        void notDeprecated(){}\n"
+            + "    }}\n"
+            + "}",
+            "public interface notDeprecated {\n"
+            + "@Deprecated class deprecatedInner01 {}\n"
+            + "@Deprecated interface deprecatedInner02 {}\n"
+            + "@Deprecated enum deprecatedInner03 {}\n"
+            + "@Deprecated @interface deprecatedInner04 {}\n"
+            + "class notDeprecatedInner01 {}\n"
+            + "interface notDeprecatedInner02 {}\n"
+            + "enum notDeprecatedInner03 {}\n"
+            + "@interface notDeprecatedInner04 {}\n"
+            + "@Deprecated void deprecated01();\n"
+            + "void notDeprecated01();\n"
+            + "@Deprecated default void deprecated02() {}\n"
+            + "default void notDeprecated02() {}\n"
+            + "@Deprecated int deprecated = 0;\n"
+            + "int notDeprecated = 0;\n"
+            + "}",
+            "public enum notDeprecated {\n"
+            + "@Deprecated deprecated, notDeprecated;\n"
+            + "@Deprecated class deprecatedInner01 {}\n"
+            + "@Deprecated interface deprecatedInner02 {}\n"
+            + "@Deprecated enum deprecatedInner03 {}\n"
+            + "@Deprecated @interface deprecatedInner04 {}\n"
+            + "class notDeprecatedInner01 {}\n"
+            + "interface notDeprecatedInner02 {}\n"
+            + "enum notDeprecatedInner03 {}\n"
+            + "@interface notDeprecatedInner04 {}\n"
+            + "@Deprecated public void deprecated() {}\n"
+            + "public void notDeprecated() {}\n"
+            + "public void f() {\n"
+            + "    @Deprecated class deprecatedLocal {\n"
+            + "        @Deprecated int deprecated;\n"
+            + "        @Deprecated void deprecated() {}\n"
+            + "        int notDeprecated;\n"
+            + "        void notDeprecated(){}\n"
+            + "    }\n"
+            + "    class notDeprecatedLocal {\n"
+            + "        @Deprecated int deprecated;\n"
+            + "        @Deprecated void deprecated() {}\n"
+            + "        int notDeprecated;\n"
+            + "        void notDeprecated(){}\n"
+            + "    }}\n"
+            + "}",
+            "public @interface notDeprecated {\n"
+            + "@Deprecated class deprecatedInner01 {}\n"
+            + "@Deprecated interface deprecatedInner02 {}\n"
+            + "@Deprecated enum deprecatedInner03 {}\n"
+            + "@Deprecated @interface deprecatedInner04 {}\n"
+            + "class notDeprecatedInner01 {}\n"
+            + "interface notDeprecatedInner02 {}\n"
+            + "enum notDeprecatedInner03 {}\n"
+            + "@interface notDeprecatedInner04 {}\n"
+            + "@Deprecated int deprecated() default 0;\n"
+            + "int notDeprecated() default 0;\n"
+            + "@Deprecated int deprecated = 0;\n"
+            + "int notDeprecated = 0;\n"
+            + "}"};
+
+    public static void main(String[] args) throws TestFailedException {
+        new DeprecatedTest().test();
+    }
+
+    public void test() throws TestFailedException {
+        try {
+            for (String src : sources) {
+                test(src);
+                test(src.replaceAll("@Deprecated", "/** @deprecated */"));
+            }
+        } catch (Exception e) {
+            addFailure(e);
+        } finally {
+            checkStatus();
+        }
+    }
+
+    private void test(String src) {
+        addTestCase(src);
+        printf("Testing test case :\n%s\n", src);
+        try {
+            Map<String, ? extends JavaFileObject> classes = compile(src).getClasses();
+            String outerClassName = classes.containsKey("deprecated")
+                    ? "deprecated"
+                    : "notDeprecated";
+            echo("Testing outer class : " + outerClassName);
+            ClassFile cf = ClassFile.read(classes.get(outerClassName).openInputStream());
+            Deprecated_attribute attr = (Deprecated_attribute)
+                    cf.getAttribute(Attribute.Deprecated);
+            testAttribute(outerClassName, attr, cf);
+            testInnerClasses(cf, classes);
+            testMethods(cf);
+            testFields(cf);
+        } catch (Exception e) {
+            addFailure(e);
+        }
+    }
+
+    private void testInnerClasses(ClassFile cf, Map<String, ? extends JavaFileObject> classes)
+            throws ConstantPoolException, IOException {
+        InnerClasses_attribute innerAttr = (InnerClasses_attribute)
+                cf.getAttribute(Attribute.InnerClasses);
+        for (Info innerClass : innerAttr.classes) {
+            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());
+            Deprecated_attribute attr = (Deprecated_attribute)
+                    innerCf.getAttribute(Attribute.Deprecated);
+            String innerClassSimpleName = innerClass.getInnerName(cf.constant_pool);
+            testAttribute(innerClassSimpleName, attr, innerCf);
+            if (innerClassName.contains("Local")) {
+                testMethods(innerCf);
+                testFields(innerCf);
+            }
+        }
+    }
+
+    private void testMethods(ClassFile cf)
+            throws ConstantPoolException {
+        for (Method m : cf.methods) {
+            String methodName = cf.constant_pool.getUTF8Value(m.name_index);
+            echo("Testing method : " + methodName);
+            Deprecated_attribute attr = (Deprecated_attribute)
+                    m.attributes.get(Attribute.Deprecated);
+            testAttribute(methodName, attr, cf);
+        }
+    }
+
+    private void testFields(ClassFile cf) throws ConstantPoolException {
+        for (Field f : cf.fields) {
+            String fieldName = cf.constant_pool.getUTF8Value(f.name_index);
+            echo("Testing field : " + fieldName);
+            Deprecated_attribute attr = (Deprecated_attribute)
+                    f.attributes.get(Attribute.Deprecated);
+            testAttribute(fieldName, attr, cf);
+        }
+    }
+
+    private void testAttribute(String name, Deprecated_attribute attr, ClassFile cf)
+            throws ConstantPoolException {
+        if (name.contains("deprecated")) {
+            testDeprecatedAttribute(name, attr, cf);
+        } else {
+            assertNull(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");
+    }
+}
--- a/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java	Thu Jul 03 15:48:23 2014 -0700
+++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java	Fri Jul 04 10:52:22 2014 +0100
@@ -23,47 +23,85 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.io.PrintStream;
+import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Stream;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileObject;
-import javax.tools.ToolProvider;
+import javax.tools.*;
 
 import static java.lang.String.format;
+import static java.lang.System.lineSeparator;
+import static java.util.Arrays.asList;
 import static java.util.Collections.emptyList;
+import static java.util.stream.Collectors.joining;
 import static java.util.stream.Collectors.toList;
 
 public class TestBase {
 
-    public Map<String, ? extends JavaFileObject> compile(String... sources) throws IOException,
+    public static final String LINE_SEPARATOR = lineSeparator();
+
+    private <S> InMemoryFileManager compile(
+            List<String> options,
+            Function<S, ? extends JavaFileObject> src2JavaFileObject,
+            List<S> sources)
+            throws IOException, CompilationException {
+
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        List<? extends JavaFileObject> src = sources.stream()
+                .map(src2JavaFileObject)
+                .collect(toList());
+
+        DiagnosticCollector<? super JavaFileObject> dc = new DiagnosticCollector<>();
+        try (InMemoryFileManager fileManager
+                     = new InMemoryFileManager(compiler.getStandardFileManager(null, null, null))) {
+            JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, dc, options, null, src);
+            boolean success = task.call();
+            if (!success) {
+                String errorMessage = dc.getDiagnostics().stream()
+                        .map(Object::toString)
+                        .collect(joining("\n"));
+                throw new CompilationException("Compilation Error\n\n" + errorMessage);
+            }
+            return fileManager;
+        }
+    }
+
+    public InMemoryFileManager compile(String... sources)
+            throws IOException, CompilationException {
+        return compile(emptyList(), sources);
+    }
+
+    /**
+     * @param options - compiler options
+     * @param sources
+     * @return map where key is className, value is corresponding ClassFile.
+     * @throws IOException
+     */
+    public InMemoryFileManager compile(List<String> options, String...sources)
+            throws IOException, CompilationException {
+        return compile(options, ToolBox.JavaSource::new, asList(sources));
+    }
+
+    public InMemoryFileManager compile(String[]... sources) throws IOException,
             CompilationException {
         return compile(emptyList(), sources);
     }
 
     /**
      * @param options -  compiler options
-     * @param sources
+     * @param sources - sources[i][0] - name of file, sources[i][1] - sources
      * @return map where key is className, value is corresponding ClassFile.
      * @throws IOException
+     * @throws CompilationException
      */
-    public Map<String, ? extends JavaFileObject> compile(List<String> options, String... sources) throws IOException,
-            CompilationException {
-
-        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-        List<? extends JavaFileObject> src = Stream.of(sources).map(ToolBox.JavaSource::new).collect(toList());
-
-        try (InMemoryFileManager fileManager = new InMemoryFileManager(compiler.getStandardFileManager(null, null, null))) {
-            boolean success = compiler.getTask(null, fileManager, null, options, null, src).call();
-            if (!success) throw new CompilationException("Compilation Error");
-            return fileManager.getClasses();
-        }
+    public InMemoryFileManager compile(List<String> options, String[]...sources)
+            throws IOException, CompilationException {
+        return compile(options, src -> new ToolBox.JavaSource(src[0], src[1]), asList(sources));
     }
 
     public void assertEquals(Object actual, Object expected, String message) {
         if (!Objects.equals(actual, expected))
-            throw new AssertionFailedException(format("%s%nGot: %s, Expected: ", message, actual, expected));
+            throw new AssertionFailedException(format("%s%nGot: %s, Expected: %s", message, actual, expected));
     }
 
     public void assertNull(Object actual, String message) {
@@ -80,18 +118,43 @@
         assertEquals(actual, true, message);
     }
 
+    public void assertFalse(boolean actual, String message) {
+        assertEquals(actual, false, message);
+    }
+
+    public File getSourceDir() {
+        return new File(System.getProperty("test.src", "."));
+    }
+
+    public File getClassDir() {
+        return new File(System.getProperty("test.classes", TestBase.class.getResource(".").getPath()));
+    }
+
     public File getSourceFile(String fileName) {
-        return new File(System.getProperty("test.src", "."), fileName);
+        return new File(getSourceDir(), fileName);
     }
 
     public File getClassFile(String fileName) {
-        return new File(System.getProperty("test.classes", TestBase.class.getResource(".").getPath()), fileName);
+        return new File(getClassDir(), fileName);
     }
 
     public File getClassFile(Class clazz) {
         return getClassFile(clazz.getName().replace(".", "/") + ".class");
     }
 
+    public void echo(String message) {
+        System.err.println(message.replace("\n", LINE_SEPARATOR));
+    }
+
+    public void printf(String template, Object...args) {
+        System.err.printf(template, Stream.of(args)
+                .map(Objects::toString)
+                .map(m -> m.replace("\n", LINE_SEPARATOR))
+                .collect(toList())
+                .toArray());
+
+    }
+
     public static class CompilationException extends Exception {
 
         public CompilationException(String message) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java	Fri Jul 04 10:52:22 2014 +0100
@@ -0,0 +1,168 @@
+/*
+ * 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.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import static java.lang.String.format;
+import static java.util.stream.Collectors.joining;
+
+public class TestResult extends TestBase {
+
+    private final List<Info> testCases;
+
+    public TestResult() {
+        testCases = new ArrayList<>();
+        testCases.add(new Info("Global test info"));
+    }
+
+    public void addTestCase(String src) {
+        testCases.add(new Info(src));
+    }
+
+    public String errorMessage() {
+        return testCases.stream().filter(Info::isFailed)
+                .map(tc -> format("Failure in test case:\n%s\n%s", tc.info(),
+                        (tc.asserts.size() > 0 ? tc.getAssertMessage() + "\n" : "")
+                                + tc.getErrorMessage()))
+                .collect(joining("\n"));
+    }
+
+    @Override
+    public void assertEquals(Object actual, Object expected, String message) {
+        getLastTestCase().assertEquals(actual, expected, message);
+    }
+
+    @Override
+    public void assertNull(Object actual, String message) {
+        getLastTestCase().assertEquals(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);
+    }
+
+    @Override
+    public void assertTrue(boolean actual, String message) {
+        getLastTestCase().assertEquals(actual, true, message);
+    }
+
+    public void addFailure(Throwable th) {
+        getLastTestCase().addFailure(th);
+    }
+
+    private Info getLastTestCase() {
+        if (testCases.size() == 1) {
+            throw new IllegalStateException("Test case should be created");
+        }
+        return testCases.get(testCases.size() - 1);
+    }
+
+    public void checkStatus() throws TestFailedException {
+        if (testCases.stream().anyMatch(Info::isFailed)) {
+            echo(errorMessage());
+            throw new TestFailedException("Test failed");
+        }
+    }
+
+    private class Info {
+
+        private final String info;
+        private final List<String> asserts;
+        private final List<Throwable> errors;
+
+        private Info(String info) {
+            this.info = info;
+            asserts = new ArrayList<>();
+            errors = new ArrayList<>();
+        }
+
+        public String info() {
+            return info;
+        }
+
+        public boolean isFailed() {
+            return !asserts.isEmpty() || !errors.isEmpty();
+        }
+
+        public void addFailure(Throwable th) {
+            errors.add(th);
+            printf("[ERROR] : %s\n", getStackTrace(th));
+        }
+
+        public void addFailure(String message) {
+            asserts.add(message);
+            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 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 getStackTrace(Throwable throwable) {
+            StringWriter stringWriter = new StringWriter();
+            try (PrintWriter printWriter = new PrintWriter(stringWriter)) {
+                throwable.printStackTrace(printWriter);
+            }
+            return stringWriter.toString();
+        }
+    }
+
+    public static class TestFailedException extends Exception {
+        public TestFailedException(String message) {
+            super(message);
+        }
+    }
+}