/* * Copyright (c) 2012, 2016, 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 8003280 8006694 8129962 * @summary Add lambda tests * Automatic test for checking correctness of structural most specific test routine * temporarily workaround combo tests are causing time out in several platforms * @library /tools/javac/lib * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.code * jdk.compiler/com.sun.tools.javac.comp * jdk.compiler/com.sun.tools.javac.main * jdk.compiler/com.sun.tools.javac.tree * jdk.compiler/com.sun.tools.javac.util * @build combo.ComboTestHelper * @run main StructuralMostSpecificTest */ import javax.lang.model.element.Element; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; import com.sun.tools.javac.api.ClientCodeWrapper; import com.sun.tools.javac.util.JCDiagnostic; import com.sun.tools.javac.util.List; import combo.ComboInstance; import combo.ComboParameter; import combo.ComboTask.Result; import combo.ComboTestHelper; public class StructuralMostSpecificTest extends ComboInstance<StructuralMostSpecificTest> { enum RetTypeKind implements ComboParameter { SHORT("short"), INT("int"), OBJECT("Object"), INTEGER("Integer"), VOID("void"), J_L_VOID("Void"); String retTypeStr; RetTypeKind(String retTypeStr) { this.retTypeStr = retTypeStr; } boolean moreSpecificThan(RetTypeKind rk) { return moreSpecificThan[this.ordinal()][rk.ordinal()]; } static boolean[][] moreSpecificThan = { // SHORT | INT | OBJECT | INTEGER | VOID | J_L_VOID /* SHORT */ { true , true , true , false , false , false }, /* INT */ { false , true , true , true , false , false }, /* OBJECT */ { false , false , true , false , false , false }, /* INTEGER */ { false , false , true , true , false , false }, /* VOID */ { false , false , false , false , true , true }, /* J_L_VOID */{ false , false , true , false , false , true } }; public String expand(String optParameter) { return retTypeStr; } } enum ArgTypeKind implements ComboParameter { SHORT("short"), INT("int"), BOOLEAN("boolean"), OBJECT("Object"), INTEGER("Integer"), DOUBLE("Double"); String argTypeStr; ArgTypeKind(String typeStr) { this.argTypeStr = typeStr; } public String expand(String optParameter) { return argTypeStr; } } enum ExceptionKind implements ComboParameter { NONE(""), EXCEPTION("throws Exception"), SQL_EXCEPTION("throws java.sql.SQLException"), IO_EXCEPTION("throws java.io.IOException"); String exceptionStr; ExceptionKind(String exceptionStr) { this.exceptionStr = exceptionStr; } public String expand(String optParameter) { return exceptionStr; } } enum LambdaReturnKind implements ComboParameter { VOID("return;"), SHORT("return (short)0;"), INT("return 0;"), INTEGER("return (Integer)null;"), NULL("return null;"); String retStr; LambdaReturnKind(String retStr) { this.retStr = retStr; } boolean compatibleWith(RetTypeKind rk) { return compatibleWith[rk.ordinal()][ordinal()]; } static boolean[][] compatibleWith = { // VOID | SHORT | INT | INTEGER | NULL /* SHORT */ { false , true , false , false , false }, /* INT */ { false , true , true , true , false }, /* OBJECT */ { false , true , true , true , true }, /* INTEGER */ { false , false , true , true , true }, /* VOID */ { true , false , false , false , false }, /* J_L_VOID */{ false , false , false , false , true } }; boolean needsConversion(RetTypeKind rk) { return needsConversion[rk.ordinal()][ordinal()]; } static boolean[][] needsConversion = { // VOID | SHORT | INT | INTEGER | NULL /* SHORT */ { false , false , false , false , false }, /* INT */ { false , false , false , true , false }, /* OBJECT */ { false , true , true , false , false }, /* INTEGER */ { false , false , true , false , false }, /* VOID */ { false , false , false , false , false }, /* J_L_VOID */{ true , false , false , false , false } }; public String expand(String optParameter) { return retStr; } } static final String sourceTemplate = "interface SAM1 {\n" + " #{RET[0]} m(#{ARG[0]} a1) #{EX[0]};\n" + "}\n" + "interface SAM2 {\n" + " #{RET[1]} m(#{ARG[1]} a1) #{EX[1]};\n" + "}\n" + "class Test {\n" + " void m(SAM1 s) { }\n" + " void m(SAM2 s) { }\n" + " { m((#{ARG[0]} x)->{ #{EXPR} }); }\n" + "}\n"; public static void main(String... args) throws Exception { new ComboTestHelper<StructuralMostSpecificTest>() .withFilter(StructuralMostSpecificTest::hasSameArguments) .withFilter(StructuralMostSpecificTest::hasCompatibleReturns) .withFilter(StructuralMostSpecificTest::hasSameOverloadPhase) .withDimension("EXPR", (x, expr) -> x.lambdaReturnKind = expr, LambdaReturnKind.values()) .withArrayDimension("RET", (x, ret, idx) -> x.returnType[idx] = ret, 2, RetTypeKind.values()) .withArrayDimension("EX", 2, ExceptionKind.values()) .withArrayDimension("ARG", (x, arg, idx) -> x.argumentKind[idx] = arg, 2, ArgTypeKind.values()) .run(StructuralMostSpecificTest::new); } LambdaReturnKind lambdaReturnKind; RetTypeKind[] returnType = new RetTypeKind[2]; ArgTypeKind[] argumentKind = new ArgTypeKind[2]; boolean hasSameArguments() { return argumentKind[0] == argumentKind[1]; } boolean hasCompatibleReturns() { return lambdaReturnKind.compatibleWith(returnType[0]) && lambdaReturnKind.compatibleWith(returnType[1]); } boolean hasSameOverloadPhase() { return lambdaReturnKind.needsConversion(returnType[0]) == lambdaReturnKind.needsConversion(returnType[1]); } @Override public void doWork() throws Throwable { check(newCompilationTask() .withSourceFromTemplate(sourceTemplate) .withOption("--debug:verboseResolution=all,-predef,-internal,-object-init") .analyze()); } void check(Result<Iterable<? extends Element>> result) { boolean m1MoreSpecific = returnType[0].moreSpecificThan(returnType[1]); boolean m2MoreSpecific = returnType[1].moreSpecificThan(returnType[0]); boolean ambiguous = (m1MoreSpecific == m2MoreSpecific); if (ambiguous != ambiguityFound(result)) { fail("invalid diagnostics for combo:\n" + result.compilationInfo() + "\n" + "\nAmbiguity found: " + ambiguityFound(result) + "\nm1 more specific: " + m1MoreSpecific + "\nm2 more specific: " + m2MoreSpecific + "\nexpected ambiguity: " + ambiguous); } if (!ambiguous) { String sigToCheck = m1MoreSpecific ? "m(SAM1)" : "m(SAM2)"; if (!sigToCheck.equals(mostSpecificSignature(result))) { fail("invalid most specific method selected:\n" + result.compilationInfo() + "\n" + "\nMost specific found: " + mostSpecificSignature(result) + "\nm1 more specific: " + m1MoreSpecific + "\nm2 more specific: " + m2MoreSpecific); } } } boolean ambiguityFound(Result<Iterable<? extends Element>> result) { return result.containsKey("compiler.err.ref.ambiguous"); } String mostSpecificSignature(Result<Iterable<? extends Element>> result) { List<Diagnostic<? extends JavaFileObject>> rsDiag = result.diagnosticsForKey("compiler.note.verbose.resolve.multi"); if (rsDiag.nonEmpty()) { ClientCodeWrapper.DiagnosticSourceUnwrapper dsu = (ClientCodeWrapper.DiagnosticSourceUnwrapper)rsDiag.head; JCDiagnostic.MultilineDiagnostic mdiag = (JCDiagnostic.MultilineDiagnostic)dsu.d; int mostSpecificIndex = (Integer)mdiag.getArgs()[2]; return mdiag.getSubdiagnostics().get(mostSpecificIndex).getArgs()[1].toString(); } else { return null; } } }