8042251: Implement classfile tests for InnerClasses attribute

Reviewed-by: jjg, anazarov, shurailine
This commit is contained in:
Andrei Eremeev 2014-08-12 13:24:40 +04:00
parent 14fcc1d07d
commit 8740c99fbd
28 changed files with 2497 additions and 36 deletions

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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("}");
}
}

View file

@ -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);
}
}

View file

@ -0,0 +1,433 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8042251
* @summary Test that inner classes have in its inner classes attribute enclosing classes and its immediate members.
* @library /tools/javac/lib ../lib
* @build TestResult TestBase InMemoryFileManager ToolBox
* @run main InnerClassesHierarchyTest
*/
import com.sun.tools.classfile.*;
import com.sun.tools.classfile.InnerClasses_attribute.Info;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.*;
import java.util.stream.Collectors;
public class InnerClassesHierarchyTest extends TestResult {
private final Map<String, Set<String>> innerClasses;
private final String outerClassName;
public InnerClassesHierarchyTest() throws IOException, ConstantPoolException {
innerClasses = new HashMap<>();
outerClassName = InnerClassesHierarchyTest.class.getSimpleName();
File classDir = getClassDir();
FilenameFilter filter =
(dir, name) -> name.matches(outerClassName + ".*\\.class");
for (File file : Arrays.asList(classDir.listFiles(filter))) {
ClassFile classFile = readClassFile(file);
String className = classFile.getName();
for (ConstantPool.CPInfo info : classFile.constant_pool.entries()) {
if (info instanceof ConstantPool.CONSTANT_Class_info) {
ConstantPool.CONSTANT_Class_info classInfo =
(ConstantPool.CONSTANT_Class_info) info;
String cpClassName = classInfo.getBaseName();
if (isInnerClass(cpClassName)) {
get(className).add(cpClassName);
}
}
}
}
}
private boolean isInnerClass(String cpClassName) {
return cpClassName.contains("$");
}
private Set<String> get(String className) {
if (!innerClasses.containsKey(className)) {
innerClasses.put(className, new HashSet<>());
}
return innerClasses.get(className);
}
public static void main(String[] args) throws IOException, ConstantPoolException, TestFailedException {
new InnerClassesHierarchyTest().test();
}
private void test() throws TestFailedException {
addTestCase("Source file is InnerClassesHierarchyTest.java");
try {
Queue<String> queue = new LinkedList<>();
Set<String> visitedClasses = new HashSet<>();
queue.add(outerClassName);
while (!queue.isEmpty()) {
String currentClassName = queue.poll();
if (!currentClassName.startsWith(outerClassName)) {
continue;
}
ClassFile cf = readClassFile(currentClassName);
InnerClasses_attribute attr = (InnerClasses_attribute)
cf.getAttribute(Attribute.InnerClasses);
assertNotNull(attr, "Class should not contain "
+ "inner classes attribute : " + currentClassName);
assertTrue(innerClasses.containsKey(currentClassName),
"map contains class name : " + currentClassName);
Set<String> setClasses = innerClasses.get(currentClassName);
if (setClasses == null) {
continue;
}
assertEquals(attr.number_of_classes,
setClasses.size(),
"Check number of inner classes : " + setClasses);
for (Info info : attr.classes) {
String innerClassName = info
.getInnerClassInfo(cf.constant_pool).getBaseName();
assertTrue(setClasses.contains(innerClassName),
currentClassName + " contains inner class : "
+ innerClassName);
if (visitedClasses.add(innerClassName)) {
queue.add(innerClassName);
}
}
}
Set<String> allClasses = innerClasses.entrySet().stream()
.flatMap(entry -> entry.getValue().stream())
.collect(Collectors.toSet());
Set<String> a_b = removeAll(visitedClasses, allClasses);
Set<String> b_a = removeAll(allClasses, visitedClasses);
assertEquals(visitedClasses, allClasses,
"All classes are found\n"
+ "visited - all classes : " + a_b
+ "\nall classes - visited : " + b_a);
} catch (Exception e) {
addFailure(e);
} finally {
checkStatus();
}
}
private Set<String> removeAll(Set<String> set1, Set<String> set2) {
Set<String> set = new HashSet<>(set1);
set.removeAll(set2);
return set;
}
public static class A1 {
public class B1 {
}
public enum B2 {
}
public interface B3 {
}
public @interface B4 {
}
public void f() {
new B1() {
};
new B3() {
};
new B4() {
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
};
class B5 {
}
}
Runnable r = () -> {
new B1() {
};
new B3() {
};
new B4() {
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
};
class B5 {
}
};
}
public enum A2 {;
public class B1 {
}
public enum B2 {
}
public interface B3 {
}
public @interface B4 {
}
public void a2() {
new B1() {
};
new B3() {
};
new B4() {
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
};
class B5 {
}
}
Runnable r = () -> {
new B1() {
};
new B3() {
};
new B4() {
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
};
class B5 {
}
};
}
public interface A3 {
public class B1 {
}
public enum B2 {
}
public interface B3 {
}
public @interface B4 {
}
default void a1() {
new B1() {
};
new B3() {
};
new B4() {
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
};
class B5 {
}
}
static void a2() {
new B1() {
};
new B3() {
};
new B4() {
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
};
class B5 {
}
}
}
public @interface A4 {
public class B1 {
}
public enum B2 {
}
public interface B3 {
}
public @interface B4 {
}
}
{
new A1() {
class B1 {
}
public void a2() {
new B1() {
};
class B5 {
}
}
};
new A3() {
class B1 {
}
public void a3() {
new B1() {
};
class B5 {
}
}
};
new A4() {
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
class B1 {
}
public void a4() {
new B1() {
};
class B5 {
}
}
};
Runnable r = () -> {
new A1() {
};
new A3() {
};
new A4() {
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
};
class B5 {
}
};
}
static {
new A1() {
class B1 {
}
public void a2() {
new B1() {
};
class B5 {
}
}
};
new A3() {
class B1 {
}
public void a3() {
new B1() {
};
class B5 {
}
}
};
new A4() {
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
class B1 {
}
public void a4() {
new B1() {
};
class B5 {
}
}
};
Runnable r = () -> {
new A1() {
};
new A3() {
};
new A4() {
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
};
class B5 {
}
};
}
public void a5() {
class A5 {
class B1 {
}
public void a5() {
new B1() {
};
class B5 {
}
}
}
Runnable r = () -> {
new A1() {
};
new A3() {
};
new A4() {
@Override
public Class<? extends Annotation> annotationType() {
return null;
}
};
class B5 {
}
};
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8042251
* @summary Testing InnerClasses_attribute of inner classes in anonymous class.
* @library /tools/javac/lib ../lib
* @build InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
* @run main InnerClassesInAnonymousClassTest
*/
import java.util.*;
public class InnerClassesInAnonymousClassTest extends InnerClassesTestBase {
private ClassType currentClassType;
public static void main(String[] args) throws TestFailedException {
InnerClassesTestBase test = new InnerClassesInAnonymousClassTest();
test.test("InnerClassesSrc$1", "Anonymous", "1");
}
@Override
public void setProperties() {
setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
setInnerAccessModifiers(Modifier.EMPTY);
setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL);
setOuterClassType(ClassType.OTHER);
setInnerClassType(ClassType.CLASS);
setSuffix("};}");
}
@Override
public List<TestCase> generateTestCases() {
currentClassType = ClassType.CLASS;
setPrefix("class Anonymous {} {new Anonymous() {");
List<TestCase> sources = super.generateTestCases();
currentClassType = ClassType.INTERFACE;
setPrefix("interface Anonymous {} {new Anonymous() {");
sources.addAll(super.generateTestCases());
currentClassType = ClassType.ANNOTATION;
setPrefix("@interface Anonymous {} {new Anonymous() {@Override public "
+ "Class<? extends java.lang.annotation.Annotation> "
+ "annotationType() {return null;}");
sources.addAll(super.generateTestCases());
return sources;
}
@Override
public void getAdditionalFlags(Map<String, Set<String>> class2Flags, ClassType type, Modifier... flags) {
super.getAdditionalFlags(class2Flags, type, flags);
class2Flags.put("Anonymous", getFlags(currentClassType, Arrays.asList(flags)));
class2Flags.put("1", new HashSet<>());
}
}

View file

@ -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);
}
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8034854 8042251
* @summary Testing InnerClasses_attribute of inner classes in inner class.
* @library /tools/javac/lib ../lib
* @build InnerClassesInInnerClassTestBase InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
* @run main InnerClassesInInnerClassTest
*/
import java.util.List;
public class InnerClassesInInnerClassTest extends InnerClassesInInnerClassTestBase {
public static void main(String[] args) throws TestFailedException {
InnerClassesTestBase test = new InnerClassesInInnerClassTest();
test.test("InnerClassesSrc$Inner", "Inner", "1");
}
@Override
public void setProperties() {
setHasSyntheticClass(true);
setOuterClassType(ClassType.CLASS);
setInnerClassType(ClassType.CLASS);
}
@Override
public List<TestCase> generateTestCases() {
setForbiddenWithoutStaticInOuterMods(true);
List<TestCase> sources = super.generateTestCases();
setForbiddenWithoutStaticInOuterMods(false);
setOuterOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL);
setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL);
sources.addAll(super.generateTestCases());
return sources;
}
}

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
/**
*
* Base class for tests that check inner classes in inner class.
*
* @author Andrei Eremeev
*/
public abstract class InnerClassesInInnerClassTestBase extends InnerClassesTestBase {
public InnerClassesInInnerClassTestBase() {
setPrefix("Inner {");
setSuffix("}");
}
@Override
public void getAdditionalFlags(
Map<String, Set<String>> class2Flags, ClassType type, Modifier...flags) {
super.getAdditionalFlags(class2Flags, type, flags);
class2Flags.put("Inner", getFlags(type, Arrays.asList(flags)));
}
}

View file

@ -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("}");
}
}

View file

@ -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);
}
}

View file

@ -0,0 +1,167 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8042251
* @summary Testing InnerClasses_attribute of inner classes in local class.
* @library /tools/javac/lib ../lib
* @build InnerClassesTestBase TestResult TestBase InMemoryFileManager ToolBox
* @run main InnerClassesInLocalClassTest
*/
import java.util.*;
public class InnerClassesInLocalClassTest extends InnerClassesTestBase {
private final static Modifier[] LOCAL_CLASS_MODIFIERS =
new Modifier[]{Modifier.EMPTY, Modifier.ABSTRACT, Modifier.FINAL};
private final static String CLASS_TEMPLATE =
"public %CLASS% OuterClass {\n" +
"%SOURCE%\n" +
"}";
private final List<Data> innerClassesData;
public InnerClassesInLocalClassTest() {
innerClassesData = new ArrayList<>();
for (Modifier outerModifier : LOCAL_CLASS_MODIFIERS) {
StringBuilder sb = new StringBuilder();
sb.append(outerModifier.getString()).append(' ');
sb.append("class Local {");
Map<String, Set<String>> class2Flags = new HashMap<>();
for (int i = 0; i < LOCAL_CLASS_MODIFIERS.length; ++i) {
Modifier innerModifier = LOCAL_CLASS_MODIFIERS[i];
sb.append(innerModifier.getString()).append(' ')
.append("class").append(' ')
.append('A').append(i).append("{}\n");
class2Flags.put("A" + i, getFlags(innerModifier));
}
sb.append("};");
class2Flags.put("1Local", getFlags(outerModifier));
innerClassesData.add(new Data(sb.toString(), class2Flags));
}
}
public static void main(String[] args) throws TestFailedException {
InnerClassesTestBase test = new InnerClassesInLocalClassTest();
test.test("OuterClass$1Local", "1Local");
}
@Override
public void setProperties() {
}
@Override
public List<TestCase> generateTestCases() {
List<TestCase> testCases = new ArrayList<>();
testCases.addAll(localClassInClassMethod());
testCases.addAll(localClassInInterfaceMethod());
return testCases;
}
private List<TestCase> localClassInClassMethod() {
List<TestCase> list = new ArrayList<>();
String template = CLASS_TEMPLATE.replace("%CLASS%", "class");
list.addAll(lambda(template));
list.addAll(constructor(template));
list.addAll(method(template,
new Modifier[]{Modifier.EMPTY, Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC},
new Modifier[]{Modifier.EMPTY, Modifier.FINAL, Modifier.STATIC}));
list.addAll(staticAndInstanceInitializer(template));
return list;
}
private List<TestCase> localClassInInterfaceMethod() {
String template = CLASS_TEMPLATE.replace("%CLASS%", "interface");
return method(template,
new Modifier[]{Modifier.EMPTY, Modifier.PUBLIC},
new Modifier[]{Modifier.DEFAULT, Modifier.STATIC});
}
private List<TestCase> generate(String template, String prefix, String suffix) {
List<TestCase> list = new ArrayList<>();
for (Data data : innerClassesData) {
list.add(new TestCase(template.replace("%SOURCE%",
prefix + data.sources + suffix),
data.class2Flags));
}
return list;
}
private List<TestCase> lambda(String template) {
return generate(template, "Runnable run = () -> {", "};");
}
private List<TestCase> constructor(String template) {
List<TestCase> list = new ArrayList<>();
for (Modifier modifier :
new Modifier[]{Modifier.EMPTY, Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC}) {
list.addAll(generate(template, modifier.getString() + " OuterClass() {", "}"));
}
return list;
}
private List<TestCase> method(String template, Modifier[] mods, Modifier[] otherMods) {
List<TestCase> list = new ArrayList<>();
for (Modifier modifier : mods) {
for (Modifier otherMod : otherMods) {
list.addAll(generate(template,
String.format("%s %s void method() {",
modifier.getString(),
otherMod.getString()),
"}"));
}
}
return list;
}
private List<TestCase> staticAndInstanceInitializer(String template) {
List<TestCase> list = new ArrayList<>();
for (Modifier modifier : new Modifier[]{Modifier.EMPTY, Modifier.STATIC}) {
list.addAll(generate(template, modifier.getString() + "{", "}"));
}
return list;
}
private Set<String> getFlags(Modifier modifier) {
HashSet<String> set = new HashSet<>();
if (modifier != Modifier.EMPTY) {
set.add("ACC_" + modifier.getString().toUpperCase());
}
return set;
}
/**
* Class represents part of sources which is inserted in other code.
*/
private static class Data {
public final String sources;
public final Map<String, Set<String>> class2Flags;
public Data(String sources, Map<String, Set<String>> class2Flags) {
this.sources = sources;
this.class2Flags = class2Flags;
}
}
}

View file

@ -0,0 +1,141 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8042251
* @summary Test that outer_class_info_index of local and anonymous class is zero.
* @library /tools/javac/lib ../lib
* @build TestBase TestResult InMemoryFileManager ToolBox
* @run main InnerClassesIndexTest
*/
import java.io.File;
import java.io.FilenameFilter;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.InnerClasses_attribute;
import com.sun.tools.classfile.InnerClasses_attribute.Info;
public class InnerClassesIndexTest extends TestResult {
public static void main(String[] args) throws TestFailedException {
new InnerClassesIndexTest().test();
}
private boolean isExcluded(String className) {
return !className.startsWith(InnerClassesIndexTest.class.getName())
|| "InnerClassesIndexTest$Inner".equals(className);
}
private Set<String> getInnerClasses() {
FilenameFilter filter = (dir, name) -> name.matches("InnerClassesIndexTest\\$.*\\.class");
return Stream.of(getClassDir().listFiles(filter))
.map(File::getName)
.map(s -> s.replace(".class", ""))
.collect(Collectors.toSet());
}
public void test() throws TestFailedException {
try {
addTestCase("Source is InnerClassesIndexTest.java");
ClassFile classFile = readClassFile(InnerClassesIndexTest.class);
InnerClasses_attribute attr = (InnerClasses_attribute)
classFile.getAttribute(Attribute.InnerClasses);
Set<String> foundClasses = new HashSet<>();
for (Info info : attr.classes) {
String innerName = classFile.constant_pool.
getClassInfo(info.inner_class_info_index).getBaseName();
echo("Testing class : " + innerName);
if (isExcluded(innerName)) {
echo("Ignored : " + innerName);
continue;
}
foundClasses.add(innerName);
assertEquals(info.outer_class_info_index, 0,
"outer_class_info_index of " + innerName);
if (innerName.matches("\\$\\d+")) {
assertEquals(info.inner_name_index, 0,
"inner_name_index of anonymous class");
}
}
Set<String> expectedClasses = getInnerClasses();
expectedClasses.remove("InnerClassesIndexTest$Inner");
assertEquals(foundClasses, expectedClasses, "All classes are found");
} catch (Exception e) {
addFailure(e);
} finally {
checkStatus();
}
}
static class Inner {
}
Inner inner1 = new Inner() {
};
static Inner inner2 = new Inner() {
};
Runnable r = () -> {
class Local {
}
new Local() {
};
};
public void local() {
class Local {
}
new Local() {
};
}
public InnerClassesIndexTest() {
class Local {
}
new Local() {
};
}
{
class Local {
}
new Local() {
};
}
static {
class Local {
}
new Local() {
};
}
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8034854 8042251
* @summary Testing inner classes attributes.
* @library /tools/javac/lib ../lib
* @build InnerClassesTestBase TestBase TestResult InMemoryFileManager ToolBox
* @run main InnerClassesTest
*/
import java.util.List;
public class InnerClassesTest extends InnerClassesTestBase {
public static void main(String[] args) throws TestFailedException {
new InnerClassesTest().test("InnerClassesSrc");
}
private List<TestCase> generateClasses() {
setInnerClassType(ClassType.CLASS);
setHasSyntheticClass(true);
return super.generateTestCases();
}
private List<TestCase> generateEnums() {
setInnerOtherModifiers(Modifier.EMPTY, Modifier.STATIC);
setInnerClassType(ClassType.ENUM);
setHasSyntheticClass(false);
return super.generateTestCases();
}
private List<TestCase> generateInterfaces() {
setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
setInnerClassType(ClassType.INTERFACE);
return super.generateTestCases();
}
private List<TestCase> generateAnnotations() {
setInnerOtherModifiers(Modifier.EMPTY, Modifier.ABSTRACT, Modifier.STATIC);
setInnerClassType(ClassType.ANNOTATION);
return super.generateTestCases();
}
@Override
public void setProperties() {
setOuterAccessModifiers(Modifier.EMPTY);
setOuterOtherModifiers(Modifier.EMPTY);
setOuterClassType(ClassType.OTHER);
}
@Override
public List<TestCase> generateTestCases() {
List<TestCase> sources = generateClasses();
sources.addAll(generateEnums());
sources.addAll(generateInterfaces());
sources.addAll(generateAnnotations());
return sources;
}
}

View file

@ -0,0 +1,446 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.InnerClasses_attribute;
import com.sun.tools.classfile.InnerClasses_attribute.Info;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Base class for tests of inner classes attribute.
* The scenario of tests:
* 1. set possible values of class modifiers.
* 2. according to set class modifiers, a test generates sources
* and golden data with {@code generateTestCases}.
* 3. a test loops through all test cases and checks InnerClasses
* attribute with {@code test}.
*
* Example, possible flags for outer class are {@code Modifier.PRIVATE and Modifier.PUBLIC},
* possible flags for inner class are {@code Modifier.EMPTY}.
* At the second step the test generates two test cases:
* 1. public class A {
* public class B {
* class C {}
* }
* }
* 2. public class A {
* private class B {
* class C {}
* }
* }
*/
public abstract class InnerClassesTestBase extends TestResult {
private Modifier[] outerAccessModifiers = {Modifier.EMPTY, Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC};
private Modifier[] outerOtherModifiers = {Modifier.EMPTY, Modifier.STATIC, Modifier.FINAL, Modifier.ABSTRACT};
private Modifier[] innerAccessModifiers = outerAccessModifiers;
private Modifier[] innerOtherModifiers = outerOtherModifiers;
private boolean isForbiddenWithoutStaticInOuterMods = false;
private ClassType outerClassType;
private ClassType innerClassType;
private boolean hasSyntheticClass;
private String prefix = "";
private String suffix = "";
/**
* Sets properties.
*
* Returns generated list of test cases. Method is called in {@code test()}.
*/
public abstract void setProperties();
/**
* Runs the test.
*
* @param classToTest expected name of outer class
* @param skipClasses classes that names should not be checked
*/
public void test(String classToTest, String...skipClasses) throws TestFailedException {
try {
for (TestCase test : generateTestCases()) {
addTestCase(test.getSource());
test(classToTest, test, skipClasses);
}
} catch (Exception e) {
addFailure(e);
} finally {
checkStatus();
}
}
/**
* If {@code flag} is {@code true} an outer class can not have static modifier.
*
* @param flag if {@code true} the outer class can not have static modifier
*/
public void setForbiddenWithoutStaticInOuterMods(boolean flag) {
isForbiddenWithoutStaticInOuterMods = flag;
}
/**
* Sets the possible access flags of an outer class.
*
* @param mods the possible access flags of an outer class
*/
public void setOuterAccessModifiers(Modifier...mods) {
outerAccessModifiers = mods;
}
/**
* Sets the possible flags of an outer class.
*
* @param mods the possible flags of an outer class
*/
public void setOuterOtherModifiers(Modifier...mods) {
outerOtherModifiers = mods;
}
/**
* Sets the possible access flags of an inner class.
*
* @param mods the possible access flags of an inner class
*/
public void setInnerAccessModifiers(Modifier...mods) {
innerAccessModifiers = mods;
}
/**
* Sets the possible flags of an inner class.
*
* @param mods the possible flags of an inner class
*/
public void setInnerOtherModifiers(Modifier...mods) {
innerOtherModifiers = mods;
}
/**
* Sets the suffix for the generated source.
*
* @param suffix a suffix
*/
public void setSuffix(String suffix) {
this.suffix = suffix;
}
/**
* Sets the prefix for the generated source.
*
* @param prefix a prefix
*/
public void setPrefix(String prefix) {
this.prefix = prefix;
}
/**
* If {@code true} synthetic class is generated.
*
* @param hasSyntheticClass if {@code true} synthetic class is generated
*/
public void setHasSyntheticClass(boolean hasSyntheticClass) {
this.hasSyntheticClass = hasSyntheticClass;
}
/**
* Sets the inner class type.
*
* @param innerClassType the inner class type
*/
public void setInnerClassType(ClassType innerClassType) {
this.innerClassType = innerClassType;
}
/**
* Sets the outer class type.
*
* @param outerClassType the outer class type
*/
public void setOuterClassType(ClassType outerClassType) {
this.outerClassType = outerClassType;
}
private void test(String classToTest, TestCase test, String...skipClasses) {
printf("Testing :\n%s\n", test.getSource());
try {
Map<String, Set<String>> class2Flags = test.getFlags();
ClassFile cf = readClassFile(compile(test.getSource())
.getClasses().get(classToTest));
InnerClasses_attribute innerClasses = (InnerClasses_attribute)
cf.getAttribute(Attribute.InnerClasses);
int count = 0;
for (Attribute a : cf.attributes.attrs) {
if (a instanceof InnerClasses_attribute) {
++count;
}
}
assertEquals(1, count, "Number of inner classes attribute");
if (innerClasses == null) {
return;
}
assertEquals(cf.constant_pool.
getUTF8Info(innerClasses.attribute_name_index).value, "InnerClasses",
"innerClasses.attribute_name_index");
// Inner Classes attribute consists of length (2 bytes)
// and 8 bytes for each inner class's entry.
assertEquals(innerClasses.attribute_length,
2 + 8 * class2Flags.size(), "innerClasses.attribute_length");
assertEquals(innerClasses.number_of_classes,
class2Flags.size(), "innerClasses.number_of_classes");
Set<String> visitedClasses = new HashSet<>();
for (Info e : innerClasses.classes) {
String baseName = cf.constant_pool.getClassInfo(
e.inner_class_info_index).getBaseName();
if (cf.major_version >= 51 && e.inner_name_index == 0) {
assertEquals(e.outer_class_info_index, 0,
"outer_class_info_index "
+ "in case of inner_name_index is zero : "
+ baseName);
}
String className = baseName.replaceFirst(".*\\$", "");
assertTrue(class2Flags.containsKey(className),
className);
assertTrue(visitedClasses.add(className),
"there are no duplicates in attribute : " + className);
assertEquals(e.inner_class_access_flags.getInnerClassFlags(),
class2Flags.get(className),
"inner_class_access_flags " + className);
if (!Arrays.asList(skipClasses).contains(className)) {
assertEquals(
cf.constant_pool.getClassInfo(e.inner_class_info_index).getBaseName(),
classToTest + "$" + className,
"inner_class_info_index of " + className);
if (e.outer_class_info_index > 0) {
assertEquals(
cf.constant_pool.getClassInfo(e.outer_class_info_index).getName(),
classToTest,
"outer_class_info_index of " + className);
}
}
}
} catch (Exception e) {
addFailure(e);
}
}
/**
* Methods generates list of test cases. Method generates all possible combinations
* of acceptable flags for nested inner classes.
*
* @return generated list of test cases
*/
protected List<TestCase> generateTestCases() {
setProperties();
List<TestCase> list = new ArrayList<>();
List<List<Modifier>> outerMods = getAllCombinations(outerAccessModifiers, outerOtherModifiers);
List<List<Modifier>> innerMods = getAllCombinations(innerAccessModifiers, innerOtherModifiers);
for (List<Modifier> outerMod : outerMods) {
if (isForbiddenWithoutStaticInOuterMods && !outerMod.contains(Modifier.STATIC)) {
continue;
}
StringBuilder sb = new StringBuilder();
sb.append("public class InnerClassesSrc {")
.append(toString(outerMod)).append(' ')
.append(outerClassType).append(' ')
.append(prefix).append(' ').append('\n');
int count = 0;
Map<String, Set<String>> class2Flags = new HashMap<>();
List<String> syntheticClasses = new ArrayList<>();
for (List<Modifier> innerMod : innerMods) {
++count;
String privateConstructor = "";
if (hasSyntheticClass && !innerMod.contains(Modifier.ABSTRACT)) {
privateConstructor = "private A" + count + "() {}";
syntheticClasses.add("new A" + count + "();");
}
sb.append(toString(innerMod)).append(' ');
sb.append(String.format("%s A%d {%s}\n", innerClassType, count, privateConstructor));
Set<String> flags = getFlags(innerClassType, innerMod);
class2Flags.put("A" + count, flags);
}
if (hasSyntheticClass) {
// Source to generate synthetic classes
sb.append(syntheticClasses.stream().collect(Collectors.joining(" ", "{", "}")));
class2Flags.put("1", new HashSet<>(Arrays.asList("ACC_STATIC", "ACC_SYNTHETIC")));
}
sb.append(suffix).append("\n}");
getAdditionalFlags(class2Flags, outerClassType, outerMod.toArray(new Modifier[outerMod.size()]));
list.add(new TestCase(sb.toString(), class2Flags));
}
return list;
}
/**
* Methods returns flags which must have type.
*
* @param type class, interface, enum or annotation
* @param mods modifiers
* @return set of access flags
*/
protected Set<String> getFlags(ClassType type, List<Modifier> mods) {
Set<String> flags = mods.stream()
.map(Modifier::getString)
.filter(str -> !str.isEmpty())
.map(str -> "ACC_" + str.toUpperCase())
.collect(Collectors.toSet());
type.addSpecificFlags(flags);
return flags;
}
private List<List<Modifier>> getAllCombinations(Modifier[] accessModifiers, Modifier[] otherModifiers) {
List<List<Modifier>> list = new ArrayList<>();
for (Modifier access : accessModifiers) {
for (int i = 0; i < otherModifiers.length; ++i) {
Modifier mod1 = otherModifiers[i];
for (int j = i + 1; j < otherModifiers.length; ++j) {
Modifier mod2 = otherModifiers[j];
if (isForbidden(mod1, mod2)) {
continue;
}
list.add(Arrays.asList(access, mod1, mod2));
}
if (mod1 == Modifier.EMPTY) {
list.add(Arrays.asList(access));
}
}
}
return list;
}
private boolean isForbidden(Modifier mod1, Modifier mod2) {
return mod1 == Modifier.FINAL && mod2 == Modifier.ABSTRACT
|| mod1 == Modifier.ABSTRACT && mod2 == Modifier.FINAL;
}
private String toString(List<Modifier> mods) {
return mods.stream()
.map(Modifier::getString)
.filter(s -> !s.isEmpty())
.collect(Collectors.joining(" "));
}
/**
* Method is called in generateTestCases().
* If you need to add additional access flags, you should override this method.
*
*
* @param class2Flags map with flags
* @param type class, interface, enum or @annotation
* @param mods modifiers
*/
public void getAdditionalFlags(Map<String, Set<String>> class2Flags, ClassType type, Modifier...mods) {
class2Flags.values().forEach(type::addFlags);
}
public enum ClassType {
CLASS("class") {
@Override
public void addSpecificFlags(Set<String> flags) {
}
},
INTERFACE("interface") {
@Override
public void addFlags(Set<String> flags) {
flags.add("ACC_STATIC");
flags.add("ACC_PUBLIC");
}
@Override
public void addSpecificFlags(Set<String> flags) {
flags.add("ACC_INTERFACE");
flags.add("ACC_ABSTRACT");
flags.add("ACC_STATIC");
}
},
ANNOTATION("@interface") {
@Override
public void addFlags(Set<String> flags) {
flags.add("ACC_STATIC");
flags.add("ACC_PUBLIC");
}
@Override
public void addSpecificFlags(Set<String> flags) {
flags.add("ACC_INTERFACE");
flags.add("ACC_ABSTRACT");
flags.add("ACC_STATIC");
flags.add("ACC_ANNOTATION");
}
},
ENUM("enum") {
@Override
public void addSpecificFlags(Set<String> flags) {
flags.add("ACC_ENUM");
flags.add("ACC_FINAL");
flags.add("ACC_STATIC");
}
},
OTHER("") {
@Override
public void addSpecificFlags(Set<String> flags) {
}
};
private final String classType;
private ClassType(String clazz) {
this.classType = clazz;
}
public abstract void addSpecificFlags(Set<String> flags);
public String toString() {
return classType;
}
public void addFlags(Set<String> set) {
}
}
public enum Modifier {
PUBLIC("public"), PRIVATE("private"),
PROTECTED("protected"), DEFAULT("default"),
FINAL("final"), ABSTRACT("abstract"),
STATIC("static"), EMPTY("");
private final String str;
private Modifier(String str) {
this.str = str;
}
public String getString() {
return str;
}
}
}

View file

@ -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);
}
}

View file

@ -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("}");
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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("}");
}
}

View file

@ -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);
}
}

View file

@ -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");
}
}

View file

@ -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

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.Map;
import java.util.Set;
/**
* Class represents test cases. This class contains source code and
* access flags for each inner class in source code.
*/
public class TestCase {
private final String sourceCode;
private final Map<String, Set<String>> class2Flags;
public TestCase(String sourceCode, Map<String, Set<String>> class2Flags) {
this.sourceCode = sourceCode;
this.class2Flags = class2Flags;
}
/**
* Returns source code.
*
* @return source code
*/
public String getSource() {
return sourceCode;
}
/**
* Returns map with entries (ClassName, set of access flags for the ClassName).
*
* @return map with entries (ClassName, set of access flags for the ClassName)
*/
public Map<String, Set<String>> getFlags() {
return class2Flags;
}
}

View file

@ -22,22 +22,23 @@
*/ */
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Stream; import java.util.stream.Collectors;
import javax.tools.DiagnosticCollector; import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler; import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject; import javax.tools.JavaFileObject;
import javax.tools.ToolProvider; import javax.tools.ToolProvider;
import static java.lang.String.format; import com.sun.tools.classfile.ClassFile;
import static java.lang.System.lineSeparator; import com.sun.tools.classfile.ConstantPoolException;
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;
/** /**
* Base class for class file attribute tests. * Base class for class file attribute tests.
@ -46,7 +47,7 @@ import static java.util.stream.Collectors.toList;
*/ */
public class TestBase { public class TestBase {
public static final String LINE_SEPARATOR = lineSeparator(); public static final String LINE_SEPARATOR = System.lineSeparator();
private <S> InMemoryFileManager compile( private <S> InMemoryFileManager compile(
List<String> options, List<String> options,
@ -57,7 +58,7 @@ public class TestBase {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
List<? extends JavaFileObject> src = sources.stream() List<? extends JavaFileObject> src = sources.stream()
.map(src2JavaFileObject) .map(src2JavaFileObject)
.collect(toList()); .collect(Collectors.toList());
DiagnosticCollector<? super JavaFileObject> dc = new DiagnosticCollector<>(); DiagnosticCollector<? super JavaFileObject> dc = new DiagnosticCollector<>();
try (InMemoryFileManager fileManager try (InMemoryFileManager fileManager
@ -67,7 +68,7 @@ public class TestBase {
if (!success) { if (!success) {
String errorMessage = dc.getDiagnostics().stream() String errorMessage = dc.getDiagnostics().stream()
.map(Object::toString) .map(Object::toString)
.collect(joining("\n")); .collect(Collectors.joining("\n"));
throw new CompilationException("Compilation Error\n\n" + errorMessage); throw new CompilationException("Compilation Error\n\n" + errorMessage);
} }
return fileManager; return fileManager;
@ -82,7 +83,7 @@ public class TestBase {
*/ */
public InMemoryFileManager compile(String... sources) public InMemoryFileManager compile(String... sources)
throws IOException, CompilationException { throws IOException, CompilationException {
return compile(emptyList(), sources); return compile(Collections.emptyList(), sources);
} }
/** /**
@ -94,7 +95,7 @@ public class TestBase {
*/ */
public InMemoryFileManager compile(List<String> options, String... sources) public InMemoryFileManager compile(List<String> options, String... sources)
throws IOException, CompilationException { 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 class TestBase {
*/ */
public InMemoryFileManager compile(String[]... sources) throws IOException, public InMemoryFileManager compile(String[]... sources) throws IOException,
CompilationException { CompilationException {
return compile(emptyList(), sources); return compile(Collections.emptyList(), sources);
} }
/** /**
@ -117,12 +118,73 @@ public class TestBase {
*/ */
public InMemoryFileManager compile(List<String> options, String[]... sources) public InMemoryFileManager compile(List<String> options, String[]... sources)
throws IOException, CompilationException { 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) { public void assertEquals(Object actual, Object expected, String message) {
if (!Objects.equals(actual, expected)) 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) { public void assertNull(Object actual, String message) {
@ -169,22 +231,18 @@ public class TestBase {
* @param message string to print. * @param message string to print.
*/ */
public void echo(String message) { 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 template template in standard String.format(...) format.
* @param args arguments to substitute in template. * @param args arguments to substitute in template.
*/ */
public void printf(String template, Object... args) { public void printf(String template, Object... args) {
System.err.printf(template, Stream.of(args) System.err.printf(String.format(template, args).replace("\n", LINE_SEPARATOR));
.map(Objects::toString)
.map(m -> m.replace("\n", LINE_SEPARATOR))
.collect(toList())
.toArray());
} }
public static class CompilationException extends Exception { public static class CompilationException extends Exception {

View file

@ -23,13 +23,15 @@
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.ArrayList; import java.util.*;
import java.util.List; import java.util.stream.Stream;
import java.util.Objects;
import static java.lang.String.format; import static java.lang.String.format;
import static java.util.stream.Collectors.joining; 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 { public class TestResult extends TestBase {
private final List<Info> testCases; private final List<Info> testCases;
@ -39,15 +41,18 @@ public class TestResult extends TestBase {
testCases.add(new Info("Global test info")); 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) return testCases.stream().filter(Info::isFailed)
.map(tc -> format("Failure in test case:\n%s\n%s", tc.info(), .map(tc -> format("Failure in test case:\n%s\n%s", tc.info(), tc.getMessage()))
(tc.asserts.size() > 0 ? tc.getAssertMessage() + "\n" : "")
+ tc.getErrorMessage()))
.collect(joining("\n")); .collect(joining("\n"));
} }
@ -76,8 +81,14 @@ public class TestResult extends TestBase {
getLastTestCase().assertEquals(actual, true, message); 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) { public void addFailure(Throwable th) {
getLastTestCase().addFailure(th); testCases.get(testCases.size() - 1).addFailure(th);
} }
private Info getLastTestCase() { private Info getLastTestCase() {
@ -87,6 +98,13 @@ public class TestResult extends TestBase {
return testCases.get(testCases.size() - 1); 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 { public void checkStatus() throws TestFailedException {
if (testCases.stream().anyMatch(Info::isFailed)) { if (testCases.stream().anyMatch(Info::isFailed)) {
echo(errorMessage()); echo(errorMessage());
@ -120,7 +138,13 @@ public class TestResult extends TestBase {
} }
public void addFailure(String message) { 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); printf("[ASSERT] : %s\n", message);
} }
@ -138,6 +162,10 @@ public class TestResult extends TestBase {
} }
} }
public String getMessage() {
return (asserts.size() > 0 ? getAssertMessage() + "\n" : "") + getErrorMessage();
}
public String getAssertMessage() { public String getAssertMessage() {
return asserts.stream() return asserts.stream()
.map(failure -> "[ASSERT] : " + failure) .map(failure -> "[ASSERT] : " + failure)
@ -146,8 +174,7 @@ public class TestResult extends TestBase {
public String getErrorMessage() { public String getErrorMessage() {
return errors.stream() return errors.stream()
.map(throwable -> .map(throwable -> format("[ERROR] : %s", getStackTrace(throwable)))
format("[ERROR] : %s", getStackTrace(throwable)))
.collect(joining("\n")); .collect(joining("\n"));
} }