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