# HG changeset patch # User emc # Date 1407967109 0 # Node ID 0768f194cad1437b42e3ebbf414e3cc954031abf # Parent bb7dd001d1902c46ca57b6d027439426ee425133# Parent d5dd2ecd2353a4935dcceb4beef076ae6b313ffe Merge diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerAnnotationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerAnnotationTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner annotations in inner annotation. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerAnnotationsInInnerAnnotationTest + */ + +public class InnerAnnotationsInInnerAnnotationTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerAnnotationsInInnerAnnotationTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.ANNOTATION); + setInnerClassType(ClassType.ANNOTATION); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerClassTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner annotations in inner class. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerAnnotationsInInnerClassTest + */ + +public class InnerAnnotationsInInnerClassTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerAnnotationsInInnerClassTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setForbiddenWithoutStaticInOuterMods(true); + setOuterClassType(ClassType.CLASS); + setInnerClassType(ClassType.ANNOTATION); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerEnumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerEnumTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner annotations in inner enum. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerAnnotationsInInnerEnumTest + */ + +public class InnerAnnotationsInInnerEnumTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerAnnotationsInInnerEnumTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC, Modifier.ABSTRACT); + setOuterClassType(ClassType.ENUM); + setInnerClassType(ClassType.ANNOTATION); + setPrefix("Inner {;"); + setSuffix("}"); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerInterfaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerAnnotationsInInnerInterfaceTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner annotations in inner interface. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerAnnotationsInInnerInterfaceTest + */ + +public class InnerAnnotationsInInnerInterfaceTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerAnnotationsInInnerInterfaceTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.INTERFACE); + setInnerClassType(ClassType.ANNOTATION); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesHierarchyTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Test that inner classes have in its inner classes attribute enclosing classes and its immediate members. + * @library /tools/javac/lib ../lib + * @build TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesHierarchyTest + */ + +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.InnerClasses_attribute.Info; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.*; +import java.util.stream.Collectors; + +public class InnerClassesHierarchyTest extends TestResult { + + private final Map> 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 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 queue = new LinkedList<>(); + Set 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 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 allClasses = innerClasses.entrySet().stream() + .flatMap(entry -> entry.getValue().stream()) + .collect(Collectors.toSet()); + + Set a_b = removeAll(visitedClasses, allClasses); + Set 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 removeAll(Set set1, Set set2) { + Set 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 annotationType() { + return null; + } + }; + class B5 { + } + } + + Runnable r = () -> { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class 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 annotationType() { + return null; + } + }; + class B5 { + } + } + + Runnable r = () -> { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class 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 annotationType() { + return null; + } + }; + class B5 { + } + } + + static void a2() { + new B1() { + }; + new B3() { + }; + new B4() { + @Override + public Class 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 annotationType() { + return null; + } + + class B1 { + } + + public void a4() { + new B1() { + }; + class B5 { + } + } + }; + Runnable r = () -> { + new A1() { + }; + new A3() { + }; + new A4() { + @Override + public Class 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 annotationType() { + return null; + } + + class B1 { + } + + public void a4() { + new B1() { + }; + class B5 { + } + } + }; + Runnable r = () -> { + new A1() { + }; + new A3() { + }; + new A4() { + @Override + public Class 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 annotationType() { + return null; + } + }; + class B5 { + } + }; + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInAnonymousClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInAnonymousClassTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner classes in anonymous class. + * @library /tools/javac/lib ../lib + * @build InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInAnonymousClassTest + */ + +import java.util.*; + +public class InnerClassesInAnonymousClassTest extends InnerClassesTestBase { + + private ClassType currentClassType; + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInAnonymousClassTest(); + test.test("InnerClassesSrc$1", "Anonymous", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL); + setOuterClassType(ClassType.OTHER); + setInnerClassType(ClassType.CLASS); + setSuffix("};}"); + } + + @Override + public List generateTestCases() { + currentClassType = ClassType.CLASS; + setPrefix("class Anonymous {} {new Anonymous() {"); + List 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 " + + "annotationType() {return null;}"); + sources.addAll(super.generateTestCases()); + return sources; + } + + @Override + public void getAdditionalFlags(Map> class2Flags, ClassType type, Modifier... flags) { + super.getAdditionalFlags(class2Flags, type, flags); + class2Flags.put("Anonymous", getFlags(currentClassType, Arrays.asList(flags))); + class2Flags.put("1", new HashSet<>()); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerAnnotationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerAnnotationTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner classes in inner annotation. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInInnerAnnotationTest + */ + +public class InnerClassesInInnerAnnotationTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInInnerAnnotationTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setOuterClassType(ClassType.ANNOTATION); + setInnerClassType(ClassType.CLASS); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8034854 8042251 + * @summary Testing InnerClasses_attribute of inner classes in inner class. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInInnerClassTest + */ + +import java.util.List; + +public class InnerClassesInInnerClassTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInInnerClassTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setHasSyntheticClass(true); + setOuterClassType(ClassType.CLASS); + setInnerClassType(ClassType.CLASS); + } + + @Override + public List generateTestCases() { + setForbiddenWithoutStaticInOuterMods(true); + List 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; + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTestBase.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Arrays; +import java.util.Map; +import java.util.Set; + +/** + * + * Base class for tests that check inner classes in inner class. + * + * @author Andrei Eremeev + */ +public abstract class InnerClassesInInnerClassTestBase extends InnerClassesTestBase { + + public InnerClassesInInnerClassTestBase() { + setPrefix("Inner {"); + setSuffix("}"); + } + + @Override + public void getAdditionalFlags( + Map> class2Flags, ClassType type, Modifier...flags) { + super.getAdditionalFlags(class2Flags, type, flags); + class2Flags.put("Inner", getFlags(type, Arrays.asList(flags))); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerEnumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerEnumTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8034854 8042251 + * @summary Testing InnerClasses_attribute of inner classes in inner enum. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInInnerEnumTest + */ + +public class InnerClassesInInnerEnumTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInInnerEnumTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.ENUM); + setInnerClassType(ClassType.CLASS); + setHasSyntheticClass(true); + setPrefix("Inner {;"); + setSuffix("}"); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerInterfaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerInterfaceTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner classes in inner interface. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInInnerInterfaceTest + */ + +public class InnerClassesInInnerInterfaceTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerClassesInInnerInterfaceTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setOuterClassType(ClassType.INTERFACE); + setInnerClassType(ClassType.CLASS); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInLocalClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesInLocalClassTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner classes in local class. + * @library /tools/javac/lib ../lib + * @build InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox + * @run main InnerClassesInLocalClassTest + */ + +import java.util.*; + +public class InnerClassesInLocalClassTest extends InnerClassesTestBase { + + private final static Modifier[] LOCAL_CLASS_MODIFIERS = + new Modifier[]{Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL}; + private final static String CLASS_TEMPLATE = + "public %CLASS% OuterClass {\n" + + "%SOURCE%\n" + + "}"; + + private final List 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> 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 generateTestCases() { + List testCases = new ArrayList<>(); + testCases.addAll(localClassInClassMethod()); + testCases.addAll(localClassInInterfaceMethod()); + return testCases; + } + + private List localClassInClassMethod() { + List 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 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 generate(String template, String prefix, String suffix) { + List list = new ArrayList<>(); + for (Data data : innerClassesData) { + list.add(new TestCase(template.replace("%SOURCE%", + prefix + data.sources + suffix), + data.class2Flags)); + } + return list; + } + + private List lambda(String template) { + return generate(template, "Runnable run = () -> {", "};"); + } + + private List constructor(String template) { + List 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 method(String template, Modifier[] mods, Modifier[] otherMods) { + List 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 staticAndInstanceInitializer(String template) { + List list = new ArrayList<>(); + for (Modifier modifier : new Modifier[]{Modifier.EMPTY, Modifier.STATIC}) { + list.addAll(generate(template, modifier.getString() + "{", "}")); + } + return list; + } + + private Set getFlags(Modifier modifier) { + HashSet 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> class2Flags; + + public Data(String sources, Map> class2Flags) { + this.sources = sources; + this.class2Flags = class2Flags; + } + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesIndexTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Test that outer_class_info_index of local and anonymous class is zero. + * @library /tools/javac/lib ../lib + * @build TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerClassesIndexTest + */ + +import java.io.File; +import java.io.FilenameFilter; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.InnerClasses_attribute; +import com.sun.tools.classfile.InnerClasses_attribute.Info; + +public class InnerClassesIndexTest extends TestResult { + + public static void main(String[] args) throws TestFailedException { + new InnerClassesIndexTest().test(); + } + + private boolean isExcluded(String className) { + return !className.startsWith(InnerClassesIndexTest.class.getName()) + || "InnerClassesIndexTest$Inner".equals(className); + } + + private Set 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 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 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() { + }; + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * @bug 8034854 8042251 + * @summary Testing inner classes attributes. + * @library /tools/javac/lib ../lib + * @build InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerClassesTest + */ + +import java.util.List; + +public class InnerClassesTest extends InnerClassesTestBase { + + public static void main(String[] args) throws TestFailedException { + new InnerClassesTest().test("InnerClassesSrc"); + } + + private List generateClasses() { + setInnerClassType(ClassType.CLASS); + setHasSyntheticClass(true); + return super.generateTestCases(); + } + + private List generateEnums() { + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setInnerClassType(ClassType.ENUM); + setHasSyntheticClass(false); + return super.generateTestCases(); + } + + private List generateInterfaces() { + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerClassType(ClassType.INTERFACE); + return super.generateTestCases(); + } + + private List 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 generateTestCases() { + List sources = generateClasses(); + sources.addAll(generateEnums()); + sources.addAll(generateInterfaces()); + sources.addAll(generateAnnotations()); + return sources; + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.InnerClasses_attribute; +import com.sun.tools.classfile.InnerClasses_attribute.Info; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Base class for tests of inner classes attribute. + * The scenario of tests: + * 1. set possible values of class modifiers. + * 2. according to set class modifiers, a test generates sources + * and golden data with {@code generateTestCases}. + * 3. a test loops through all test cases and checks InnerClasses + * attribute with {@code test}. + * + * Example, possible flags for outer class are {@code Modifier.PRIVATE and Modifier.PUBLIC}, + * possible flags for inner class are {@code Modifier.EMPTY}. + * At the second step the test generates two test cases: + * 1. public class A { + * public class B { + * class C {} + * } + * } + * 2. public class A { + * private class B { + * class C {} + * } + * } + */ +public abstract class InnerClassesTestBase extends TestResult { + + private Modifier[] outerAccessModifiers = {Modifier.EMPTY, Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC}; + private Modifier[] outerOtherModifiers = {Modifier.EMPTY, Modifier.STATIC, Modifier.FINAL, Modifier.ABSTRACT}; + private Modifier[] innerAccessModifiers = outerAccessModifiers; + private Modifier[] innerOtherModifiers = outerOtherModifiers; + private boolean isForbiddenWithoutStaticInOuterMods = false; + + private ClassType outerClassType; + private ClassType innerClassType; + private boolean hasSyntheticClass; + private String prefix = ""; + private String suffix = ""; + + /** + * Sets properties. + * + * Returns generated list of test cases. Method is called in {@code test()}. + */ + public abstract void setProperties(); + + /** + * Runs the test. + * + * @param classToTest expected name of outer class + * @param skipClasses classes that names should not be checked + */ + public void test(String classToTest, String...skipClasses) throws TestFailedException { + try { + for (TestCase test : generateTestCases()) { + addTestCase(test.getSource()); + test(classToTest, test, skipClasses); + } + } catch (Exception e) { + addFailure(e); + } finally { + checkStatus(); + } + } + + /** + * If {@code flag} is {@code true} an outer class can not have static modifier. + * + * @param flag if {@code true} the outer class can not have static modifier + */ + public void setForbiddenWithoutStaticInOuterMods(boolean flag) { + isForbiddenWithoutStaticInOuterMods = flag; + } + + /** + * Sets the possible access flags of an outer class. + * + * @param mods the possible access flags of an outer class + */ + public void setOuterAccessModifiers(Modifier...mods) { + outerAccessModifiers = mods; + } + + /** + * Sets the possible flags of an outer class. + * + * @param mods the possible flags of an outer class + */ + public void setOuterOtherModifiers(Modifier...mods) { + outerOtherModifiers = mods; + } + + /** + * Sets the possible access flags of an inner class. + * + * @param mods the possible access flags of an inner class + */ + public void setInnerAccessModifiers(Modifier...mods) { + innerAccessModifiers = mods; + } + + /** + * Sets the possible flags of an inner class. + * + * @param mods the possible flags of an inner class + */ + public void setInnerOtherModifiers(Modifier...mods) { + innerOtherModifiers = mods; + } + + /** + * Sets the suffix for the generated source. + * + * @param suffix a suffix + */ + public void setSuffix(String suffix) { + this.suffix = suffix; + } + + /** + * Sets the prefix for the generated source. + * + * @param prefix a prefix + */ + public void setPrefix(String prefix) { + this.prefix = prefix; + } + + /** + * If {@code true} synthetic class is generated. + * + * @param hasSyntheticClass if {@code true} synthetic class is generated + */ + public void setHasSyntheticClass(boolean hasSyntheticClass) { + this.hasSyntheticClass = hasSyntheticClass; + } + + /** + * Sets the inner class type. + * + * @param innerClassType the inner class type + */ + public void setInnerClassType(ClassType innerClassType) { + this.innerClassType = innerClassType; + } + + /** + * Sets the outer class type. + * + * @param outerClassType the outer class type + */ + public void setOuterClassType(ClassType outerClassType) { + this.outerClassType = outerClassType; + } + + private void test(String classToTest, TestCase test, String...skipClasses) { + printf("Testing :\n%s\n", test.getSource()); + try { + Map> 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 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 generateTestCases() { + setProperties(); + List list = new ArrayList<>(); + + List> outerMods = getAllCombinations(outerAccessModifiers, outerOtherModifiers); + List> innerMods = getAllCombinations(innerAccessModifiers, innerOtherModifiers); + + for (List 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> class2Flags = new HashMap<>(); + List syntheticClasses = new ArrayList<>(); + for (List 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 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 getFlags(ClassType type, List mods) { + Set 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> getAllCombinations(Modifier[] accessModifiers, Modifier[] otherModifiers) { + List> 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 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> class2Flags, ClassType type, Modifier...mods) { + class2Flags.values().forEach(type::addFlags); + } + + public enum ClassType { + CLASS("class") { + @Override + public void addSpecificFlags(Set flags) { + } + }, + INTERFACE("interface") { + @Override + public void addFlags(Set flags) { + flags.add("ACC_STATIC"); + flags.add("ACC_PUBLIC"); + } + + @Override + public void addSpecificFlags(Set flags) { + flags.add("ACC_INTERFACE"); + flags.add("ACC_ABSTRACT"); + flags.add("ACC_STATIC"); + } + }, + ANNOTATION("@interface") { + @Override + public void addFlags(Set flags) { + flags.add("ACC_STATIC"); + flags.add("ACC_PUBLIC"); + } + + @Override + public void addSpecificFlags(Set flags) { + flags.add("ACC_INTERFACE"); + flags.add("ACC_ABSTRACT"); + flags.add("ACC_STATIC"); + flags.add("ACC_ANNOTATION"); + } + }, + ENUM("enum") { + @Override + public void addSpecificFlags(Set flags) { + flags.add("ACC_ENUM"); + flags.add("ACC_FINAL"); + flags.add("ACC_STATIC"); + } + }, + OTHER("") { + @Override + public void addSpecificFlags(Set flags) { + } + }; + + private final String classType; + + private ClassType(String clazz) { + this.classType = clazz; + } + + public abstract void addSpecificFlags(Set flags); + + public String toString() { + return classType; + } + + public void addFlags(Set 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; + } + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerAnnotationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerAnnotationTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner enums in inner annotation. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerEnumInInnerAnnotationTest + */ + +public class InnerEnumInInnerAnnotationTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerEnumInInnerAnnotationTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.ANNOTATION); + setInnerClassType(ClassType.ENUM); + } +} \ No newline at end of file diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerEnumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerEnumTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner enums in inner enum. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerEnumInInnerEnumTest + */ + +public class InnerEnumInInnerEnumTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerEnumInInnerEnumTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.ENUM); + setInnerClassType(ClassType.ENUM); + setPrefix("Inner {;"); + setSuffix("}"); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerInterfaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerInterfaceTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner enums in inner interface. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerEnumInInnerInterfaceTest + */ + +public class InnerEnumInInnerInterfaceTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerEnumInInnerInterfaceTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.INTERFACE); + setInnerClassType(ClassType.ENUM); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumsInInnerClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumsInInnerClassTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner enums in inner class. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerEnumsInInnerClassTest + */ + +public class InnerEnumsInInnerClassTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerEnumsInInnerClassTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setForbiddenWithoutStaticInOuterMods(true); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setOuterClassType(ClassType.CLASS); + setInnerClassType(ClassType.ENUM); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerAnnotationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerAnnotationTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner interfaces in inner annotation. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerInterfacesInInnerAnnotationTest + */ + +public class InnerInterfacesInInnerAnnotationTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerInterfacesInInnerAnnotationTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.ANNOTATION); + setInnerClassType(ClassType.INTERFACE); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerClassTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Testing InnerClasses_attribute of inner interfaces in inner class. + * @author aeremeev + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerInterfacesInInnerClassTest + */ + +public class InnerInterfacesInInnerClassTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerInterfacesInInnerClassTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setForbiddenWithoutStaticInOuterMods(true); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.CLASS); + setInnerClassType(ClassType.INTERFACE); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerEnumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerEnumTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner interfaces in inner enum. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerInterfacesInInnerEnumTest + */ + +public class InnerInterfacesInInnerEnumTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerInterfacesInInnerEnumTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.ENUM); + setInnerClassType(ClassType.INTERFACE); + setPrefix("Inner {;"); + setSuffix("}"); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerInterfaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerInterfacesInInnerInterfaceTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Testing InnerClasses_attribute of inner interfaces in inner interface. + * @library /tools/javac/lib ../lib + * @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox + * @run main InnerInterfacesInInnerInterfaceTest + */ + +import java.util.List; + +public class InnerInterfacesInInnerInterfaceTest extends InnerClassesInInnerClassTestBase { + + public static void main(String[] args) throws TestFailedException { + InnerClassesTestBase test = new InnerInterfacesInInnerInterfaceTest(); + test.test("InnerClassesSrc$Inner", "Inner", "1"); + } + + @Override + public void setProperties() { + setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setInnerAccessModifiers(Modifier.EMPTY, Modifier.PUBLIC); + setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC); + setOuterClassType(ClassType.INTERFACE); + setInnerClassType(ClassType.INTERFACE); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/NoInnerClassesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/NoInnerClassesTest.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8042251 + * @summary Test that there are no inner classes attributes in case of there are no inner classes. + * @library /tools/javac/lib ../lib + * @build TestBase InMemoryFileManager ToolBox + * @run main NoInnerClassesTest + */ + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPoolException; + +import java.io.IOException; + +public class NoInnerClassesTest extends TestBase { + + public static void main(String[] args) throws IOException, ConstantPoolException { + new NoInnerClassesTest().test(); + } + + public void test() throws IOException, ConstantPoolException { + ClassFile classFile = readClassFile("NoInnerClassesTest"); + assertNull(classFile.getAttribute(Attribute.InnerClasses), "Found inner class attribute"); + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/README.txt Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,92 @@ +The description of the tests for the InnerClasses attribute. + +InnerClassesTestBase is the base class for tests of inner classes attribute. +Each tests extends the base class. +The scenario of tests: + 1. set possible values of class modifiers, outer/inner class types. + 2. according to set class modifiers, a test generates sources + and golden data with generateTestCases. + 3. a test loops through all test cases and checks InnerClasses attribute in method test(). + +Example, possible flags for outer class are Modifier.PRIVATE and Modifier.PUBLIC, +possible flags for inner class are Modifier.EMPTY, outer class type is CLASS +and inner class type is CLASS. +At the second step the test generates two test cases: + 1. public class A { + public class B { + class C {} + } + } + 2. public class A { + private class B { + class C {} + } + } + +The list of tests. + +Test: test if there is not inner class, the InnerClasses attribute +is not generated (NoInnerClasses.java). + +Test: inner classes in anonymous class (InnerClassesInAnonymousClassTest.java). +Possible access flags of the inner class: abstract and final. + +Test: inner classes in local class (InnerClassesInLocalClassTest.java). +Locations of local class: static and instance initializer, constructor, method, lambda, +default and static methods of interface. + +Test: test the outer_class_info_index and inner_name_index of +local and anonymous classes (InnerClassesIndexTest.java). + +List of test cases for Inner*InInner*Test: + * InnerClassesInInnerClassTest + outer flags: all possible flags + inner flags: all possible flags + * InnerClassesInInnerEnumTest + outer flags: all access flags, abstract + inner flags: all possible flags + * InnerClassesInInnerAnnotationTest + outer flags: all access flags, abstract + inner flags: all flags, except private and protected + * InnerClassesInInnerInterfaceTest + outer flags: all access flags, abstract + inner flags: all flags, except private and protected + + * InnerEnumsInInnerClassTest + outer flags: all possible flags + inner flags: all possible flags + * InnerEnumsInInnerEnumTest + outer flags: all possible flags + inner flags: all possible flags + * InnerEnumsInInnerAnnotationTest + outer flags: all access flags, abstract, static + inner flags: public, static + * InnerEnumsInInnerInterfaceTest + outer flags: all access flags, abstract, static + inner flags: public, static + + * InnerAnnotationInInnerClassTest + outer flags: all possible flags, except static + inner flags: all access flags, abstract and static + * InnerAnnotationInInnerEnumTest + outer flags: all access flags, static + inner flags: all access flags, abstract and static + * InnerAnnotationInInnerAnnotation + outer flags: all access flags, static and abstract + inner flags: public, abstract, static + * InnerAnnotationInInnerInterface + outer flags: all access flags, static and abstract + inner flags: public, abstract, static + + * InnerInterfaceInInnerClassTest + outer flags: all possible flags, except static + inner flags: all access flags, abstract and static + * InnerInterfaceInInnerEnumTest + outer flags: all access flags, static + inner flags: all access flags, abstract and static + * InnerInterfaceInInnerAnnotation + outer flags: all access flags, static and abstract + inner flags: public, abstract, static + * InnerInterfaceInInnerInterface + outer flags: all access flags, static and abstract + inner flags: public, abstract, static \ No newline at end of file diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/innerclasses/TestCase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/TestCase.java Wed Aug 13 21:58:29 2014 +0000 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Map; +import java.util.Set; + +/** + * Class represents test cases. This class contains source code and + * access flags for each inner class in source code. + */ +public class TestCase { + + private final String sourceCode; + private final Map> class2Flags; + + public TestCase(String sourceCode, Map> 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> getFlags() { + return class2Flags; + } +} diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java --- a/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java Wed Aug 13 13:20:31 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java Wed Aug 13 21:58:29 2014 +0000 @@ -22,22 +22,23 @@ */ import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.function.Function; -import java.util.stream.Stream; +import java.util.stream.Collectors; + import javax.tools.DiagnosticCollector; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.ToolProvider; -import static java.lang.String.format; -import static java.lang.System.lineSeparator; -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPoolException; /** * Base class for class file attribute tests. @@ -46,7 +47,7 @@ */ public class TestBase { - public static final String LINE_SEPARATOR = lineSeparator(); + public static final String LINE_SEPARATOR = System.lineSeparator(); private InMemoryFileManager compile( List options, @@ -57,7 +58,7 @@ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); List src = sources.stream() .map(src2JavaFileObject) - .collect(toList()); + .collect(Collectors.toList()); DiagnosticCollector 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 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 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 { diff -r bb7dd001d190 -r 0768f194cad1 langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java --- a/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java Wed Aug 13 13:20:31 2014 -0700 +++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestResult.java Wed Aug 13 21:58:29 2014 +0000 @@ -23,13 +23,15 @@ import java.io.PrintWriter; import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; +import java.util.stream.Stream; import static java.lang.String.format; import static java.util.stream.Collectors.joining; +/** + * This class accumulates test results. Test results can be checked with method @{code checkStatus}. + */ public class TestResult extends TestBase { private final List 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")); }