langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java
changeset 15040 99fd9483d3f0
parent 14547 86d8d242b0c4
child 15384 5a8d00abf076
equal deleted inserted replaced
15039:80190ab051c0 15040:99fd9483d3f0
     1 /*
     1 /*
     2  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    23 
    23 
    24 /**
    24 /**
    25  * @test
    25  * @test
    26  * @bug 8003280
    26  * @bug 8003280
    27  * @summary Add lambda tests
    27  * @summary Add lambda tests
    28  *  perform automated checks in type inference in lambda expressions in different contexts
    28  *  perform automated checks in type inference in lambda expressions
       
    29  *  in different contexts
       
    30  * @library ../../../lib
       
    31  * @build JavacTestingAbstractThreadedTest
    29  * @compile  TypeInferenceComboTest.java
    32  * @compile  TypeInferenceComboTest.java
    30  * @run main/timeout=360 TypeInferenceComboTest
    33  * @run main/timeout=360 TypeInferenceComboTest
    31  */
    34  */
    32 
    35 
    33 import com.sun.source.util.JavacTask;
       
    34 import java.net.URI;
    36 import java.net.URI;
    35 import java.util.Arrays;
    37 import java.util.Arrays;
    36 import javax.tools.Diagnostic;
    38 import javax.tools.Diagnostic;
    37 import javax.tools.JavaCompiler;
       
    38 import javax.tools.JavaFileObject;
    39 import javax.tools.JavaFileObject;
    39 import javax.tools.SimpleJavaFileObject;
    40 import javax.tools.SimpleJavaFileObject;
    40 import javax.tools.ToolProvider;
    41 import com.sun.source.util.JavacTask;
    41 import javax.tools.StandardJavaFileManager;
    42 
    42 
    43 public class TypeInferenceComboTest
    43 public class TypeInferenceComboTest {
    44     extends JavacTestingAbstractThreadedTest
       
    45     implements Runnable {
    44     enum Context {
    46     enum Context {
    45         ASSIGNMENT("SAM#Type s = #LBody;"),
    47         ASSIGNMENT("SAM#Type s = #LBody;"),
    46         METHOD_CALL("#GenericDeclKind void method1(SAM#Type s) { }\n" +
    48         METHOD_CALL("#GenericDeclKind void method1(SAM#Type s) { }\n" +
    47                     "void method2() {\n" +
    49                     "void method2() {\n" +
    48                     "    method1(#LBody);\n" +
    50                     "    method1(#LBody);\n" +
    57 
    59 
    58         Context(String context) {
    60         Context(String context) {
    59             this.context = context;
    61             this.context = context;
    60         }
    62         }
    61 
    63 
    62         String getContext(SamKind sk, TypeKind samTargetT, Keyword kw, TypeKind parameterT, TypeKind returnT, LambdaKind lk, ParameterKind pk, GenericDeclKind gdk, LambdaBody lb) {
    64         String getContext(SamKind sk, TypeKind samTargetT, Keyword kw,
       
    65                 TypeKind parameterT, TypeKind returnT, LambdaKind lk,
       
    66                 ParameterKind pk, GenericDeclKind gdk, LambdaBody lb) {
    63             String result = context;
    67             String result = context;
    64             if (sk == SamKind.GENERIC) {
    68             if (sk == SamKind.GENERIC) {
    65                 if(this == Context.METHOD_CALL) {
    69                 if(this == Context.METHOD_CALL) {
    66                     result = result.replaceAll("#GenericDeclKind", gdk.getGenericDeclKind(samTargetT));
    70                     result = result.replaceAll("#GenericDeclKind",
       
    71                             gdk.getGenericDeclKind(samTargetT));
    67                     if(gdk == GenericDeclKind.NON_GENERIC)
    72                     if(gdk == GenericDeclKind.NON_GENERIC)
    68                         result = result.replaceAll("#Type", "<" + samTargetT.typeStr + ">");
    73                         result = result.replaceAll("#Type", "<" +
       
    74                                 samTargetT.typeStr + ">");
    69                     else //#GenericDeclKind is <T> or <T extends xxx>
    75                     else //#GenericDeclKind is <T> or <T extends xxx>
    70                         result = result.replaceAll("#Type", "<T>");
    76                         result = result.replaceAll("#Type", "<T>");
    71                 }
    77                 }
    72                 else {
    78                 else {
    73                     if(kw == Keyword.VOID)
    79                     if(kw == Keyword.VOID)
    74                         result = result.replaceAll("#Type", "<" + samTargetT.typeStr + ">");
    80                         result = result.replaceAll("#Type", "<" +
       
    81                                 samTargetT.typeStr + ">");
    75                     else
    82                     else
    76                         result = result.replaceAll("#Type", "<? " + kw.keyStr + " " + samTargetT.typeStr + ">");
    83                         result = result.replaceAll("#Type", "<? " + kw.keyStr +
       
    84                                 " " + samTargetT.typeStr + ">");
    77                 }
    85                 }
    78             }
    86             }
    79             else
    87             else
    80                 result = result.replaceAll("#Type", "").replaceAll("#GenericDeclKind", "");
    88                 result = result.replaceAll("#Type", "").
    81 
    89                         replaceAll("#GenericDeclKind", "");
    82             return result.replaceAll("#LBody", lb.getLambdaBody(samTargetT, parameterT, returnT, lk, pk));
    90 
       
    91             return result.replaceAll("#LBody",
       
    92                     lb.getLambdaBody(samTargetT, parameterT, returnT, lk, pk));
    83         }
    93         }
    84     }
    94     }
    85 
    95 
    86     enum SamKind {
    96     enum SamKind {
    87         GENERIC("interface SAM<T> { #R m(#ARG); }"),
    97         GENERIC("interface SAM<T> { #R m(#ARG); }"),
    92         SamKind(String sam_str) {
   102         SamKind(String sam_str) {
    93             this.sam_str = sam_str;
   103             this.sam_str = sam_str;
    94         }
   104         }
    95 
   105 
    96         String getSam(TypeKind parameterT, TypeKind returnT) {
   106         String getSam(TypeKind parameterT, TypeKind returnT) {
    97             return sam_str.replaceAll("#ARG", parameterT == TypeKind.VOID ? "" : parameterT.typeStr + " arg")
   107             return sam_str.replaceAll("#ARG",
    98                           .replaceAll("#R", returnT.typeStr);
   108                     parameterT == TypeKind.VOID ?
       
   109                         "" : parameterT.typeStr + " arg")
       
   110                     .replaceAll("#R", returnT.typeStr);
    99         }
   111         }
   100     }
   112     }
   101 
   113 
   102     enum TypeKind {
   114     enum TypeKind {
   103         VOID("void", ""),
   115         VOID("void", ""),
   104         STRING("String", "\"hello\""),
   116         STRING("String", "\"hello\""),
   105         INTEGER("Integer", "1"),
   117         INTEGER("Integer", "1"),
   106         INT("int", "0"),
   118         INT("int", "0"),
   107         COMPARATOR("java.util.Comparator<String>", "(java.util.Comparator<String>)(a, b) -> a.length()-b.length()"),
   119         COMPARATOR("java.util.Comparator<String>",
       
   120                 "(java.util.Comparator<String>)(a, b) -> a.length()-b.length()"),
   108         SAM("SAM2", "null"),
   121         SAM("SAM2", "null"),
   109         GENERIC("T", null);
   122         GENERIC("T", null);
   110 
   123 
   111         String typeStr;
   124         String typeStr;
   112         String valStr;
   125         String valStr;
   150             this.keyStr = keyStr;
   163             this.keyStr = keyStr;
   151         }
   164         }
   152     }
   165     }
   153 
   166 
   154     enum LambdaBody {
   167     enum LambdaBody {
   155         RETURN_VOID("() -> #RET"),//no parameters, return type is one of the TypeKind
   168         //no parameters, return type is one of the TypeKind
   156         RETURN_ARG("(#PK arg) -> #RET");//has parameters, return type is one of the TypeKind
   169         RETURN_VOID("() -> #RET"),
       
   170         //has parameters, return type is one of the TypeKind
       
   171         RETURN_ARG("(#PK arg) -> #RET");
   157 
   172 
   158         String bodyStr;
   173         String bodyStr;
   159 
   174 
   160         LambdaBody(String bodyStr) {
   175         LambdaBody(String bodyStr) {
   161             this.bodyStr = bodyStr;
   176             this.bodyStr = bodyStr;
   162         }
   177         }
   163 
   178 
   164         String getLambdaBody(TypeKind samTargetT, TypeKind parameterT, TypeKind returnT, LambdaKind lk, ParameterKind pk) {
   179         String getLambdaBody(TypeKind samTargetT, TypeKind parameterT,
       
   180                 TypeKind returnT, LambdaKind lk, ParameterKind pk) {
   165             String result = bodyStr.replaceAll("#PK", pk.paramTemplate);
   181             String result = bodyStr.replaceAll("#PK", pk.paramTemplate);
   166 
   182 
   167             if(result.contains("#TYPE")) {
   183             if(result.contains("#TYPE")) {
   168                 if (parameterT == TypeKind.GENERIC && this != RETURN_VOID)
   184                 if (parameterT == TypeKind.GENERIC && this != RETURN_VOID)
   169                     result = result.replaceAll("#TYPE", samTargetT == null? "": samTargetT.typeStr);
   185                     result = result.replaceAll("#TYPE",
       
   186                             samTargetT == null? "": samTargetT.typeStr);
   170                 else
   187                 else
   171                     result = result.replaceAll("#TYPE", parameterT.typeStr);
   188                     result = result.replaceAll("#TYPE", parameterT.typeStr);
   172             }
   189             }
   173             if (this == RETURN_ARG && parameterT == returnT)
   190             if (this == RETURN_ARG && parameterT == returnT)
   174                 return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", "arg"));
   191                 return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", "arg"));
   175             else {
   192             else {
   176                 if(returnT != TypeKind.GENERIC)
   193                 if(returnT != TypeKind.GENERIC)
   177                     return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", (returnT==TypeKind.VOID && lk==LambdaKind.EXPRESSION)? "{}" : returnT.valStr));
   194                     return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL",
       
   195                             (returnT==TypeKind.VOID &&
       
   196                             lk==LambdaKind.EXPRESSION) ? "{}" : returnT.valStr));
   178                 else
   197                 else
   179                     return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", samTargetT.valStr));
   198                     return result.replaceAll("#RET",
       
   199                             lk.stmt.replaceAll("#VAL", samTargetT.valStr));
   180             }
   200             }
   181         }
   201         }
   182     }
   202     }
   183 
   203 
   184     enum GenericDeclKind {
   204     enum GenericDeclKind {
   201             if (lambdaBodyType != LambdaBody.RETURN_VOID)
   221             if (lambdaBodyType != LambdaBody.RETURN_VOID)
   202                 return false;
   222                 return false;
   203         }
   223         }
   204         else if (lambdaBodyType != LambdaBody.RETURN_ARG)
   224         else if (lambdaBodyType != LambdaBody.RETURN_ARG)
   205             return false;
   225             return false;
   206         if (  genericDeclKind == GenericDeclKind.GENERIC_NOBOUND || genericDeclKind == GenericDeclKind.GENERIC_BOUND ) {
   226         if (  genericDeclKind == GenericDeclKind.GENERIC_NOBOUND ||
   207             if ( parameterType == TypeKind.GENERIC && parameterKind == ParameterKind.IMPLICIT) //cyclic inference
   227                 genericDeclKind == GenericDeclKind.GENERIC_BOUND ) {
       
   228             if ( parameterType == TypeKind.GENERIC &&
       
   229                     parameterKind == ParameterKind.IMPLICIT) //cyclic inference
   208                 return false;
   230                 return false;
   209         }
   231         }
   210         return true;
   232         return true;
   211     }
   233     }
   212 
   234 
   214                          "interface SAM2 {\n" +
   236                          "interface SAM2 {\n" +
   215                          "    SAM m();\n" +
   237                          "    SAM m();\n" +
   216                          "}\n";
   238                          "}\n";
   217     SourceFile samSourceFile = new SourceFile("Sam.java", templateStr) {
   239     SourceFile samSourceFile = new SourceFile("Sam.java", templateStr) {
   218         public String toString() {
   240         public String toString() {
   219             return template.replaceAll("#C", samKind.getSam(parameterType, returnType));
   241             return template.replaceAll("#C",
       
   242                     samKind.getSam(parameterType, returnType));
   220         }
   243         }
   221     };
   244     };
   222 
   245 
   223     SourceFile clientSourceFile = new SourceFile("Client.java",
   246     SourceFile clientSourceFile = new SourceFile("Client.java",
   224                                                  "class Client { \n" +
   247                                                  "class Client { \n" +
   225                                                  "    #Context\n" +
   248                                                  "    #Context\n" +
   226                                                  "}") {
   249                                                  "}") {
   227         public String toString() {
   250         public String toString() {
   228             return template.replaceAll("#Context", context.getContext(samKind, samTargetType, keyword, parameterType, returnType, lambdaKind, parameterKind, genericDeclKind, lambdaBodyType));
   251             return template.replaceAll("#Context",
       
   252                     context.getContext(samKind, samTargetType, keyword,
       
   253                     parameterType, returnType, lambdaKind, parameterKind,
       
   254                     genericDeclKind, lambdaBodyType));
   229         }
   255         }
   230     };
   256     };
   231 
   257 
   232     void test() throws Exception {
   258     public void run() {
   233         System.out.println("kk:");
   259         outWriter.println("kk:");
   234         StringBuilder sb = new StringBuilder("SamKind:");
   260         StringBuilder sb = new StringBuilder("SamKind:");
   235         sb.append(samKind).append(" SamTargetType:").append(samTargetType).append(" ParameterType:").append(parameterType)
   261         sb.append(samKind).append(" SamTargetType:")
   236             .append(" ReturnType:").append(returnType).append(" Context:").append(context).append(" LambdaKind:").append(lambdaKind)
   262             .append(samTargetType).append(" ParameterType:").append(parameterType)
   237             .append(" LambdaBodyType:").append(lambdaBodyType).append(" ParameterKind:").append(parameterKind).append(" Keyword:").append(keyword);
   263             .append(" ReturnType:").append(returnType).append(" Context:")
   238         System.out.println(sb);
   264             .append(context).append(" LambdaKind:").append(lambdaKind)
       
   265             .append(" LambdaBodyType:").append(lambdaBodyType)
       
   266             .append(" ParameterKind:").append(parameterKind).append(" Keyword:")
       
   267             .append(keyword);
       
   268         outWriter.println(sb);
   239         DiagnosticChecker dc = new DiagnosticChecker();
   269         DiagnosticChecker dc = new DiagnosticChecker();
   240         JavacTask ct = (JavacTask)comp.getTask(null, fm, dc, null, null, Arrays.asList(samSourceFile, clientSourceFile));
   270         JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), dc,
   241         ct.analyze();
   271                 null, null, Arrays.asList(samSourceFile, clientSourceFile));
       
   272         try {
       
   273             ct.analyze();
       
   274         } catch (Throwable t) {
       
   275             processException(t);
       
   276         }
   242         if (dc.errorFound == checkTypeInference()) {
   277         if (dc.errorFound == checkTypeInference()) {
   243             throw new AssertionError(samSourceFile + "\n\n" + clientSourceFile + "\n" + parameterType + " " + returnType);
   278             throw new AssertionError(samSourceFile + "\n\n" +
       
   279                     clientSourceFile + "\n" + parameterType + " " + returnType);
   244         }
   280         }
   245     }
   281     }
   246 
   282 
   247     abstract class SourceFile extends SimpleJavaFileObject {
   283     abstract class SourceFile extends SimpleJavaFileObject {
   248 
   284 
   259         }
   295         }
   260 
   296 
   261         public abstract String toString();
   297         public abstract String toString();
   262     }
   298     }
   263 
   299 
   264     static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
   300     static class DiagnosticChecker
       
   301         implements javax.tools.DiagnosticListener<JavaFileObject> {
   265 
   302 
   266         boolean errorFound = false;
   303         boolean errorFound = false;
   267 
   304 
   268         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   305         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   269             if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   306             if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   281     LambdaKind lambdaKind;
   318     LambdaKind lambdaKind;
   282     ParameterKind parameterKind;
   319     ParameterKind parameterKind;
   283     Keyword keyword;
   320     Keyword keyword;
   284     GenericDeclKind genericDeclKind;
   321     GenericDeclKind genericDeclKind;
   285 
   322 
   286     static JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
   323     TypeInferenceComboTest(SamKind sk, TypeKind samTargetT, TypeKind parameterT,
   287     static StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
   324             TypeKind returnT, LambdaBody lb, Context c, LambdaKind lk,
   288 
   325             ParameterKind pk, Keyword kw, GenericDeclKind gdk) {
   289     TypeInferenceComboTest(SamKind sk, TypeKind samTargetT, TypeKind parameterT, TypeKind returnT, LambdaBody lb, Context c, LambdaKind lk, ParameterKind pk, Keyword kw, GenericDeclKind gdk) {
       
   290         samKind = sk;
   326         samKind = sk;
   291         samTargetType = samTargetT;
   327         samTargetType = samTargetT;
   292         parameterType = parameterT;
   328         parameterType = parameterT;
   293         returnType = returnT;
   329         returnType = returnT;
   294         context = c;
   330         context = c;
   306                     for(LambdaBody lb : LambdaBody.values()) {
   342                     for(LambdaBody lb : LambdaBody.values()) {
   307                         for (ParameterKind parameterK : ParameterKind.values()) {
   343                         for (ParameterKind parameterK : ParameterKind.values()) {
   308                             for(LambdaKind lambdaK : LambdaKind.values()) {
   344                             for(LambdaKind lambdaK : LambdaKind.values()) {
   309                                 for (SamKind sk : SamKind.values()) {
   345                                 for (SamKind sk : SamKind.values()) {
   310                                     if (sk == SamKind.NON_GENERIC) {
   346                                     if (sk == SamKind.NON_GENERIC) {
   311                                         if(parameterT != TypeKind.GENERIC && returnT != TypeKind.GENERIC )
   347                                         generateNonGenericSAM(ct, returnT,
   312                                             new TypeInferenceComboTest(sk, null, parameterT, returnT, lb, ct, lambdaK, parameterK, null, null).test();
   348                                                 parameterT, lb, parameterK,
       
   349                                                 lambdaK, sk);
   313                                     }
   350                                     }
   314                                     else if (sk == SamKind.GENERIC) {
   351                                     else if (sk == SamKind.GENERIC) {
   315                                         for (Keyword kw : Keyword.values()) {
   352                                         generateGenericSAM(ct, returnT,
   316                                             for (TypeKind samTargetT : TypeKind.values()) {
   353                                                 parameterT, lb, parameterK,
   317                                                 if(samTargetT != TypeKind.VOID && samTargetT != TypeKind.INT && samTargetT != TypeKind.GENERIC
   354                                                 lambdaK, sk);
   318                                                    && (parameterT == TypeKind.GENERIC || returnT == TypeKind.GENERIC)) {
       
   319                                                     if(ct != Context.METHOD_CALL) {
       
   320                                                         new TypeInferenceComboTest(sk, samTargetT, parameterT, returnT, lb, ct, lambdaK, parameterK, kw, null).test();
       
   321                                                     }
       
   322                                                     else {//Context.METHOD_CALL
       
   323                                                         for (GenericDeclKind gdk : GenericDeclKind.values())
       
   324                                                             new TypeInferenceComboTest(sk, samTargetT, parameterT, returnT, lb, ct, lambdaK, parameterK, kw, gdk).test();
       
   325                                                     }
       
   326                                                 }
       
   327                                             }
       
   328                                         }
       
   329                                     }
   355                                     }
   330                                 }
   356                                 }
   331                             }
   357                             }
   332                         }
   358                         }
   333                     }
   359                     }
   334                 }
   360                 }
   335             }
   361             }
   336         }
   362         }
   337     }
   363 
       
   364         checkAfterExec(false);
       
   365     }
       
   366 
       
   367     static void generateNonGenericSAM(Context ct, TypeKind returnT,
       
   368             TypeKind parameterT, LambdaBody lb, ParameterKind parameterK,
       
   369             LambdaKind lambdaK, SamKind sk) {
       
   370         if(parameterT != TypeKind.GENERIC && returnT != TypeKind.GENERIC ) {
       
   371             pool.execute(new TypeInferenceComboTest(sk, null, parameterT,
       
   372                     returnT, lb, ct, lambdaK, parameterK, null, null));
       
   373         }
       
   374     }
       
   375 
       
   376     static void generateGenericSAM(Context ct, TypeKind returnT,
       
   377             TypeKind parameterT, LambdaBody lb, ParameterKind parameterK,
       
   378             LambdaKind lambdaK, SamKind sk) {
       
   379         for (Keyword kw : Keyword.values()) {
       
   380             for (TypeKind samTargetT : TypeKind.values()) {
       
   381                 if(samTargetT != TypeKind.VOID &&
       
   382                    samTargetT != TypeKind.INT &&
       
   383                    samTargetT != TypeKind.GENERIC &&
       
   384                    (parameterT == TypeKind.GENERIC ||
       
   385                    returnT == TypeKind.GENERIC)) {
       
   386                     if(ct != Context.METHOD_CALL) {
       
   387                         pool.execute(
       
   388                             new TypeInferenceComboTest(sk, samTargetT, parameterT,
       
   389                                 returnT, lb, ct, lambdaK, parameterK, kw, null));
       
   390                     } else {//Context.METHOD_CALL
       
   391                         for (GenericDeclKind gdk :
       
   392                                 GenericDeclKind.values())
       
   393                             pool.execute(
       
   394                                     new TypeInferenceComboTest(sk, samTargetT,
       
   395                                     parameterT, returnT, lb, ct, lambdaK,
       
   396                                     parameterK, kw, gdk));
       
   397                     }
       
   398                 }
       
   399             }
       
   400          }
       
   401     }
       
   402 
   338 }
   403 }