test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/ConflictingDefaultsTest.java
changeset 50243 4fac3c99487d
equal deleted inserted replaced
50242:9a87afc49148 50243:4fac3c99487d
       
     1 /*
       
     2  * Copyright (c) 2013, 2018, 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  */
       
    23 
       
    24 package vm.runtime.defmeth;
       
    25 
       
    26 import nsk.share.test.TestBase;
       
    27 import vm.runtime.defmeth.shared.DefMethTest;
       
    28 import vm.runtime.defmeth.shared.annotation.KnownFailure;
       
    29 import vm.runtime.defmeth.shared.annotation.NotApplicableFor;
       
    30 import vm.runtime.defmeth.shared.data.*;
       
    31 import static vm.runtime.defmeth.shared.data.method.body.CallMethod.Invoke.*;
       
    32 import static vm.runtime.defmeth.shared.data.method.body.CallMethod.IndexbyteOp.*;
       
    33 import vm.runtime.defmeth.shared.builder.TestBuilder;
       
    34 import static vm.runtime.defmeth.shared.ExecutionMode.*;
       
    35 
       
    36 /**
       
    37  * Tests on conflicting defaults.
       
    38  *
       
    39  * It is allowable to inherit a default through multiple paths (such as
       
    40  * through a diamond-shaped interface hierarchy), but the resolution procedure
       
    41  * is looking for a unique, most specific default-providing interface.
       
    42  *
       
    43  * If one default shadows  another (where a subinterface provides a different
       
    44  * default for an extension method declared in a superinterface), then the less
       
    45  * specific interface is pruned from consideration no matter where it appears
       
    46  * in the inheritance hierarchy.  If two or more extended interfaces provide
       
    47  * default implementations, and one is not a superinterface of the other, then
       
    48  * neither is used and a linkage exception is thrown indicating conflicting
       
    49  * default implementations.
       
    50  */
       
    51 public class ConflictingDefaultsTest extends DefMethTest {
       
    52     public static void main(String[] args) {
       
    53         TestBase.runTest(new ConflictingDefaultsTest(), args);
       
    54     }
       
    55 
       
    56     /*
       
    57      * Conflict
       
    58      *
       
    59      * interface I { int m() default { return 1; } }
       
    60      * interface J { int m() default { return 2; } }
       
    61      * class C implements I, J {}
       
    62      *
       
    63      * TEST: C c = new C(); c.m() ==> ICCE
       
    64      */
       
    65     public void testConflict() {
       
    66         TestBuilder b = factory.getBuilder();
       
    67 
       
    68         Interface I = b.intf("I")
       
    69                 .defaultMethod("m", "()I").returns(1).build()
       
    70             .build();
       
    71 
       
    72         Interface J = b.intf("J")
       
    73                 .defaultMethod("m", "()I").returns(2).build()
       
    74             .build();
       
    75 
       
    76         ConcreteClass C = b.clazz("C").implement(I,J).build();
       
    77 
       
    78         b.test().callSite(C, C, "m","()I")
       
    79                 .throws_(IncompatibleClassChangeError.class)
       
    80             .done()
       
    81 
       
    82         .run();
       
    83     }
       
    84 
       
    85     /*
       
    86      * Maximally-specific Default (0.6.3 spec change)
       
    87      *
       
    88      * interface I { int m(); }
       
    89      * interface J { int m() default { return 2; } }
       
    90      * class C implements I, J {}
       
    91      *
       
    92      * TEST: C c = new C(); c.m() return 2
       
    93      */
       
    94     public void testMaximallySpecificDefault() {
       
    95         TestBuilder b = factory.getBuilder();
       
    96 
       
    97         Interface I = b.intf("I")
       
    98                 .abstractMethod("m", "()I").build()
       
    99             .build();
       
   100 
       
   101         Interface J = b.intf("J")
       
   102                 .defaultMethod("m", "()I").returns(2).build()
       
   103             .build();
       
   104 
       
   105         ConcreteClass C = b.clazz("C").implement(I,J).build();
       
   106 
       
   107         b.test().callSite(C, C, "m","()I")
       
   108                 .returns(2)
       
   109             .done()
       
   110 
       
   111         .run();
       
   112     }
       
   113 
       
   114     /*
       
   115      * Reabstract
       
   116      *
       
   117      * interface I { int m() default { return 1; } }
       
   118      * interface J extends I { int m(); }
       
   119      * class C implements J {}
       
   120      *
       
   121      * TEST: C c = new C(); c.m() ==> AME
       
   122      */
       
   123     public void testReabstract() {
       
   124         TestBuilder b = factory.getBuilder();
       
   125 
       
   126         Interface I = b.intf("I")
       
   127                 .defaultMethod("m", "()I").returns(1).build()
       
   128             .build();
       
   129 
       
   130         Interface J = b.intf("J").extend(I)
       
   131                 .abstractMethod("m", "()I").build()
       
   132             .build();
       
   133 
       
   134         ConcreteClass C = b.clazz("C").implement(J).build();
       
   135 
       
   136         b.test().callSite(C, C, "m","()I")
       
   137                 .throws_(AbstractMethodError.class)
       
   138             .done()
       
   139 
       
   140         .run();
       
   141     }
       
   142 
       
   143     /*
       
   144      * Reabstract2
       
   145      *
       
   146      * interface I { int m() default { return 1; } }
       
   147      * interface J extends I { int m(); }
       
   148      * class C implements J {}
       
   149      * class D extends C { callSuper C.m}
       
   150      *
       
   151      * TEST: C c = new C(); c.m() ==> AME
       
   152      * TEST: J j = new C(); j.m() ==> AME
       
   153      * TEST: I i = new C(); i.m() ==> AME
       
   154      * TEST: D d = new D(); d.m() ==> callSuper C.m ==> AME
       
   155      */
       
   156     public void testReabstract2() {
       
   157         TestBuilder b = factory.getBuilder();
       
   158 
       
   159         Interface I = b.intf("I")
       
   160                 .defaultMethod("m", "()I").returns(1).build()
       
   161             .build();
       
   162 
       
   163         Interface J = b.intf("J").extend(I)
       
   164                 .abstractMethod("m", "()I").build()
       
   165             .build();
       
   166 
       
   167         ConcreteClass C = b.clazz("C").implement(J).build();
       
   168         ConcreteClass D = b.clazz("D").extend(C)
       
   169                 .concreteMethod("m", "()I").callSuper(C, "m", "()I").build()
       
   170             .build();
       
   171 
       
   172         b.test().callSite(C, C, "m","()I")
       
   173                 .throws_(AbstractMethodError.class)
       
   174             .done()
       
   175          .test().callSite(J, C, "m","()I")
       
   176                 .throws_(AbstractMethodError.class)
       
   177             .done()
       
   178          .test().callSite(I, C, "m","()I")
       
   179                 .throws_(AbstractMethodError.class)
       
   180             .done()
       
   181          .test().callSite(D, D, "m","()I")
       
   182                 .throws_(AbstractMethodError.class)
       
   183             .done()
       
   184 
       
   185         .run();
       
   186     }
       
   187 
       
   188     /*
       
   189      * ReabstractConflictingDefaults
       
   190      *
       
   191      * interface I { int m() default { return 1; } }
       
   192      * interface J { int m() default { return 2; } }
       
   193      * interface K extends I,J { int m(); }
       
   194      * class A implements I,J {}
       
   195      * class C extends A implements K {}
       
   196      *
       
   197      * TEST: A c = new C(); c.m() ==> AME
       
   198      */
       
   199     public void testReabstractConflictingDefaults() {
       
   200         TestBuilder b = factory.getBuilder();
       
   201 
       
   202         Interface I = b.intf("I")
       
   203                 .defaultMethod("m", "()I").returns(1).build()
       
   204             .build();
       
   205 
       
   206         Interface J = b.intf("J")
       
   207                 .defaultMethod("m", "()I").returns(2).build()
       
   208             .build();
       
   209 
       
   210         Interface K = b.intf("K").extend(I,J)
       
   211                 .abstractMethod("m", "()I").build()
       
   212             .build();
       
   213 
       
   214         ConcreteClass A = b.clazz("A").implement(I,J).build();
       
   215         ConcreteClass C = b.clazz("C").extend(A).implement(K).build();
       
   216 
       
   217         b.test().callSite(A, C, "m","()I")
       
   218                 .throws_(AbstractMethodError.class)
       
   219             .done()
       
   220 
       
   221         .run();
       
   222     }
       
   223 
       
   224 
       
   225     /*
       
   226      * ReabstractConflictingDefaultsInvokeInterface
       
   227      *
       
   228      * interface I { int m() default { return 1; } }
       
   229      * interface J { int m() default { return 2; } }
       
   230      * interface K extends I,J { int m(); }
       
   231      * interface L extends K { }
       
   232      * class A implements I,J {}
       
   233      * class C extends A implements K {}
       
   234      * class D extends C implements L {}
       
   235      *
       
   236      * TEST: I i = new A(); i.m() ==> ICCE
       
   237      * TEST: K k = new C(); k.m() ==> AME
       
   238      * TEST: L l = new D(); l.m() ==> AME
       
   239      */
       
   240     public void testReabstractConflictingDefaultsInvokeInterface() {
       
   241         TestBuilder b = factory.getBuilder();
       
   242 
       
   243         Interface I = b.intf("I")
       
   244                 .defaultMethod("m", "()I").returns(1).build()
       
   245             .build();
       
   246 
       
   247         Interface J = b.intf("J")
       
   248                 .defaultMethod("m", "()I").returns(2).build()
       
   249             .build();
       
   250 
       
   251         Interface K = b.intf("K").extend(I,J)
       
   252                 .abstractMethod("m", "()I").build()
       
   253             .build();
       
   254 
       
   255         Interface L = b.intf("L").extend(K)
       
   256             .build();
       
   257 
       
   258         ConcreteClass A = b.clazz("A").implement(I,J).build();
       
   259         ConcreteClass C = b.clazz("C").extend(A).implement(K).build();
       
   260         ConcreteClass D = b.clazz("D").extend(C).implement(L).build();
       
   261 
       
   262         b.test().callSite(I, A, "m","()I")
       
   263                 .throws_(IncompatibleClassChangeError.class)
       
   264             .done()
       
   265          .test().callSite(K, C, "m","()I")
       
   266                 .throws_(AbstractMethodError.class)
       
   267             .done()
       
   268          .test().callSite(L, D, "m","()I")
       
   269                 .throws_(AbstractMethodError.class)
       
   270             .done()
       
   271 
       
   272         .run();
       
   273     }
       
   274 
       
   275     /*
       
   276      * ReabstractConflictingDefaultsSuper
       
   277      *
       
   278      * interface I { int m() default { return 1; } }
       
   279      * interface J { int m() default { return 2; } }
       
   280      * interface K extends I,J { int m(); }
       
   281      * interface L extends K { }
       
   282      * class A implements I,J {}
       
   283      * class C extends A implements K {}
       
   284      * class D extends C implements L {int m() {callSuper A.m }
       
   285      *
       
   286      * TEST: I i = new A(); i.m() ==> ICCE
       
   287      * TEST: K k = new C(); CallSuper k.m() ==> AME
       
   288      * TEST: L l = new D(); l.m() ==> AME
       
   289      */
       
   290     public void testReabstractConflictingDefaultsSuper() {
       
   291         TestBuilder b = factory.getBuilder();
       
   292 
       
   293         Interface I = b.intf("I")
       
   294                 .defaultMethod("m", "()I").returns(1).build()
       
   295             .build();
       
   296 
       
   297         Interface J = b.intf("J")
       
   298                 .defaultMethod("m", "()I").returns(2).build()
       
   299             .build();
       
   300 
       
   301         Interface K = b.intf("K").extend(I,J)
       
   302                 .abstractMethod("m", "()I").build()
       
   303             .build();
       
   304 
       
   305         Interface L = b.intf("L").extend(K)
       
   306             .build();
       
   307 
       
   308         ConcreteClass A = b.clazz("A").implement(I,J).build();
       
   309         ConcreteClass C = b.clazz("C").extend(A).implement(K).build();
       
   310         ConcreteClass D = b.clazz("D").extend(C).implement(L)
       
   311                 .concreteMethod("m", "()I").callSuper(A, "m", "()I").build()
       
   312             .build();
       
   313 
       
   314         b.test().callSite(I, A, "m","()I")
       
   315                 .throws_(IncompatibleClassChangeError.class)
       
   316             .done()
       
   317          .test().callSite(L, D, "m","()I")
       
   318                 .throws_(AbstractMethodError.class)
       
   319             .done()
       
   320 
       
   321         .run();
       
   322     }
       
   323 
       
   324     /*
       
   325      * testReabstractResolveMethod00705m2
       
   326      *
       
   327      * Test case for JDK-8027804: JCK resolveMethod test fails expecting AME
       
   328      *
       
   329      * This test is an extension of the JCK test resolveMethod00705m2
       
   330      * with additional invoke* bytecodes specified for testing purposes.
       
   331      *
       
   332      * interface I { int m() default { return 1; } }
       
   333      * interface J implements I { int m(); }
       
   334      * class A implements J,I {}
       
   335      * class C extends A {}
       
   336      *
       
   337      * TEST: A a = new C(); a.m() ==> AME (invokevirtual)
       
   338      *       C c = new C(); c.m() ==> AME (invokevirtual)
       
   339      *       J j = new C(); j.m() ==> AME (invokeinterface)
       
   340      *       I i = new C(); i.m() ==> AME (invokeinterface)
       
   341      *       c.test_Cmethod_ISMR(); c.super.m() ==> AME (invokespecial MR)
       
   342      *       a.test_Amethod_ISIMR(); j.super.m() ==> AME (invokespecial IMR)
       
   343      *
       
   344      *       For ver > 49, error will be AME
       
   345      *       For ver = 49, error will be VE
       
   346      */
       
   347 
       
   348     @NotApplicableFor(modes = { REDEFINITION }) // Can't redefine a class that gets error during loading
       
   349     public void testReabstractResolveMethod00705m2() {
       
   350         TestBuilder b = factory.getBuilder();
       
   351 
       
   352         Interface I = b.intf("I")
       
   353                 .defaultMethod("m", "()I").returns(1).build()
       
   354             .build();
       
   355 
       
   356         Interface J = b.intf("J").extend(I)
       
   357             .abstractMethod("m", "()I").build()
       
   358             .build();
       
   359 
       
   360         ConcreteClass A = b.clazz("A").implement(J,I)
       
   361                 .concreteMethod("test_Amethod_ISIMR", "()V")
       
   362                     .invoke(SPECIAL, b.clazzByName("J"), b.clazzByName("A"),
       
   363                          "m", "()I", INTERFACEMETHODREF)
       
   364                 .build()
       
   365             .build();
       
   366 
       
   367         ConcreteClass C = b.clazz("C").extend(A)
       
   368                 .concreteMethod("test_Cmethod_ISMR", "()V")
       
   369                     .invoke(SPECIAL, b.clazzByName("C"), b.clazzByName("C"),
       
   370                          "m", "()I", CALLSITE)
       
   371                 .build()
       
   372             .build();
       
   373 
       
   374         Class expectedError1, expectedError2;
       
   375         if (factory.getVer() >=52) {
       
   376             expectedError1 = expectedError2 = AbstractMethodError.class;
       
   377         } else {
       
   378             expectedError1 = expectedError2 = VerifyError.class;
       
   379         }
       
   380 
       
   381          b.test().callSite(A, C, "m", "()I")
       
   382                  .throws_(expectedError2)
       
   383              .done()
       
   384           .test().callSite(C, C, "m", "()I")
       
   385                  .throws_(expectedError2)
       
   386              .done()
       
   387           .test().callSite(J, C, "m", "()I")
       
   388                  .throws_(expectedError1)
       
   389              .done()
       
   390           .test().callSite(I, C, "m", "()I")
       
   391                  .throws_(expectedError1)
       
   392              .done()
       
   393           .test().callSite(C, C, "test_Cmethod_ISMR", "()V")
       
   394                  .throws_(expectedError2)
       
   395              .done()
       
   396           .test().callSite(A, C, "test_Amethod_ISIMR", "()V")
       
   397                  .throws_(expectedError2)
       
   398              .done()
       
   399 
       
   400          .run();
       
   401     }
       
   402 
       
   403     /*
       
   404      * Shadow
       
   405      *
       
   406      * interface I { int m() default { return 1; } }
       
   407      * interface J extends I { int m() default { return 2; } }
       
   408      * class C implements J {}
       
   409      *
       
   410      * TEST: [I|J|C] c = new C(); c.m() == 2;
       
   411      */
       
   412     public void testShadow() {
       
   413         TestBuilder b = factory.getBuilder();
       
   414 
       
   415         Interface I = b.intf("I")
       
   416                 .defaultMethod("m", "()I").returns(1).build()
       
   417             .build();
       
   418 
       
   419         Interface J = b.intf("J").extend(I)
       
   420                 .defaultMethod("m", "()I").returns(2).build()
       
   421             .build();
       
   422 
       
   423         ConcreteClass C = b.clazz("C").implement(J).build();
       
   424 
       
   425         b.test().callSite(I, C, "m","()I")
       
   426                 .returns(2)
       
   427             .done()
       
   428         .test()
       
   429                 .callSite(J, C, "m","()I")
       
   430                 .returns(2)
       
   431             .done()
       
   432         .test()
       
   433                 .callSite(C, C, "m","()I")
       
   434                 .returns(2)
       
   435             .done()
       
   436 
       
   437         .run();
       
   438     }
       
   439 
       
   440     /*
       
   441      * Disqualified
       
   442      *
       
   443      * interface I { int m() default { return 1; } }
       
   444      * interface J extends I { int m() default { return 2; } }
       
   445      * class C implements I, J {}
       
   446      *
       
   447      * TEST: [I|J|C] c = new C(); c.m() == 2;
       
   448      */
       
   449     public void testDisqualified() {
       
   450         TestBuilder b = factory.getBuilder();
       
   451 
       
   452         Interface I = b.intf("I")
       
   453                 .defaultMethod("m", "()I").returns(1).build()
       
   454             .build();
       
   455 
       
   456         Interface J = b.intf("J").extend(I)
       
   457                 .defaultMethod("m", "()I").returns(2).build()
       
   458             .build();
       
   459 
       
   460         ConcreteClass C = b.clazz("C").implement(I,J).build();
       
   461 
       
   462         b.test()
       
   463                 .callSite(I, C, "m","()I")
       
   464                 .returns(2)
       
   465             .done()
       
   466         .test()
       
   467                 .callSite(J, C, "m","()I")
       
   468                 .returns(2)
       
   469             .done()
       
   470         .test()
       
   471                 .callSite(C, C, "m","()I")
       
   472                 .returns(2)
       
   473             .done()
       
   474 
       
   475         .run();
       
   476     }
       
   477 
       
   478     /*
       
   479      * Mixed arity
       
   480      *
       
   481      * interface I { int m() default { return 1; } }
       
   482      * interface J { int m(int i) default { return 2; } }
       
   483      * class C implements I, J {}
       
   484      *
       
   485      * TEST: I i = new C(); i.m() == 1; i.m(0) ==> NSME
       
   486      * TEST: J j = new C(); j.m() ==> NSME; j.m(0) == 2
       
   487      * TEST: C c = new C(); c.m() == 1; c.m(0) == 2
       
   488      */
       
   489     @KnownFailure(modes = { INVOKE_EXACT, INVOKE_GENERIC, INDY }) // IncompatibleClassChangeError instead of NoSuchMethodError
       
   490     public void testMixedArity1() {
       
   491         TestBuilder b = factory.getBuilder();
       
   492 
       
   493         Interface I = b.intf("I")
       
   494                 .defaultMethod("m", "()I").returns(1).build()
       
   495             .build();
       
   496 
       
   497         Interface J = b.intf("J")
       
   498                 .defaultMethod("m", "(I)I").returns(2).build()
       
   499             .build();
       
   500 
       
   501         ConcreteClass C = b.clazz("C").implement(I,J).build();
       
   502 
       
   503         // I i = new C(); ...
       
   504         b.test()
       
   505                 .callSite(I, C, "m","()I")
       
   506                 .returns(1)
       
   507             .done()
       
   508         .test()
       
   509                 .callSite(I, C, "m","(I)I")
       
   510                 .params(0)
       
   511                 .throws_(NoSuchMethodError.class)
       
   512             .done()
       
   513 
       
   514         // J j = new C(); ...
       
   515         .test()
       
   516                 .callSite(J, C, "m","()I")
       
   517                 .throws_(NoSuchMethodError.class)
       
   518             .done()
       
   519         .test()
       
   520                 .callSite(J, C, "m","(I)I")
       
   521                 .params(0)
       
   522                 .returns(2)
       
   523             .done()
       
   524 
       
   525         // C c = new C(); ...
       
   526         .test()
       
   527                 .callSite(C, C, "m","()I")
       
   528                 .returns(1)
       
   529             .done()
       
   530         .test()
       
   531                 .callSite(C, C, "m","(I)I")
       
   532                 .params(0)
       
   533                 .returns(2)
       
   534             .done()
       
   535 
       
   536         .run();
       
   537     }
       
   538 
       
   539     /*
       
   540      * Mixed arity
       
   541      *
       
   542      * interface I { int m() default { return 1; } }
       
   543      * interface J { int m() default { return 2; } }
       
   544      * class C implements I, J { int m(int i) { return 3; }}
       
   545      *
       
   546      * TEST: I i = new C(); i.m() ==> ICCE
       
   547      * TEST: J j = new C(); j.m() ==> ICCE
       
   548      * TEST: C c = new C(); c.m() ==> ICCE; c.m(0) == 3
       
   549      */
       
   550     public void testMixedArity2() {
       
   551         TestBuilder b = factory.getBuilder();
       
   552 
       
   553         Interface I = b.intf("I")
       
   554                 .defaultMethod("m", "()I").returns(1).build()
       
   555             .build();
       
   556 
       
   557         Interface J = b.intf("J")
       
   558                 .defaultMethod("m", "()I").returns(2).build()
       
   559             .build();
       
   560 
       
   561         ConcreteClass C = b.clazz("C").implement(I,J)
       
   562                 .concreteMethod("m", "(I)I").returns(3).build()
       
   563             .build();
       
   564 
       
   565         // I i = new C(); ...
       
   566         b.test()
       
   567                 .callSite(I, C, "m","()I")
       
   568                 .throws_(IncompatibleClassChangeError.class)
       
   569             .done()
       
   570 
       
   571         // J j = new C(); ...
       
   572         .test()
       
   573                 .callSite(J, C, "m","()I")
       
   574                 .throws_(IncompatibleClassChangeError.class)
       
   575             .done()
       
   576 
       
   577         // C c = new C(); ...
       
   578         .test()
       
   579                 .callSite(C, C, "m","()I")
       
   580                 .throws_(IncompatibleClassChangeError.class)
       
   581             .done()
       
   582         .test()
       
   583                 .callSite(C, C, "m","(I)I")
       
   584                 .params(0)
       
   585                 .returns(3)
       
   586             .done()
       
   587 
       
   588         .run();
       
   589     }
       
   590 }