test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java

Sat, 17 Nov 2012 19:01:03 +0000

author
mcimadamore
date
Sat, 17 Nov 2012 19:01:03 +0000
changeset 1415
01c9d4161882
child 1482
954541f13717
permissions
-rw-r--r--

8003280: Add lambda tests
Summary: Turn on lambda expression, method reference and default method support
Reviewed-by: jjg

     1 /*
     2  * Copyright (c) 2012, 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  *  Automatic test for checking correctness of structural most specific test routine
    29  * @run main/timeout=360 StructuralMostSpecificTest
    30  */
    32 import com.sun.source.util.JavacTask;
    33 import com.sun.tools.javac.api.ClientCodeWrapper;
    34 import com.sun.tools.javac.util.JCDiagnostic;
    35 import java.net.URI;
    36 import java.util.Arrays;
    37 import javax.tools.Diagnostic;
    38 import javax.tools.JavaCompiler;
    39 import javax.tools.JavaFileObject;
    40 import javax.tools.SimpleJavaFileObject;
    41 import javax.tools.StandardJavaFileManager;
    42 import javax.tools.ToolProvider;
    44 public class StructuralMostSpecificTest {
    46     static int checkCount = 0;
    48     enum RetTypeKind {
    49         SHORT("short"),
    50         INT("int"),
    51         OBJECT("Object"),
    52         INTEGER("Integer"),
    53         VOID("void"),
    54         J_L_VOID("Void");
    56         String retTypeStr;
    58         RetTypeKind(String retTypeStr) {
    59             this.retTypeStr = retTypeStr;
    60         }
    62         boolean moreSpecificThan(RetTypeKind rk) {
    63             return moreSpecificThan[this.ordinal()][rk.ordinal()];
    64         }
    66         static boolean[][] moreSpecificThan = {
    67                 //              SHORT |  INT  | OBJECT | INTEGER | VOID  | J_L_VOID
    68                 /* SHORT */   { true  , true  , true   , false   , false , false },
    69                 /* INT */     { false , true  , true   , true    , false , false },
    70                 /* OBJECT */  { false , false , true   , false   , false , false },
    71                 /* INTEGER */ { false , false , true   , true    , false , false },
    72                 /* VOID */    { false , false , false  , false   , true  , true  },
    73                 /* J_L_VOID */{ false , false , true   , false   , false , true  } };
    74     }
    76     enum ArgTypeKind {
    77         SHORT("short"),
    78         INT("int"),
    79         BOOLEAN("boolean"),
    80         OBJECT("Object"),
    81         INTEGER("Integer"),
    82         DOUBLE("Double");
    84         String argTypeStr;
    86         ArgTypeKind(String typeStr) {
    87             this.argTypeStr = typeStr;
    88         }
    89     }
    91     enum ExceptionKind {
    92         NONE(""),
    93         EXCEPTION("throws Exception"),
    94         SQL_EXCEPTION("throws java.sql.SQLException"),
    95         IO_EXCEPTION("throws java.io.IOException");
    97         String exceptionStr;
    99         ExceptionKind(String exceptionStr) {
   100             this.exceptionStr = exceptionStr;
   101         }
   102     }
   104     enum LambdaReturnKind {
   105         VOID("return;"),
   106         SHORT("return (short)0;"),
   107         INT("return 0;"),
   108         INTEGER("return (Integer)null"),
   109         NULL("return null;");
   111         String retStr;
   113         LambdaReturnKind(String retStr) {
   114             this.retStr = retStr;
   115         }
   117         boolean compatibleWith(RetTypeKind rk) {
   118             return compatibleWith[rk.ordinal()][ordinal()];
   119         }
   121         static boolean[][] compatibleWith = {
   122                 //              VOID  | SHORT | INT     | INTEGER | NULL
   123                 /* SHORT */   { false , true  , false   , false   , false },
   124                 /* INT */     { false , true  , true    , true    , false },
   125                 /* OBJECT */  { false , true  , true    , true    , true  },
   126                 /* INTEGER */ { false , false , true    , true    , true  },
   127                 /* VOID */    { true  , false , false   , false   , false },
   128                 /* J_L_VOID */{ false , false , false   , false   , true  } };
   130         boolean needsConversion(RetTypeKind rk) {
   131             return needsConversion[rk.ordinal()][ordinal()];
   132         }
   134         static boolean[][] needsConversion = {
   135                 //              VOID  | SHORT | INT     | INTEGER | NULL
   136                 /* SHORT */   { false , false , false   , false   , false },
   137                 /* INT */     { false , false , false   , true    , false },
   138                 /* OBJECT */  { false , true  , true    , false   , false },
   139                 /* INTEGER */ { false , false , true    , false   , false },
   140                 /* VOID */    { false , false , false   , false   , false },
   141                 /* J_L_VOID */{ true  , false , false   , false   , false } };
   142     }
   144     public static void main(String... args) throws Exception {
   146         //create default shared JavaCompiler - reused across multiple compilations
   147         JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
   148         StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
   150         for (LambdaReturnKind lrk : LambdaReturnKind.values()) {
   151             for (RetTypeKind rk1 : RetTypeKind.values()) {
   152                 for (RetTypeKind rk2 : RetTypeKind.values()) {
   153                     for (ExceptionKind ek1 : ExceptionKind.values()) {
   154                         for (ExceptionKind ek2 : ExceptionKind.values()) {
   155                             for (ArgTypeKind ak11 : ArgTypeKind.values()) {
   156                                 for (ArgTypeKind ak12 : ArgTypeKind.values()) {
   157                                     new StructuralMostSpecificTest(lrk, rk1, rk2, ek1, ek2, ak11, ak12).run(comp, fm);
   158                                 }
   159                             }
   160                         }
   161                     }
   162                 }
   163             }
   164         }
   165         System.out.println("Total check executed: " + checkCount);
   166     }
   168     LambdaReturnKind lrk;
   169     RetTypeKind rt1, rt2;
   170     ArgTypeKind ak1, ak2;
   171     ExceptionKind ek1, ek2;
   172     JavaSource source;
   173     DiagnosticChecker diagChecker;
   175     StructuralMostSpecificTest(LambdaReturnKind lrk, RetTypeKind rt1, RetTypeKind rt2,
   176             ExceptionKind ek1, ExceptionKind ek2, ArgTypeKind ak1, ArgTypeKind ak2) {
   177         this.lrk = lrk;
   178         this.rt1 = rt1;
   179         this.rt2 = rt2;
   180         this.ek1 = ek1;
   181         this.ek2 = ek2;
   182         this.ak1 = ak1;
   183         this.ak2 = ak2;
   184         this.source = new JavaSource();
   185         this.diagChecker = new DiagnosticChecker();
   186     }
   188     class JavaSource extends SimpleJavaFileObject {
   190         String template = "interface SAM1 {\n" +
   191                           "   #R1 m(#A1 a1) #E1;\n" +
   192                           "}\n" +
   193                           "interface SAM2 {\n" +
   194                           "   #R2 m(#A2 a1) #E2;\n" +
   195                           "}\n" +
   196                           "class Test {\n" +
   197                           "   void m(SAM1 s) { }\n" +
   198                           "   void m(SAM2 s) { }\n" +
   199                           "   { m(x->{ #LR }); }\n" +
   200                           "}\n";
   202         String source;
   204         public JavaSource() {
   205             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   206             source = template.replaceAll("#LR", lrk.retStr)
   207                     .replaceAll("#R1", rt1.retTypeStr)
   208                     .replaceAll("#R2", rt2.retTypeStr)
   209                     .replaceAll("#A1", ak1.argTypeStr)
   210                     .replaceAll("#A2", ak2.argTypeStr)
   211                     .replaceAll("#E1", ek1.exceptionStr)
   212                     .replaceAll("#E2", ek2.exceptionStr);
   213         }
   215         @Override
   216         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   217             return source;
   218         }
   219     }
   221     void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
   222         JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
   223                 Arrays.asList("-XDverboseResolution=all,-predef,-internal,-object-init"),
   224                 null, Arrays.asList(source));
   225         try {
   226             ct.analyze();
   227         } catch (Throwable ex) {
   228             throw new AssertionError("Error thron when analyzing the following source:\n" + source.getCharContent(true));
   229         }
   230         check();
   231     }
   233     void check() {
   234         checkCount++;
   236         if (!lrk.compatibleWith(rt1) || !lrk.compatibleWith(rt2))
   237             return;
   239         if (lrk.needsConversion(rt1) != lrk.needsConversion(rt2))
   240             return;
   242         boolean m1MoreSpecific = moreSpecific(rt1, rt2, ek1, ek2, ak1, ak2);
   243         boolean m2MoreSpecific = moreSpecific(rt2, rt1, ek2, ek1, ak2, ak1);
   245         boolean ambiguous = (m1MoreSpecific == m2MoreSpecific);
   247         if (ambiguous != diagChecker.ambiguityFound) {
   248             throw new Error("invalid diagnostics for source:\n" +
   249                 source.getCharContent(true) +
   250                 "\nAmbiguity found: " + diagChecker.ambiguityFound +
   251                 "\nm1 more specific: " + m1MoreSpecific +
   252                 "\nm2 more specific: " + m2MoreSpecific +
   253                 "\nexpected ambiguity: " + ambiguous);
   254         }
   256         if (!ambiguous) {
   257             String sigToCheck = m1MoreSpecific ? "m(SAM1)" : "m(SAM2)";
   258             if (!sigToCheck.equals(diagChecker.mostSpecificSig)) {
   259                 throw new Error("invalid most specific method selected:\n" +
   260                 source.getCharContent(true) +
   261                 "\nMost specific found: " + diagChecker.mostSpecificSig +
   262                 "\nm1 more specific: " + m1MoreSpecific +
   263                 "\nm2 more specific: " + m2MoreSpecific);
   264             }
   265         }
   266     }
   268     boolean moreSpecific(RetTypeKind rk1, RetTypeKind rk2, ExceptionKind ek1, ExceptionKind ek2,
   269             ArgTypeKind ak1, ArgTypeKind ak2) {
   270         if (!rk1.moreSpecificThan(rk2))
   271             return false;
   273         if (ak1 != ak2)
   274             return false;
   276         return true;
   277     }
   279     static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
   281         boolean ambiguityFound;
   282         String mostSpecificSig;
   284         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   285             try {
   286                 if (diagnostic.getKind() == Diagnostic.Kind.ERROR &&
   287                         diagnostic.getCode().equals("compiler.err.ref.ambiguous")) {
   288                     ambiguityFound = true;
   289                 } else if (diagnostic.getKind() == Diagnostic.Kind.NOTE &&
   290                         diagnostic.getCode().equals("compiler.note.verbose.resolve.multi")) {
   291                     ClientCodeWrapper.DiagnosticSourceUnwrapper dsu =
   292                             (ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic;
   293                     JCDiagnostic.MultilineDiagnostic mdiag = (JCDiagnostic.MultilineDiagnostic)dsu.d;
   294                     int mostSpecificIndex = (Integer)mdiag.getArgs()[2];
   295                     mostSpecificSig = ((JCDiagnostic)mdiag.getSubdiagnostics().get(mostSpecificIndex)).getArgs()[1].toString();
   296                 }
   297             } catch (RuntimeException t) {
   298                 t.printStackTrace();
   299                 throw t;
   300             }
   301         }
   302     }
   303 }

mercurial