| /* |
| * Copyright (c) 2012, 2015, 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 8004102 8006694 8129962 |
| * @summary Add lambda tests |
| * perform several automated checks in lambda conversion, esp. around accessibility |
| * 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 FunctionalInterfaceConversionTest |
| */ |
| |
| import java.io.IOException; |
| |
| import combo.ComboInstance; |
| import combo.ComboParameter; |
| import combo.ComboTask.Result; |
| import combo.ComboTestHelper; |
| |
| |
| public class FunctionalInterfaceConversionTest extends ComboInstance<FunctionalInterfaceConversionTest> { |
| |
| enum PackageKind implements ComboParameter { |
| NO_PKG(""), |
| PKG_A("a"); |
| |
| String pkg; |
| |
| PackageKind(String pkg) { |
| this.pkg = pkg; |
| } |
| |
| @Override |
| public String expand(String optParameter) { |
| return this == NO_PKG ? |
| "" : |
| "package " + pkg + ";"; |
| } |
| |
| String getImportStat() { |
| return this == NO_PKG ? |
| "" : |
| "import " + pkg + ".*;"; |
| } |
| } |
| |
| enum SamKind implements ComboParameter { |
| CLASS("public class Sam { }"), |
| ABSTACT_CLASS("public abstract class Sam { }"), |
| ANNOTATION("public @interface Sam { }"), |
| ENUM("public enum Sam { }"), |
| INTERFACE("public interface Sam { \n #{METH1}; \n }"); |
| |
| String sam_str; |
| |
| SamKind(String sam_str) { |
| this.sam_str = sam_str; |
| } |
| |
| @Override |
| public String expand(String optParameter) { |
| return sam_str; |
| } |
| } |
| |
| enum ModifierKind implements ComboParameter { |
| PUBLIC("public"), |
| PACKAGE(""); |
| |
| String modifier_str; |
| |
| ModifierKind(String modifier_str) { |
| this.modifier_str = modifier_str; |
| } |
| |
| @Override |
| public String expand(String optParameter) { |
| return modifier_str; |
| } |
| } |
| |
| enum TypeKind implements ComboParameter { |
| EXCEPTION("Exception"), |
| PKG_CLASS("PackageClass"); |
| |
| String typeStr; |
| |
| TypeKind(String typeStr) { |
| this.typeStr = typeStr; |
| } |
| |
| @Override |
| public String expand(String optParameter) { |
| return typeStr; |
| } |
| } |
| |
| enum ExprKind implements ComboParameter { |
| LAMBDA("x -> null"), |
| MREF("this::m"); |
| |
| String exprStr; |
| |
| ExprKind(String exprStr) { |
| this.exprStr = exprStr; |
| } |
| |
| @Override |
| public String expand(String optParameter) { |
| return exprStr; |
| } |
| } |
| |
| enum MethodKind implements ComboParameter { |
| NONE(""), |
| NON_GENERIC("public abstract #{RET} m(#{ARG} s) throws #{THROWN};"), |
| GENERIC("public abstract <X> #{RET} m(#{ARG} s) throws #{THROWN};"); |
| |
| String methodTemplate; |
| |
| MethodKind(String methodTemplate) { |
| this.methodTemplate = methodTemplate; |
| } |
| |
| @Override |
| public String expand(String optParameter) { |
| return methodTemplate; |
| } |
| } |
| |
| public static void main(String[] args) throws Exception { |
| new ComboTestHelper<FunctionalInterfaceConversionTest>() |
| .withDimension("PKG", (x, pkg) -> x.samPkg = pkg, PackageKind.values()) |
| .withDimension("MOD", (x, mod) -> x.modKind = mod, ModifierKind.values()) |
| .withDimension("CLAZZ", (x, sam) -> x.samKind = sam, SamKind.values()) |
| .withDimension("METH1", (x, meth) -> x.samMeth = meth, MethodKind.values()) |
| .withDimension("METH2", (x, meth) -> x.clientMeth = meth, MethodKind.values()) |
| .withDimension("RET", (x, ret) -> x.retType = ret, TypeKind.values()) |
| .withDimension("ARG", (x, arg) -> x.argType = arg, TypeKind.values()) |
| .withDimension("THROWN", (x, thrown) -> x.thrownType = thrown, TypeKind.values()) |
| .withDimension("EXPR", (x, expr) -> x.exprKind = expr, ExprKind.values()) |
| .run(FunctionalInterfaceConversionTest::new); |
| } |
| |
| PackageKind samPkg; |
| ModifierKind modKind; |
| SamKind samKind; |
| MethodKind samMeth; |
| MethodKind clientMeth; |
| TypeKind retType; |
| TypeKind argType; |
| TypeKind thrownType; |
| ExprKind exprKind; |
| |
| String samSource = "#{PKG} \n #{CLAZZ}"; |
| String pkgClassSource = "#{PKG}\n #{MOD} class PackageClass extends Exception { }"; |
| String clientSource = "#{IMP}\n abstract class Client { \n" + |
| " Sam s = #{EXPR};\n" + |
| " #{METH2} \n }"; |
| |
| @Override |
| public void doWork() throws IOException { |
| newCompilationTask() |
| .withSourceFromTemplate("Sam", samSource) |
| .withSourceFromTemplate("PackageClass", pkgClassSource) |
| .withSourceFromTemplate("Client", clientSource, this::importStmt) |
| .analyze(this::check); |
| } |
| |
| ComboParameter importStmt(String name) { |
| switch (name) { |
| case "IMP": return new ComboParameter.Constant<>(samPkg.getImportStat()); |
| default: return null; |
| } |
| } |
| |
| void check(Result<?> res) { |
| if (res.hasErrors() == checkSamConversion()) { |
| fail("Unexpected compilation result; " + res.compilationInfo()); |
| } |
| } |
| |
| boolean checkSamConversion() { |
| if (samKind != SamKind.INTERFACE) { |
| //sam type must be an interface |
| return false; |
| } else if (samMeth == MethodKind.NONE) { |
| //interface must have at least a method |
| return false; |
| } else if (exprKind == ExprKind.LAMBDA && |
| samMeth != MethodKind.NON_GENERIC) { |
| //target method for lambda must be non-generic |
| return false; |
| } else if (exprKind == ExprKind.MREF && |
| clientMeth == MethodKind.NONE) { |
| return false; |
| } else if (samPkg != PackageKind.NO_PKG && |
| modKind != ModifierKind.PUBLIC && |
| (retType == TypeKind.PKG_CLASS || |
| argType == TypeKind.PKG_CLASS || |
| thrownType == TypeKind.PKG_CLASS)) { |
| //target must not contain inaccessible types |
| return false; |
| } else { |
| return true; |
| } |
| } |
| } |