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 * @library /tools/javac/lib 31 * @modules jdk.compiler/com.sun.tools.javac.api 32 * jdk.compiler/com.sun.tools.javac.code 33 * jdk.compiler/com.sun.tools.javac.comp 34 * jdk.compiler/com.sun.tools.javac.main 35 * jdk.compiler/com.sun.tools.javac.tree 36 * jdk.compiler/com.sun.tools.javac.util 37 * @build combo.ComboTestHelper 38 * @run main FunctionalInterfaceConversionTest 39 */ 40 41 import java.io.IOException; 42 43 import combo.ComboInstance; 44 import combo.ComboParameter; 45 import combo.ComboTask.Result; 46 import combo.ComboTestHelper; 47 48 49 public class FunctionalInterfaceConversionTest extends ComboInstance<FunctionalInterfaceConversionTest> { 50 51 enum PackageKind implements ComboParameter { 52 NO_PKG(""), 53 PKG_A("a"); 54 55 String pkg; 56 PackageKind(String pkg)57 PackageKind(String pkg) { 58 this.pkg = pkg; 59 } 60 61 @Override expand(String optParameter)62 public String expand(String optParameter) { 63 return this == NO_PKG ? 64 "" : 65 "package " + pkg + ";"; 66 } 67 getImportStat()68 String getImportStat() { 69 return this == NO_PKG ? 70 "" : 71 "import " + pkg + ".*;"; 72 } 73 } 74 75 enum SamKind implements ComboParameter { 76 CLASS("public class Sam { }"), 77 ABSTACT_CLASS("public abstract class Sam { }"), 78 ANNOTATION("public @interface Sam { }"), 79 ENUM("public enum Sam { }"), 80 INTERFACE("public interface Sam { \n #{METH1}; \n }"); 81 82 String sam_str; 83 SamKind(String sam_str)84 SamKind(String sam_str) { 85 this.sam_str = sam_str; 86 } 87 88 @Override expand(String optParameter)89 public String expand(String optParameter) { 90 return sam_str; 91 } 92 } 93 94 enum ModifierKind implements ComboParameter { 95 PUBLIC("public"), 96 PACKAGE(""); 97 98 String modifier_str; 99 ModifierKind(String modifier_str)100 ModifierKind(String modifier_str) { 101 this.modifier_str = modifier_str; 102 } 103 104 @Override expand(String optParameter)105 public String expand(String optParameter) { 106 return modifier_str; 107 } 108 } 109 110 enum TypeKind implements ComboParameter { 111 EXCEPTION("Exception"), 112 PKG_CLASS("PackageClass"); 113 114 String typeStr; 115 TypeKind(String typeStr)116 TypeKind(String typeStr) { 117 this.typeStr = typeStr; 118 } 119 120 @Override expand(String optParameter)121 public String expand(String optParameter) { 122 return typeStr; 123 } 124 } 125 126 enum ExprKind implements ComboParameter { 127 LAMBDA("x -> null"), 128 MREF("this::m"); 129 130 String exprStr; 131 ExprKind(String exprStr)132 ExprKind(String exprStr) { 133 this.exprStr = exprStr; 134 } 135 136 @Override expand(String optParameter)137 public String expand(String optParameter) { 138 return exprStr; 139 } 140 } 141 142 enum MethodKind implements ComboParameter { 143 NONE(""), 144 NON_GENERIC("public abstract #{RET} m(#{ARG} s) throws #{THROWN};"), 145 GENERIC("public abstract <X> #{RET} m(#{ARG} s) throws #{THROWN};"); 146 147 String methodTemplate; 148 MethodKind(String methodTemplate)149 MethodKind(String methodTemplate) { 150 this.methodTemplate = methodTemplate; 151 } 152 153 @Override expand(String optParameter)154 public String expand(String optParameter) { 155 return methodTemplate; 156 } 157 } 158 main(String[] args)159 public static void main(String[] args) throws Exception { 160 new ComboTestHelper<FunctionalInterfaceConversionTest>() 161 .withDimension("PKG", (x, pkg) -> x.samPkg = pkg, PackageKind.values()) 162 .withDimension("MOD", (x, mod) -> x.modKind = mod, ModifierKind.values()) 163 .withDimension("CLAZZ", (x, sam) -> x.samKind = sam, SamKind.values()) 164 .withDimension("METH1", (x, meth) -> x.samMeth = meth, MethodKind.values()) 165 .withDimension("METH2", (x, meth) -> x.clientMeth = meth, MethodKind.values()) 166 .withDimension("RET", (x, ret) -> x.retType = ret, TypeKind.values()) 167 .withDimension("ARG", (x, arg) -> x.argType = arg, TypeKind.values()) 168 .withDimension("THROWN", (x, thrown) -> x.thrownType = thrown, TypeKind.values()) 169 .withDimension("EXPR", (x, expr) -> x.exprKind = expr, ExprKind.values()) 170 .run(FunctionalInterfaceConversionTest::new); 171 } 172 173 PackageKind samPkg; 174 ModifierKind modKind; 175 SamKind samKind; 176 MethodKind samMeth; 177 MethodKind clientMeth; 178 TypeKind retType; 179 TypeKind argType; 180 TypeKind thrownType; 181 ExprKind exprKind; 182 183 String samSource = "#{PKG} \n #{CLAZZ}"; 184 String pkgClassSource = "#{PKG}\n #{MOD} class PackageClass extends Exception { }"; 185 String clientSource = "#{IMP}\n abstract class Client { \n" + 186 " Sam s = #{EXPR};\n" + 187 " #{METH2} \n }"; 188 189 @Override doWork()190 public void doWork() throws IOException { 191 newCompilationTask() 192 .withSourceFromTemplate("Sam", samSource) 193 .withSourceFromTemplate("PackageClass", pkgClassSource) 194 .withSourceFromTemplate("Client", clientSource, this::importStmt) 195 .analyze(this::check); 196 } 197 importStmt(String name)198 ComboParameter importStmt(String name) { 199 switch (name) { 200 case "IMP": return new ComboParameter.Constant<>(samPkg.getImportStat()); 201 default: return null; 202 } 203 } 204 check(Result<?> res)205 void check(Result<?> res) { 206 if (res.hasErrors() == checkSamConversion()) { 207 fail("Unexpected compilation result; " + res.compilationInfo()); 208 } 209 } 210 checkSamConversion()211 boolean checkSamConversion() { 212 if (samKind != SamKind.INTERFACE) { 213 //sam type must be an interface 214 return false; 215 } else if (samMeth == MethodKind.NONE) { 216 //interface must have at least a method 217 return false; 218 } else if (exprKind == ExprKind.LAMBDA && 219 samMeth != MethodKind.NON_GENERIC) { 220 //target method for lambda must be non-generic 221 return false; 222 } else if (exprKind == ExprKind.MREF && 223 clientMeth == MethodKind.NONE) { 224 return false; 225 } else if (samPkg != PackageKind.NO_PKG && 226 modKind != ModifierKind.PUBLIC && 227 (retType == TypeKind.PKG_CLASS || 228 argType == TypeKind.PKG_CLASS || 229 thrownType == TypeKind.PKG_CLASS)) { 230 //target must not contain inaccessible types 231 return false; 232 } else { 233 return true; 234 } 235 } 236 } 237