1 /* 2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @bug 8003280 8004102 8006694 8129962 27 * @summary Add lambda tests 28 * perform several automated checks in lambda conversion, esp. around accessibility 29 * temporarily workaround combo tests are causing time out in several platforms 30 * @enablePreview 31 * @library /tools/javac/lib 32 * @modules jdk.compiler/com.sun.tools.javac.api 33 * jdk.compiler/com.sun.tools.javac.file 34 * jdk.compiler/com.sun.tools.javac.util 35 * @build combo.ComboTestHelper 36 * @run main FunctionalInterfaceConversionTest 37 */ 38 39 import java.io.IOException; 40 41 import combo.ComboInstance; 42 import combo.ComboParameter; 43 import combo.ComboTask.Result; 44 import combo.ComboTestHelper; 45 46 47 public class FunctionalInterfaceConversionTest extends ComboInstance<FunctionalInterfaceConversionTest> { 48 49 enum PackageKind implements ComboParameter { 50 NO_PKG(""), 51 PKG_A("a"); 52 53 String pkg; 54 55 PackageKind(String pkg) { 56 this.pkg = pkg; 57 } 58 59 @Override 60 public String expand(String optParameter) { 61 return this == NO_PKG ? 62 "" : 63 "package " + pkg + ";"; 64 } 65 66 String getImportStat() { 67 return this == NO_PKG ? 68 "" : 69 "import " + pkg + ".*;"; 70 } 71 } 72 73 enum SamKind implements ComboParameter { 74 CLASS("public class Sam { }"), 75 ABSTACT_CLASS("public abstract class Sam { }"), 76 ANNOTATION("public @interface Sam { }"), 77 ENUM("public enum Sam { }"), 78 INTERFACE("public interface Sam { \n #{METH1}; \n }"); 79 80 String sam_str; 81 82 SamKind(String sam_str) { 83 this.sam_str = sam_str; 84 } 85 86 @Override 87 public String expand(String optParameter) { 88 return sam_str; 89 } 90 } 91 92 enum ModifierKind implements ComboParameter { 93 PUBLIC("public"), 94 PACKAGE(""); 95 96 String modifier_str; 97 98 ModifierKind(String modifier_str) { 99 this.modifier_str = modifier_str; 100 } 101 102 @Override 103 public String expand(String optParameter) { 104 return modifier_str; 105 } 106 } 107 108 enum TypeKind implements ComboParameter { 109 EXCEPTION("Exception"), 110 PKG_CLASS("PackageClass"); 111 112 String typeStr; 113 114 TypeKind(String typeStr) { 115 this.typeStr = typeStr; 116 } 117 118 @Override 119 public String expand(String optParameter) { 120 return typeStr; 121 } 122 } 123 124 enum ExprKind implements ComboParameter { 125 LAMBDA("x -> null"), 126 MREF("this::m"); 127 128 String exprStr; 129 130 ExprKind(String exprStr) { 131 this.exprStr = exprStr; 132 } 133 134 @Override 135 public String expand(String optParameter) { 136 return exprStr; 137 } 138 } 139 140 enum MethodKind implements ComboParameter { 141 NONE(""), 142 NON_GENERIC("public abstract #{RET} m(#{ARG} s) throws #{THROWN};"), 143 GENERIC("public abstract <X> #{RET} m(#{ARG} s) throws #{THROWN};"); 144 145 String methodTemplate; 146 147 MethodKind(String methodTemplate) { 148 this.methodTemplate = methodTemplate; 149 } 150 151 @Override 152 public String expand(String optParameter) { 153 return methodTemplate; 154 } 155 } 156 157 public static void main(String[] args) throws Exception { 158 new ComboTestHelper<FunctionalInterfaceConversionTest>() 159 .withDimension("PKG", (x, pkg) -> x.samPkg = pkg, PackageKind.values()) 160 .withDimension("MOD", (x, mod) -> x.modKind = mod, ModifierKind.values()) 161 .withDimension("CLAZZ", (x, sam) -> x.samKind = sam, SamKind.values()) 162 .withDimension("METH1", (x, meth) -> x.samMeth = meth, MethodKind.values()) 163 .withDimension("METH2", (x, meth) -> x.clientMeth = meth, MethodKind.values()) 164 .withDimension("RET", (x, ret) -> x.retType = ret, TypeKind.values()) 165 .withDimension("ARG", (x, arg) -> x.argType = arg, TypeKind.values()) 166 .withDimension("THROWN", (x, thrown) -> x.thrownType = thrown, TypeKind.values()) 167 .withDimension("EXPR", (x, expr) -> x.exprKind = expr, ExprKind.values()) 168 .run(FunctionalInterfaceConversionTest::new); 169 } 170 171 PackageKind samPkg; 172 ModifierKind modKind; 173 SamKind samKind; 174 MethodKind samMeth; 175 MethodKind clientMeth; 176 TypeKind retType; 177 TypeKind argType; 178 TypeKind thrownType; 179 ExprKind exprKind; 180 181 String samSource = "#{PKG} \n #{CLAZZ}"; 182 String pkgClassSource = "#{PKG}\n #{MOD} class PackageClass extends Exception { }"; 183 String clientSource = "#{IMP}\n abstract class Client { \n" + 184 " Sam s = #{EXPR};\n" + 185 " #{METH2} \n }"; 186 187 @Override 188 public void doWork() throws IOException { 189 newCompilationTask() 190 .withSourceFromTemplate("Sam", samSource) 191 .withSourceFromTemplate("PackageClass", pkgClassSource) 192 .withSourceFromTemplate("Client", clientSource, this::importStmt) 193 .analyze(this::check); 194 } 195 196 ComboParameter importStmt(String name) { 197 switch (name) { 198 case "IMP": return new ComboParameter.Constant<>(samPkg.getImportStat()); 199 default: return null; 200 } 201 } 202 203 void check(Result<?> res) { 204 if (res.hasErrors() == checkSamConversion()) { 205 fail("Unexpected compilation result; " + res.compilationInfo()); 206 } 207 } 208 209 boolean checkSamConversion() { 210 if (samKind != SamKind.INTERFACE) { 211 //sam type must be an interface 212 return false; 213 } else if (samMeth == MethodKind.NONE) { 214 //interface must have at least a method 215 return false; 216 } else if (exprKind == ExprKind.LAMBDA && 217 samMeth != MethodKind.NON_GENERIC) { 218 //target method for lambda must be non-generic 219 return false; 220 } else if (exprKind == ExprKind.MREF && 221 clientMeth == MethodKind.NONE) { 222 return false; 223 } else if (samPkg != PackageKind.NO_PKG && 224 modKind != ModifierKind.PUBLIC && 225 (retType == TypeKind.PKG_CLASS || 226 argType == TypeKind.PKG_CLASS || 227 thrownType == TypeKind.PKG_CLASS)) { 228 //target must not contain inaccessible types 229 return false; 230 } else { 231 return true; 232 } 233 } 234 }