test/tools/javac/cast/intersection/IntersectionTypeCastTest.java

Wed, 23 Jan 2013 20:57:40 +0000

author
vromero
date
Wed, 23 Jan 2013 20:57:40 +0000
changeset 1520
5c956be64b9e
parent 1511
c7c41a044e7c
child 2047
5f915a0c9615
permissions
-rw-r--r--

8006694: temporarily workaround combo tests are causing time out in several platforms
Reviewed-by: jjg
Contributed-by: maurizio.cimadamore@oracle.com

     1 /*
     2  * Copyright (c) 2012, 2013, 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 8002099 8006694
    27  * @summary Add support for intersection types in cast expression
    28  *  temporarily workaround combo tests are causing time out in several platforms
    29  * @library ../../lib
    30  * @build JavacTestingAbstractThreadedTest
    31  * @run main/othervm/timeout=360 IntersectionTypeCastTest
    32  */
    34 // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
    35 // see JDK-8006746
    37 import java.net.URI;
    38 import java.util.Arrays;
    39 import javax.tools.Diagnostic;
    40 import javax.tools.JavaCompiler;
    41 import javax.tools.JavaFileObject;
    42 import javax.tools.SimpleJavaFileObject;
    43 import javax.tools.ToolProvider;
    45 import com.sun.source.util.JavacTask;
    46 import com.sun.tools.javac.util.List;
    47 import com.sun.tools.javac.util.ListBuffer;
    49 public class IntersectionTypeCastTest
    50     extends JavacTestingAbstractThreadedTest
    51     implements Runnable {
    53     interface Type {
    54         boolean subtypeOf(Type that);
    55         String asString();
    56         boolean isClass();
    57         boolean isInterface();
    58     }
    60     enum InterfaceKind implements Type {
    61         A("interface A { }\n", "A", null),
    62         B("interface B { }\n", "B", null),
    63         C("interface C extends A { }\n", "C", A);
    65         String declStr;
    66         String typeStr;
    67         InterfaceKind superInterface;
    69         InterfaceKind(String declStr, String typeStr,
    70                 InterfaceKind superInterface) {
    71             this.declStr = declStr;
    72             this.typeStr = typeStr;
    73             this.superInterface = superInterface;
    74         }
    76         @Override
    77         public boolean subtypeOf(Type that) {
    78             return this == that || superInterface == that ||
    79                    that == ClassKind.OBJECT;
    80         }
    82         @Override
    83         public String asString() {
    84             return typeStr;
    85         }
    87         @Override
    88         public boolean isClass() {
    89             return false;
    90         }
    92         @Override
    93         public boolean isInterface() {
    94             return true;
    95         }
    96     }
    98     enum ClassKind implements Type {
    99         OBJECT(null, "Object"),
   100         CA("#M class CA implements A { }\n", "CA",
   101            InterfaceKind.A),
   102         CB("#M class CB implements B { }\n", "CB",
   103            InterfaceKind.B),
   104         CAB("#M class CAB implements A, B { }\n", "CAB",
   105             InterfaceKind.A, InterfaceKind.B),
   106         CC("#M class CC implements C { }\n", "CC",
   107            InterfaceKind.C, InterfaceKind.A),
   108         CCA("#M class CCA implements C, A { }\n", "CCA",
   109             InterfaceKind.C, InterfaceKind.A),
   110         CCB("#M class CCB implements C, B { }\n", "CCB",
   111             InterfaceKind.C, InterfaceKind.A, InterfaceKind.B),
   112         CCAB("#M class CCAB implements C, A, B { }\n", "CCAB",
   113              InterfaceKind.C, InterfaceKind.A, InterfaceKind.B);
   115         String declTemplate;
   116         String typeStr;
   117         List<InterfaceKind> superInterfaces;
   119         ClassKind(String declTemplate, String typeStr,
   120                 InterfaceKind... superInterfaces) {
   121             this.declTemplate = declTemplate;
   122             this.typeStr = typeStr;
   123             this.superInterfaces = List.from(superInterfaces);
   124         }
   126         String getDecl(ModifierKind mod) {
   127             return declTemplate != null ?
   128                     declTemplate.replaceAll("#M", mod.modStr) :
   129                     "";
   130         }
   132         @Override
   133         public boolean subtypeOf(Type that) {
   134             return this == that || superInterfaces.contains(that) ||
   135                     that == OBJECT;
   136         }
   138         @Override
   139         public String asString() {
   140             return typeStr;
   141         }
   143         @Override
   144         public boolean isClass() {
   145             return true;
   146         }
   148         @Override
   149         public boolean isInterface() {
   150             return false;
   151         }
   152     }
   154     enum ModifierKind {
   155         NONE(""),
   156         FINAL("final");
   158         String modStr;
   160         ModifierKind(String modStr) {
   161             this.modStr = modStr;
   162         }
   163     }
   165     enum CastKind {
   166         CLASS("(#C)", 0),
   167         INTERFACE("(#I0)", 1),
   168         INTERSECTION2("(#C & #I0)", 1),
   169         INTERSECTION3("(#C & #I0 & #I1)", 2);
   170         //INTERSECTION4("(#C & #I0 & #I1 & #I2)", 3);
   172         String castTemplate;
   173         int interfaceBounds;
   175         CastKind(String castTemplate, int interfaceBounds) {
   176             this.castTemplate = castTemplate;
   177             this.interfaceBounds = interfaceBounds;
   178         }
   179     }
   181     static class CastInfo {
   182         CastKind kind;
   183         Type[] types;
   185         CastInfo(CastKind kind, Type... types) {
   186             this.kind = kind;
   187             this.types = types;
   188         }
   190         String getCast() {
   191             String temp = kind.castTemplate.replaceAll("#C",
   192                     types[0].asString());
   193             for (int i = 0; i < kind.interfaceBounds ; i++) {
   194                 temp = temp.replace(String.format("#I%d", i),
   195                                     types[i + 1].asString());
   196             }
   197             return temp;
   198         }
   200         boolean hasDuplicateTypes() {
   201             for (int i = 0 ; i < types.length ; i++) {
   202                 for (int j = 0 ; j < types.length ; j++) {
   203                     if (i != j && types[i] == types[j]) {
   204                         return true;
   205                     }
   206                 }
   207             }
   208             return false;
   209         }
   211         boolean compatibleWith(ModifierKind mod, CastInfo that) {
   212             for (Type t1 : types) {
   213                 for (Type t2 : that.types) {
   214                     boolean compat =
   215                             t1.subtypeOf(t2) ||
   216                             t2.subtypeOf(t1) ||
   217                             (t1.isInterface() && t2.isInterface()) || //side-cast (1)
   218                             (mod == ModifierKind.NONE &&
   219                             (t1.isInterface() != t2.isInterface())); //side-cast (2)
   220                     if (!compat) return false;
   221                 }
   222             }
   223             return true;
   224         }
   225     }
   227     public static void main(String... args) throws Exception {
   228         for (ModifierKind mod : ModifierKind.values()) {
   229             for (CastInfo cast1 : allCastInfo()) {
   230                 for (CastInfo cast2 : allCastInfo()) {
   231                     pool.execute(
   232                         new IntersectionTypeCastTest(mod, cast1, cast2));
   233                 }
   234             }
   235         }
   236         checkAfterExec();
   237     }
   239     static List<CastInfo> allCastInfo() {
   240         ListBuffer<CastInfo> buf = ListBuffer.lb();
   241         for (CastKind kind : CastKind.values()) {
   242             for (ClassKind clazz : ClassKind.values()) {
   243                 if (kind == CastKind.INTERFACE && clazz != ClassKind.OBJECT) {
   244                     continue;
   245                 } else if (kind.interfaceBounds == 0) {
   246                     buf.append(new CastInfo(kind, clazz));
   247                     continue;
   248                 } else {
   249                     for (InterfaceKind intf1 : InterfaceKind.values()) {
   250                         if (kind.interfaceBounds == 1) {
   251                             buf.append(new CastInfo(kind, clazz, intf1));
   252                             continue;
   253                         } else {
   254                             for (InterfaceKind intf2 : InterfaceKind.values()) {
   255                                 if (kind.interfaceBounds == 2) {
   256                                     buf.append(
   257                                             new CastInfo(kind, clazz, intf1, intf2));
   258                                     continue;
   259                                 } else {
   260                                     for (InterfaceKind intf3 : InterfaceKind.values()) {
   261                                         buf.append(
   262                                                 new CastInfo(kind, clazz, intf1,
   263                                                              intf2, intf3));
   264                                         continue;
   265                                     }
   266                                 }
   267                             }
   268                         }
   269                     }
   270                 }
   271             }
   272         }
   273         return buf.toList();
   274     }
   276     ModifierKind mod;
   277     CastInfo cast1, cast2;
   278     JavaSource source;
   279     DiagnosticChecker diagChecker;
   281     IntersectionTypeCastTest(ModifierKind mod, CastInfo cast1, CastInfo cast2) {
   282         this.mod = mod;
   283         this.cast1 = cast1;
   284         this.cast2 = cast2;
   285         this.source = new JavaSource();
   286         this.diagChecker = new DiagnosticChecker();
   287     }
   289     @Override
   290     public void run() {
   291         final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
   293         JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), diagChecker,
   294                 null, null, Arrays.asList(source));
   295         try {
   296             ct.analyze();
   297         } catch (Throwable ex) {
   298             throw new AssertionError("Error thrown when compiling the following code:\n" +
   299                     source.getCharContent(true));
   300         }
   301         check();
   302     }
   304     class JavaSource extends SimpleJavaFileObject {
   306         String bodyTemplate = "class Test {\n" +
   307                               "   void test() {\n" +
   308                               "      Object o = #C1#C2null;\n" +
   309                               "   } }";
   311         String source = "";
   313         public JavaSource() {
   314             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   315             for (ClassKind ck : ClassKind.values()) {
   316                 source += ck.getDecl(mod);
   317             }
   318             for (InterfaceKind ik : InterfaceKind.values()) {
   319                 source += ik.declStr;
   320             }
   321             source += bodyTemplate.replaceAll("#C1", cast1.getCast()).
   322                     replaceAll("#C2", cast2.getCast());
   323         }
   325         @Override
   326         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   327             return source;
   328         }
   329     }
   331     void check() {
   332         checkCount.incrementAndGet();
   334         boolean errorExpected = cast1.hasDuplicateTypes() ||
   335                 cast2.hasDuplicateTypes();
   337         errorExpected |= !cast2.compatibleWith(mod, cast1);
   339         if (errorExpected != diagChecker.errorFound) {
   340             throw new Error("invalid diagnostics for source:\n" +
   341                 source.getCharContent(true) +
   342                 "\nFound error: " + diagChecker.errorFound +
   343                 "\nExpected error: " + errorExpected);
   344         }
   345     }
   347     static class DiagnosticChecker
   348         implements javax.tools.DiagnosticListener<JavaFileObject> {
   350         boolean errorFound;
   352         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   353             if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   354                 errorFound = true;
   355             }
   356         }
   357     }
   359 }

mercurial