test/tools/javac/lambda/lambdaExpression/SamConversionComboTest.java

Mon, 21 Jan 2013 20:13:56 +0000

author
mcimadamore
date
Mon, 21 Jan 2013 20:13:56 +0000
changeset 1510
7873d37f5b37
parent 1415
01c9d4161882
child 2227
998b10c43157
permissions
-rw-r--r--

8005244: Implement overload resolution as per latest spec EDR
Summary: Add support for stuck expressions and provisional applicability
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 2011, 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  */
    24 /**
    25  * @test
    26  * @bug 8003280
    27  * @summary Add lambda tests
    28  *   Test SAM conversion of lambda expressions in combinations of different contexts,
    29  *           lambda body types(statement/expression), explict/implicit target type etc, to verify
    30  *           SAM conversion being conducted successfully as expected.
    31  */
    33 import com.sun.source.util.JavacTask;
    34 import java.net.URI;
    35 import java.util.Arrays;
    36 import javax.tools.Diagnostic;
    37 import javax.tools.JavaCompiler;
    38 import javax.tools.JavaFileObject;
    39 import javax.tools.SimpleJavaFileObject;
    40 import javax.tools.ToolProvider;
    42 public class SamConversionComboTest {
    44     enum FInterface {
    45         A("A", "interface A { Integer m(int i); }"),
    46         B("B", "interface B { int m(Integer i); }"),
    47         C("C", "interface C { int m(Integer i) throws Exception; }");
    49         String interfaceType;
    50         String interfaceDef;
    52         FInterface(String interfaceType, String interfaceDef) {
    53             this.interfaceType = interfaceType;
    54             this.interfaceDef = interfaceDef;
    55         }
    57         String getParameterType() {
    58             switch(this) {
    59             case A:
    60                 return "int";
    61             case B:
    62             case C:
    63                 return "Integer";
    64             default:
    65                 return null;
    66             }
    67         }
    68     }
    70     enum Context {
    71         ASSIGNMENT("#FType f = #LBody;"),
    72         METHOD_CALL("void method1(#FType f) { }\n" +
    73                     "    void method2() {\n" +
    74                     "        method1(#LBody);\n" +
    75                     "    }"),
    76         CONSTRUCTOR("X x = new X(#LBody);"),
    77         RETURN_OF_METHOD("#FType method1() {\n" +
    78                          "    return #LBody;\n" +
    79                          "}"),
    80         ARRAY_INITIALIZER("Object[] oarray = {\"a\", 1, (#FType)#LBody};"),
    81         LAMBDA_BODY("#FType f = n -> ((#FType)#LBody).m(n);"),
    82         CAST("void test() throws Exception { int n = ((#FType)#LBody).m(1); }"),
    83         CONDITIONAL_EXPRESSION("#FType f = 2 > 1 ? #LBody : null;");
    85         String context;
    87         Context(String context) {
    88             this.context = context;
    89         }
    91         String getContext(FInterface f, LambdaKind lk, LambdaBody lb, ReturnValue rv) {
    92             return context.replace("#FType", f.interfaceType).replace("#LBody", lb.getLambdaBody(f, lk, rv));
    93         }
    94     }
    96     enum LambdaKind {
    97         EXPRESSION("#VAL"),
    98         STATEMENT("{return #VAL;}"),
    99         EXCEPTION_STMT("{throw new Exception();}");
   101         String stmt;
   103         LambdaKind(String stmt) {
   104             this.stmt = stmt;
   105         }
   106     }
   108     enum ReturnValue {
   109         INT("i + 1"),
   110         INTEGER("new Integer(i+1)"),
   111         INT2("i.intValue() + 1"),
   112         STRING("i + \"\""),
   113         DOUBLE("i * 1.0");
   115         String rValue;
   117         ReturnValue(String rValue) {
   118             this.rValue = rValue;
   119         }
   120     }
   122     enum LambdaBody {
   123         IMPLICIT("i -> #RET"),//type inferred
   124         EXPLICIT("(#Type i) -> #RET");//explicit type
   126         String bodyStr;
   128         LambdaBody(String bodyStr) {
   129             this.bodyStr = bodyStr;
   130         }
   132         String getLambdaBody(FInterface fi, LambdaKind lk, ReturnValue rv) {
   133             return bodyStr.replace("#Type", fi.getParameterType()).replace("#RET", lk.stmt.replace("#VAL", rv.rValue));
   134         }
   135     }
   137     boolean checkSamConversion() {
   138         if(lambdaKind != LambdaKind.EXCEPTION_STMT && (returnValue == ReturnValue.DOUBLE || returnValue == ReturnValue.STRING)) //return type mismatch
   139             return false;
   140         if(context != Context.CONSTRUCTOR) {//context other than construcotr argument
   141             if(fInterface != FInterface.C && lambdaKind == LambdaKind.EXCEPTION_STMT)
   142                 return false;
   143             if(fInterface == FInterface.A && returnValue == ReturnValue.INT2)
   144                 return false;
   145         }
   146         else { //constructor argument context
   147             //match X(A a) or X(B b) or X(C c)
   148             if (lambdaKind == LambdaKind.EXCEPTION_STMT) {
   149                 return false; //ambiguous target type
   150             }
   151             else if(lambdaBody == LambdaBody.IMPLICIT) {
   152                 return false;
   153             }
   154             else { //explicit parameter type
   155                 if(fInterface.getParameterType().equals("Integer")) //ambiguous target type
   156                 //e.g. X x = new X((Integer i) -> i + 1);
   157                     return false;
   158                 if(returnValue == ReturnValue.INT2)
   159                 //e.g. X x = new X(int i -> i.intValue() + 1);
   160                     return false;
   161             }
   162         }
   163         return true;
   164     }
   166     SourceFile samSourceFile = new SourceFile("FInterface.java", "#C") {
   167         public String toString() {
   168             String interfaces = "";
   169             for(FInterface fi : FInterface.values())
   170                 interfaces += fi.interfaceDef + "\n";
   171             return template.replace("#C", interfaces);
   172         }
   173     };
   175     String clientTemplate = "class Client {\n" +
   176                             "    #Context\n" +
   177                             "}\n\n" +
   179                             "class X {\n" +
   180                             "    int value = 0;\n\n" +
   182                             "    X(A a) {\n" +
   183                             "        value = a.m(6);\n" +
   184                             "    }\n\n" +
   186                             "    X(B b) {\n" +
   187                             "        value = b.m(7);\n" +
   188                             "    }\n\n" +
   190                             "    X(C c) {\n" +
   191                             "        try {\n" +
   192                             "            value = c.m(8);\n" +
   193                             "        } catch (Exception e){}\n" +
   194                             "    }\n" +
   195                             "}";
   196     SourceFile clientSourceFile = new SourceFile("Client.java", clientTemplate) {
   197         public String toString() {
   198             return template.replace("#Context", context.getContext(fInterface, lambdaKind, lambdaBody, returnValue));
   199         }
   200     };
   202     void test() throws Exception {
   203         System.out.println("\n====================================");
   204         System.out.println(fInterface + ", " +  context + ", " + lambdaKind + ", " + lambdaBody + ", " + returnValue);
   205         System.out.println(samSourceFile + "\n");
   206         String clientFileStr = clientSourceFile.toString();
   207         System.out.println(clientFileStr.substring(0, clientFileStr.indexOf("\n\n")));
   209         final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
   210         DiagnosticChecker dc = new DiagnosticChecker();
   211         JavacTask ct = (JavacTask)tool.getTask(null, null, dc, null, null, Arrays.asList(samSourceFile, clientSourceFile));
   212         ct.analyze();
   213         if (dc.errorFound == checkSamConversion()) {
   214             throw new AssertionError(samSourceFile + "\n\n" + clientSourceFile);
   215         }
   216         count++;
   217     }
   219     abstract class SourceFile extends SimpleJavaFileObject {
   221         protected String template;
   223         public SourceFile(String filename, String template) {
   224             super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE);
   225             this.template = template;
   226         }
   228         @Override
   229         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   230             return toString();
   231         }
   233         public abstract String toString();
   234     }
   236     static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
   238         boolean errorFound = false;
   240         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   241             if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   242                 errorFound = true;
   243             }
   244         }
   245     }
   247     FInterface fInterface;
   248     Context context;
   249     LambdaBody lambdaBody;
   250     LambdaKind lambdaKind;
   251     ReturnValue returnValue;
   252     static int count = 0;
   254     SamConversionComboTest(FInterface f, Context c, LambdaBody lb, LambdaKind lk, ReturnValue rv) {
   255         fInterface = f;
   256         context = c;
   257         lambdaKind = lk;
   258         lambdaBody = lb;
   259         returnValue = rv;
   260     }
   262     public static void main(String[] args) throws Exception {
   263         for(Context ct : Context.values()) {
   264             for (FInterface fi : FInterface.values()) {
   265                 for (LambdaKind lk: LambdaKind.values()) {
   266                     for (LambdaBody lb : LambdaBody.values()) {
   267                         for(ReturnValue rv : ReturnValue.values()) {
   268                             new SamConversionComboTest(fi, ct, lb, lk, rv).test();
   269                         }
   270                     }
   271                 }
   272             }
   273         }
   274         System.out.println("total tests: " + count);
   275     }
   276 }

mercurial