mcimadamore@1434: /* vromero@1482: * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. mcimadamore@1434: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. mcimadamore@1434: * mcimadamore@1434: * This code is free software; you can redistribute it and/or modify it mcimadamore@1434: * under the terms of the GNU General Public License version 2 only, as mcimadamore@1434: * published by the Free Software Foundation. mcimadamore@1434: * mcimadamore@1434: * This code is distributed in the hope that it will be useful, but WITHOUT mcimadamore@1434: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or mcimadamore@1434: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License mcimadamore@1434: * version 2 for more details (a copy is included in the LICENSE file that mcimadamore@1434: * accompanied this code). mcimadamore@1434: * mcimadamore@1434: * You should have received a copy of the GNU General Public License version mcimadamore@1434: * 2 along with this work; if not, write to the Free Software Foundation, mcimadamore@1434: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. mcimadamore@1434: * mcimadamore@1434: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA mcimadamore@1434: * or visit www.oracle.com if you need additional information or have any mcimadamore@1434: * questions. mcimadamore@1434: */ mcimadamore@1434: mcimadamore@1434: /** mcimadamore@1434: * @test vromero@1520: * @bug 8003280 8004102 8006694 mcimadamore@1434: * @summary Add lambda tests mcimadamore@1434: * perform several automated checks in lambda conversion, esp. around accessibility vromero@1520: * temporarily workaround combo tests are causing time out in several platforms mcimadamore@1434: * @author Maurizio Cimadamore vromero@1482: * @library ../lib vromero@1482: * @build JavacTestingAbstractThreadedTest vromero@1520: * @run main/othervm FunctionalInterfaceConversionTest mcimadamore@1434: */ mcimadamore@1434: vromero@1520: // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) vromero@1520: // see JDK-8006746 vromero@1520: vromero@1482: import java.io.IOException; mcimadamore@1434: import java.net.URI; mcimadamore@1434: import java.util.Arrays; mcimadamore@1434: import javax.tools.Diagnostic; mcimadamore@1434: import javax.tools.JavaCompiler; mcimadamore@1434: import javax.tools.JavaFileObject; mcimadamore@1434: import javax.tools.SimpleJavaFileObject; mcimadamore@1434: import javax.tools.ToolProvider; vromero@1482: import com.sun.source.util.JavacTask; mcimadamore@1434: vromero@1482: public class FunctionalInterfaceConversionTest vromero@1482: extends JavacTestingAbstractThreadedTest vromero@1482: implements Runnable { mcimadamore@1434: mcimadamore@1434: enum PackageKind { mcimadamore@1434: NO_PKG(""), mcimadamore@1434: PKG_A("a"); mcimadamore@1434: mcimadamore@1434: String pkg; mcimadamore@1434: mcimadamore@1434: PackageKind(String pkg) { mcimadamore@1434: this.pkg = pkg; mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: String getPkgDecl() { mcimadamore@1434: return this == NO_PKG ? mcimadamore@1434: "" : mcimadamore@1434: "package " + pkg + ";"; mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: String getImportStat() { mcimadamore@1434: return this == NO_PKG ? mcimadamore@1434: "" : mcimadamore@1434: "import " + pkg + ".*;"; mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: enum SamKind { mcimadamore@1434: CLASS("public class Sam { }"), mcimadamore@1434: ABSTACT_CLASS("public abstract class Sam { }"), mcimadamore@1434: ANNOTATION("public @interface Sam { }"), mcimadamore@1434: ENUM("public enum Sam { }"), mcimadamore@1434: INTERFACE("public interface Sam { \n #METH; \n }"); mcimadamore@1434: mcimadamore@1434: String sam_str; mcimadamore@1434: mcimadamore@1434: SamKind(String sam_str) { mcimadamore@1434: this.sam_str = sam_str; mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: String getSam(String methStr) { mcimadamore@1434: return sam_str.replaceAll("#METH", methStr); mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: enum ModifierKind { mcimadamore@1434: PUBLIC("public"), mcimadamore@1434: PACKAGE(""); mcimadamore@1434: mcimadamore@1434: String modifier_str; mcimadamore@1434: mcimadamore@1434: ModifierKind(String modifier_str) { mcimadamore@1434: this.modifier_str = modifier_str; mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: boolean stricterThan(ModifierKind that) { mcimadamore@1434: return this.ordinal() > that.ordinal(); mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: enum TypeKind { mcimadamore@1434: EXCEPTION("Exception"), mcimadamore@1434: PKG_CLASS("PackageClass"); mcimadamore@1434: mcimadamore@1434: String typeStr; mcimadamore@1434: mcimadamore@1434: private TypeKind(String typeStr) { mcimadamore@1434: this.typeStr = typeStr; mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: enum ExprKind { mcimadamore@1434: LAMBDA("x -> null"), mcimadamore@1434: MREF("this::m"); mcimadamore@1434: mcimadamore@1434: String exprStr; mcimadamore@1434: mcimadamore@1434: private ExprKind(String exprStr) { mcimadamore@1434: this.exprStr = exprStr; mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: enum MethodKind { mcimadamore@1434: NONE(""), mcimadamore@1434: NON_GENERIC("public abstract #R m(#ARG s) throws #T;"), mcimadamore@1434: GENERIC("public abstract #R m(#ARG s) throws #T;"); mcimadamore@1434: mcimadamore@1434: String methodTemplate; mcimadamore@1434: mcimadamore@1434: private MethodKind(String methodTemplate) { mcimadamore@1434: this.methodTemplate = methodTemplate; mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: String getMethod(TypeKind retType, TypeKind argType, TypeKind thrownType) { mcimadamore@1434: return methodTemplate.replaceAll("#R", retType.typeStr). mcimadamore@1434: replaceAll("#ARG", argType.typeStr). mcimadamore@1434: replaceAll("#T", thrownType.typeStr); mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: public static void main(String[] args) throws Exception { mcimadamore@1434: for (PackageKind samPkg : PackageKind.values()) { mcimadamore@1434: for (ModifierKind modKind : ModifierKind.values()) { mcimadamore@1434: for (SamKind samKind : SamKind.values()) { mcimadamore@1434: for (MethodKind samMeth : MethodKind.values()) { mcimadamore@1434: for (MethodKind clientMeth : MethodKind.values()) { mcimadamore@1434: for (TypeKind retType : TypeKind.values()) { mcimadamore@1434: for (TypeKind argType : TypeKind.values()) { mcimadamore@1434: for (TypeKind thrownType : TypeKind.values()) { mcimadamore@1434: for (ExprKind exprKind : ExprKind.values()) { vromero@1482: pool.execute( vromero@1482: new FunctionalInterfaceConversionTest( vromero@1482: samPkg, modKind, samKind, vromero@1482: samMeth, clientMeth, retType, vromero@1482: argType, thrownType, exprKind)); mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: } vromero@1482: vromero@1482: checkAfterExec(false); mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: PackageKind samPkg; mcimadamore@1434: ModifierKind modKind; mcimadamore@1434: SamKind samKind; mcimadamore@1434: MethodKind samMeth; mcimadamore@1434: MethodKind clientMeth; mcimadamore@1434: TypeKind retType; mcimadamore@1434: TypeKind argType; mcimadamore@1434: TypeKind thrownType; mcimadamore@1434: ExprKind exprKind; mcimadamore@1434: DiagnosticChecker dc; mcimadamore@1434: mcimadamore@1434: SourceFile samSourceFile = new SourceFile("Sam.java", "#P \n #C") { vromero@1482: @Override mcimadamore@1434: public String toString() { mcimadamore@1434: return template.replaceAll("#P", samPkg.getPkgDecl()). vromero@1482: replaceAll("#C", samKind.getSam( vromero@1482: samMeth.getMethod(retType, argType, thrownType))); mcimadamore@1434: } mcimadamore@1434: }; mcimadamore@1434: vromero@1482: SourceFile pkgClassSourceFile = vromero@1482: new SourceFile("PackageClass.java", vromero@1482: "#P\n #M class PackageClass extends Exception { }") { vromero@1482: @Override mcimadamore@1434: public String toString() { mcimadamore@1434: return template.replaceAll("#P", samPkg.getPkgDecl()). mcimadamore@1434: replaceAll("#M", modKind.modifier_str); mcimadamore@1434: } mcimadamore@1434: }; mcimadamore@1434: vromero@1482: SourceFile clientSourceFile = vromero@1482: new SourceFile("Client.java", vromero@1482: "#I\n abstract class Client { \n" + vromero@1482: " Sam s = #E;\n" + vromero@1482: " #M \n }") { vromero@1482: @Override mcimadamore@1434: public String toString() { mcimadamore@1434: return template.replaceAll("#I", samPkg.getImportStat()) mcimadamore@1434: .replaceAll("#E", exprKind.exprStr) mcimadamore@1434: .replaceAll("#M", clientMeth.getMethod(retType, argType, thrownType)); mcimadamore@1434: } mcimadamore@1434: }; mcimadamore@1434: vromero@1482: FunctionalInterfaceConversionTest(PackageKind samPkg, ModifierKind modKind, vromero@1482: SamKind samKind, MethodKind samMeth, MethodKind clientMeth, vromero@1482: TypeKind retType, TypeKind argType, TypeKind thrownType, vromero@1482: ExprKind exprKind) { mcimadamore@1434: this.samPkg = samPkg; mcimadamore@1434: this.modKind = modKind; mcimadamore@1434: this.samKind = samKind; mcimadamore@1434: this.samMeth = samMeth; mcimadamore@1434: this.clientMeth = clientMeth; mcimadamore@1434: this.retType = retType; mcimadamore@1434: this.argType = argType; mcimadamore@1434: this.thrownType = thrownType; mcimadamore@1434: this.exprKind = exprKind; mcimadamore@1434: this.dc = new DiagnosticChecker(); mcimadamore@1434: } mcimadamore@1434: vromero@1482: @Override vromero@1482: public void run() { vromero@1482: final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); vromero@1482: vromero@1482: JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), dc, null, null, vromero@1482: Arrays.asList(samSourceFile, pkgClassSourceFile, clientSourceFile)); vromero@1482: try { vromero@1482: ct.analyze(); vromero@1482: } catch (IOException ex) { vromero@1482: throw new AssertionError("Test failing with cause", ex.getCause()); vromero@1482: } mcimadamore@1434: if (dc.errorFound == checkSamConversion()) { vromero@1482: throw new AssertionError(samSourceFile + "\n\n" + vromero@1482: pkgClassSourceFile + "\n\n" + clientSourceFile); mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: boolean checkSamConversion() { mcimadamore@1434: if (samKind != SamKind.INTERFACE) { mcimadamore@1434: //sam type must be an interface mcimadamore@1434: return false; mcimadamore@1434: } else if (samMeth == MethodKind.NONE) { mcimadamore@1434: //interface must have at least a method mcimadamore@1434: return false; mcimadamore@1434: } else if (exprKind == ExprKind.LAMBDA && mcimadamore@1434: samMeth != MethodKind.NON_GENERIC) { mcimadamore@1434: //target method for lambda must be non-generic mcimadamore@1434: return false; mcimadamore@1434: } else if (exprKind == ExprKind.MREF && mcimadamore@1434: clientMeth == MethodKind.NONE) { mcimadamore@1434: return false; mcimadamore@1434: } else if (samPkg != PackageKind.NO_PKG && mcimadamore@1434: modKind != ModifierKind.PUBLIC && mcimadamore@1434: (retType == TypeKind.PKG_CLASS || mcimadamore@1434: argType == TypeKind.PKG_CLASS || mcimadamore@1434: thrownType == TypeKind.PKG_CLASS)) { mcimadamore@1434: //target must not contain inaccessible types mcimadamore@1434: return false; mcimadamore@1434: } else { mcimadamore@1434: return true; mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: abstract class SourceFile extends SimpleJavaFileObject { mcimadamore@1434: mcimadamore@1434: protected String template; mcimadamore@1434: mcimadamore@1434: public SourceFile(String filename, String template) { mcimadamore@1434: super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE); mcimadamore@1434: this.template = template; mcimadamore@1434: } mcimadamore@1434: mcimadamore@1434: @Override mcimadamore@1434: public CharSequence getCharContent(boolean ignoreEncodingErrors) { mcimadamore@1434: return toString(); mcimadamore@1434: } mcimadamore@1434: vromero@1482: @Override mcimadamore@1434: public abstract String toString(); mcimadamore@1434: } mcimadamore@1434: vromero@1482: static class DiagnosticChecker vromero@1482: implements javax.tools.DiagnosticListener { mcimadamore@1434: mcimadamore@1434: boolean errorFound = false; mcimadamore@1434: vromero@1482: @Override mcimadamore@1434: public void report(Diagnostic diagnostic) { mcimadamore@1434: if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { mcimadamore@1434: errorFound = true; mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: } mcimadamore@1434: }