Mercurial > hg > openjdk > lambda > jdk
changeset 5383:b3b65a3d441e lambda-b48
Summary: Added shapegen tests for both javac and separate compilation
line wrap: on
line diff
--- a/test-ng/build.xml Sat Jun 30 15:09:37 2012 -0700 +++ b/test-ng/build.xml Thu Jul 12 13:07:55 2012 -0400 @@ -41,12 +41,13 @@ <jvmarg value="-ea" /> <jvmarg value="-esa" /> <jvmarg value="-Xverify:all" /> + <jvmarg value="-Xmx2g" /> <sysproperty key="lambda.metafactory" value="${lambda.metafactory}" /> </testng> </target> <target name="clean"> - <delete includeEmptyDirs="true" failonerror="true"> + <delete includeEmptyDirs="true" failonerror="false"> <fileset dir="${build.dir}" /> <fileset dir="${generated.dir}" /> </delete>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/tests/org/openjdk/tests/javac/FDTest.java Thu Jul 12 13:07:55 2012 -0400 @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2012, 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. + */ + +package org.openjdk.tests.javac; + +import org.openjdk.tests.shapegen.*; + +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.util.Pair; + +import java.net.URI; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.tools.Diagnostic; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +import org.testng.annotations.Test; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.DataProvider; +import static org.testng.Assert.*; + +public class FDTest { + + public enum TestKind { + POSITIVE, + NEGATIVE; + + Collection<Hierarchy> getHierarchy(HierarchyGenerator hg) { + return this == POSITIVE ? + hg.getOK() : hg.getErr(); + } + } + + public static JavaCompiler comp; + public static StandardJavaFileManager fm; + + @BeforeSuite + static void init() { + // create default shared JavaCompiler - reused across multiple + // compilations + + comp = ToolProvider.getSystemJavaCompiler(); + fm = comp.getStandardFileManager(null, null, null); + } + + public static void main(String[] args) throws Exception { + init(); + + for (Pair<TestKind,Hierarchy> fdtest : generateCases()) { + runTest(fdtest.fst, fdtest.snd, comp, fm); + } + } + + @Test(dataProvider = "fdCases") + public void testOneCase(TestKind tk, Hierarchy hs) + throws Exception { + FDTest.runTest(tk, hs, comp, fm); + } + + @DataProvider(name = "fdCases") + public Object[][] caseGenerator() { + List<Pair<TestKind, Hierarchy>> cases = generateCases(); + Object[][] fdCases = new Object[cases.size()][]; + for (int i = 0; i < cases.size(); ++i) { + fdCases[i] = new Object[2]; + fdCases[i][0] = cases.get(i).fst; + fdCases[i][1] = cases.get(i).snd; + } + return fdCases; + } + + public static List<Pair<TestKind, Hierarchy>> generateCases() { + ArrayList<Pair<TestKind,Hierarchy>> list = new ArrayList<>(); + HierarchyGenerator hg = new HierarchyGenerator(); + for (TestKind tk : TestKind.values()) { + for (Hierarchy hs : tk.getHierarchy(hg)) { + list.add(new Pair<>(tk, hs)); + } + } + return list; + } + + public static void runTest(TestKind tk, Hierarchy hs, + JavaCompiler comp, StandardJavaFileManager fm) throws Exception { + new FDTest(tk, hs).run(comp, fm); + } + + TestKind tk; + Hierarchy hs; + DefenderTestSource source; + DiagnosticChecker diagChecker; + + public FDTest() {} + + FDTest(TestKind tk, Hierarchy hs) { + this.tk = tk; + this.hs = hs; + this.source = new DefenderTestSource(); + this.diagChecker = new DiagnosticChecker(); + } + + void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { + JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, + null, null, Arrays.asList(source)); + try { + ct.analyze(); + } catch (Throwable ex) { + fail("Error thrown when analyzing the following source:\n" + source.getCharContent(true)); + } + check(); + } + + void check() { + boolean errorExpected = tk == TestKind.NEGATIVE; + if (errorExpected != diagChecker.errorFound) { + fail("problem in source: \n" + + "\nerror found = " + diagChecker.errorFound + + "\nerror expected = " + errorExpected + + "\n" + dumpHierarchy() + + "\n" + source.getCharContent(true)); + } + } + + String dumpHierarchy() { + StringBuilder buf = new StringBuilder(); + buf.append("root = " + hs.root + "\n"); + for (ClassCase cc : hs.all) { + buf.append(" class name = " + cc.getName() + "\n"); + buf.append(" class OK = " + cc.get_OK() + "\n"); + buf.append(" prov = " + cc.get_mprov() + "\n"); + + } + return buf.toString(); + } + + class DefenderTestSource extends SimpleJavaFileObject { + + String source; + + public DefenderTestSource() { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + StringBuilder buf = new StringBuilder(); + List<ClassCase> defaultRef = new ArrayList<>(); + for (ClassCase cc : hs.all) { + Hierarchy.genClassDef(buf, cc, null, defaultRef); + } + source = buf.toString(); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } + + static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { + + boolean errorFound; + + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { + errorFound = true; + } + } + } +}
--- a/test-ng/tests/org/openjdk/tests/separate/Compiler.java Sat Jun 30 15:09:37 2012 -0700 +++ b/test-ng/tests/org/openjdk/tests/separate/Compiler.java Thu Jul 12 13:07:55 2012 -0400 @@ -46,7 +46,10 @@ System.getProperty("user.dir") + File.separator + "gen-separate"); private static final File root = new File(targetDir); + private List<File> tempDirs; private boolean verbose; + private JavaCompiler systemJavaCompiler; + private StandardJavaFileManager fm; private static class SourceFile extends SimpleJavaFileObject { private final String content; @@ -65,8 +68,13 @@ public Compiler(boolean verbose) { this.verbose = verbose; + this.tempDirs = new ArrayList<>(); + this.systemJavaCompiler = ToolProvider.getSystemJavaCompiler(); + this.fm = systemJavaCompiler.getStandardFileManager(null, null, null); } + public void setVerbose(boolean v) { this.verbose = v; } + /** * Compile hierarchies starting with each of the 'types' and return * a ClassLoader that can be used to load the compiled classes. @@ -123,11 +131,8 @@ type.generate(accum); - JavaCompiler systemJavaCompiler = ToolProvider.getSystemJavaCompiler(); - StandardJavaFileManager fm = - systemJavaCompiler.getStandardFileManager(null, null, null); - JavacTask ct = (JavacTask)systemJavaCompiler.getTask( - null, fm, null, null, null, files); + JavacTask ct = (JavacTask)this.systemJavaCompiler.getTask( + null, this.fm, null, null, null, files); File destDir = null; do { int value = counter.incrementAndGet(); @@ -144,8 +149,8 @@ try { destDir.mkdirs(); - fm.setLocation(StandardLocation.CLASS_OUTPUT, - Arrays.asList(destDir)); + this.fm.setLocation( + StandardLocation.CLASS_OUTPUT, Arrays.asList(destDir)); } catch (IOException e) { throw new RuntimeException( "IOException encountered during compilation"); @@ -155,6 +160,15 @@ throw new RuntimeException( "Compilation failure in " + type.getName() + " unit"); } + this.tempDirs.add(destDir); return destDir; } + + void cleanup() { + tempDirs.forEach(dir -> { + Arrays.asList(dir.listFiles()).forEach(file -> { file.delete(); }); + dir.delete(); + }); + tempDirs = new ArrayList<>(); + } }
--- a/test-ng/tests/org/openjdk/tests/separate/SourceModel.java Sat Jun 30 15:09:37 2012 -0700 +++ b/test-ng/tests/org/openjdk/tests/separate/SourceModel.java Thu Jul 12 13:07:55 2012 -0400 @@ -120,6 +120,18 @@ public Class getSuperclass() { return null; } protected abstract void setSuperClass(Extends supertype); + public void addSuperType(Extends sup) { + assert sup.getType() instanceof Interface : "Must be an interface"; + this.supertypes.add(sup); + } + public void addSuperType(Interface iface) { + this.supertypes.add(new Extends(iface)); + } + + public void addMethod(Method m) { + this.methods.add(m); + } + // Convenience method for creation. Parameters are interpreted // according to their type. Class (or Extends with a Class type) is // considered a superclass (only one allowed). TypeParameters are @@ -133,16 +145,16 @@ if (ext.supertype instanceof Class) { setSuperClass(ext); } else if (ext.supertype instanceof Interface) { - this.supertypes.add(ext); + addSuperType(ext); } else { assert false : "What is this thing?"; } } else if (p instanceof Interface) { - this.supertypes.add(new Extends((Interface)p)); + addSuperType((Interface)p); } else if (p instanceof TypeParameter) { this.parameters.add((TypeParameter)p); } else if (p instanceof Method) { - this.methods.add((Method)p); + addMethod((Method)p); } else { assert false : "What is this thing?"; } @@ -228,16 +240,19 @@ public static class Class extends Type { private Extends superClass; + private boolean isAbstract; public Class(String name, List<TypeParameter> params, Extends sprClass, List<Extends> interfaces, List<Method> methods) { super(name, params, interfaces, methods); this.superClass = sprClass; + this.isAbstract = false; } public Class(String name, Element ... components) { super(name, null, null, null); this.superClass = null; + this.isAbstract = false; for (Element p : components) { addComponent(p); @@ -245,16 +260,24 @@ } @Override - protected void setSuperClass(Extends ext) { + public void setSuperClass(Extends ext) { assert this.superClass == null : "Multiple superclasses defined"; + assert ext.getType() instanceof Class : "Must be a class"; this.superClass = ext; } + public void setSuperClass(Class c) { + setSuperClass(new Extends(c)); + } + @Override public Class getSuperclass() { return superClass == null ? null : (Class)superClass.supertype; } + public boolean getIsAbstract() { return this.isAbstract; } + public void setIsAbstract(boolean v) { this.isAbstract = v; } + public void generate(SourceProcessor processor) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); @@ -263,7 +286,7 @@ } public void generate(PrintWriter pw) { - pw.print("public class "); + pw.printf("public %sclass ", getIsAbstract() ? "abstract " : ""); generateName(pw); if (superClass != null) { pw.print("extends ");
--- a/test-ng/tests/org/openjdk/tests/separate/TestHarness.java Sat Jun 30 15:09:37 2012 -0700 +++ b/test-ng/tests/org/openjdk/tests/separate/TestHarness.java Thu Jul 12 13:07:55 2012 -0400 @@ -41,9 +41,23 @@ public class TestHarness { + /** + * Creates a per-thread persistent compiler object to allow as much + * sharing as possible, but still allows for parallel execution of tests. + */ + protected ThreadLocal<Compiler> compilerLocal = new ThreadLocal<Compiler>() { + protected synchronized Compiler initialValue() { + return new Compiler(false); + } + }; + protected boolean verbose; public static final String stdMethodName = SourceModel.stdMethodName; + protected TestHarness() { + this.verbose = false; + } + public void debugTest() { this.verbose = true; } @@ -60,9 +74,13 @@ clsName = clsName.substring(clsName.lastIndexOf(".") + 1); System.out.println("Test " + clsName + "." + result.getName() + " FAILED"); - } + } } + private static final ConcreteMethod stdCM = ConcreteMethod.returns("-1"); + private static final PresentMethod stdPM = + new PresentMethod("int", stdMethodName); + /** * Returns a class which has a static method with the same name as * 'method', whose body creates an new instance of 'specimen' and invokes @@ -84,8 +102,13 @@ String params = Arrays.asList(args).into(new StringJoiner(", ")).toString(); - Class iv = new Class("IV", StaticMethod.returns(String.format( - "(new %s()).%s(%s)", specimen.getName(), method.getName(), params))); + StaticMethod sm = new StaticMethod( + method.getReturnType(), method.getName(), + String.format("return (new %s()).%s(%s);", + specimen.getName(), method.getName(), params)); + + Class iv = new Class("IV", sm); + iv.addCompilationDependency(stub); iv.addCompilationDependency(cm); @@ -125,6 +148,9 @@ * Uses 'loader' to load class 'clzz', and calls the static method * 'method'. If the return value does not equal 'value' (or if an * exception is thrown), then a test failure is indicated. + * + * If 'value' is null, then no equality check is performed -- the assertion + * fails only if an exception is thrown. */ protected void assertStaticCallEquals( ClassLoader loader, Class clzz, String method, Object value) { @@ -143,7 +169,9 @@ try { Object res = m.invoke(null); assertNotNull(res); - assertEquals(res, value); + if (value != null) { + assertEquals(res, value); + } } catch (InvocationTargetException | IllegalAccessException e) { fail("Unexpected exception thrown: " + e.getCause()); } @@ -159,11 +187,14 @@ Object value, Class target, ConcreteMethod method, String returns, String ... args) { + Compiler compiler = compilerLocal.get(); + compiler.setVerbose(this.verbose); + Class iv = invokeVirtualHarness(target, method, returns, args); - Compiler compiler = new Compiler(this.verbose); ClassLoader loader = compiler.compile(iv, target); assertStaticCallEquals(loader, iv, method.getName(), value); + compiler.cleanup(); } /** @@ -171,8 +202,8 @@ * a return type of 'int', and no arguments. */ public void assertInvokeVirtualEquals(int value, Class target) { - ConcreteMethod method = ConcreteMethod.returns("-1"); - assertInvokeVirtualEquals(new Integer(value), target, method, "-1"); + assertInvokeVirtualEquals( + new Integer(value), target, stdCM, "-1"); } /** @@ -181,14 +212,17 @@ * then invokes the method. If the returned value does not match * 'value' then a test failure is indicated. */ - public void assertInvokeInterfaceEquals( - Object value, Class target, Extends iface, PresentMethod method, - String ... args) { + public void assertInvokeInterfaceEquals(Object value, Class target, + Extends iface, PresentMethod method, String ... args) { + + Compiler compiler = compilerLocal.get(); + compiler.setVerbose(this.verbose); + Class ii = invokeInterfaceHarness(target, iface, method, args); - Compiler compiler = new Compiler(this.verbose); ClassLoader loader = compiler.compile(ii, target); assertStaticCallEquals(loader, ii, method.getName(), value); + compiler.cleanup(); } /** @@ -197,9 +231,14 @@ */ public void assertInvokeInterfaceEquals( int value, Class target, Interface iface) { - PresentMethod m = new PresentMethod("int", stdMethodName); + + Compiler compiler = compilerLocal.get(); + compiler.setVerbose(this.verbose); + assertInvokeInterfaceEquals( - new Integer(value), target, new Extends(iface), m); + new Integer(value), target, new Extends(iface), stdPM); + + compiler.cleanup(); } /** @@ -211,8 +250,10 @@ public void assertThrows(java.lang.Class<?> exceptionType, Class target, ConcreteMethod method, String returns, String ... args) { + Compiler compiler = compilerLocal.get(); + compiler.setVerbose(this.verbose); + Class iv = invokeVirtualHarness(target, method, returns, args); - Compiler compiler = new Compiler(this.verbose); ClassLoader loader = compiler.compile(iv, target); java.lang.Class<?> cls = null; @@ -236,6 +277,7 @@ } assertEquals(e.getCause().getClass(), exceptionType); } + compiler.cleanup(); } /** @@ -243,7 +285,6 @@ * a return type of 'int', and no arguments. */ public void assertThrows(java.lang.Class<?> exceptionType, Class target) { - ConcreteMethod m = ConcreteMethod.returns("-1"); - assertThrows(exceptionType, target, m, "-1"); + assertThrows(exceptionType, target, stdCM, "-1"); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/tests/org/openjdk/tests/shapegen/ClassCase.java Thu Jul 12 13:07:55 2012 -0400 @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package org.openjdk.tests.shapegen; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * + * @author Robert Field + */ +public class ClassCase { + + public enum Kind { + IVAC (true, "v"), + IPRESENT (true, "p"), + IDEFAULT (true, "d"), + CNONE (false, "n"), + CABSTRACT (false, "a"), + CCONCRETE (false, "c"); + + private final String prefix; + public final boolean isInterface; + + Kind(boolean isInterface, String prefix) { + this.isInterface = isInterface; + this.prefix = prefix; + } + + public String getPrefix() { return prefix; } + } + + public final Kind kind; + private final ClassCase superclass; + private final List<ClassCase> supertypes; + + private String name; + private boolean _OK; + private boolean _HasClassMethod; + private Set<ClassCase> _mprov; + private boolean _IsConcrete; + private boolean _HasDefault; + private ClassCase _mres; + private ClassCase _mdefend; + + private Set<RuleGroup> executed = new HashSet<RuleGroup>(); + + public ClassCase(Kind kind, ClassCase superclass, List<ClassCase> interfaces) { + this.kind = kind; + this.superclass = superclass; + + // Set supertypes from superclass (if any) and interfaces + List<ClassCase> lc; + if (superclass == null) { + lc = interfaces; + } else { + lc = new ArrayList<>(); + lc.add(superclass); + lc.addAll(interfaces); + } + this.supertypes = lc; + } + + public final boolean isInterface() { return kind.isInterface; } + public final boolean isClass() { return !kind.isInterface; } + + public Set<ClassCase> get_mprov() { + exec(RuleGroup.PROVENENCE); + return _mprov; + } + + public void set_mprov(ClassCase cc) { + Set<ClassCase> s = new HashSet<>(); + s.add(cc); + _mprov = s; + } + + public void set_mprov(Set<ClassCase> s) { + _mprov = s; + } + + public ClassCase get_mres() { + exec(RuleGroup.RESOLUTION); + return _mres; + } + + public void set_mres(ClassCase cc) { + _mres = cc; + } + + public ClassCase get_mdefend() { + exec(RuleGroup.DEFENDER); + return _mdefend; + } + + public void set_mdefend(ClassCase cc) { + _mdefend = cc; + } + + public boolean get_HasClassMethod() { + exec(RuleGroup.PROVENENCE); + return _HasClassMethod; + } + + public void set_HasClassMethod(boolean bool) { + _HasClassMethod = bool; + } + + public boolean get_HasDefault() { + exec(RuleGroup.MARKER); + return _HasDefault; + } + + public void set_HasDefault(boolean bool) { + _HasDefault = bool; + } + + public boolean get_IsConcrete() { + exec(RuleGroup.MARKER); + return _IsConcrete; + } + + public void set_IsConcrete(boolean bool) { + _IsConcrete = bool; + } + + public boolean get_OK() { + exec(RuleGroup.CHECKING); + return _OK; + } + + public void set_OK(boolean bool) { + _OK = bool; + } + + public boolean isMethodDefined() { + for (ClassCase cc : supertypes) { + if (cc.isMethodDefined()) { + return true; + } + } + switch (kind) { + case CCONCRETE: + case CABSTRACT: + case IPRESENT: + case IDEFAULT: + return true; + default: + return false; + } + } + + public boolean isAbstract() { + return isMethodDefined() && (get_mres()==null); + } + + public boolean hasSuperclass() { + return superclass != null; + } + + public ClassCase getSuperclass() { + return superclass; + } + + public List<ClassCase> getSupertypes() { + return supertypes; + } + + public List<ClassCase> getInterfaces() { + if (superclass != null) { + if (supertypes.get(0) != superclass) { + throw new AssertionError("superclass missing from supertypes"); + } + return supertypes.subList(1, supertypes.size()); + } else { + return supertypes; + } + } + + public boolean isSubtypeOf(ClassCase cc) { + // S-Refl + if (cc.equals(this)) { + return true; + } + + // S-Def + for (ClassCase sp : getSupertypes()) { + if (cc.equals(sp)) { + return true; + } + } + + // _S-Trans + for (ClassCase sp : getSupertypes()) { + if (sp.isSubtypeOf(cc)) { + return true; + } + } + + return false; + } + + public void init(Map<String, Integer> namingContext) { + if (name != null) { + return; // Already inited + } + + for (ClassCase sup : supertypes) { + sup.init(namingContext); + } + + // Build name + StringBuilder sb = new StringBuilder(); + if (!supertypes.isEmpty()) { + sb.append(isInterface() ? "I" : "C"); + for (ClassCase cc : supertypes) { + sb.append(cc.getName()); + } + sb.append(kind.isInterface ? "i" : "c"); + } + sb.append(kind.prefix); + String pname = sb.toString(); + Integer icnt = namingContext.get(pname); + int cnt = icnt == null ? 0 : icnt; + ++cnt; + namingContext.put(pname, cnt); + if (cnt > 1) { + sb.append(cnt); + } + this.name = sb.toString(); + } + + public boolean isa(Kind... kinds) { + for (Kind k : kinds) { + if (kind == k) { + return true; + } + } + return false; + } + + private void exec(RuleGroup rg ) { + if (!executed.contains(rg)) { + rg.exec(this); + executed.add(rg); + } + } + + public void collectClasses(Set<ClassCase> seen) { + seen.add(this); + for (ClassCase cc : supertypes) { + cc.collectClasses(seen); + } + } + + public String getID() { + if (name == null) { + throw new Error("Access to uninitialized ClassCase"); + } else { + return name; + } + } + + public final String getName() { + if (name == null) { + return "ClassCase uninited@" + hashCode(); + } else { + return name; + } + } + + @Override + public boolean equals(Object obj) { + return obj instanceof ClassCase && getID().equals(((ClassCase)obj).getID()); + } + + @Override + public int hashCode() { + return getID().hashCode(); + } + + @Override + public String toString() { + return getName(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/tests/org/openjdk/tests/shapegen/Hierarchy.java Thu Jul 12 13:07:55 2012 -0400 @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package org.openjdk.tests.shapegen; + +import java.util.ArrayList; +import java.util.List; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.openjdk.tests.shapegen.ClassCase.Kind.*; + +/** + * + * @author Robert Field + */ +public class Hierarchy { + + public final ClassCase root; + public final Set<ClassCase> all; + + public Hierarchy(ClassCase root) { + this.root = root; + root.init(new HashMap<String,Integer>()); + Set<ClassCase> allClasses = new HashSet<>(); + root.collectClasses(allClasses); + this.all = allClasses; + } + + public boolean anyDefaults() { + for (ClassCase cc : all) { + if (cc.kind == IDEFAULT) { + return true; + } + } + return false; + } + + public boolean get_OK() { + return root.get_OK(); + } + + public String testName() { + return root + "Test"; + } + + private static void genInterfaceList(StringBuilder buf, String prefix, List<ClassCase> interfaces) { + if (!interfaces.isEmpty()) { + buf.append(" "); + buf.append(prefix); + buf.append(" "); + buf.append(interfaces.get(0)); + for (int i = 1; i < interfaces.size(); ++i) { + buf.append(", " + interfaces.get(i)); + } + } + } + + public static void genClassDef(StringBuilder buf, ClassCase cc, String implClass, List<ClassCase> defaultRef) { + if (cc.isInterface()) { + buf.append("interface "); + buf.append(cc.getName() + " "); + genInterfaceList(buf, "extends", cc.getInterfaces()); + buf.append(" {\n"); + + switch (cc.kind) { + case IDEFAULT: + buf.append(" String m() default { return \"\"; }\n"); + defaultRef.add(cc); + break; + case IPRESENT: + buf.append(" String m();\n"); + break; + case IVAC: + break; + default: + throw new AssertionError("Unexpected kind"); + } + buf.append("}\n\n"); + } else { + buf.append((cc.isAbstract()? "abstract " : "")); + buf.append(" class " + cc.getName()); + if (cc.getSuperclass() != null) { + buf.append(" extends " + cc.getSuperclass()); + } + + genInterfaceList(buf, "implements", cc.getInterfaces()); + buf.append(" {\n"); + + switch (cc.kind) { + case CCONCRETE: + buf.append(" public String m() { return \"\"; }\n"); + break; + case CABSTRACT: + buf.append(" public abstract String m();\n"); + break; + case CNONE: + break; + default: + throw new AssertionError("Unexpected kind"); + } + buf.append("}\n\n"); + } + } + + @Override + public boolean equals(Object obj) { + return obj instanceof Hierarchy && root.getID().equals(((Hierarchy)obj).root.getID()); + } + + @Override + public int hashCode() { + return root.getID().hashCode(); + } + + @Override + public String toString() { + return root.getName(); + } + + private static String classNames[] = { + "C", "D", "E", "F", "G", "H", "S", "T", "U", "V" + }; + + private static String interfaceNames[] = { + "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R" + }; + + private static int CLASS_INDEX = 0; + private static int INTERFACE_INDEX = 1; + private static int NUM_INDICIES = 2; + + public List<String> getDescription() { + Map<ClassCase,String> nameMap = new HashMap<>(); + assignNames(root, new int[NUM_INDICIES], nameMap); + + ArrayList<String> res = new ArrayList<>(); + if (root.getSupertypes().size() == 0) { + res.add(nameMap.get(root) + root.kind.getPrefix() + "()"); + } else { + genCaseDescription(root, res, new HashSet<ClassCase>(), nameMap); + } + return res; + } + + private static void assignNames( + ClassCase cc, int indices[], Map<ClassCase,String> names) { + String name = names.get(cc); + if (name == null) { + if (cc.isInterface()) { + names.put(cc, interfaceNames[indices[INTERFACE_INDEX]++]); + } else { + names.put(cc, classNames[indices[CLASS_INDEX]++]); + } + for (int i = 0; i < cc.getSupertypes().size(); ++i) { + assignNames(cc.getSupertypes().get(i), indices, names); + } + } + } + + private static void genCaseDescription( + ClassCase cc, List<String> res, Set<ClassCase> alreadyDone, + Map<ClassCase,String> nameMap) { + if (!alreadyDone.contains(cc)) { + if (cc.getSupertypes().size() > 0) { + StringBuilder sb = new StringBuilder(); + sb.append(nameMap.get(cc)); + sb.append(cc.kind.getPrefix()); + sb.append("("); + for (int i = 0; i < cc.getSupertypes().size(); ++i) { + ClassCase supertype = cc.getSupertypes().get(i); + if (i != 0) { + sb.append(","); + } + genCaseDescription(supertype, res, alreadyDone, nameMap); + sb.append(nameMap.get(supertype)); + sb.append(supertype.kind.getPrefix()); + } + sb.append(")"); + res.add(sb.toString()); + } + } + alreadyDone.add(cc); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/tests/org/openjdk/tests/shapegen/HierarchyGenerator.java Thu Jul 12 13:07:55 2012 -0400 @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package org.openjdk.tests.shapegen; + +import org.openjdk.tests.shapegen.ClassCase.Kind; + +import java.util.Collection; +import java.util.Set; +import java.util.HashSet; +import java.util.Collections; +import java.util.ArrayList; +import java.util.List; + +import static org.openjdk.tests.shapegen.ClassCase.Kind.*; + +import static java.lang.Math.pow; + +/** + * + * @author Robert Field + */ +public final class HierarchyGenerator { + + private int okcnt = 0; + private int errcnt = 0; + private Set<Hierarchy> uniqueOK = new HashSet<>(); + private Set<Hierarchy> uniqueErr = new HashSet<>(); + + /** + * @param args the command line arguments + */ + public HierarchyGenerator() { + organize("exhaustive interface", iExhaustive(2)); + organize("exhaustive class", cExhaustive()); + organize("shapes interface", iShapes()); + organize("shapes class/interface", ciShapes()); + + System.out.printf("\nExpect OK: %d -- unique %d", okcnt, uniqueOK.size()); + System.out.printf("\nExpect Error: %d -- unique %d\n", errcnt, uniqueErr.size()); + } + + public Collection<Hierarchy> getOK() { + return uniqueOK; + } + + public Collection<Hierarchy> getErr() { + return uniqueErr; + } + + private void organize(String tname, List<Hierarchy> totest) { + System.out.printf("\nGenerating %s....\n", tname); + int nodefault = 0; + List<Hierarchy> ok = new ArrayList<>(); + List<Hierarchy> err = new ArrayList<>(); + for (Hierarchy cc : totest) { + if (cc.anyDefaults()) { + //System.out.printf(" %s\n", cc); + if (cc.get_OK()) { + ok.add(cc); + } else { + err.add(cc); + } + } else { + ++nodefault; + } + } + + errcnt += err.size(); + okcnt += ok.size(); + uniqueErr.addAll(err); + uniqueOK.addAll(ok); + + System.out.printf(" %5d No default\n %5d Error\n %5d OK\n %5d Total\n", + nodefault, err.size(), ok.size(), totest.size()); + } + + public List<Hierarchy> iExhaustive(int idepth) { + List<ClassCase> current = new ArrayList<>(); + for (int i = 0; i < idepth; ++i) { + current = ilayer(current); + } + return wrapInClassAndHierarchy(current); + } + + private List<ClassCase> ilayer(List<ClassCase> srcLayer) { + List<ClassCase> lay = new ArrayList<>(); + for (int i = (int) pow(2, srcLayer.size()) - 1; i >= 0; --i) { + List<ClassCase> itfs = new ArrayList<>(); + for (int b = srcLayer.size() - 1; b >= 0; --b) { + if ((i & (1<<b)) != 0) { + itfs.add(srcLayer.get(b)); + } + } + lay.add(new ClassCase(IVAC, null, itfs)); + lay.add(new ClassCase(IPRESENT, null, itfs)); + lay.add(new ClassCase(IDEFAULT, null, itfs)); + lay.add(new ClassCase(IDEFAULT, null, itfs)); + } + return lay; + } + + public List<Hierarchy> cExhaustive() { + final Kind[] iKinds = new Kind[]{IDEFAULT, IVAC, IPRESENT, null}; + final Kind[] cKinds = new Kind[]{CNONE, CABSTRACT, CCONCRETE}; + List<Hierarchy> totest = new ArrayList<>(); + for (int i1 = 0; i1 < iKinds.length; ++i1) { + for (int i2 = 0; i2 < iKinds.length; ++i2) { + for (int i3 = 0; i3 < iKinds.length; ++i3) { + for (int c1 = 0; c1 < cKinds.length; ++c1) { + for (int c2 = 0; c2 < cKinds.length; ++c2) { + for (int c3 = 0; c3 < cKinds.length; ++c3) { + totest.add( new Hierarchy( + new ClassCase(cKinds[c1], + new ClassCase(cKinds[c2], + new ClassCase(cKinds[c3], + null, + iList(iKinds[i1]) + ), + iList(iKinds[i2]) + ), + iList(iKinds[i3]) + ))); + } + } + } + } + } + } + return totest; + } + + public static final List<ClassCase> EMPTY_LIST = new ArrayList<>(); + + private List<ClassCase> iList(Kind kind) { + if (kind == null) { + return EMPTY_LIST; + } else { + List<ClassCase> itfs = new ArrayList<>(); + itfs.add(new ClassCase(kind, null, EMPTY_LIST)); + return itfs; + } + } + + public List<Hierarchy> ciShapes() { + return wrapInHierarchy(TTShape.allCases(true)); + } + + public List<Hierarchy> iShapes() { + return wrapInClassAndHierarchy(TTShape.allCases(false)); + } + + public List<Hierarchy> wrapInClassAndHierarchy(List<ClassCase> ihs) { + List<Hierarchy> totest = new ArrayList<>(); + for (ClassCase cc : ihs) { + List<ClassCase> interfaces = new ArrayList<>(); + interfaces.add(cc); + totest.add(new Hierarchy(new ClassCase(CNONE, null, interfaces))); + } + return totest; + } + + public List<Hierarchy> wrapInHierarchy(List<ClassCase> ihs) { + List<Hierarchy> totest = new ArrayList<>(); + for (ClassCase cc : ihs) { + totest.add(new Hierarchy(cc)); + } + return totest; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/tests/org/openjdk/tests/shapegen/Rule.java Thu Jul 12 13:07:55 2012 -0400 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package org.openjdk.tests.shapegen; + +/** + * + * @author Robert Field + */ +public abstract class Rule { + + public final String name; + + public Rule(String name) { + this.name = name; + } + + abstract boolean guard(ClassCase cc); + + abstract void eval(ClassCase cc); + + @Override + public String toString() { + return name; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/tests/org/openjdk/tests/shapegen/RuleGroup.java Thu Jul 12 13:07:55 2012 -0400 @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package org.openjdk.tests.shapegen; + +import java.util.HashSet; +import java.util.Set; + +import static org.openjdk.tests.shapegen.ClassCase.Kind.*; + +/** + * + * @author Robert Field + */ +public class RuleGroup { + + final String name; + private final Rule[] rules; + + public RuleGroup(String name, Rule[] rules) { + this.name = name; + this.rules = rules; + } + + public boolean exec(ClassCase cc) { + boolean found = false; + for (Rule rule : rules) { + if (rule.guard(cc)) { + if (found) { + throw new RuntimeException("Bad rules -- multiple matches " + toString() + " for " + cc); + } else { + rule.eval(cc); + found = true; + } + } + } + return found; + } + + @Override + public String toString() { + return name; + } + + public static RuleGroup PROVENENCE = new RuleGroup("Provenence", new Rule[] { + new Rule("P-CDeclare") { + boolean guard(ClassCase cc) { + return cc.isa(CCONCRETE, CABSTRACT); + } + + void eval(ClassCase cc) { + cc.set_mprov(cc); + cc.set_HasClassMethod(true); + } + }, + + new Rule("P-IDeclare") { + boolean guard(ClassCase cc) { + return cc.isa(IDEFAULT, IPRESENT); + } + + void eval(ClassCase cc) { + cc.set_mprov(cc); + } + }, + + new Rule("P-IntfInh") { + boolean guard(ClassCase cc) { + return cc.isa(IVAC, CNONE) && !(cc.hasSuperclass() && cc.getSuperclass().get_HasClassMethod()); + } + + void eval(ClassCase cc) { + Set<ClassCase> _S = new HashSet<>(); + for (ClassCase t : cc.getSupertypes()) { + _S.addAll(t.get_mprov()); + } + Set<ClassCase> tops = new HashSet<>(); + for (ClassCase _W : _S) { + for (ClassCase _V : _S) { + if (_V.equals(_W) || !(_V.isSubtypeOf(_W))) { + tops.add(_W); + } + } + } + cc.set_mprov(tops); + } + }, + + new Rule("P-ClassInh") { + boolean guard(ClassCase cc) { + return cc.isa(CNONE) && (cc.hasSuperclass() && cc.getSuperclass().get_HasClassMethod()); + } + + void eval(ClassCase cc) { + cc.set_mprov(cc.getSuperclass()); + cc.set_HasClassMethod(true); + } + }, + + }); + + public static RuleGroup MARKER = new RuleGroup("Marker", new Rule[] { + new Rule("M-Default") { + boolean guard(ClassCase cc) { + return cc.isa(IDEFAULT); + } + + void eval(ClassCase cc) { + cc.set_HasDefault(true); + } + }, + + new Rule("M-Conc") { + boolean guard(ClassCase cc) { + return cc.isa(CCONCRETE); + } + + void eval(ClassCase cc) { + cc.set_IsConcrete(true); + } + }, + + }); + + public static RuleGroup RESOLUTION = new RuleGroup("Resolution", new Rule[] { + new Rule("R-Resolve") { + boolean guard(ClassCase cc) { + if (!(cc.isClass() && cc.get_mprov().size() == 1)) { + return false; + } + ClassCase _V = cc.get_mprov().iterator().next(); + return _V.get_IsConcrete() || _V.get_HasDefault(); + } + + void eval(ClassCase cc) { + ClassCase _V = cc.get_mprov().iterator().next(); + cc.set_mres(_V); + } + }, + + }); + + public static RuleGroup DEFENDER = new RuleGroup("Defender", new Rule[] { + new Rule("D-Defend") { + boolean guard(ClassCase cc) { + ClassCase mresSuper = cc.hasSuperclass() ? cc.getSuperclass().get_mres() : null; + boolean eq = cc.get_mres() == null ? mresSuper == null : cc.get_mres().equals(mresSuper); + return cc.isa(CNONE) && !eq; + } + + void eval(ClassCase cc) { + cc.set_mdefend(cc.get_mres()); + } + }, + + }); + + public static RuleGroup CHECKING = new RuleGroup("Checking", new Rule[] { + new Rule("C-Check") { + boolean guard(ClassCase cc) { + for (ClassCase t : cc.getSupertypes()) { + if (! t.get_OK()) { + return false; + } + } + int defenderCount = 0; + int provCount = 0; + for (ClassCase prov : cc.get_mprov()) { + if (prov.get_HasDefault()) { + defenderCount++; + } + provCount++; + } + return provCount <= 1 || defenderCount == 0; + } + + void eval(ClassCase cc) { + cc.set_OK(true); + } + }, + + }); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/tests/org/openjdk/tests/shapegen/TTNode.java Thu Jul 12 13:07:55 2012 -0400 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package org.openjdk.tests.shapegen; + +import org.openjdk.tests.shapegen.ClassCase.Kind; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static org.openjdk.tests.shapegen.ClassCase.Kind.*; + +/** + * Type Template Node + * + * @author Robert Field + */ +public class TTNode { + + final List<TTNode> supertypes; + final boolean canBeClass; + + private int currentKindIndex; + private Kind[] kinds; + + public TTNode(List<TTNode> subtypes, boolean canBeClass) { + this.supertypes = subtypes; + this.canBeClass = canBeClass; + } + + public void start(boolean includeClasses) { + kinds = + supertypes.isEmpty()? + (new Kind[]{IDEFAULT, IPRESENT}) + : ((includeClasses && canBeClass)? + new Kind[]{CNONE, IVAC, IDEFAULT, IPRESENT} + : new Kind[]{IVAC, IDEFAULT, IPRESENT}); + currentKindIndex = 0; + + for (TTNode sub : supertypes) { + sub.start(includeClasses); + } + } + + public boolean next() { + ++currentKindIndex; + if (currentKindIndex >= kinds.length) { + currentKindIndex = 0; + return false; + } else { + return true; + } + } + + public void collectAllSubtypes(Set<TTNode> subs) { + subs.add(this); + for (TTNode n : supertypes) { + n.collectAllSubtypes(subs); + } + } + + private Kind getKind() { + return kinds[currentKindIndex]; + } + + boolean isInterface() { + return getKind().isInterface; + } + + boolean isClass() { + return !isInterface(); + } + + boolean hasDefault() { + return getKind() == IDEFAULT; + } + + public boolean isValid() { + for (TTNode n : supertypes) { + if (!n.isValid() || (isInterface() && n.isClass())) { + return false; + } + } + return true; + } + + public ClassCase genCase() { + ClassCase subclass; + List<TTNode> ttintfs; + if (isClass() && !supertypes.isEmpty() && supertypes.get(0).isClass()) { + subclass = supertypes.get(0).genCase(); + ttintfs = supertypes.subList(1, supertypes.size()); + } else { + subclass = null; + ttintfs = supertypes; + } + List<ClassCase> intfs = new ArrayList<>(); + for (TTNode node : ttintfs) { + intfs.add(node.genCase()); + } + return new ClassCase(getKind(), subclass, intfs); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/tests/org/openjdk/tests/shapegen/TTParser.java Thu Jul 12 13:07:55 2012 -0400 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package org.openjdk.tests.shapegen; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.io.IOException; +import java.io.StringReader; + +import static java.lang.Character.isLetter; +import static java.lang.Character.isUpperCase; +import static java.lang.Character.isWhitespace; + +/** + * Parse a type template definition string + * + * input :: classDef + * classDef :: letter [ ( classDef* ) ] + * + * @author Robert Field + */ +public class TTParser extends StringReader { + + private Map<Character, TTNode> letterMap = new HashMap<>(); + private char ch; + + private final String def; + + public TTParser(String s) { + super(s); + this.def = s; + } + + private void advance() throws IOException { + do { + ch = (char)read(); + } while (isWhitespace(ch)); + } + + public TTNode parse() { + try { + advance(); + return classDef(); + } catch (IOException t) { + throw new RuntimeException(t); + } + } + + private TTNode classDef() throws IOException { + if (!isLetter(ch)) { + if (ch == (char)-1) { + throw new IOException("Unexpected end of type template in " + def); + } else { + throw new IOException("Unexpected character in type template: " + (Character)ch + " in " + def); + } + } + char nodeCh = ch; + TTNode node = letterMap.get(nodeCh); + boolean canBeClass = isUpperCase(nodeCh); + advance(); + if (node == null) { + List<TTNode> subtypes = new ArrayList<>(); + if (ch == '(') { + advance(); + while (ch != ')') { + subtypes.add(classDef()); + } + advance(); + } + node = new TTNode(subtypes, canBeClass); + letterMap.put(nodeCh, node); + } + return node; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/tests/org/openjdk/tests/shapegen/TTShape.java Thu Jul 12 13:07:55 2012 -0400 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2012, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package org.openjdk.tests.shapegen; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * + * @author Robert Field + */ +public class TTShape { + + private final TTNode root; + private final TTNode[] nodes; + + TTShape(TTNode root) { + this.root = root; + Set<TTNode> subs = new HashSet<>(); + root.collectAllSubtypes(subs); + nodes = subs.toArray(new TTNode[subs.size()]); + } + + private List<ClassCase> toCases(boolean includeClasses) { + List<ClassCase> ccs = new ArrayList<>(); + root.start(includeClasses); + int i; + outer: + while (true) { + if (root.isValid()) { + ClassCase cc = root.genCase(); + //System.out.println(cc); + ccs.add(cc); + } + + i = 0; + do { + if (i >= nodes.length) { + break outer; + } + } while(!nodes[i++].next()); + } + return ccs; + } + + public static List<ClassCase> allCases(boolean includeClasses) { + List<ClassCase> ccs = new ArrayList<>(); + for (TTShape shape : SHAPES) { + ccs.addAll(shape.toCases(includeClasses)); + } + return ccs; + } + + public static TTShape parse(String s) { + return new TTShape(new TTParser(s).parse()); + } + + public static final TTShape[] SHAPES = new TTShape[] { + parse("a"), + parse("a(b)"), + parse("A(bb)"), + parse("A(B(d)c(d))"), + parse("A(b(c))"), + parse("A(B(cd)d)"), + parse("A(B(c)c)"), + parse("A(B(Ce)d(e))"), + parse("A(B(C)d(e))"), + parse("A(Bc(d))"), + parse("A(B(d)dc)"), + parse("A(B(dc)dc)"), + parse("A(B(c(d))d)"), + parse("A(B(C(d))d)"), + parse("A(B(C(e)d(e))e)"), + parse("A(B(c(d))c)"), + parse("A(B(dc(d))c)"), + parse("A(B(C(d))d)"), + }; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-ng/tests/org/openjdk/tests/vm/FDSeparateCompilationTest.java Thu Jul 12 13:07:55 2012 -0400 @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2012 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package org.openjdk.tests.vm; + +import java.lang.reflect.*; +import java.util.*; +import java.io.File; +import java.io.IOException; + +import org.testng.ITestResult; +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; +import org.testng.annotations.AfterMethod; + +import org.openjdk.tests.separate.*; +import org.openjdk.tests.separate.Compiler; + +import org.openjdk.tests.shapegen.Hierarchy; +import org.openjdk.tests.shapegen.HierarchyGenerator; +import org.openjdk.tests.shapegen.ClassCase; + +import static org.testng.Assert.*; +import static org.openjdk.tests.separate.SourceModel.*; +import static org.openjdk.tests.separate.SourceModel.Class; +import static org.openjdk.tests.separate.SourceModel.Method; +import static org.openjdk.tests.separate.SourceModel.Type; + +public class FDSeparateCompilationTest extends TestHarness { + + private static String EMPTY = "\"\""; + + @DataProvider(name = "allShapes", parallel = true) + public Object[][] hierarchyGenerator() { + ArrayList<Object[]> allCases = new ArrayList<>(); + + HierarchyGenerator hg = new HierarchyGenerator(); + hg.getOK().map(x -> new Object[] { x }).into(allCases); + hg.getErr().map(x -> new Object[] { x }).into(allCases); + return allCases.toArray(new Object[0][]); + } + + // The expected value obtained when invoking the method from the specified + // class. If returns null, then an AbstractMethodError is expected. + private static String getExpectedResult(ClassCase cc) { + Set<ClassCase> provs = cc.get_mprov(); + if (cc.get_mres() != null) { + return cc.get_mres().getName(); + } else if (provs != null && provs.size() == 1) { + ClassCase cand = provs.getOnly(); + switch (cand.kind) { + case CCONCRETE: + case IDEFAULT: + return cand.getName(); + case CNONE: + case IVAC: + return getExpectedResult(cand); + } + } + return null; + } + + private static final ConcreteMethod canonicalMethod = new ConcreteMethod( + "String", "m", "returns " + EMPTY + ";"); + + @Test(groups = "vm", dataProvider = "allShapes") + public void separateCompilationTest(Hierarchy hs) { + ClassCase cc = hs.root; + Type type = sourceTypeFrom(hs.root); + + Class specimen = null; + if (type instanceof Class) { + Class ctype = (Class)type; + if (ctype.getIsAbstract()) { + specimen = new Class("S", ctype); + } else { + specimen = ctype; + } + } else { + specimen = new Class("S", (Interface)type); + } + + String value = getExpectedResult(cc); + if (value != null) { + assertInvokeVirtualEquals(value, specimen, canonicalMethod, EMPTY); + } else { + assertThrows(AbstractMethodError.class, specimen, + canonicalMethod, EMPTY); + } + } + + @AfterMethod + public void printCaseError(ITestResult result) { + if (result.getStatus() == ITestResult.FAILURE) { + Hierarchy hs = (Hierarchy)result.getParameters()[0]; + System.out.println("Separate compilation case " + hs); + printCaseDetails(hs); + } + } + + private void printCaseDetails(Hierarchy hs) { + String exp = getExpectedResult(hs.root); + hs.getDescription().forEach( + x -> { System.out.println(" " + x); }); + if (exp != null) { + System.out.println(" Expected \"" + exp + "\""); + } else { + System.out.println(" Expected AbstractMethodError"); + } + } + + private Type sourceTypeFrom(ClassCase cc) { + Type type = null; + + if (cc.isInterface()) { + Interface iface = new Interface(cc.getName()); + for (ClassCase scc : cc.getInterfaces()) { + Interface supertype = (Interface)sourceTypeFrom(scc); + iface.addSuperType(supertype); + } + type = iface; + } else { + Class cls = new Class(cc.getName()); + if (cc.hasSuperclass()) { + Class superc = (Class)sourceTypeFrom(cc.getSuperclass()); + cls.setSuperClass(superc); + } + for (ClassCase scc : cc.getInterfaces()) { + Interface supertype = (Interface)sourceTypeFrom(scc); + cls.addSuperType(supertype); + } + if (cc.isAbstract()) { + cls.setIsAbstract(true); + } + type = cls; + } + Method method = methodFrom(cc); + if (method != null) { + type.addMethod(method); + } + return type; + } + + private Method methodFrom(ClassCase cc) { + switch (cc.kind) { + case IVAC: + case CNONE: return null; + case IPRESENT: + return new PresentMethod("String", "m"); + case IDEFAULT: + return new DefaultMethod( + "String", "m", "return \"" + cc.getName() + "\";"); + case CABSTRACT: + return new AbstractMethod("String", "m"); + case CCONCRETE: + return new ConcreteMethod( + "String", "m", "return \"" + cc.getName() + "\";"); + default: + fail("Unknown method type in class"); + return null; + } + } +}