1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,392 @@ 1.4 +/* 1.5 + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + */ 1.26 + 1.27 +/** 1.28 + * @test 1.29 + * @bug 8003280 8006694 1.30 + * @summary Add lambda tests 1.31 + * perform automated checks in type inference in lambda expressions 1.32 + * in different contexts 1.33 + * temporarily workaround combo tests are causing time out in several platforms 1.34 + * @library ../../../lib 1.35 + * @build JavacTestingAbstractThreadedTest 1.36 + * @compile TypeInferenceComboTest.java 1.37 + * @run main/othervm/timeout=360 TypeInferenceComboTest 1.38 + */ 1.39 + 1.40 +// use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) 1.41 +// see JDK-8006746 1.42 + 1.43 +import java.net.URI; 1.44 +import java.util.Arrays; 1.45 +import javax.tools.Diagnostic; 1.46 +import javax.tools.JavaFileObject; 1.47 +import javax.tools.SimpleJavaFileObject; 1.48 +import com.sun.source.util.JavacTask; 1.49 + 1.50 +public class TypeInferenceComboTest 1.51 + extends JavacTestingAbstractThreadedTest 1.52 + implements Runnable { 1.53 + enum Context { 1.54 + ASSIGNMENT("SAM#Type s = #LBody;"), 1.55 + METHOD_CALL("#GenericDeclKind void method1(SAM#Type s) { }\n" + 1.56 + "void method2() {\n" + 1.57 + " method1(#LBody);\n" + 1.58 + "}"), 1.59 + RETURN_OF_METHOD("SAM#Type method1() {\n" + 1.60 + " return #LBody;\n" + 1.61 + "}"), 1.62 + LAMBDA_RETURN_EXPRESSION("SAM2 s2 = () -> {return (SAM#Type)#LBody;};\n"), 1.63 + ARRAY_INITIALIZER("Object[] oarray = {\"a\", 1, (SAM#Type)#LBody};"); 1.64 + 1.65 + String context; 1.66 + 1.67 + Context(String context) { 1.68 + this.context = context; 1.69 + } 1.70 + 1.71 + String getContext(SamKind sk, TypeKind samTargetT, Keyword kw, 1.72 + TypeKind parameterT, TypeKind returnT, LambdaKind lk, 1.73 + ParameterKind pk, GenericDeclKind gdk, LambdaBody lb) { 1.74 + String result = context; 1.75 + if (sk == SamKind.GENERIC) { 1.76 + if(this == Context.METHOD_CALL) { 1.77 + result = result.replaceAll("#GenericDeclKind", 1.78 + gdk.getGenericDeclKind(samTargetT)); 1.79 + if(gdk == GenericDeclKind.NON_GENERIC) 1.80 + result = result.replaceAll("#Type", "<" + 1.81 + samTargetT.typeStr + ">"); 1.82 + else //#GenericDeclKind is <T> or <T extends xxx> 1.83 + result = result.replaceAll("#Type", "<T>"); 1.84 + } 1.85 + else { 1.86 + if(kw == Keyword.VOID) 1.87 + result = result.replaceAll("#Type", "<" + 1.88 + samTargetT.typeStr + ">"); 1.89 + else 1.90 + result = result.replaceAll("#Type", "<? " + kw.keyStr + 1.91 + " " + samTargetT.typeStr + ">"); 1.92 + } 1.93 + } 1.94 + else 1.95 + result = result.replaceAll("#Type", ""). 1.96 + replaceAll("#GenericDeclKind", ""); 1.97 + 1.98 + return result.replaceAll("#LBody", 1.99 + lb.getLambdaBody(samTargetT, parameterT, returnT, lk, pk)); 1.100 + } 1.101 + } 1.102 + 1.103 + enum SamKind { 1.104 + GENERIC("interface SAM<T> { #R m(#ARG); }"), 1.105 + NON_GENERIC("interface SAM { #R m(#ARG); }"); 1.106 + 1.107 + String sam_str; 1.108 + 1.109 + SamKind(String sam_str) { 1.110 + this.sam_str = sam_str; 1.111 + } 1.112 + 1.113 + String getSam(TypeKind parameterT, TypeKind returnT) { 1.114 + return sam_str.replaceAll("#ARG", 1.115 + parameterT == TypeKind.VOID ? 1.116 + "" : parameterT.typeStr + " arg") 1.117 + .replaceAll("#R", returnT.typeStr); 1.118 + } 1.119 + } 1.120 + 1.121 + enum TypeKind { 1.122 + VOID("void", ""), 1.123 + STRING("String", "\"hello\""), 1.124 + INTEGER("Integer", "1"), 1.125 + INT("int", "0"), 1.126 + COMPARATOR("java.util.Comparator<String>", 1.127 + "(java.util.Comparator<String>)(a, b) -> a.length()-b.length()"), 1.128 + SAM("SAM2", "null"), 1.129 + GENERIC("T", null); 1.130 + 1.131 + String typeStr; 1.132 + String valStr; 1.133 + 1.134 + TypeKind(String typeStr, String valStr) { 1.135 + this.typeStr = typeStr; 1.136 + this.valStr = valStr; 1.137 + } 1.138 + } 1.139 + 1.140 + enum LambdaKind { 1.141 + EXPRESSION("#VAL"), 1.142 + STATEMENT("{return #VAL;}"); 1.143 + 1.144 + String stmt; 1.145 + 1.146 + LambdaKind(String stmt) { 1.147 + this.stmt = stmt; 1.148 + } 1.149 + } 1.150 + 1.151 + enum ParameterKind { 1.152 + EXPLICIT("#TYPE"), 1.153 + IMPLICIT(""); 1.154 + 1.155 + String paramTemplate; 1.156 + 1.157 + ParameterKind(String paramTemplate) { 1.158 + this.paramTemplate = paramTemplate; 1.159 + } 1.160 + } 1.161 + 1.162 + enum Keyword { 1.163 + SUPER("super"), 1.164 + EXTENDS("extends"), 1.165 + VOID(""); 1.166 + 1.167 + String keyStr; 1.168 + 1.169 + Keyword(String keyStr) { 1.170 + this.keyStr = keyStr; 1.171 + } 1.172 + } 1.173 + 1.174 + enum LambdaBody { 1.175 + //no parameters, return type is one of the TypeKind 1.176 + RETURN_VOID("() -> #RET"), 1.177 + //has parameters, return type is one of the TypeKind 1.178 + RETURN_ARG("(#PK arg) -> #RET"); 1.179 + 1.180 + String bodyStr; 1.181 + 1.182 + LambdaBody(String bodyStr) { 1.183 + this.bodyStr = bodyStr; 1.184 + } 1.185 + 1.186 + String getLambdaBody(TypeKind samTargetT, TypeKind parameterT, 1.187 + TypeKind returnT, LambdaKind lk, ParameterKind pk) { 1.188 + String result = bodyStr.replaceAll("#PK", pk.paramTemplate); 1.189 + 1.190 + if(result.contains("#TYPE")) { 1.191 + if (parameterT == TypeKind.GENERIC && this != RETURN_VOID) 1.192 + result = result.replaceAll("#TYPE", 1.193 + samTargetT == null? "": samTargetT.typeStr); 1.194 + else 1.195 + result = result.replaceAll("#TYPE", parameterT.typeStr); 1.196 + } 1.197 + if (this == RETURN_ARG && parameterT == returnT) 1.198 + return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", "arg")); 1.199 + else { 1.200 + if(returnT != TypeKind.GENERIC) 1.201 + return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", 1.202 + (returnT==TypeKind.VOID && 1.203 + lk==LambdaKind.EXPRESSION) ? "{}" : returnT.valStr)); 1.204 + else 1.205 + return result.replaceAll("#RET", 1.206 + lk.stmt.replaceAll("#VAL", samTargetT.valStr)); 1.207 + } 1.208 + } 1.209 + } 1.210 + 1.211 + enum GenericDeclKind { 1.212 + NON_GENERIC(""), 1.213 + GENERIC_NOBOUND("<T>"), 1.214 + GENERIC_BOUND("<T extends #ExtendedType>"); 1.215 + String typeStr; 1.216 + 1.217 + GenericDeclKind(String typeStr) { 1.218 + this.typeStr = typeStr; 1.219 + } 1.220 + 1.221 + String getGenericDeclKind(TypeKind et) { 1.222 + return typeStr.replaceAll("#ExtendedType", et==null? "":et.typeStr); 1.223 + } 1.224 + } 1.225 + 1.226 + boolean checkTypeInference() { 1.227 + if (parameterType == TypeKind.VOID) { 1.228 + if (lambdaBodyType != LambdaBody.RETURN_VOID) 1.229 + return false; 1.230 + } 1.231 + else if (lambdaBodyType != LambdaBody.RETURN_ARG) 1.232 + return false; 1.233 + 1.234 + return true; 1.235 + } 1.236 + 1.237 + String templateStr = "#C\n" + 1.238 + "interface SAM2 {\n" + 1.239 + " SAM m();\n" + 1.240 + "}\n"; 1.241 + SourceFile samSourceFile = new SourceFile("Sam.java", templateStr) { 1.242 + public String toString() { 1.243 + return template.replaceAll("#C", 1.244 + samKind.getSam(parameterType, returnType)); 1.245 + } 1.246 + }; 1.247 + 1.248 + SourceFile clientSourceFile = new SourceFile("Client.java", 1.249 + "class Client { \n" + 1.250 + " #Context\n" + 1.251 + "}") { 1.252 + public String toString() { 1.253 + return template.replaceAll("#Context", 1.254 + context.getContext(samKind, samTargetType, keyword, 1.255 + parameterType, returnType, lambdaKind, parameterKind, 1.256 + genericDeclKind, lambdaBodyType)); 1.257 + } 1.258 + }; 1.259 + 1.260 + public void run() { 1.261 + DiagnosticChecker dc = new DiagnosticChecker(); 1.262 + JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), dc, 1.263 + null, null, Arrays.asList(samSourceFile, clientSourceFile)); 1.264 + try { 1.265 + ct.analyze(); 1.266 + } catch (Throwable t) { 1.267 + processException(t); 1.268 + } 1.269 + if (dc.errorFound == checkTypeInference()) { 1.270 + throw new AssertionError(samSourceFile + "\n\n" + 1.271 + clientSourceFile + "\n" + parameterType + " " + returnType); 1.272 + } 1.273 + } 1.274 + 1.275 + abstract class SourceFile extends SimpleJavaFileObject { 1.276 + 1.277 + protected String template; 1.278 + 1.279 + public SourceFile(String filename, String template) { 1.280 + super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE); 1.281 + this.template = template; 1.282 + } 1.283 + 1.284 + @Override 1.285 + public CharSequence getCharContent(boolean ignoreEncodingErrors) { 1.286 + return toString(); 1.287 + } 1.288 + 1.289 + public abstract String toString(); 1.290 + } 1.291 + 1.292 + static class DiagnosticChecker 1.293 + implements javax.tools.DiagnosticListener<JavaFileObject> { 1.294 + 1.295 + boolean errorFound = false; 1.296 + 1.297 + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 1.298 + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { 1.299 + errorFound = true; 1.300 + } 1.301 + } 1.302 + } 1.303 + 1.304 + SamKind samKind; 1.305 + TypeKind samTargetType; 1.306 + TypeKind parameterType; 1.307 + TypeKind returnType; 1.308 + Context context; 1.309 + LambdaBody lambdaBodyType; 1.310 + LambdaKind lambdaKind; 1.311 + ParameterKind parameterKind; 1.312 + Keyword keyword; 1.313 + GenericDeclKind genericDeclKind; 1.314 + 1.315 + TypeInferenceComboTest(SamKind sk, TypeKind samTargetT, TypeKind parameterT, 1.316 + TypeKind returnT, LambdaBody lb, Context c, LambdaKind lk, 1.317 + ParameterKind pk, Keyword kw, GenericDeclKind gdk) { 1.318 + samKind = sk; 1.319 + samTargetType = samTargetT; 1.320 + parameterType = parameterT; 1.321 + returnType = returnT; 1.322 + context = c; 1.323 + lambdaKind = lk; 1.324 + parameterKind = pk; 1.325 + keyword = kw; 1.326 + lambdaBodyType = lb; 1.327 + genericDeclKind = gdk; 1.328 + } 1.329 + 1.330 + public static void main(String[] args) throws Exception { 1.331 + for(Context ct : Context.values()) { 1.332 + for (TypeKind returnT : TypeKind.values()) { 1.333 + for (TypeKind parameterT : TypeKind.values()) { 1.334 + for(LambdaBody lb : LambdaBody.values()) { 1.335 + for (ParameterKind parameterK : ParameterKind.values()) { 1.336 + for(LambdaKind lambdaK : LambdaKind.values()) { 1.337 + for (SamKind sk : SamKind.values()) { 1.338 + if (sk == SamKind.NON_GENERIC) { 1.339 + generateNonGenericSAM(ct, returnT, 1.340 + parameterT, lb, parameterK, 1.341 + lambdaK, sk); 1.342 + } 1.343 + else if (sk == SamKind.GENERIC) { 1.344 + generateGenericSAM(ct, returnT, 1.345 + parameterT, lb, parameterK, 1.346 + lambdaK, sk); 1.347 + } 1.348 + } 1.349 + } 1.350 + } 1.351 + } 1.352 + } 1.353 + } 1.354 + } 1.355 + 1.356 + checkAfterExec(false); 1.357 + } 1.358 + 1.359 + static void generateNonGenericSAM(Context ct, TypeKind returnT, 1.360 + TypeKind parameterT, LambdaBody lb, ParameterKind parameterK, 1.361 + LambdaKind lambdaK, SamKind sk) { 1.362 + if(parameterT != TypeKind.GENERIC && returnT != TypeKind.GENERIC ) { 1.363 + pool.execute(new TypeInferenceComboTest(sk, null, parameterT, 1.364 + returnT, lb, ct, lambdaK, parameterK, null, null)); 1.365 + } 1.366 + } 1.367 + 1.368 + static void generateGenericSAM(Context ct, TypeKind returnT, 1.369 + TypeKind parameterT, LambdaBody lb, ParameterKind parameterK, 1.370 + LambdaKind lambdaK, SamKind sk) { 1.371 + for (Keyword kw : Keyword.values()) { 1.372 + for (TypeKind samTargetT : TypeKind.values()) { 1.373 + if(samTargetT != TypeKind.VOID && 1.374 + samTargetT != TypeKind.INT && 1.375 + samTargetT != TypeKind.GENERIC && 1.376 + (parameterT == TypeKind.GENERIC || 1.377 + returnT == TypeKind.GENERIC)) { 1.378 + if(ct != Context.METHOD_CALL) { 1.379 + pool.execute( 1.380 + new TypeInferenceComboTest(sk, samTargetT, parameterT, 1.381 + returnT, lb, ct, lambdaK, parameterK, kw, null)); 1.382 + } else {//Context.METHOD_CALL 1.383 + for (GenericDeclKind gdk : 1.384 + GenericDeclKind.values()) 1.385 + pool.execute( 1.386 + new TypeInferenceComboTest(sk, samTargetT, 1.387 + parameterT, returnT, lb, ct, lambdaK, 1.388 + parameterK, kw, gdk)); 1.389 + } 1.390 + } 1.391 + } 1.392 + } 1.393 + } 1.394 + 1.395 +}