Merge
authoremc
Wed, 13 Aug 2014 21:58:29 +0000
changeset 26102 0768f194cad1
parent 26100 bb7dd001d190 (current diff)
parent 26101 d5dd2ecd2353 (diff)
child 26103 3f96599b20da
Merge
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerAnnotationTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,48 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner annotations in inner annotation.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
+ * @run main InnerAnnotationsInInnerAnnotationTest
+ */
+
+public class InnerAnnotationsInInnerAnnotationTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerAnnotationsInInnerAnnotationTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC);
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setOuterClassType(ClassType.ANNOTATION);
+        setInnerClassType(ClassType.ANNOTATION);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerClassTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,47 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner annotations in inner class.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
+ * @run main InnerAnnotationsInInnerClassTest
+ */
+
+public class InnerAnnotationsInInnerClassTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerAnnotationsInInnerClassTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setForbiddenWithoutStaticInOuterMods(true);
+        setOuterClassType(ClassType.CLASS);
+        setInnerClassType(ClassType.ANNOTATION);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerEnumTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,49 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner annotations in inner enum.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
+ * @run main InnerAnnotationsInInnerEnumTest
+ */
+
+public class InnerAnnotationsInInnerEnumTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerAnnotationsInInnerEnumTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC);
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC, Modifier.ABSTRACT);
+        setOuterClassType(ClassType.ENUM);
+        setInnerClassType(ClassType.ANNOTATION);
+        setPrefix("Inner {;");
+        setSuffix("}");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerInterfaceTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,48 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner annotations in inner interface.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
+ * @run main InnerAnnotationsInInnerInterfaceTest
+ */
+
+public class InnerAnnotationsInInnerInterfaceTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerAnnotationsInInnerInterfaceTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC);
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setOuterClassType(ClassType.INTERFACE);
+        setInnerClassType(ClassType.ANNOTATION);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,433 @@
+/*
+ * 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 8042251
+ * @summary Test that inner classes have in its inner classes attribute enclosing classes and its immediate members.
+ * @library /tools/javac/lib ../lib
+ * @build TestResult TestBase InMemoryFileManager ToolBox
+ * @run main InnerClassesHierarchyTest
+ */
+
+import com.sun.tools.classfile.*;
+import com.sun.tools.classfile.InnerClasses_attribute.Info;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class InnerClassesHierarchyTest extends TestResult {
+
+    private final Map<String, Set<String>> innerClasses;
+    private final String outerClassName;
+
+    public InnerClassesHierarchyTest() throws IOException, ConstantPoolException {
+        innerClasses = new HashMap<>();
+        outerClassName = InnerClassesHierarchyTest.class.getSimpleName();
+        File classDir = getClassDir();
+        FilenameFilter filter =
+                (dir, name) -> name.matches(outerClassName + ".*\\.class");
+        for (File file : Arrays.asList(classDir.listFiles(filter))) {
+            ClassFile classFile = readClassFile(file);
+            String className = classFile.getName();
+            for (ConstantPool.CPInfo info : classFile.constant_pool.entries()) {
+                if (info instanceof ConstantPool.CONSTANT_Class_info) {
+                    ConstantPool.CONSTANT_Class_info classInfo =
+                            (ConstantPool.CONSTANT_Class_info) info;
+                    String cpClassName = classInfo.getBaseName();
+                    if (isInnerClass(cpClassName)) {
+                        get(className).add(cpClassName);
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean isInnerClass(String cpClassName) {
+        return cpClassName.contains("$");
+    }
+
+    private Set<String> get(String className) {
+        if (!innerClasses.containsKey(className)) {
+            innerClasses.put(className, new HashSet<>());
+        }
+        return innerClasses.get(className);
+    }
+
+    public static void main(String[] args) throws IOException, ConstantPoolException, TestFailedException {
+        new InnerClassesHierarchyTest().test();
+    }
+
+    private void test() throws TestFailedException {
+        addTestCase("Source file is InnerClassesHierarchyTest.java");
+        try {
+            Queue<String> queue = new LinkedList<>();
+            Set<String> visitedClasses = new HashSet<>();
+            queue.add(outerClassName);
+            while (!queue.isEmpty()) {
+                String currentClassName = queue.poll();
+                if (!currentClassName.startsWith(outerClassName)) {
+                    continue;
+                }
+                ClassFile cf = readClassFile(currentClassName);
+                InnerClasses_attribute attr = (InnerClasses_attribute)
+                        cf.getAttribute(Attribute.InnerClasses);
+                assertNotNull(attr, "Class should not contain "
+                        + "inner classes attribute : " + currentClassName);
+                assertTrue(innerClasses.containsKey(currentClassName),
+                        "map contains class name : " + currentClassName);
+                Set<String> setClasses = innerClasses.get(currentClassName);
+                if (setClasses == null) {
+                    continue;
+                }
+                assertEquals(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),
+                            currentClassName + " contains inner class : "
+                                    + innerClassName);
+                    if (visitedClasses.add(innerClassName)) {
+                        queue.add(innerClassName);
+                    }
+                }
+            }
+            Set<String> allClasses = innerClasses.entrySet().stream()
+                    .flatMap(entry -> entry.getValue().stream())
+                    .collect(Collectors.toSet());
+
+            Set<String> a_b = removeAll(visitedClasses, allClasses);
+            Set<String> b_a = removeAll(allClasses, visitedClasses);
+            assertEquals(visitedClasses, allClasses,
+                    "All classes are found\n"
+                    + "visited - all classes : " + a_b
+                    + "\nall classes - visited : " + b_a);
+        } catch (Exception e) {
+            addFailure(e);
+        } finally {
+            checkStatus();
+        }
+    }
+
+    private Set<String> removeAll(Set<String> set1, Set<String> set2) {
+        Set<String> set = new HashSet<>(set1);
+        set.removeAll(set2);
+        return set;
+    }
+
+    public static class A1 {
+
+        public class B1 {
+        }
+
+        public enum B2 {
+        }
+
+        public interface B3 {
+        }
+
+        public @interface B4 {
+        }
+
+        public void f() {
+            new B1() {
+            };
+            new B3() {
+            };
+            new B4() {
+                @Override
+                public Class<? extends Annotation> annotationType() {
+                    return null;
+                }
+            };
+            class B5 {
+            }
+        }
+
+        Runnable r = () -> {
+            new B1() {
+            };
+            new B3() {
+            };
+            new B4() {
+                @Override
+                public Class<? extends Annotation> annotationType() {
+                    return null;
+                }
+            };
+            class B5 {
+            }
+        };
+    }
+
+    public enum A2 {;
+
+        public class B1 {
+        }
+
+        public enum B2 {
+        }
+
+        public interface B3 {
+        }
+
+        public @interface B4 {
+        }
+
+        public void a2() {
+            new B1() {
+            };
+            new B3() {
+            };
+            new B4() {
+                @Override
+                public Class<? extends Annotation> annotationType() {
+                    return null;
+                }
+            };
+            class B5 {
+            }
+        }
+
+        Runnable r = () -> {
+            new B1() {
+            };
+            new B3() {
+            };
+            new B4() {
+                @Override
+                public Class<? extends Annotation> annotationType() {
+                    return null;
+                }
+            };
+            class B5 {
+            }
+        };
+    }
+
+    public interface A3 {
+
+        public class B1 {
+        }
+
+        public enum B2 {
+        }
+
+        public interface B3 {
+        }
+
+        public @interface B4 {
+        }
+
+        default void a1() {
+            new B1() {
+            };
+            new B3() {
+            };
+            new B4() {
+                @Override
+                public Class<? extends Annotation> annotationType() {
+                    return null;
+                }
+            };
+            class B5 {
+            }
+        }
+
+        static void a2() {
+            new B1() {
+            };
+            new B3() {
+            };
+            new B4() {
+                @Override
+                public Class<? extends Annotation> annotationType() {
+                    return null;
+                }
+            };
+            class B5 {
+            }
+        }
+    }
+
+    public @interface A4 {
+
+        public class B1 {
+        }
+
+        public enum B2 {
+        }
+
+        public interface B3 {
+        }
+
+        public @interface B4 {
+        }
+    }
+
+    {
+        new A1() {
+            class B1 {
+            }
+
+            public void a2() {
+                new B1() {
+                };
+                class B5 {
+                }
+            }
+        };
+        new A3() {
+            class B1 {
+            }
+
+            public void a3() {
+                new B1() {
+                };
+                class B5 {
+                }
+            }
+        };
+        new A4() {
+            @Override
+            public Class<? extends Annotation> annotationType() {
+                return null;
+            }
+
+            class B1 {
+            }
+
+            public void a4() {
+                new B1() {
+                };
+                class B5 {
+                }
+            }
+        };
+        Runnable r = () -> {
+            new A1() {
+            };
+            new A3() {
+            };
+            new A4() {
+                @Override
+                public Class<? extends Annotation> annotationType() {
+                    return null;
+                }
+            };
+            class B5 {
+            }
+        };
+    }
+
+    static {
+        new A1() {
+            class B1 {
+            }
+
+            public void a2() {
+                new B1() {
+                };
+                class B5 {
+                }
+            }
+        };
+        new A3() {
+            class B1 {
+            }
+
+            public void a3() {
+                new B1() {
+                };
+                class B5 {
+                }
+            }
+        };
+        new A4() {
+            @Override
+            public Class<? extends Annotation> annotationType() {
+                return null;
+            }
+
+            class B1 {
+            }
+
+            public void a4() {
+                new B1() {
+                };
+                class B5 {
+                }
+            }
+        };
+        Runnable r = () -> {
+            new A1() {
+            };
+            new A3() {
+            };
+            new A4() {
+                @Override
+                public Class<? extends Annotation> annotationType() {
+                    return null;
+                }
+            };
+            class B5 {
+            }
+        };
+    }
+
+    public void a5() {
+        class A5 {
+
+            class B1 {
+            }
+
+            public void a5() {
+                new B1() {
+                };
+
+                class B5 {
+                }
+            }
+        }
+        Runnable r = () -> {
+            new A1() {
+            };
+            new A3() {
+            };
+            new A4() {
+                @Override
+                public Class<? extends Annotation> annotationType() {
+                    return null;
+                }
+            };
+            class B5 {
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInAnonymousClassTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,78 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner classes in anonymous class.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
+ * @run main InnerClassesInAnonymousClassTest
+ */
+
+import java.util.*;
+
+public class InnerClassesInAnonymousClassTest extends InnerClassesTestBase {
+
+    private ClassType currentClassType;
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerClassesInAnonymousClassTest();
+        test.test("InnerClassesSrc$1", "Anonymous", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setInnerAccessModifiers(Modifier.EMPTY);
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL);
+        setOuterClassType(ClassType.OTHER);
+        setInnerClassType(ClassType.CLASS);
+        setSuffix("};}");
+    }
+
+    @Override
+    public List<TestCase> generateTestCases() {
+        currentClassType = ClassType.CLASS;
+        setPrefix("class Anonymous {} {new Anonymous() {");
+        List<TestCase> sources = super.generateTestCases();
+
+        currentClassType = ClassType.INTERFACE;
+        setPrefix("interface Anonymous {} {new Anonymous() {");
+        sources.addAll(super.generateTestCases());
+
+        currentClassType = ClassType.ANNOTATION;
+        setPrefix("@interface Anonymous {} {new Anonymous() {@Override public "
+                + "Class<? extends java.lang.annotation.Annotation> "
+                + "annotationType() {return null;}");
+        sources.addAll(super.generateTestCases());
+        return sources;
+    }
+
+    @Override
+    public void getAdditionalFlags(Map<String, Set<String>> class2Flags, ClassType type, Modifier... flags) {
+        super.getAdditionalFlags(class2Flags, type, flags);
+        class2Flags.put("Anonymous", getFlags(currentClassType, Arrays.asList(flags)));
+        class2Flags.put("1", new HashSet<>());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerAnnotationTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,47 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner classes in inner annotation.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
+ * @run main InnerClassesInInnerAnnotationTest
+ */
+
+public class InnerClassesInInnerAnnotationTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerClassesInInnerAnnotationTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC);
+        setOuterClassType(ClassType.ANNOTATION);
+        setInnerClassType(ClassType.CLASS);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,61 @@
+/*
+ * 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 8034854 8042251
+ * @summary Testing InnerClasses_attribute of inner classes in inner class.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
+ * @run main InnerClassesInInnerClassTest
+ */
+
+import java.util.List;
+
+public class InnerClassesInInnerClassTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerClassesInInnerClassTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setHasSyntheticClass(true);
+        setOuterClassType(ClassType.CLASS);
+        setInnerClassType(ClassType.CLASS);
+    }
+
+    @Override
+    public List<TestCase> generateTestCases() {
+        setForbiddenWithoutStaticInOuterMods(true);
+        List<TestCase> sources = super.generateTestCases();
+
+        setForbiddenWithoutStaticInOuterMods(false);
+        setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL);
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL);
+        sources.addAll(super.generateTestCases());
+
+        return sources;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTestBase.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,47 @@
+/*
+ * 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.util.Arrays;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *
+ * Base class for tests that check inner classes in inner class.
+ *
+ * @author Andrei Eremeev
+ */
+public abstract class InnerClassesInInnerClassTestBase extends InnerClassesTestBase {
+
+    public InnerClassesInInnerClassTestBase() {
+        setPrefix("Inner {");
+        setSuffix("}");
+    }
+
+    @Override
+    public void getAdditionalFlags(
+            Map<String, Set<String>> class2Flags, ClassType type, Modifier...flags) {
+        super.getAdditionalFlags(class2Flags, type, flags);
+        class2Flags.put("Inner", getFlags(type, Arrays.asList(flags)));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerEnumTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,49 @@
+/*
+ * 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 8034854 8042251
+ * @summary Testing InnerClasses_attribute of inner classes in inner enum.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
+ * @run main InnerClassesInInnerEnumTest
+ */
+
+public class InnerClassesInInnerEnumTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerClassesInInnerEnumTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC);
+        setOuterClassType(ClassType.ENUM);
+        setInnerClassType(ClassType.CLASS);
+        setHasSyntheticClass(true);
+        setPrefix("Inner {;");
+        setSuffix("}");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerInterfaceTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,47 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner classes in inner interface.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
+ * @run main InnerClassesInInnerInterfaceTest
+ */
+
+public class InnerClassesInInnerInterfaceTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerClassesInInnerInterfaceTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT);
+        setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC);
+        setOuterClassType(ClassType.INTERFACE);
+        setInnerClassType(ClassType.CLASS);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInLocalClassTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,167 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner classes in local class.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
+ * @run main InnerClassesInLocalClassTest
+ */
+
+import java.util.*;
+
+public class InnerClassesInLocalClassTest extends InnerClassesTestBase {
+
+    private final static Modifier[] LOCAL_CLASS_MODIFIERS =
+            new Modifier[]{Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL};
+    private final static String CLASS_TEMPLATE =
+            "public %CLASS% OuterClass {\n" +
+            "%SOURCE%\n" +
+            "}";
+
+    private final List<Data> innerClassesData;
+
+    public InnerClassesInLocalClassTest() {
+        innerClassesData = new ArrayList<>();
+        for (Modifier outerModifier : LOCAL_CLASS_MODIFIERS) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(outerModifier.getString()).append(' ');
+            sb.append("class Local {");
+            Map<String, Set<String>> class2Flags = new HashMap<>();
+            for (int i = 0; i < LOCAL_CLASS_MODIFIERS.length; ++i) {
+                Modifier innerModifier = LOCAL_CLASS_MODIFIERS[i];
+                sb.append(innerModifier.getString()).append(' ')
+                        .append("class").append(' ')
+                        .append('A').append(i).append("{}\n");
+                class2Flags.put("A" + i, getFlags(innerModifier));
+            }
+            sb.append("};");
+            class2Flags.put("1Local", getFlags(outerModifier));
+            innerClassesData.add(new Data(sb.toString(), class2Flags));
+        }
+    }
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerClassesInLocalClassTest();
+        test.test("OuterClass$1Local", "1Local");
+    }
+
+    @Override
+    public void setProperties() {
+    }
+
+    @Override
+    public List<TestCase> generateTestCases() {
+        List<TestCase> testCases = new ArrayList<>();
+        testCases.addAll(localClassInClassMethod());
+        testCases.addAll(localClassInInterfaceMethod());
+        return testCases;
+    }
+
+    private List<TestCase> localClassInClassMethod() {
+        List<TestCase> list = new ArrayList<>();
+        String template = CLASS_TEMPLATE.replace("%CLASS%", "class");
+        list.addAll(lambda(template));
+        list.addAll(constructor(template));
+        list.addAll(method(template,
+                new Modifier[]{Modifier.EMPTY, Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC},
+                new Modifier[]{Modifier.EMPTY, Modifier.FINAL, Modifier.STATIC}));
+        list.addAll(staticAndInstanceInitializer(template));
+        return list;
+    }
+
+    private List<TestCase> localClassInInterfaceMethod() {
+        String template = CLASS_TEMPLATE.replace("%CLASS%", "interface");
+        return method(template,
+                new Modifier[]{Modifier.EMPTY, Modifier.PUBLIC},
+                new Modifier[]{Modifier.DEFAULT, Modifier.STATIC});
+    }
+
+    private List<TestCase> generate(String template, String prefix, String suffix) {
+        List<TestCase> list = new ArrayList<>();
+        for (Data data : innerClassesData) {
+            list.add(new TestCase(template.replace("%SOURCE%",
+                    prefix + data.sources + suffix),
+                    data.class2Flags));
+        }
+        return list;
+    }
+
+    private List<TestCase> lambda(String template) {
+        return generate(template, "Runnable run = () -> {", "};");
+    }
+
+    private List<TestCase> constructor(String template) {
+        List<TestCase> list = new ArrayList<>();
+        for (Modifier modifier :
+                new Modifier[]{Modifier.EMPTY, Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC}) {
+            list.addAll(generate(template, modifier.getString() + " OuterClass() {", "}"));
+        }
+        return list;
+    }
+
+    private List<TestCase> method(String template, Modifier[] mods, Modifier[] otherMods) {
+        List<TestCase> list = new ArrayList<>();
+        for (Modifier modifier : mods) {
+            for (Modifier otherMod : otherMods) {
+                list.addAll(generate(template,
+                        String.format("%s %s void method() {",
+                                modifier.getString(),
+                                otherMod.getString()),
+                        "}"));
+            }
+        }
+        return list;
+    }
+
+    private List<TestCase> staticAndInstanceInitializer(String template) {
+        List<TestCase> list = new ArrayList<>();
+        for (Modifier modifier : new Modifier[]{Modifier.EMPTY, Modifier.STATIC}) {
+            list.addAll(generate(template, modifier.getString() + "{", "}"));
+        }
+        return list;
+    }
+
+    private Set<String> getFlags(Modifier modifier) {
+        HashSet<String> set = new HashSet<>();
+        if (modifier != Modifier.EMPTY) {
+            set.add("ACC_" + modifier.getString().toUpperCase());
+        }
+        return set;
+    }
+
+    /**
+     * Class represents part of sources which is inserted in other code.
+     */
+    private static class Data {
+        public final String sources;
+        public final Map<String, Set<String>> class2Flags;
+
+        public Data(String sources, Map<String, Set<String>> class2Flags) {
+            this.sources = sources;
+            this.class2Flags = class2Flags;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,141 @@
+/*
+ * 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 8042251
+ * @summary Test that outer_class_info_index of local and anonymous class is zero.
+ * @library /tools/javac/lib ../lib
+ * @build TestBase TestResult InMemoryFileManager ToolBox
+ * @run main InnerClassesIndexTest
+ */
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.InnerClasses_attribute;
+import com.sun.tools.classfile.InnerClasses_attribute.Info;
+
+public class InnerClassesIndexTest extends TestResult {
+
+    public static void main(String[] args) throws TestFailedException {
+        new InnerClassesIndexTest().test();
+    }
+
+    private boolean isExcluded(String className) {
+        return !className.startsWith(InnerClassesIndexTest.class.getName())
+                || "InnerClassesIndexTest$Inner".equals(className);
+    }
+
+    private Set<String> getInnerClasses() {
+        FilenameFilter filter = (dir, name) -> name.matches("InnerClassesIndexTest\\$.*\\.class");
+        return Stream.of(getClassDir().listFiles(filter))
+                .map(File::getName)
+                .map(s -> s.replace(".class", ""))
+                .collect(Collectors.toSet());
+    }
+
+    public void test() throws TestFailedException {
+        try {
+            addTestCase("Source is InnerClassesIndexTest.java");
+            ClassFile classFile = readClassFile(InnerClassesIndexTest.class);
+            InnerClasses_attribute attr = (InnerClasses_attribute)
+                    classFile.getAttribute(Attribute.InnerClasses);
+
+            Set<String> foundClasses = new HashSet<>();
+            for (Info info : attr.classes) {
+                String innerName = classFile.constant_pool.
+                        getClassInfo(info.inner_class_info_index).getBaseName();
+                echo("Testing class : " + innerName);
+                if (isExcluded(innerName)) {
+                    echo("Ignored : " + innerName);
+                    continue;
+                }
+                foundClasses.add(innerName);
+                assertEquals(info.outer_class_info_index, 0,
+                        "outer_class_info_index of " + innerName);
+                if (innerName.matches("\\$\\d+")) {
+                    assertEquals(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");
+        } catch (Exception e) {
+            addFailure(e);
+        } finally {
+            checkStatus();
+        }
+    }
+
+    static class Inner {
+    }
+
+    Inner inner1 = new Inner() {
+    };
+
+    static Inner inner2 = new Inner() {
+    };
+
+    Runnable r = () -> {
+        class Local {
+        }
+        new Local() {
+        };
+    };
+
+    public void local() {
+        class Local {
+        }
+        new Local() {
+        };
+    }
+
+    public InnerClassesIndexTest() {
+        class Local {
+        }
+        new Local() {
+        };
+    }
+
+    {
+        class Local {
+        }
+        new Local() {
+        };
+    }
+
+    static {
+        class Local {
+        }
+        new Local() {
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,82 @@
+/*
+ * 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 8034854 8042251
+ * @summary Testing inner classes attributes.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
+ * @run main InnerClassesTest
+ */
+
+import java.util.List;
+
+public class InnerClassesTest extends InnerClassesTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        new InnerClassesTest().test("InnerClassesSrc");
+    }
+
+    private List<TestCase> generateClasses() {
+        setInnerClassType(ClassType.CLASS);
+        setHasSyntheticClass(true);
+        return super.generateTestCases();
+    }
+
+    private List<TestCase> generateEnums() {
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC);
+        setInnerClassType(ClassType.ENUM);
+        setHasSyntheticClass(false);
+        return super.generateTestCases();
+    }
+
+    private List<TestCase> generateInterfaces() {
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setInnerClassType(ClassType.INTERFACE);
+        return super.generateTestCases();
+    }
+
+    private List<TestCase> generateAnnotations() {
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setInnerClassType(ClassType.ANNOTATION);
+        return super.generateTestCases();
+    }
+
+    @Override
+    public void setProperties() {
+        setOuterAccessModifiers(Modifier.EMPTY);
+        setOuterOtherModifiers(Modifier.EMPTY);
+        setOuterClassType(ClassType.OTHER);
+    }
+
+    @Override
+    public List<TestCase> generateTestCases() {
+        List<TestCase> sources = generateClasses();
+        sources.addAll(generateEnums());
+        sources.addAll(generateInterfaces());
+        sources.addAll(generateAnnotations());
+        return sources;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,446 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.InnerClasses_attribute;
+import com.sun.tools.classfile.InnerClasses_attribute.Info;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Base class for tests of inner classes attribute.
+ * The scenario of tests:
+ *   1. set possible values of class modifiers.
+ *   2. according to set class modifiers, a test generates sources
+ * and golden data with {@code generateTestCases}.
+ *   3. a test loops through all test cases and checks InnerClasses
+ * attribute with {@code test}.
+ *
+ * Example, possible flags for outer class are {@code Modifier.PRIVATE and Modifier.PUBLIC},
+ * possible flags for inner class are {@code Modifier.EMPTY}.
+ * At the second step the test generates two test cases:
+ *   1. public class A {
+ *        public class B {
+ *          class C {}
+ *        }
+ *      }
+ *   2. public class A {
+ *        private class B {
+ *          class C {}
+ *        }
+ *      }
+ */
+public abstract class InnerClassesTestBase extends TestResult {
+
+    private Modifier[] outerAccessModifiers = {Modifier.EMPTY, Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC};
+    private Modifier[] outerOtherModifiers = {Modifier.EMPTY, Modifier.STATIC, Modifier.FINAL, Modifier.ABSTRACT};
+    private Modifier[] innerAccessModifiers = outerAccessModifiers;
+    private Modifier[] innerOtherModifiers = outerOtherModifiers;
+    private boolean isForbiddenWithoutStaticInOuterMods = false;
+
+    private ClassType outerClassType;
+    private ClassType innerClassType;
+    private boolean hasSyntheticClass;
+    private String prefix = "";
+    private String suffix = "";
+
+    /**
+     * Sets properties.
+     *
+     * Returns generated list of test cases. Method is called in {@code test()}.
+     */
+    public abstract void setProperties();
+
+    /**
+     * Runs the test.
+     *
+     * @param classToTest expected name of outer class
+     * @param skipClasses classes that names should not be checked
+     */
+    public void test(String classToTest, String...skipClasses) throws TestFailedException {
+        try {
+            for (TestCase test : generateTestCases()) {
+                addTestCase(test.getSource());
+                test(classToTest, test, skipClasses);
+            }
+        } catch (Exception e) {
+            addFailure(e);
+        } finally {
+            checkStatus();
+        }
+    }
+
+    /**
+     * If {@code flag} is {@code true} an outer class can not have static modifier.
+     *
+     * @param flag if {@code true} the outer class can not have static modifier
+     */
+    public void setForbiddenWithoutStaticInOuterMods(boolean flag) {
+        isForbiddenWithoutStaticInOuterMods = flag;
+    }
+
+    /**
+     * Sets the possible access flags of an outer class.
+     *
+     * @param mods the possible access flags of an outer class
+     */
+    public void setOuterAccessModifiers(Modifier...mods) {
+        outerAccessModifiers = mods;
+    }
+
+    /**
+     * Sets the possible flags of an outer class.
+     *
+     * @param mods the possible flags of an outer class
+     */
+    public void setOuterOtherModifiers(Modifier...mods) {
+        outerOtherModifiers = mods;
+    }
+
+    /**
+     * Sets the possible access flags of an inner class.
+     *
+     * @param mods the possible access flags of an inner class
+     */
+    public void setInnerAccessModifiers(Modifier...mods) {
+        innerAccessModifiers = mods;
+    }
+
+    /**
+     * Sets the possible flags of an inner class.
+     *
+     * @param mods the possible flags of an inner class
+     */
+    public void setInnerOtherModifiers(Modifier...mods) {
+        innerOtherModifiers = mods;
+    }
+
+    /**
+     * Sets the suffix for the generated source.
+     *
+     * @param suffix a suffix
+     */
+    public void setSuffix(String suffix) {
+        this.suffix = suffix;
+    }
+
+    /**
+     * Sets the prefix for the generated source.
+     *
+     * @param prefix a prefix
+     */
+    public void setPrefix(String prefix) {
+        this.prefix = prefix;
+    }
+
+    /**
+     * If {@code true} synthetic class is generated.
+     *
+     * @param hasSyntheticClass if {@code true} synthetic class is generated
+     */
+    public void setHasSyntheticClass(boolean hasSyntheticClass) {
+        this.hasSyntheticClass = hasSyntheticClass;
+    }
+
+    /**
+     * Sets the inner class type.
+     *
+     * @param innerClassType the inner class type
+     */
+    public void setInnerClassType(ClassType innerClassType) {
+        this.innerClassType = innerClassType;
+    }
+
+    /**
+     * Sets the outer class type.
+     *
+     * @param outerClassType the outer class type
+     */
+    public void setOuterClassType(ClassType outerClassType) {
+        this.outerClassType = outerClassType;
+    }
+
+    private void test(String classToTest, TestCase test, String...skipClasses) {
+        printf("Testing :\n%s\n", test.getSource());
+        try {
+            Map<String, Set<String>> class2Flags = test.getFlags();
+            ClassFile cf = readClassFile(compile(test.getSource())
+                    .getClasses().get(classToTest));
+            InnerClasses_attribute innerClasses = (InnerClasses_attribute)
+                    cf.getAttribute(Attribute.InnerClasses);
+            int count = 0;
+            for (Attribute a : cf.attributes.attrs) {
+                if (a instanceof InnerClasses_attribute) {
+                    ++count;
+                }
+            }
+            assertEquals(1, count, "Number of inner classes attribute");
+            if (innerClasses == null) {
+                return;
+            }
+            assertEquals(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,
+                    2 + 8 * class2Flags.size(), "innerClasses.attribute_length");
+            assertEquals(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);
+                }
+                String className = baseName.replaceFirst(".*\\$", "");
+                assertTrue(class2Flags.containsKey(className),
+                        className);
+                assertTrue(visitedClasses.add(className),
+                        "there are no duplicates in attribute : " + className);
+                assertEquals(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);
+                    if (e.outer_class_info_index > 0) {
+                        assertEquals(
+                                cf.constant_pool.getClassInfo(e.outer_class_info_index).getName(),
+                                classToTest,
+                                "outer_class_info_index of " + className);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            addFailure(e);
+        }
+    }
+
+    /**
+     * Methods generates list of test cases. Method generates all possible combinations
+     * of acceptable flags for nested inner classes.
+     *
+     * @return generated list of test cases
+     */
+    protected List<TestCase> generateTestCases() {
+        setProperties();
+        List<TestCase> list = new ArrayList<>();
+
+        List<List<Modifier>> outerMods = getAllCombinations(outerAccessModifiers, outerOtherModifiers);
+        List<List<Modifier>> innerMods = getAllCombinations(innerAccessModifiers, innerOtherModifiers);
+
+        for (List<Modifier> outerMod : outerMods) {
+            if (isForbiddenWithoutStaticInOuterMods && !outerMod.contains(Modifier.STATIC)) {
+                continue;
+            }
+            StringBuilder sb = new StringBuilder();
+            sb.append("public class InnerClassesSrc {")
+                    .append(toString(outerMod)).append(' ')
+                    .append(outerClassType).append(' ')
+                    .append(prefix).append(' ').append('\n');
+            int count = 0;
+            Map<String, Set<String>> class2Flags = new HashMap<>();
+            List<String> syntheticClasses = new ArrayList<>();
+            for (List<Modifier> innerMod : innerMods) {
+                ++count;
+                String privateConstructor = "";
+                if (hasSyntheticClass && !innerMod.contains(Modifier.ABSTRACT)) {
+                    privateConstructor = "private A" + count + "() {}";
+                    syntheticClasses.add("new A" + count + "();");
+                }
+                sb.append(toString(innerMod)).append(' ');
+                sb.append(String.format("%s A%d {%s}\n", innerClassType, count, privateConstructor));
+                Set<String> flags = getFlags(innerClassType, innerMod);
+                class2Flags.put("A" + count, flags);
+            }
+            if (hasSyntheticClass) {
+                // Source to generate synthetic classes
+                sb.append(syntheticClasses.stream().collect(Collectors.joining(" ", "{", "}")));
+                class2Flags.put("1", new HashSet<>(Arrays.asList("ACC_STATIC", "ACC_SYNTHETIC")));
+            }
+            sb.append(suffix).append("\n}");
+            getAdditionalFlags(class2Flags, outerClassType, outerMod.toArray(new Modifier[outerMod.size()]));
+            list.add(new TestCase(sb.toString(), class2Flags));
+        }
+        return list;
+    }
+
+    /**
+     * Methods returns flags which must have type.
+     *
+     * @param type class, interface, enum or annotation
+     * @param mods modifiers
+     * @return set of access flags
+     */
+    protected Set<String> getFlags(ClassType type, List<Modifier> mods) {
+        Set<String> flags = mods.stream()
+                .map(Modifier::getString)
+                .filter(str -> !str.isEmpty())
+                .map(str -> "ACC_" + str.toUpperCase())
+                .collect(Collectors.toSet());
+        type.addSpecificFlags(flags);
+        return flags;
+    }
+
+    private List<List<Modifier>> getAllCombinations(Modifier[] accessModifiers, Modifier[] otherModifiers) {
+        List<List<Modifier>> list = new ArrayList<>();
+        for (Modifier access : accessModifiers) {
+            for (int i = 0; i < otherModifiers.length; ++i) {
+                Modifier mod1 = otherModifiers[i];
+                for (int j = i + 1; j < otherModifiers.length; ++j) {
+                    Modifier mod2 = otherModifiers[j];
+                    if (isForbidden(mod1, mod2)) {
+                        continue;
+                    }
+                    list.add(Arrays.asList(access, mod1, mod2));
+                }
+                if (mod1 == Modifier.EMPTY) {
+                    list.add(Arrays.asList(access));
+                }
+            }
+        }
+        return list;
+    }
+
+    private boolean isForbidden(Modifier mod1, Modifier mod2) {
+        return mod1 == Modifier.FINAL && mod2 == Modifier.ABSTRACT
+                || mod1 == Modifier.ABSTRACT && mod2 == Modifier.FINAL;
+    }
+
+    private String toString(List<Modifier> mods) {
+        return mods.stream()
+                .map(Modifier::getString)
+                .filter(s -> !s.isEmpty())
+                .collect(Collectors.joining(" "));
+    }
+
+    /**
+     * Method is called in generateTestCases().
+     * If you need to add additional access flags, you should override this method.
+     *
+     *
+     * @param class2Flags map with flags
+     * @param type class, interface, enum or @annotation
+     * @param mods modifiers
+     */
+    public void getAdditionalFlags(Map<String, Set<String>> class2Flags, ClassType type, Modifier...mods) {
+        class2Flags.values().forEach(type::addFlags);
+    }
+
+    public enum ClassType {
+        CLASS("class") {
+            @Override
+            public void addSpecificFlags(Set<String> flags) {
+            }
+        },
+        INTERFACE("interface") {
+            @Override
+            public void addFlags(Set<String> flags) {
+                flags.add("ACC_STATIC");
+                flags.add("ACC_PUBLIC");
+            }
+
+            @Override
+            public void addSpecificFlags(Set<String> flags) {
+                flags.add("ACC_INTERFACE");
+                flags.add("ACC_ABSTRACT");
+                flags.add("ACC_STATIC");
+            }
+        },
+        ANNOTATION("@interface") {
+            @Override
+            public void addFlags(Set<String> flags) {
+                flags.add("ACC_STATIC");
+                flags.add("ACC_PUBLIC");
+            }
+
+            @Override
+            public void addSpecificFlags(Set<String> flags) {
+                flags.add("ACC_INTERFACE");
+                flags.add("ACC_ABSTRACT");
+                flags.add("ACC_STATIC");
+                flags.add("ACC_ANNOTATION");
+            }
+        },
+        ENUM("enum") {
+            @Override
+            public void addSpecificFlags(Set<String> flags) {
+                flags.add("ACC_ENUM");
+                flags.add("ACC_FINAL");
+                flags.add("ACC_STATIC");
+            }
+        },
+        OTHER("") {
+            @Override
+            public void addSpecificFlags(Set<String> flags) {
+            }
+        };
+
+        private final String classType;
+
+        private ClassType(String clazz) {
+            this.classType = clazz;
+        }
+
+        public abstract void addSpecificFlags(Set<String> flags);
+
+        public String toString() {
+            return classType;
+        }
+
+        public void addFlags(Set<String> set) {
+        }
+    }
+
+    public enum Modifier {
+        PUBLIC("public"), PRIVATE("private"),
+        PROTECTED("protected"), DEFAULT("default"),
+        FINAL("final"), ABSTRACT("abstract"),
+        STATIC("static"), EMPTY("");
+
+        private final String str;
+
+        private Modifier(String str) {
+            this.str = str;
+        }
+
+        public String getString() {
+            return str;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerAnnotationTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,49 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner enums in inner annotation.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
+ * @run main InnerEnumInInnerAnnotationTest
+ */
+
+public class InnerEnumInInnerAnnotationTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerEnumInInnerAnnotationTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC);
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC);
+        setOuterClassType(ClassType.ANNOTATION);
+        setInnerClassType(ClassType.ENUM);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerEnumTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,49 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner enums in inner enum.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
+ * @run main InnerEnumInInnerEnumTest
+ */
+
+public class InnerEnumInInnerEnumTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerEnumInInnerEnumTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC);
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC);
+        setOuterClassType(ClassType.ENUM);
+        setInnerClassType(ClassType.ENUM);
+        setPrefix("Inner {;");
+        setSuffix("}");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerInterfaceTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,48 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner enums in inner interface.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
+ * @run main InnerEnumInInnerInterfaceTest
+ */
+
+public class InnerEnumInInnerInterfaceTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerEnumInInnerInterfaceTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC);
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC);
+        setOuterClassType(ClassType.INTERFACE);
+        setInnerClassType(ClassType.ENUM);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumsInInnerClassTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,47 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner enums in inner class.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
+ * @run main InnerEnumsInInnerClassTest
+ */
+
+public class InnerEnumsInInnerClassTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerEnumsInInnerClassTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setForbiddenWithoutStaticInOuterMods(true);
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC);
+        setOuterClassType(ClassType.CLASS);
+        setInnerClassType(ClassType.ENUM);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerAnnotationTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,48 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner interfaces in inner annotation.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
+ * @run main InnerInterfacesInInnerAnnotationTest
+ */
+
+public class InnerInterfacesInInnerAnnotationTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerInterfacesInInnerAnnotationTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC);
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setOuterClassType(ClassType.ANNOTATION);
+        setInnerClassType(ClassType.INTERFACE);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerClassTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,47 @@
+/*
+ * 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
+ * @summary Testing InnerClasses_attribute of inner interfaces in inner class.
+ * @author aeremeev
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
+ * @run main InnerInterfacesInInnerClassTest
+ */
+
+public class InnerInterfacesInInnerClassTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerInterfacesInInnerClassTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setForbiddenWithoutStaticInOuterMods(true);
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setOuterClassType(ClassType.CLASS);
+        setInnerClassType(ClassType.INTERFACE);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerEnumTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,49 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner interfaces in inner enum.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
+ * @run main InnerInterfacesInInnerEnumTest
+ */
+
+public class InnerInterfacesInInnerEnumTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerInterfacesInInnerEnumTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC);
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setOuterClassType(ClassType.ENUM);
+        setInnerClassType(ClassType.INTERFACE);
+        setPrefix("Inner {;");
+        setSuffix("}");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerInterfaceTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,50 @@
+/*
+ * 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 8042251
+ * @summary Testing InnerClasses_attribute of inner interfaces in inner interface.
+ * @library /tools/javac/lib ../lib
+ * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
+ * @run main InnerInterfacesInInnerInterfaceTest
+ */
+
+import java.util.List;
+
+public class InnerInterfacesInInnerInterfaceTest extends InnerClassesInInnerClassTestBase {
+
+    public static void main(String[] args) throws TestFailedException {
+        InnerClassesTestBase test = new InnerInterfacesInInnerInterfaceTest();
+        test.test("InnerClassesSrc$Inner", "Inner", "1");
+    }
+
+    @Override
+    public void setProperties() {
+        setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC);
+        setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
+        setOuterClassType(ClassType.INTERFACE);
+        setInnerClassType(ClassType.INTERFACE);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/NoInnerClassesTest.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,49 @@
+/*
+ * 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 8042251
+ * @summary Test that there are no inner classes attributes in case of there are no inner classes.
+ * @library /tools/javac/lib ../lib
+ * @build TestBase InMemoryFileManager ToolBox
+ * @run main NoInnerClassesTest
+ */
+
+import com.sun.tools.classfile.Attribute;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPoolException;
+
+import java.io.IOException;
+
+public class NoInnerClassesTest extends TestBase {
+
+    public static void main(String[] args) throws IOException, ConstantPoolException {
+        new NoInnerClassesTest().test();
+    }
+
+    public void test() throws IOException, ConstantPoolException {
+        ClassFile classFile = readClassFile("NoInnerClassesTest");
+        assertNull(classFile.getAttribute(Attribute.InnerClasses), "Found inner class attribute");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/README.txt	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,92 @@
+The description of the tests for the InnerClasses attribute.
+
+InnerClassesTestBase is the base class for tests of inner classes attribute.
+Each tests extends the base class.
+The scenario of tests:
+    1. set possible values of class modifiers, outer/inner class types.
+    2. according to set class modifiers, a test generates sources
+       and golden data with generateTestCases.
+    3. a test loops through all test cases and checks InnerClasses attribute in method test().
+
+Example, possible flags for outer class are Modifier.PRIVATE and Modifier.PUBLIC,
+possible flags for inner class are Modifier.EMPTY, outer class type is CLASS
+and inner class type is CLASS.
+At the second step the test generates two test cases:
+  1. public class A {
+       public class B {
+         class C {}
+        }
+     }
+  2. public class A {
+       private class B {
+         class C {}
+       }
+     }
+
+The list of tests.
+
+Test: test if there is not inner class, the InnerClasses attribute
+is not generated (NoInnerClasses.java).
+
+Test: inner classes in anonymous class (InnerClassesInAnonymousClassTest.java).
+Possible access flags of the inner class: abstract and final.
+
+Test: inner classes in local class (InnerClassesInLocalClassTest.java).
+Locations of local class: static and instance initializer, constructor, method, lambda,
+default and static methods of interface.
+
+Test: test the outer_class_info_index and inner_name_index of
+local and anonymous classes (InnerClassesIndexTest.java).
+
+List of test cases for Inner*InInner*Test:
+    * InnerClassesInInnerClassTest
+        outer flags: all possible flags
+        inner flags: all possible flags
+    * InnerClassesInInnerEnumTest
+        outer flags: all access flags, abstract
+        inner flags: all possible flags
+    * InnerClassesInInnerAnnotationTest
+        outer flags: all access flags, abstract
+        inner flags: all flags, except private and protected
+    * InnerClassesInInnerInterfaceTest
+        outer flags: all access flags, abstract
+        inner flags: all flags, except private and protected
+
+    * InnerEnumsInInnerClassTest
+        outer flags: all possible flags
+        inner flags: all possible flags
+    * InnerEnumsInInnerEnumTest
+        outer flags: all possible flags
+        inner flags: all possible flags
+    * InnerEnumsInInnerAnnotationTest
+        outer flags: all access flags, abstract, static
+        inner flags: public, static
+    * InnerEnumsInInnerInterfaceTest
+        outer flags: all access flags, abstract, static
+        inner flags: public, static
+
+    * InnerAnnotationInInnerClassTest
+        outer flags: all possible flags, except static
+        inner flags: all access flags, abstract and static
+    * InnerAnnotationInInnerEnumTest
+        outer flags: all access flags, static
+        inner flags: all access flags, abstract and static
+    * InnerAnnotationInInnerAnnotation
+        outer flags: all access flags, static and abstract
+        inner flags: public, abstract, static
+    * InnerAnnotationInInnerInterface
+        outer flags: all access flags, static and abstract
+        inner flags: public, abstract, static
+
+    * InnerInterfaceInInnerClassTest
+        outer flags: all possible flags, except static
+        inner flags: all access flags, abstract and static
+    * InnerInterfaceInInnerEnumTest
+        outer flags: all access flags, static
+        inner flags: all access flags, abstract and static
+    * InnerInterfaceInInnerAnnotation
+        outer flags: all access flags, static and abstract
+        inner flags: public, abstract, static
+    * InnerInterfaceInInnerInterface
+        outer flags: all access flags, static and abstract
+        inner flags: public, abstract, static
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/TestCase.java	Wed Aug 13 21:58:29 2014 +0000
@@ -0,0 +1,58 @@
+/*
+ * 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.util.Map;
+import java.util.Set;
+
+/**
+ * Class represents test cases. This class contains source code and
+ * access flags for each inner class in source code.
+ */
+public class TestCase {
+
+    private final String sourceCode;
+    private final Map<String, Set<String>> class2Flags;
+
+    public TestCase(String sourceCode, Map<String, Set<String>> class2Flags) {
+        this.sourceCode = sourceCode;
+        this.class2Flags = class2Flags;
+    }
+
+    /**
+     * Returns source code.
+     *
+     * @return source code
+     */
+    public String getSource() {
+        return sourceCode;
+    }
+
+    /**
+     * Returns map with entries (ClassName, set of access flags for the ClassName).
+     *
+     * @return map with entries (ClassName, set of access flags for the ClassName)
+     */
+    public Map<String, Set<String>> getFlags() {
+        return class2Flags;
+    }
+}
--- a/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java	Wed Aug 13 13:20:31 2014 -0700
+++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java	Wed Aug 13 21:58:29 2014 +0000
@@ -22,22 +22,23 @@
  */
 
 import java.io.File;
+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.function.Function;
-import java.util.stream.Stream;
+import java.util.stream.Collectors;
+
 import javax.tools.DiagnosticCollector;
 import javax.tools.JavaCompiler;
 import javax.tools.JavaFileObject;
 import javax.tools.ToolProvider;
 
-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;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPoolException;
 
 /**
  * Base class for class file attribute tests.
@@ -46,7 +47,7 @@
  */
 public class TestBase {
 
-    public static final String LINE_SEPARATOR = lineSeparator();
+    public static final String LINE_SEPARATOR = System.lineSeparator();
 
     private <S> InMemoryFileManager compile(
             List<String> options,
@@ -57,7 +58,7 @@
         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
         List<? extends JavaFileObject> src = sources.stream()
                 .map(src2JavaFileObject)
-                .collect(toList());
+                .collect(Collectors.toList());
 
         DiagnosticCollector<? super JavaFileObject> dc = new DiagnosticCollector<>();
         try (InMemoryFileManager fileManager
@@ -67,7 +68,7 @@
             if (!success) {
                 String errorMessage = dc.getDiagnostics().stream()
                         .map(Object::toString)
-                        .collect(joining("\n"));
+                        .collect(Collectors.joining("\n"));
                 throw new CompilationException("Compilation Error\n\n" + errorMessage);
             }
             return fileManager;
@@ -82,7 +83,7 @@
      */
     public InMemoryFileManager compile(String... sources)
             throws IOException, CompilationException {
-        return compile(emptyList(), sources);
+        return compile(Collections.emptyList(), sources);
     }
 
     /**
@@ -94,7 +95,7 @@
      */
     public InMemoryFileManager compile(List<String> options, String... sources)
             throws IOException, CompilationException {
-        return compile(options, ToolBox.JavaSource::new, asList(sources));
+        return compile(options, ToolBox.JavaSource::new, Arrays.asList(sources));
     }
 
     /**
@@ -105,7 +106,7 @@
      */
     public InMemoryFileManager compile(String[]... sources) throws IOException,
             CompilationException {
-        return compile(emptyList(), sources);
+        return compile(Collections.emptyList(), sources);
     }
 
     /**
@@ -117,12 +118,73 @@
      */
     public InMemoryFileManager compile(List<String> options, String[]... sources)
             throws IOException, CompilationException {
-        return compile(options, src -> new ToolBox.JavaSource(src[0], src[1]), asList(sources));
+        return compile(options, src -> new ToolBox.JavaSource(src[0], src[1]), Arrays.asList(sources));
+    }
+
+    /**
+     * Returns class file that is read from {@code is}.
+     *
+     * @param is an input stream
+     * @return class file that is read from {@code is}
+     * @throws IOException if I/O error occurs
+     * @throws ConstantPoolException if constant pool error occurs
+     */
+    public ClassFile readClassFile(InputStream is) throws IOException, ConstantPoolException {
+        return ClassFile.read(is);
+    }
+
+    /**
+     * Returns class file that is read from {@code fileObject}.
+     *
+     * @param fileObject a file object
+     * @return class file that is read from {@code fileObject}
+     * @throws IOException if I/O error occurs
+     * @throws ConstantPoolException if constant pool error occurs
+     */
+    public ClassFile readClassFile(JavaFileObject fileObject) throws IOException, ConstantPoolException {
+        return readClassFile(fileObject.openInputStream());
+    }
+
+    /**
+     * Returns class file that corresponds to {@code clazz}.
+     *
+     * @param clazz a class
+     * @return class file that is read from {@code clazz}
+     * @throws IOException if I/O error occurs
+     * @throws ConstantPoolException if constant pool error occurs
+     */
+    public ClassFile readClassFile(Class<?> clazz) throws IOException, ConstantPoolException {
+        return readClassFile(getClassFile(clazz));
+    }
+
+    /**
+     * Returns class file that corresponds to {@code className}.
+     *
+     * @param className a class name
+     * @return class file that is read from {@code className}
+     * @throws IOException if I/O error occurs
+     * @throws ConstantPoolException if constant pool error occurs
+     */
+    public ClassFile readClassFile(String className) throws IOException, ConstantPoolException {
+        return readClassFile(getClassFile(className + ".class"));
+    }
+
+    /**
+     * Returns class file that is read from {@code file}.
+     *
+     * @param file a file
+     * @return class file that is read from {@code file}
+     * @throws IOException if I/O error occurs
+     * @throws ConstantPoolException if constant pool error occurs
+     */
+    public ClassFile readClassFile(File file) throws IOException, ConstantPoolException {
+        return readClassFile(new FileInputStream(file));
     }
 
     public void assertEquals(Object actual, Object expected, String message) {
         if (!Objects.equals(actual, expected))
-            throw new AssertionFailedException(format("%s%nGot: %s, Expected: %s", message, actual, expected));
+            throw new AssertionFailedException(String.format("%s%nGot: %s, Expected: %s",
+                    message, actual, expected));
     }
 
     public void assertNull(Object actual, String message) {
@@ -169,22 +231,18 @@
      * @param message string to print.
      */
     public void echo(String message) {
-        System.err.println(message.replace("\n", LINE_SEPARATOR));
+        printf(message + "\n");
     }
 
     /**
-     * Substitutes args in template and prints result to standard error. New lines are converted to system dependent NL.
+     * Substitutes args in template and prints result to standard error.
+     * New lines are converted to system dependent NL.
      *
      * @param template template in standard String.format(...) format.
      * @param args arguments to substitute in template.
      */
     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());
-
+        System.err.printf(String.format(template, args).replace("\n", LINE_SEPARATOR));
     }
 
     public static class CompilationException extends Exception {
--- a/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java	Wed Aug 13 13:20:31 2014 -0700
+++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java	Wed Aug 13 21:58:29 2014 +0000
@@ -23,13 +23,15 @@
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
+import java.util.stream.Stream;
 
 import static java.lang.String.format;
 import static java.util.stream.Collectors.joining;
 
+/**
+ * This class accumulates test results. Test results can be checked with method @{code checkStatus}.
+ */
 public class TestResult extends TestBase {
 
     private final List<Info> testCases;
@@ -39,15 +41,18 @@
         testCases.add(new Info("Global test info"));
     }
 
-    public void addTestCase(String src) {
-        testCases.add(new Info(src));
+    /**
+     * Adds new test case info.
+     *
+     * @param info the information about test case
+     */
+    public void addTestCase(String info) {
+        testCases.add(new Info(info));
     }
 
-    public String errorMessage() {
+    private 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()))
+                .map(tc -> format("Failure in test case:\n%s\n%s", tc.info(), tc.getMessage()))
                 .collect(joining("\n"));
     }
 
@@ -76,8 +81,14 @@
         getLastTestCase().assertEquals(actual, true, 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 void addFailure(Throwable th) {
-        getLastTestCase().addFailure(th);
+        testCases.get(testCases.size() - 1).addFailure(th);
     }
 
     private Info getLastTestCase() {
@@ -87,6 +98,13 @@
         return testCases.get(testCases.size() - 1);
     }
 
+    /**
+     * Throws {@code TestFailedException} if one of the asserts are failed
+     * or an exception occurs. Prints error message of failed test cases.
+     *
+     * @throws TestFailedException if one of the asserts are failed
+     *                             or an exception occurs
+     */
     public void checkStatus() throws TestFailedException {
         if (testCases.stream().anyMatch(Info::isFailed)) {
             echo(errorMessage());
@@ -120,7 +138,13 @@
         }
 
         public void addFailure(String message) {
-            asserts.add(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);
         }
 
@@ -138,6 +162,10 @@
             }
         }
 
+        public String getMessage() {
+            return (asserts.size() > 0 ? getAssertMessage() + "\n" : "") + getErrorMessage();
+        }
+
         public String getAssertMessage() {
             return asserts.stream()
                     .map(failure -> "[ASSERT] : " + failure)
@@ -146,8 +174,7 @@
 
         public String getErrorMessage() {
             return errors.stream()
-                    .map(throwable ->
-                            format("[ERROR] : %s", getStackTrace(throwable)))
+                    .map(throwable -> format("[ERROR] : %s", getStackTrace(throwable)))
                     .collect(joining("\n"));
         }