mcimadamore@1415: /* vromero@1482: * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. mcimadamore@1415: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. mcimadamore@1415: * mcimadamore@1415: * This code is free software; you can redistribute it and/or modify it mcimadamore@1415: * under the terms of the GNU General Public License version 2 only, as mcimadamore@1415: * published by the Free Software Foundation. mcimadamore@1415: * mcimadamore@1415: * This code is distributed in the hope that it will be useful, but WITHOUT mcimadamore@1415: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or mcimadamore@1415: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License mcimadamore@1415: * version 2 for more details (a copy is included in the LICENSE file that mcimadamore@1415: * accompanied this code). mcimadamore@1415: * mcimadamore@1415: * You should have received a copy of the GNU General Public License version mcimadamore@1415: * 2 along with this work; if not, write to the Free Software Foundation, mcimadamore@1415: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. mcimadamore@1415: * mcimadamore@1415: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA mcimadamore@1415: * or visit www.oracle.com if you need additional information or have any mcimadamore@1415: * questions. mcimadamore@1415: */ mcimadamore@1415: mcimadamore@1415: /* mcimadamore@1415: * @test vromero@1520: * @bug 8003280 8006694 mcimadamore@1415: * @summary Add lambda tests mcimadamore@1415: * Automatic test for checking correctness of structural most specific test routine vromero@1520: * temporarily workaround combo tests are causing time out in several platforms vromero@1482: * @library ../../lib vromero@1482: * @build JavacTestingAbstractThreadedTest vromero@1520: * @run main/othervm/timeout=600 StructuralMostSpecificTest mcimadamore@1415: */ mcimadamore@1415: vromero@1520: // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) vromero@1520: // see JDK-8006746 vromero@1520: vromero@1482: import java.net.URI; vromero@1482: import java.util.Arrays; vromero@1482: import javax.tools.Diagnostic; vromero@1482: import javax.tools.JavaFileObject; vromero@1482: import javax.tools.SimpleJavaFileObject; mcimadamore@1415: import com.sun.source.util.JavacTask; mcimadamore@1415: import com.sun.tools.javac.api.ClientCodeWrapper; mcimadamore@1415: import com.sun.tools.javac.util.JCDiagnostic; mcimadamore@1415: vromero@1482: public class StructuralMostSpecificTest vromero@1482: extends JavacTestingAbstractThreadedTest vromero@1482: implements Runnable { mcimadamore@1415: mcimadamore@1415: enum RetTypeKind { mcimadamore@1415: SHORT("short"), mcimadamore@1415: INT("int"), mcimadamore@1415: OBJECT("Object"), mcimadamore@1415: INTEGER("Integer"), mcimadamore@1415: VOID("void"), mcimadamore@1415: J_L_VOID("Void"); mcimadamore@1415: mcimadamore@1415: String retTypeStr; mcimadamore@1415: mcimadamore@1415: RetTypeKind(String retTypeStr) { mcimadamore@1415: this.retTypeStr = retTypeStr; mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: boolean moreSpecificThan(RetTypeKind rk) { mcimadamore@1415: return moreSpecificThan[this.ordinal()][rk.ordinal()]; mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: static boolean[][] moreSpecificThan = { mcimadamore@1415: // SHORT | INT | OBJECT | INTEGER | VOID | J_L_VOID mcimadamore@1415: /* SHORT */ { true , true , true , false , false , false }, mcimadamore@1415: /* INT */ { false , true , true , true , false , false }, mcimadamore@1415: /* OBJECT */ { false , false , true , false , false , false }, mcimadamore@1415: /* INTEGER */ { false , false , true , true , false , false }, mcimadamore@1415: /* VOID */ { false , false , false , false , true , true }, mcimadamore@1415: /* J_L_VOID */{ false , false , true , false , false , true } }; mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: enum ArgTypeKind { mcimadamore@1415: SHORT("short"), mcimadamore@1415: INT("int"), mcimadamore@1415: BOOLEAN("boolean"), mcimadamore@1415: OBJECT("Object"), mcimadamore@1415: INTEGER("Integer"), mcimadamore@1415: DOUBLE("Double"); mcimadamore@1415: mcimadamore@1415: String argTypeStr; mcimadamore@1415: mcimadamore@1415: ArgTypeKind(String typeStr) { mcimadamore@1415: this.argTypeStr = typeStr; mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: enum ExceptionKind { mcimadamore@1415: NONE(""), mcimadamore@1415: EXCEPTION("throws Exception"), mcimadamore@1415: SQL_EXCEPTION("throws java.sql.SQLException"), mcimadamore@1415: IO_EXCEPTION("throws java.io.IOException"); mcimadamore@1415: mcimadamore@1415: String exceptionStr; mcimadamore@1415: mcimadamore@1415: ExceptionKind(String exceptionStr) { mcimadamore@1415: this.exceptionStr = exceptionStr; mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: enum LambdaReturnKind { mcimadamore@1415: VOID("return;"), mcimadamore@1415: SHORT("return (short)0;"), mcimadamore@1415: INT("return 0;"), vromero@1482: INTEGER("return (Integer)null;"), mcimadamore@1415: NULL("return null;"); mcimadamore@1415: mcimadamore@1415: String retStr; mcimadamore@1415: mcimadamore@1415: LambdaReturnKind(String retStr) { mcimadamore@1415: this.retStr = retStr; mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: boolean compatibleWith(RetTypeKind rk) { mcimadamore@1415: return compatibleWith[rk.ordinal()][ordinal()]; mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: static boolean[][] compatibleWith = { mcimadamore@1415: // VOID | SHORT | INT | INTEGER | NULL mcimadamore@1415: /* SHORT */ { false , true , false , false , false }, mcimadamore@1415: /* INT */ { false , true , true , true , false }, mcimadamore@1415: /* OBJECT */ { false , true , true , true , true }, mcimadamore@1415: /* INTEGER */ { false , false , true , true , true }, mcimadamore@1415: /* VOID */ { true , false , false , false , false }, mcimadamore@1415: /* J_L_VOID */{ false , false , false , false , true } }; mcimadamore@1415: mcimadamore@1415: boolean needsConversion(RetTypeKind rk) { mcimadamore@1415: return needsConversion[rk.ordinal()][ordinal()]; mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: static boolean[][] needsConversion = { mcimadamore@1415: // VOID | SHORT | INT | INTEGER | NULL mcimadamore@1415: /* SHORT */ { false , false , false , false , false }, mcimadamore@1415: /* INT */ { false , false , false , true , false }, mcimadamore@1415: /* OBJECT */ { false , true , true , false , false }, mcimadamore@1415: /* INTEGER */ { false , false , true , false , false }, mcimadamore@1415: /* VOID */ { false , false , false , false , false }, mcimadamore@1415: /* J_L_VOID */{ true , false , false , false , false } }; mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: public static void main(String... args) throws Exception { mcimadamore@1415: for (LambdaReturnKind lrk : LambdaReturnKind.values()) { mcimadamore@1415: for (RetTypeKind rk1 : RetTypeKind.values()) { mcimadamore@1415: for (RetTypeKind rk2 : RetTypeKind.values()) { mcimadamore@1415: for (ExceptionKind ek1 : ExceptionKind.values()) { mcimadamore@1415: for (ExceptionKind ek2 : ExceptionKind.values()) { mcimadamore@1415: for (ArgTypeKind ak11 : ArgTypeKind.values()) { mcimadamore@1415: for (ArgTypeKind ak12 : ArgTypeKind.values()) { vromero@1482: pool.execute( vromero@1482: new StructuralMostSpecificTest(lrk, rk1, vromero@1482: rk2, ek1, ek2, ak11, ak12)); mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: } vromero@1482: vromero@1482: checkAfterExec(); mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: LambdaReturnKind lrk; mcimadamore@1415: RetTypeKind rt1, rt2; mcimadamore@1415: ArgTypeKind ak1, ak2; mcimadamore@1415: ExceptionKind ek1, ek2; mcimadamore@1415: JavaSource source; mcimadamore@1415: DiagnosticChecker diagChecker; mcimadamore@1415: mcimadamore@1415: StructuralMostSpecificTest(LambdaReturnKind lrk, RetTypeKind rt1, RetTypeKind rt2, mcimadamore@1415: ExceptionKind ek1, ExceptionKind ek2, ArgTypeKind ak1, ArgTypeKind ak2) { mcimadamore@1415: this.lrk = lrk; mcimadamore@1415: this.rt1 = rt1; mcimadamore@1415: this.rt2 = rt2; mcimadamore@1415: this.ek1 = ek1; mcimadamore@1415: this.ek2 = ek2; mcimadamore@1415: this.ak1 = ak1; mcimadamore@1415: this.ak2 = ak2; mcimadamore@1415: this.source = new JavaSource(); mcimadamore@1415: this.diagChecker = new DiagnosticChecker(); mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: class JavaSource extends SimpleJavaFileObject { mcimadamore@1415: mcimadamore@1415: String template = "interface SAM1 {\n" + mcimadamore@1415: " #R1 m(#A1 a1) #E1;\n" + mcimadamore@1415: "}\n" + mcimadamore@1415: "interface SAM2 {\n" + mcimadamore@1415: " #R2 m(#A2 a1) #E2;\n" + mcimadamore@1415: "}\n" + mcimadamore@1415: "class Test {\n" + mcimadamore@1415: " void m(SAM1 s) { }\n" + mcimadamore@1415: " void m(SAM2 s) { }\n" + mcimadamore@1415: " { m(x->{ #LR }); }\n" + mcimadamore@1415: "}\n"; mcimadamore@1415: mcimadamore@1415: String source; mcimadamore@1415: mcimadamore@1415: public JavaSource() { mcimadamore@1415: super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); mcimadamore@1415: source = template.replaceAll("#LR", lrk.retStr) mcimadamore@1415: .replaceAll("#R1", rt1.retTypeStr) mcimadamore@1415: .replaceAll("#R2", rt2.retTypeStr) mcimadamore@1415: .replaceAll("#A1", ak1.argTypeStr) mcimadamore@1415: .replaceAll("#A2", ak2.argTypeStr) mcimadamore@1415: .replaceAll("#E1", ek1.exceptionStr) mcimadamore@1415: .replaceAll("#E2", ek2.exceptionStr); mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: @Override mcimadamore@1415: public CharSequence getCharContent(boolean ignoreEncodingErrors) { mcimadamore@1415: return source; mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: vromero@1482: public void run() { vromero@1482: JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker, mcimadamore@1415: Arrays.asList("-XDverboseResolution=all,-predef,-internal,-object-init"), mcimadamore@1415: null, Arrays.asList(source)); mcimadamore@1415: try { mcimadamore@1415: ct.analyze(); mcimadamore@1415: } catch (Throwable ex) { vromero@1482: throw new vromero@1482: AssertionError("Error thron when analyzing the following source:\n" + vromero@1482: source.getCharContent(true)); mcimadamore@1415: } mcimadamore@1415: check(); mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: void check() { vromero@1482: checkCount.incrementAndGet(); mcimadamore@1415: mcimadamore@1415: if (!lrk.compatibleWith(rt1) || !lrk.compatibleWith(rt2)) mcimadamore@1415: return; mcimadamore@1415: mcimadamore@1415: if (lrk.needsConversion(rt1) != lrk.needsConversion(rt2)) mcimadamore@1415: return; mcimadamore@1415: mcimadamore@1415: boolean m1MoreSpecific = moreSpecific(rt1, rt2, ek1, ek2, ak1, ak2); mcimadamore@1415: boolean m2MoreSpecific = moreSpecific(rt2, rt1, ek2, ek1, ak2, ak1); mcimadamore@1415: mcimadamore@1415: boolean ambiguous = (m1MoreSpecific == m2MoreSpecific); mcimadamore@1415: mcimadamore@1415: if (ambiguous != diagChecker.ambiguityFound) { mcimadamore@1415: throw new Error("invalid diagnostics for source:\n" + mcimadamore@1415: source.getCharContent(true) + mcimadamore@1415: "\nAmbiguity found: " + diagChecker.ambiguityFound + mcimadamore@1415: "\nm1 more specific: " + m1MoreSpecific + mcimadamore@1415: "\nm2 more specific: " + m2MoreSpecific + mcimadamore@1415: "\nexpected ambiguity: " + ambiguous); mcimadamore@1415: } mcimadamore@1415: mcimadamore@1415: if (!ambiguous) { mcimadamore@1415: String sigToCheck = m1MoreSpecific ? "m(SAM1)" : "m(SAM2)"; mcimadamore@1415: if (!sigToCheck.equals(diagChecker.mostSpecificSig)) { mcimadamore@1415: throw new Error("invalid most specific method selected:\n" + mcimadamore@1415: source.getCharContent(true) + mcimadamore@1415: "\nMost specific found: " + diagChecker.mostSpecificSig + mcimadamore@1415: "\nm1 more specific: " + m1MoreSpecific + mcimadamore@1415: "\nm2 more specific: " + m2MoreSpecific); mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: vromero@1482: boolean moreSpecific(RetTypeKind rk1, RetTypeKind rk2, ExceptionKind ek1, vromero@1482: ExceptionKind ek2, ArgTypeKind ak1, ArgTypeKind ak2) { mcimadamore@1415: if (!rk1.moreSpecificThan(rk2)) mcimadamore@1415: return false; mcimadamore@1415: mcimadamore@1415: if (ak1 != ak2) mcimadamore@1415: return false; mcimadamore@1415: mcimadamore@1415: return true; mcimadamore@1415: } mcimadamore@1415: vromero@1482: static class DiagnosticChecker vromero@1482: implements javax.tools.DiagnosticListener { mcimadamore@1415: mcimadamore@1415: boolean ambiguityFound; mcimadamore@1415: String mostSpecificSig; mcimadamore@1415: mcimadamore@1415: public void report(Diagnostic diagnostic) { mcimadamore@1415: try { mcimadamore@1415: if (diagnostic.getKind() == Diagnostic.Kind.ERROR && mcimadamore@1415: diagnostic.getCode().equals("compiler.err.ref.ambiguous")) { mcimadamore@1415: ambiguityFound = true; mcimadamore@1415: } else if (diagnostic.getKind() == Diagnostic.Kind.NOTE && vromero@1482: diagnostic.getCode() vromero@1482: .equals("compiler.note.verbose.resolve.multi")) { mcimadamore@1415: ClientCodeWrapper.DiagnosticSourceUnwrapper dsu = vromero@1482: (ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic; vromero@1482: JCDiagnostic.MultilineDiagnostic mdiag = vromero@1482: (JCDiagnostic.MultilineDiagnostic)dsu.d; mcimadamore@1415: int mostSpecificIndex = (Integer)mdiag.getArgs()[2]; vromero@1482: mostSpecificSig = vromero@1482: ((JCDiagnostic)mdiag.getSubdiagnostics() vromero@1482: .get(mostSpecificIndex)).getArgs()[1].toString(); mcimadamore@1415: } mcimadamore@1415: } catch (RuntimeException t) { mcimadamore@1415: t.printStackTrace(); mcimadamore@1415: throw t; mcimadamore@1415: } mcimadamore@1415: } mcimadamore@1415: } vromero@1482: mcimadamore@1415: }