test/tools/javac/generics/rawOverride/7062745/GenericOverrideTest.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) 2011, 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 7062745 8006694
    27  * @summary  Regression: difference in overload resolution when two methods
    28  *  are maximally specific
    29  *  temporarily workaround combo tests are causing time out in several platforms
    30  * @library ../../../lib
    31  * @build JavacTestingAbstractThreadedTest
    32  * @run main/othervm GenericOverrideTest
    33  */
    35 // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
    36 // see JDK-8006746
    38 import java.net.URI;
    39 import java.util.Arrays;
    40 import javax.tools.Diagnostic;
    41 import javax.tools.JavaFileObject;
    42 import javax.tools.SimpleJavaFileObject;
    43 import com.sun.source.util.JavacTask;
    45 public class GenericOverrideTest
    46     extends JavacTestingAbstractThreadedTest
    47     implements Runnable {
    49     enum SourceLevel {
    50         SOURCE_7("-source", "7"),
    51         SOURCE_DEFAULT();
    53         String[] opts;
    55         SourceLevel(String... opts) {
    56             this.opts = opts;
    57         }
    58     }
    60     enum SignatureKind {
    61         NON_GENERIC(""),
    62         GENERIC("<X>");
    64         String paramStr;
    66         private SignatureKind(String paramStr) {
    67             this.paramStr = paramStr;
    68         }
    69     }
    71     enum ReturnTypeKind {
    72         LIST("List"),
    73         ARRAYLIST("ArrayList");
    75         String retStr;
    77         private ReturnTypeKind(String retStr) {
    78             this.retStr = retStr;
    79         }
    81         boolean moreSpecificThan(ReturnTypeKind that) {
    82             switch (this) {
    83                 case LIST:
    84                     return that == this;
    85                 case ARRAYLIST:
    86                     return that == LIST || that == ARRAYLIST;
    87                 default: throw new AssertionError("Unexpected ret kind: " + this);
    88             }
    89         }
    90     }
    92     enum TypeArgumentKind {
    93         NONE(""),
    94         UNBOUND("<?>"),
    95         INTEGER("<Number>"),
    96         NUMBER("<Integer>"),
    97         TYPEVAR("<X>");
    99         String typeargStr;
   101         private TypeArgumentKind(String typeargStr) {
   102             this.typeargStr = typeargStr;
   103         }
   105         boolean compatibleWith(SignatureKind sig) {
   106             switch (this) {
   107                 case TYPEVAR: return sig != SignatureKind.NON_GENERIC;
   108                 default: return true;
   109             }
   110         }
   112         boolean moreSpecificThan(TypeArgumentKind that, boolean strict) {
   113             switch (this) {
   114                 case NONE:
   115                     return that == this || !strict;
   116                 case UNBOUND:
   117                     return that == this || that == NONE;
   118                 case INTEGER:
   119                 case NUMBER:
   120                 case TYPEVAR:
   121                     return that == this || that == NONE || that == UNBOUND;
   122                 default: throw new AssertionError("Unexpected typearg kind: " + this);
   123             }
   124         }
   126         boolean assignableTo(TypeArgumentKind that, SignatureKind sig, SourceLevel level) {
   127             switch (this) {
   128                 case NONE:
   129                     //this case needs to workaround to javac's impl of 15.12.2.8 being too strict
   130                     //ideally should be just 'return true' (see 7067746/8015505)
   131                     return level == SourceLevel.SOURCE_DEFAULT ||
   132                             sig == SignatureKind.NON_GENERIC || that == NONE;
   133                 case UNBOUND:
   134                     return that == this || that == NONE;
   135                 case INTEGER:
   136                 case NUMBER:
   137                     return that == this || that == NONE || that == UNBOUND;
   138                 case TYPEVAR:
   139                     return true;
   140                 default: throw new AssertionError("Unexpected typearg kind: " + this);
   141             }
   142         }
   143     }
   145     public static void main(String... args) throws Exception {
   146         for (SignatureKind sig1 : SignatureKind.values()) {
   147             for (ReturnTypeKind rt1 : ReturnTypeKind.values()) {
   148                 for (TypeArgumentKind ta1 : TypeArgumentKind.values()) {
   149                     if (!ta1.compatibleWith(sig1)) continue;
   150                     for (SignatureKind sig2 : SignatureKind.values()) {
   151                         for (ReturnTypeKind rt2 : ReturnTypeKind.values()) {
   152                             for (TypeArgumentKind ta2 : TypeArgumentKind.values()) {
   153                                 if (!ta2.compatibleWith(sig2)) continue;
   154                                 for (ReturnTypeKind rt3 : ReturnTypeKind.values()) {
   155                                     for (TypeArgumentKind ta3 : TypeArgumentKind.values()) {
   156                                         if (!ta3.compatibleWith(SignatureKind.NON_GENERIC))
   157                                             continue;
   158                                         for (SourceLevel level : SourceLevel.values()) {
   159                                             pool.execute(
   160                                                     new GenericOverrideTest(sig1,
   161                                                     rt1, ta1, sig2, rt2,
   162                                                     ta2, rt3, ta3, level));
   163                                         }
   164                                     }
   165                                 }
   166                             }
   167                         }
   168                     }
   169                 }
   170             }
   171         }
   173         checkAfterExec();
   174     }
   176     SignatureKind sig1, sig2;
   177     ReturnTypeKind rt1, rt2, rt3;
   178     TypeArgumentKind ta1, ta2, ta3;
   179     SourceLevel level;
   180     JavaSource source;
   181     DiagnosticChecker diagChecker;
   183     GenericOverrideTest(SignatureKind sig1, ReturnTypeKind rt1, TypeArgumentKind ta1,
   184             SignatureKind sig2, ReturnTypeKind rt2, TypeArgumentKind ta2,
   185             ReturnTypeKind rt3, TypeArgumentKind ta3, SourceLevel level) {
   186         this.sig1 = sig1;
   187         this.sig2 = sig2;
   188         this.rt1 = rt1;
   189         this.rt2 = rt2;
   190         this.rt3 = rt3;
   191         this.ta1 = ta1;
   192         this.ta2 = ta2;
   193         this.ta3 = ta3;
   194         this.level = level;
   195         this.source = new JavaSource();
   196         this.diagChecker = new DiagnosticChecker();
   197     }
   199     class JavaSource extends SimpleJavaFileObject {
   201         String template = "import java.util.*;\n" +
   202                           "interface A { #S1 #R1#TA1 m(); }\n" +
   203                           "interface B { #S2 #R2#TA2 m(); }\n" +
   204                           "interface AB extends A, B {}\n" +
   205                           "class Test {\n" +
   206                           "  void test(AB ab) { #R3#TA3 n = ab.m(); }\n" +
   207                           "}";
   209         String source;
   211         public JavaSource() {
   212             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
   213             source = template.replace("#S1", sig1.paramStr).
   214                     replace("#S2", sig2.paramStr).
   215                     replace("#R1", rt1.retStr).
   216                     replace("#R2", rt2.retStr).
   217                     replace("#R3", rt3.retStr).
   218                     replace("#TA1", ta1.typeargStr).
   219                     replace("#TA2", ta2.typeargStr).
   220                     replace("#TA3", ta3.typeargStr);
   221         }
   223         @Override
   224         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
   225             return source;
   226         }
   227     }
   229     @Override
   230     public void run() {
   231         JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
   232                 level.opts != null ? Arrays.asList(level.opts) : null,
   233                 null, Arrays.asList(source));
   234         try {
   235             ct.analyze();
   236         } catch (Throwable ex) {
   237             throw new AssertionError("Error thrown when compiling the following code:\n" +
   238                     source.getCharContent(true));
   239         }
   240         check();
   241     }
   243     void check() {
   244         checkCount.incrementAndGet();
   246         boolean errorExpected = false;
   247         int mostSpecific = 0;
   249         //first check that either |R1| <: |R2| or |R2| <: |R1|
   250         if (rt1 != rt2) {
   251             if (!rt1.moreSpecificThan(rt2) &&
   252                     !rt2.moreSpecificThan(rt1)) {
   253                 errorExpected = true;
   254             } else {
   255                 mostSpecific = rt1.moreSpecificThan(rt2) ? 1 : 2;
   256             }
   257         }
   259         //check that either TA1 <= TA2 or TA2 <= TA1 (unless most specific return found above is raw)
   260         if (!errorExpected) {
   261             if (ta1 != ta2) {
   262                 boolean useStrictCheck = ta1.moreSpecificThan(ta2, true) ||
   263                         ta2.moreSpecificThan(ta1, true);
   264                 if (!ta1.moreSpecificThan(ta2, useStrictCheck) &&
   265                         !ta2.moreSpecificThan(ta1, useStrictCheck)) {
   266                     errorExpected = true;
   267                 } else {
   268                     int mostSpecific2 = ta1.moreSpecificThan(ta2, useStrictCheck) ? 1 : 2;
   269                     if (mostSpecific != 0 && mostSpecific2 != mostSpecific) {
   270                         errorExpected = mostSpecific == 1 ?
   271                                 ta1 != TypeArgumentKind.NONE :
   272                                 ta2 != TypeArgumentKind.NONE;
   273                     } else {
   274                         mostSpecific = mostSpecific2;
   275                     }
   276                 }
   277             } else if (mostSpecific == 0) {
   278                 //when no signature is better than the other, an arbitrary choice
   279                 //must be made - javac always picks the second signature
   280                 mostSpecific = 2;
   281             }
   282         }
   284         //finally, check that most specific return type is compatible with expected type
   285         if (!errorExpected) {
   286             ReturnTypeKind msrt = mostSpecific == 1 ? rt1 : rt2;
   287             TypeArgumentKind msta = mostSpecific == 1 ? ta1 : ta2;
   288             SignatureKind mssig = mostSpecific == 1 ? sig1 : sig2;
   290             if (!msrt.moreSpecificThan(rt3) ||
   291                     !msta.assignableTo(ta3, mssig, level)) {
   292                 errorExpected = true;
   293             }
   294         }
   296         if (errorExpected != diagChecker.errorFound) {
   297             throw new Error("invalid diagnostics for source:\n" +
   298                 source.getCharContent(true) +
   299                 "\nFound error: " + diagChecker.errorFound +
   300                 "\nExpected error: " + errorExpected);
   301         }
   302     }
   304     static class DiagnosticChecker
   305         implements javax.tools.DiagnosticListener<JavaFileObject> {
   307         boolean errorFound;
   309         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   310             if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   311                 errorFound = true;
   312             }
   313         }
   314     }
   316 }

mercurial