5b1a78dc92
Reviewed-by: jjg
310 lines
9.9 KiB
Java
310 lines
9.9 KiB
Java
/*
|
|
* Copyright (c) 2012, 2013, 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
|
|
* @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
|
|
* @author Maurizio Cimadamore
|
|
* @library ../lib
|
|
* @build JavacTestingAbstractThreadedTest
|
|
* @run main/othervm FunctionalInterfaceConversionTest
|
|
*/
|
|
|
|
// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
|
|
// see JDK-8006746
|
|
|
|
import java.io.IOException;
|
|
import java.net.URI;
|
|
import java.util.Arrays;
|
|
import javax.tools.Diagnostic;
|
|
import javax.tools.JavaCompiler;
|
|
import javax.tools.JavaFileObject;
|
|
import javax.tools.SimpleJavaFileObject;
|
|
import javax.tools.ToolProvider;
|
|
import com.sun.source.util.JavacTask;
|
|
|
|
public class FunctionalInterfaceConversionTest
|
|
extends JavacTestingAbstractThreadedTest
|
|
implements Runnable {
|
|
|
|
enum PackageKind {
|
|
NO_PKG(""),
|
|
PKG_A("a");
|
|
|
|
String pkg;
|
|
|
|
PackageKind(String pkg) {
|
|
this.pkg = pkg;
|
|
}
|
|
|
|
String getPkgDecl() {
|
|
return this == NO_PKG ?
|
|
"" :
|
|
"package " + pkg + ";";
|
|
}
|
|
|
|
String getImportStat() {
|
|
return this == NO_PKG ?
|
|
"" :
|
|
"import " + pkg + ".*;";
|
|
}
|
|
}
|
|
|
|
enum SamKind {
|
|
CLASS("public class Sam { }"),
|
|
ABSTACT_CLASS("public abstract class Sam { }"),
|
|
ANNOTATION("public @interface Sam { }"),
|
|
ENUM("public enum Sam { }"),
|
|
INTERFACE("public interface Sam { \n #METH; \n }");
|
|
|
|
String sam_str;
|
|
|
|
SamKind(String sam_str) {
|
|
this.sam_str = sam_str;
|
|
}
|
|
|
|
String getSam(String methStr) {
|
|
return sam_str.replaceAll("#METH", methStr);
|
|
}
|
|
}
|
|
|
|
enum ModifierKind {
|
|
PUBLIC("public"),
|
|
PACKAGE("");
|
|
|
|
String modifier_str;
|
|
|
|
ModifierKind(String modifier_str) {
|
|
this.modifier_str = modifier_str;
|
|
}
|
|
|
|
boolean stricterThan(ModifierKind that) {
|
|
return this.ordinal() > that.ordinal();
|
|
}
|
|
}
|
|
|
|
enum TypeKind {
|
|
EXCEPTION("Exception"),
|
|
PKG_CLASS("PackageClass");
|
|
|
|
String typeStr;
|
|
|
|
private TypeKind(String typeStr) {
|
|
this.typeStr = typeStr;
|
|
}
|
|
}
|
|
|
|
enum ExprKind {
|
|
LAMBDA("x -> null"),
|
|
MREF("this::m");
|
|
|
|
String exprStr;
|
|
|
|
private ExprKind(String exprStr) {
|
|
this.exprStr = exprStr;
|
|
}
|
|
}
|
|
|
|
enum MethodKind {
|
|
NONE(""),
|
|
NON_GENERIC("public abstract #R m(#ARG s) throws #T;"),
|
|
GENERIC("public abstract <X> #R m(#ARG s) throws #T;");
|
|
|
|
String methodTemplate;
|
|
|
|
private MethodKind(String methodTemplate) {
|
|
this.methodTemplate = methodTemplate;
|
|
}
|
|
|
|
String getMethod(TypeKind retType, TypeKind argType, TypeKind thrownType) {
|
|
return methodTemplate.replaceAll("#R", retType.typeStr).
|
|
replaceAll("#ARG", argType.typeStr).
|
|
replaceAll("#T", thrownType.typeStr);
|
|
}
|
|
}
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
for (PackageKind samPkg : PackageKind.values()) {
|
|
for (ModifierKind modKind : ModifierKind.values()) {
|
|
for (SamKind samKind : SamKind.values()) {
|
|
for (MethodKind samMeth : MethodKind.values()) {
|
|
for (MethodKind clientMeth : MethodKind.values()) {
|
|
for (TypeKind retType : TypeKind.values()) {
|
|
for (TypeKind argType : TypeKind.values()) {
|
|
for (TypeKind thrownType : TypeKind.values()) {
|
|
for (ExprKind exprKind : ExprKind.values()) {
|
|
pool.execute(
|
|
new FunctionalInterfaceConversionTest(
|
|
samPkg, modKind, samKind,
|
|
samMeth, clientMeth, retType,
|
|
argType, thrownType, exprKind));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
checkAfterExec(false);
|
|
}
|
|
|
|
PackageKind samPkg;
|
|
ModifierKind modKind;
|
|
SamKind samKind;
|
|
MethodKind samMeth;
|
|
MethodKind clientMeth;
|
|
TypeKind retType;
|
|
TypeKind argType;
|
|
TypeKind thrownType;
|
|
ExprKind exprKind;
|
|
DiagnosticChecker dc;
|
|
|
|
SourceFile samSourceFile = new SourceFile("Sam.java", "#P \n #C") {
|
|
@Override
|
|
public String toString() {
|
|
return template.replaceAll("#P", samPkg.getPkgDecl()).
|
|
replaceAll("#C", samKind.getSam(
|
|
samMeth.getMethod(retType, argType, thrownType)));
|
|
}
|
|
};
|
|
|
|
SourceFile pkgClassSourceFile =
|
|
new SourceFile("PackageClass.java",
|
|
"#P\n #M class PackageClass extends Exception { }") {
|
|
@Override
|
|
public String toString() {
|
|
return template.replaceAll("#P", samPkg.getPkgDecl()).
|
|
replaceAll("#M", modKind.modifier_str);
|
|
}
|
|
};
|
|
|
|
SourceFile clientSourceFile =
|
|
new SourceFile("Client.java",
|
|
"#I\n abstract class Client { \n" +
|
|
" Sam s = #E;\n" +
|
|
" #M \n }") {
|
|
@Override
|
|
public String toString() {
|
|
return template.replaceAll("#I", samPkg.getImportStat())
|
|
.replaceAll("#E", exprKind.exprStr)
|
|
.replaceAll("#M", clientMeth.getMethod(retType, argType, thrownType));
|
|
}
|
|
};
|
|
|
|
FunctionalInterfaceConversionTest(PackageKind samPkg, ModifierKind modKind,
|
|
SamKind samKind, MethodKind samMeth, MethodKind clientMeth,
|
|
TypeKind retType, TypeKind argType, TypeKind thrownType,
|
|
ExprKind exprKind) {
|
|
this.samPkg = samPkg;
|
|
this.modKind = modKind;
|
|
this.samKind = samKind;
|
|
this.samMeth = samMeth;
|
|
this.clientMeth = clientMeth;
|
|
this.retType = retType;
|
|
this.argType = argType;
|
|
this.thrownType = thrownType;
|
|
this.exprKind = exprKind;
|
|
this.dc = new DiagnosticChecker();
|
|
}
|
|
|
|
@Override
|
|
public void run() {
|
|
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
|
|
|
|
JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), dc, null, null,
|
|
Arrays.asList(samSourceFile, pkgClassSourceFile, clientSourceFile));
|
|
try {
|
|
ct.analyze();
|
|
} catch (IOException ex) {
|
|
throw new AssertionError("Test failing with cause", ex.getCause());
|
|
}
|
|
if (dc.errorFound == checkSamConversion()) {
|
|
throw new AssertionError(samSourceFile + "\n\n" +
|
|
pkgClassSourceFile + "\n\n" + clientSourceFile);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
abstract class SourceFile extends SimpleJavaFileObject {
|
|
|
|
protected String template;
|
|
|
|
public SourceFile(String filename, String template) {
|
|
super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE);
|
|
this.template = template;
|
|
}
|
|
|
|
@Override
|
|
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
|
return toString();
|
|
}
|
|
|
|
@Override
|
|
public abstract String toString();
|
|
}
|
|
|
|
static class DiagnosticChecker
|
|
implements javax.tools.DiagnosticListener<JavaFileObject> {
|
|
|
|
boolean errorFound = false;
|
|
|
|
@Override
|
|
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
|
|
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
|
|
errorFound = true;
|
|
}
|
|
}
|
|
}
|
|
}
|