8042251: Implement classfile tests for InnerClasses attribute.
Reviewed-by: jjg, anazarov, shurailine
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerAnnotationTest.java Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 Tue Aug 12 13:24:40 2014 +0400
@@ -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 14:25:46 2014 -0400
+++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java Tue Aug 12 13:24:40 2014 +0400
@@ -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 14:25:46 2014 -0400
+++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java Tue Aug 12 13:24:40 2014 +0400
@@ -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"));
}