test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java

Wed, 27 Apr 2016 01:34:52 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17

     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 7192246 8006694
    27  * @summary Automatic test for checking correctness of default super/this resolution
    28  *  temporarily workaround combo tests are causing time out in several platforms
    29  * @library ../../lib
    30  * @build JavacTestingAbstractThreadedTest
    31  * @run main/othervm TestDefaultSuperCall
    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 java.util.ArrayList;
    40 import java.util.List;
    41 import javax.tools.Diagnostic;
    42 import javax.tools.JavaFileObject;
    43 import javax.tools.SimpleJavaFileObject;
    45 import com.sun.source.util.JavacTask;
    47 public class TestDefaultSuperCall
    48     extends JavacTestingAbstractThreadedTest
    49     implements Runnable {
    51     enum InterfaceKind {
    52         DEFAULT("interface A extends B { default void m() { } }"),
    53         ABSTRACT("interface A extends B { void m(); }"),
    54         NONE("interface A extends B { }");
    56         String interfaceStr;
    58         InterfaceKind(String interfaceStr) {
    59             this.interfaceStr = interfaceStr;
    60         }
    62         boolean methodDefined() {
    63             return this == DEFAULT;
    64         }
    65     }
    67     enum PruneKind {
    68         NO_PRUNE("interface C { }"),
    69         PRUNE("interface C extends A { }");
    71         boolean methodDefined(InterfaceKind ik) {
    72             return this == PRUNE &&
    73                     ik.methodDefined();
    74         }
    76         String interfaceStr;
    78         PruneKind(String interfaceStr) {
    79             this.interfaceStr = interfaceStr;
    80         }
    81     }
    83     enum QualifierKind {
    84         DIRECT_1("C"),
    85         DIRECT_2("A"),
    86         INDIRECT("B"),
    87         UNRELATED("E"),
    88         ENCLOSING_1(null),
    89         ENCLOSING_2(null);
    91         String qualifierStr;
    93         QualifierKind(String qualifierStr) {
    94             this.qualifierStr = qualifierStr;
    95         }
    97         String getQualifier(Shape sh) {
    98             switch (this) {
    99                 case ENCLOSING_1: return sh.enclosingAt(0);
   100                 case ENCLOSING_2: return sh.enclosingAt(1);
   101                 default:
   102                     return qualifierStr;
   103             }
   104         }
   106         boolean isEnclosing() {
   107             return this == ENCLOSING_1 ||
   108                     this == ENCLOSING_2;
   109         }
   111         boolean allowSuperCall(InterfaceKind ik, PruneKind pk) {
   112             switch (this) {
   113                 case DIRECT_1:
   114                     return pk.methodDefined(ik);
   115                 case DIRECT_2:
   116                     return ik.methodDefined() && pk == PruneKind.NO_PRUNE;
   117                 default:
   118                     return false;
   119             }
   120         }
   121     }
   123     enum ExprKind {
   124         THIS("this"),
   125         SUPER("super");
   127         String exprStr;
   129         ExprKind(String exprStr) {
   130             this.exprStr = exprStr;
   131         }
   132     }
   134     enum ElementKind {
   135         INTERFACE("interface #N { #B }", true),
   136         INTERFACE_EXTENDS("interface #N extends A, C { #B }", true),
   137         CLASS("class #N { #B }", false),
   138         CLASS_EXTENDS("abstract class #N implements A, C { #B }", false),
   139         STATIC_CLASS("static class #N { #B }", true),
   140         STATIC_CLASS_EXTENDS("abstract static class #N implements A, C { #B }", true),
   141         ANON_CLASS("new Object() { #B };", false),
   142         METHOD("void test() { #B }", false),
   143         STATIC_METHOD("static void test() { #B }", true),
   144         DEFAULT_METHOD("default void test() { #B }", false);
   146         String templateDecl;
   147         boolean isStatic;
   149         ElementKind(String templateDecl, boolean isStatic) {
   150             this.templateDecl = templateDecl;
   151             this.isStatic = isStatic;
   152         }
   154         boolean isClassDecl() {
   155             switch(this) {
   156                 case METHOD:
   157                 case STATIC_METHOD:
   158                 case DEFAULT_METHOD:
   159                     return false;
   160                 default:
   161                     return true;
   162             }
   163         }
   165         boolean isAllowedEnclosing(ElementKind ek, boolean isTop) {
   166             switch (this) {
   167                 case CLASS:
   168                 case CLASS_EXTENDS:
   169                     //class is implicitly static inside interface, so skip this combo
   170                     return ek.isClassDecl() &&
   171                             ek != INTERFACE && ek != INTERFACE_EXTENDS;
   172                 case ANON_CLASS:
   173                     return !ek.isClassDecl();
   174                 case METHOD:
   175                     return ek == CLASS || ek == CLASS_EXTENDS ||
   176                             ek == STATIC_CLASS || ek == STATIC_CLASS_EXTENDS ||
   177                             ek == ANON_CLASS;
   178                 case INTERFACE:
   179                 case INTERFACE_EXTENDS:
   180                 case STATIC_CLASS:
   181                 case STATIC_CLASS_EXTENDS:
   182                 case STATIC_METHOD:
   183                     return (isTop && (ek == CLASS || ek == CLASS_EXTENDS)) ||
   184                             ek == STATIC_CLASS || ek == STATIC_CLASS_EXTENDS;
   185                 case DEFAULT_METHOD:
   186                     return ek == INTERFACE || ek == INTERFACE_EXTENDS;
   187                 default:
   188                     throw new AssertionError("Bad enclosing element kind" + this);
   189             }
   190         }
   192         boolean isAllowedTop() {
   193             switch (this) {
   194                 case CLASS:
   195                 case CLASS_EXTENDS:
   196                 case INTERFACE:
   197                 case INTERFACE_EXTENDS:
   198                     return true;
   199                 default:
   200                     return false;
   201             }
   202         }
   204         boolean hasSuper() {
   205             return this == INTERFACE_EXTENDS ||
   206                     this == STATIC_CLASS_EXTENDS ||
   207                     this == CLASS_EXTENDS;
   208         }
   209     }
   211     static class Shape {
   213         String shapeStr;
   214         List<ElementKind> enclosingElements;
   215         List<String> enclosingNames;
   216         List<String> elementsWithMethod;
   218         Shape(ElementKind... elements) {
   219             enclosingElements = new ArrayList<>();
   220             enclosingNames = new ArrayList<>();
   221             elementsWithMethod = new ArrayList<>();
   222             int count = 0;
   223             String prevName = null;
   224             for (ElementKind ek : elements) {
   225                 String name = "name"+count++;
   226                 if (ek.isStatic) {
   227                     enclosingElements = new ArrayList<>();
   228                     enclosingNames = new ArrayList<>();
   229                 }
   230                 if (ek.isClassDecl()) {
   231                     enclosingElements.add(ek);
   232                     enclosingNames.add(name);
   233                 } else {
   234                     elementsWithMethod.add(prevName);
   235                 }
   236                 String element = ek.templateDecl.replaceAll("#N", name);
   237                 shapeStr = shapeStr ==
   238                         null ? element : shapeStr.replaceAll("#B", element);
   239                 prevName = name;
   240             }
   241         }
   243         String getShape(QualifierKind qk, ExprKind ek) {
   244             String methName = ek == ExprKind.THIS ? "test" : "m";
   245             String call = qk.getQualifier(this) + "." +
   246                     ek.exprStr + "." + methName + "();";
   247             return shapeStr.replaceAll("#B", call);
   248         }
   250         String enclosingAt(int index) {
   251             return index < enclosingNames.size() ?
   252                     enclosingNames.get(index) : "BAD";
   253         }
   254     }
   256     public static void main(String... args) throws Exception {
   257         for (InterfaceKind ik : InterfaceKind.values()) {
   258             for (PruneKind pk : PruneKind.values()) {
   259                 for (ElementKind ek1 : ElementKind.values()) {
   260                     if (!ek1.isAllowedTop()) continue;
   261                     for (ElementKind ek2 : ElementKind.values()) {
   262                         if (!ek2.isAllowedEnclosing(ek1, true)) continue;
   263                         for (ElementKind ek3 : ElementKind.values()) {
   264                             if (!ek3.isAllowedEnclosing(ek2, false)) continue;
   265                             for (ElementKind ek4 : ElementKind.values()) {
   266                                 if (!ek4.isAllowedEnclosing(ek3, false)) continue;
   267                                 for (ElementKind ek5 : ElementKind.values()) {
   268                                     if (!ek5.isAllowedEnclosing(ek4, false) ||
   269                                             ek5.isClassDecl()) continue;
   270                                     for (QualifierKind qk : QualifierKind.values()) {
   271                                         for (ExprKind ek : ExprKind.values()) {
   272                                             pool.execute(
   273                                                     new TestDefaultSuperCall(ik, pk,
   274                                                     new Shape(ek1, ek2, ek3,
   275                                                     ek4, ek5), qk, ek));
   276                                         }
   277                                     }
   278                                 }
   279                             }
   280                         }
   281                     }
   282                 }
   283             }
   284         }
   286         checkAfterExec();
   287     }
   289     InterfaceKind ik;
   290     PruneKind pk;
   291     Shape sh;
   292     QualifierKind qk;
   293     ExprKind ek;
   294     JavaSource source;
   295     DiagnosticChecker diagChecker;
   297     TestDefaultSuperCall(InterfaceKind ik, PruneKind pk, Shape sh,
   298             QualifierKind qk, ExprKind ek) {
   299         this.ik = ik;
   300         this.pk = pk;
   301         this.sh = sh;
   302         this.qk = qk;
   303         this.ek = ek;
   304         this.source = new JavaSource();
   305         this.diagChecker = new DiagnosticChecker();
   306     }
   308     class JavaSource extends SimpleJavaFileObject {
   310         String template = "interface E {}\n" +
   311                           "interface B { }\n" +
   312                           "#I\n" +
   313                           "#P\n" +
   314                           "#C";
   316         String source;
   318         public JavaSource() {
   319             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   320             source = template.replaceAll("#I", ik.interfaceStr)
   321                     .replaceAll("#P", pk.interfaceStr)
   322                     .replaceAll("#C", sh.getShape(qk, ek));
   323         }
   325         @Override
   326         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   327             return source;
   328         }
   329     }
   331     public void run() {
   332         JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
   333                 null, null, Arrays.asList(source));
   334         try {
   335             ct.analyze();
   336         } catch (Throwable ex) {
   337             processException(ex);
   338             return;
   339         }
   340         check();
   341     }
   343     void check() {
   344         boolean errorExpected = false;
   346         boolean badEnclosing = false;
   347         boolean badThis = false;
   348         boolean badSuper = false;
   350         if (qk == QualifierKind.ENCLOSING_1 &&
   351                 sh.enclosingNames.size() < 1) {
   352             errorExpected |= true;
   353             badEnclosing = true;
   354         }
   356         if (qk == QualifierKind.ENCLOSING_2 &&
   357                 sh.enclosingNames.size() < 2) {
   358             errorExpected |= true;
   359             badEnclosing = true;
   360         }
   362         if (ek == ExprKind.THIS) {
   363             boolean found = false;
   364             for (int i = 0; i < sh.enclosingElements.size(); i++) {
   365                 if (sh.enclosingElements.get(i) == ElementKind.ANON_CLASS) continue;
   366                 if (sh.enclosingNames.get(i).equals(qk.getQualifier(sh))) {
   367                     found = sh.elementsWithMethod.contains(sh.enclosingNames.get(i));
   368                     break;
   369                 }
   370             }
   371             errorExpected |= !found;
   372             if (!found) {
   373                 badThis = true;
   374             }
   375         }
   377         if (ek == ExprKind.SUPER) {
   379             int lastIdx = sh.enclosingElements.size() - 1;
   380             boolean found = lastIdx == -1 ? false :
   381                     sh.enclosingElements.get(lastIdx).hasSuper() &&
   382                     qk.allowSuperCall(ik, pk);
   384             errorExpected |= !found;
   385             if (!found) {
   386                 badSuper = true;
   387             }
   388         }
   390         checkCount.incrementAndGet();
   391         if (diagChecker.errorFound != errorExpected) {
   392             throw new AssertionError("Problem when compiling source:\n" +
   393                     source.getCharContent(true) +
   394                     "\nenclosingElems: " + sh.enclosingElements +
   395                     "\nenclosingNames: " + sh.enclosingNames +
   396                     "\nelementsWithMethod: " + sh.elementsWithMethod +
   397                     "\nbad encl: " + badEnclosing +
   398                     "\nbad this: " + badThis +
   399                     "\nbad super: " + badSuper +
   400                     "\nqual kind: " + qk +
   401                     "\nfound error: " + diagChecker.errorFound);
   402         }
   403     }
   405     static class DiagnosticChecker
   406         implements javax.tools.DiagnosticListener<JavaFileObject> {
   408         boolean errorFound;
   410         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   411             if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   412                 errorFound = true;
   413             }
   414         }
   415     }
   417 }

mercurial