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.data.*;
  30 import vm.runtime.defmeth.shared.data.method.param.NewInstanceParam;
  31 import vm.runtime.defmeth.shared.builder.TestBuilder;
  32 import static vm.runtime.defmeth.shared.ExecutionMode.*;
  33 import static vm.runtime.defmeth.shared.data.method.body.CallMethod.Invoke.*;
  34 import static vm.runtime.defmeth.shared.data.method.body.CallMethod.IndexbyteOp.*;
  35 
  36 /**
  37  * Tests on interaction of default methods with abstract methods
  38  *
  39  * The rule: "the superclass always wins."
  40  *
  41  * In searching the superclass hierarchy, a declaration in a superclass is
  42  * preferred to a default in an interface. This preference includes abstract
  43  * methods in superclasses as well; the defaults are only considered when
  44  * the entire implementation hierarchy is silent on the status of the method
  45  * in question.
  46  */
  47 public class DefaultVsAbstractTest extends DefMethTest {
  48 
  49     public static void main(String[] args) {
  50         TestBase.runTest(new DefaultVsAbstractTest(), args);
  51     }
  52 
  53     /*
  54      * interface I          { public int m() default { return 1; } }
  55      * class C implements I { public abstract int m(); }
  56      *
  57      * TEST: new C() throws InstantiationError
  58      */
  59     public void test0() {
  60         TestBuilder b = factory.getBuilder();
  61 
  62         Interface I = b.intf("I")
  63                 .defaultMethod("m", "()I").returns(1).build()
  64             .build();
  65 
  66         ConcreteClass C = b.clazz("C").implement(I)
  67                 .abstractMethod("m", "()I").build()
  68             .build();
  69 
  70         b.test()
  71             .callSite(I, C, "m", "()I")
  72             .throws_(InstantiationError.class)
  73             .done()
  74         .run();
  75     }
  76 
  77     /*
  78      * interface I          {
  79      *     public int m() default { return 1; }
  80      * }
  81      * class C implements I {
  82      *     public abstract int m();
  83      * }
  84      * class D extends C {}
  85      *
  86      * TEST: I i = new D(); i.m() ==> AME
  87      * TEST: C c = new D(); c.m() ==> AME
  88      * TEST: D d = new D(); d.m() ==> AME
  89      */
  90     @KnownFailure(modes = {INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY }) // Test1_I_D_m: NPE instead of AME
  91                                                                                    // Test3_D_D_m: AME => IAE => ICCE instead of AME
  92     public void test1() {
  93         TestBuilder b = factory.getBuilder();
  94 
  95         Interface I = b.intf("I")
  96                 .defaultMethod("m", "()I").returns(1).build()
  97             .build();
  98 
  99         ConcreteClass C = b.clazz("C").implement(I)
 100                 .abstractMethod("m", "()I").build()
 101             .build();
 102 
 103         ConcreteClass D = b.clazz("D").extend(C).build();
 104 
 105         b.test()
 106             .callSite(I, D, "m",  "()I")
 107             .throws_(AbstractMethodError.class)
 108             .done()
 109         .test()
 110             .callSite(C, D, "m", "()I")
 111             .throws_(AbstractMethodError.class)
 112             .done()
 113         .test()
 114             .callSite(D, D, "m", "()I")
 115             .throws_(AbstractMethodError.class)
 116             .done()
 117         .run();
 118     }
 119 
 120     /*
 121      * interface I {
 122      *     default  public int m() { return 1; }
 123      * }
 124      * class C     {
 125      *     abstract public int m();
 126      * }
 127      * class D extends C implements I {}
 128      *
 129      * TEST: I o = new D(); o.m()I throws AME
 130      * TEST: C o = new D(); o.m()I throws AME
 131      * TEST: D o = new D(); o.m()I throws AME
 132      */
 133     @KnownFailure(modes = { INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY }) // Test1_I_D_m: NPE instead of AME
 134                                                                                     // Test3_D_D_m: AME => IAE => ICCE instead of AME
 135     public void test2() {
 136         TestBuilder b = factory.getBuilder();
 137 
 138         Interface I = b.intf("I")
 139                 .defaultMethod("m", "()I").returns(1).build()
 140             .build();
 141 
 142         ConcreteClass C = b.clazz("C")
 143                 .abstractMethod("m", "()I").build()
 144             .build();
 145 
 146         ConcreteClass D = b.clazz("D").extend(C).implement(I).build();
 147 
 148         b.test()
 149             .callSite(I, D, "m", "()I")
 150             .throws_(AbstractMethodError.class)
 151             .done()
 152         .test()
 153             .callSite(C, D, "m", "()I")
 154             .throws_(AbstractMethodError.class)
 155             .done()
 156         .test()
 157             .callSite(D, D, "m", "()I")
 158             .throws_(AbstractMethodError.class)
 159             .done()
 160         .run();
 161     }
 162 
 163     /*
 164      * interface I {
 165      *     default public int m() { return 1; }
 166      * }
 167      * class C {
 168      *     abstract public int m();
 169      * }
 170      * class D extends C implements I {
 171      *     public int m()  { return 2; }
 172      * }
 173      *
 174      * TEST: I o = new D(); o.m()I == 2
 175      * TEST: C o = new D(); o.m()I == 2
 176      * TEST: D o = new D(); o.m()I == 2
 177      */
 178     public void test3() {
 179         TestBuilder b = factory.getBuilder();
 180 
 181         Interface I = b.intf("I")
 182                 .defaultMethod("m", "()I").returns(1).build()
 183             .build();
 184 
 185         ConcreteClass C = b.clazz("C")
 186                 .abstractMethod("m", "()I").build()
 187             .build();
 188 
 189         ConcreteClass D = b.clazz("D").extend(C).implement(I)
 190                 .concreteMethod("m", "()I").returns(2)
 191                 .build()
 192             .build();
 193 
 194         b.test() // I i = new D(); ...
 195             .callSite(I, D, "m", "()I").returns(2)
 196             .done()
 197         .test()  // C c = new D(); ...
 198             .callSite(C, D, "m", "()I").returns(2)
 199             .done()
 200         .test()  // D d = new C(); ...
 201             .callSite(D, D, "m", "()I").returns(2)
 202             .done()
 203         .run();
 204     }
 205 
 206     /*
 207      * interface I {
 208      *     default public int m() { return 1; }
 209      * }
 210      * class E {
 211      *     abstract public int m();
 212      * }
 213      * class D extends E {}
 214      * class C extends D implements I {}
 215      *
 216      * TEST: I o = new C(); o.m()I throws AME
 217      * TEST: E o = new C(); o.m()I throws AME
 218      * TEST: D o = new C(); o.m()I throws AME
 219      * TEST: C o = new C(); o.m()I throws AME
 220      */
 221     @KnownFailure(modes = {
 222         INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY // Test1_I_C_m: NPE instead of AME
 223                                                              // Test3_D_C_m: AME => IAE => ICCE instead of AME
 224                                                              // Test4_C_C_m: AME => IAE => ICCE instead of AME
 225     })
 226     public void test4() {
 227         TestBuilder b = factory.getBuilder();
 228 
 229         Interface I = b.intf("I")
 230                 .defaultMethod("m", "()I").returns(1).build()
 231                 .build();
 232 
 233         ConcreteClass E = b.clazz("E")
 234                 .abstractMethod("m", "()I").build()
 235                 .build();
 236 
 237         ConcreteClass D = b.clazz("D").extend(E).build();
 238 
 239         ConcreteClass C = b.clazz("C").extend(D).implement(I).build();
 240 
 241         b.test() // I i = new C(); ...
 242             .callSite(I, C, "m", "()I")
 243             .throws_(AbstractMethodError.class)
 244             .done()
 245         .test() // E e = new C(); ...
 246             .callSite(E, C, "m", "()I")
 247             .throws_(AbstractMethodError.class)
 248             .done()
 249         .test() // D d = new C(); ...
 250             .callSite(D, C, "m", "()I")
 251             .throws_(AbstractMethodError.class)
 252             .done()
 253         .test() // C c = new C(); ...
 254             .callSite(C, C, "m", "()I")
 255             .throws_(AbstractMethodError.class)
 256             .done()
 257         .run();
 258     }
 259 
 260     /*
 261      * interface I {
 262      *     default public int m() { return 1; }
 263      * }
 264      * class E {
 265      *     abstract public int m();
 266      * }
 267      * class D extends E {
 268      *     public int m()  { return 2; }
 269      * }
 270      * class C extends D implements I {}
 271      *
 272      * TEST: I o = new C(); o.m()I == 2
 273      * TEST: I o = new C(); o.m()I == 2
 274      * TEST: I o = new C(); o.m()I == 2
 275      * TEST: I o = new C(); o.m()I == 2
 276      */
 277     public void test5() {
 278         TestBuilder b = factory.getBuilder();
 279 
 280         Interface I = b.intf("I")
 281                 .defaultMethod("m", "()I").returns(1).build()
 282             .build();
 283 
 284         ConcreteClass E = b.clazz("E")
 285                 .abstractMethod("m", "()I").build()
 286             .build();
 287 
 288         ConcreteClass D = b.clazz("D").extend(E)
 289                 .concreteMethod("m", "()I").returns(2).build()
 290             .build();
 291 
 292         ConcreteClass C = b.clazz("C").extend(D).implement(I).build();
 293 
 294         b.test() // I i = new C(); ...
 295             .callSite(I, C, "m", "()I")
 296             .returns(2)
 297             .done()
 298         .test() // E e = new C(); ...
 299             .callSite(I, C, "m", "()I")
 300             .returns(2)
 301             .done()
 302         .test() // D d = new C(); ...
 303             .callSite(I, C, "m", "()I")
 304             .returns(2)
 305             .done()
 306         .test() // C c = new C(); ...
 307             .callSite(I, C, "m", "()I")
 308             .returns(2)
 309             .done()
 310         .run();
 311     }
 312 
 313     /*
 314      * interface I {
 315      *     default public int m() { return 1; }
 316      * }
 317      * interface J {
 318      *     default public int m() { return 2; }
 319      * }
 320      * class E {
 321      *     abstract public int m();
 322      * }
 323      * class D extends E {
 324      *     public int m()  { return 3; }
 325      * }
 326      * class C extends D implements I, J {}
 327      *
 328      * TEST: I o = new C(); o.m()I == 3
 329      * TEST: J o = new C(); o.m()I == 3
 330      * TEST: E o = new C(); o.m()I == 3
 331      * TEST: D o = new C(); o.m()I == 3
 332      * TEST: J o = new C(); o.m()I == 3
 333      */
 334     public void test6() {
 335         TestBuilder b = factory.getBuilder();
 336 
 337         Interface I = b.intf("I")
 338                 .defaultMethod("m", "()I").returns(1).build()
 339             .build();
 340 
 341         Interface J = b.intf("J")
 342                 .defaultMethod("m", "()I").returns(2).build()
 343             .build();
 344 
 345         ConcreteClass E = b.clazz("E")
 346                 .abstractMethod("m", "()I").build()
 347             .build();
 348 
 349         ConcreteClass D = b.clazz("D").extend(E)
 350                 .concreteMethod("m", "()I").returns(3).build()
 351             .build();
 352 
 353         ConcreteClass C = b.clazz("C").extend(D).implement(I, J).build();
 354 
 355 
 356         b.test() // I i = new C(); ...
 357             .callSite(I, C, "m", "()I").returns(3)
 358             .done()
 359         .test() // J j = new C(); ...
 360             .callSite(J, C, "m", "()I").returns(3)
 361             .done()
 362         .test()  // E e = new C(); ...
 363             .callSite(E, C, "m", "()I").returns(3)
 364             .done()
 365         .test()  // D d = new C(); ...
 366             .callSite(D, C, "m", "()I").returns(3)
 367             .done()
 368         .test() // C c = new C(); ...
 369             .callSite(J, C, "m", "()I").returns(3)
 370             .done()
 371         .run();
 372     }
 373 
 374     /*
 375      * interface I {
 376      *     abstract public int m();
 377      * }
 378      *
 379      * interface J {
 380      *     default public int m() { return 1; }
 381      * }
 382      *
 383      * class A implements I;
 384      *
 385      * class B extends A implements J;
 386      *
 387      * TEST: A o = new B(); o.m()I
 388      *                returns 1 for REFLECTION and INVOKE_WITH_ARGS
 389      *                ICCE for other modes
 390      */
 391     public void testInvokeInterfaceClassDefaultMethod() {
 392         TestBuilder b = factory.getBuilder();
 393 
 394         Interface I = b.intf("I")
 395             .abstractMethod("m", "()I").build()
 396             .build();
 397 
 398         Interface J = b.intf("J")
 399             .extend(I)
 400             .defaultMethod("m", "()I").returns(1).build()
 401             .build();
 402 
 403         ConcreteClass A = b.clazz("A").implement(I).build();
 404 
 405         ConcreteClass B = b.clazz("B").extend(A).implement(J).build();
 406 
 407         String exeMode = factory.getExecutionMode();
 408 
 409         // the test passes in the reflection mode because there's no way to
 410         // express invokeinterface on a class using Reflection API
 411         // In the test generator, vm.runtime.defmeth.shared.executor.ReflectionTest,
 412         // the invokeinterface is switched to invokevirtual.
 413         //
 414         // the test passes in the INVOKE_WITH_ARGS mode due to the fix for
 415         // JDK-8032010 to conform with the removal of the following check
 416         // during method resolution in JVMS-5.4.3.3 Method Resolution
 417         // "If method lookup succeeds and the method is abstract, but C is not
 418         // abstract, method resolution throws an AbstractMethodError."
 419         if (exeMode.equals("REFLECTION") ||
 420             exeMode.equals("INVOKE_WITH_ARGS")) {
 421             b.test().interfaceCallSite(A, B, "m", "()I")
 422              .returns(1).done()
 423              .run();
 424         } else {
 425             // ICCE in other modes due to
 426             // JVMS-5.4.3.4. Interface Method Resolution
 427             //   When resolving an interface method reference:
 428             //     If C is not an interface, interface method resolution throws an IncompatibleClassChangeError.
 429             b.test().interfaceCallSite(A, B, "m", "()I")
 430              .throws_(IncompatibleClassChangeError.class).done()
 431              .run();
 432         }
 433     }
 434 
 435     /*
 436      * interface I {
 437      *     abstract public int m();
 438      * }
 439      *
 440      * interface J {
 441      *     abstract public int m();
 442      * }
 443      *
 444      * class A implements I;
 445      *
 446      * class B extends A implements J;
 447      *
 448      * TEST: A o = new B(); o.m()I
 449      *                ICCE for DIRECT mode
 450      *                AME for REFLECTION and INVOKE_WITH_ARGS modes
 451      *                IAE for other modes
 452      */
 453     public void testInvokeInterfaceClassAbstractMethod() {
 454         TestBuilder b = factory.getBuilder();
 455 
 456         Interface I = b.intf("I")
 457             .abstractMethod("m", "()I").build()
 458             .build();
 459 
 460         Interface J = b.intf("J")
 461             .abstractMethod("m", "()I").build()
 462             .build();
 463 
 464         ConcreteClass A = b.clazz("A").implement(I).build();
 465 
 466         ConcreteClass B = b.clazz("B").extend(A).implement(J).build();
 467 
 468         String exeMode = factory.getExecutionMode();
 469 
 470         // ICCE in direct mode due to
 471         // JVMS-5.4.3.4. Interface Method Resolution
 472         //   When resolving an interface method reference:
 473         //     If C is not an interface, interface method resolution throws an IncompatibleClassChangeError.
 474         Class expectedError = IncompatibleClassChangeError.class;;
 475 
 476         b.test().interfaceCallSite(A, B, "m", "()I")
 477          .throws_(expectedError).done()
 478          .run();
 479 
 480     }
 481 
 482     /*
 483      * interface I {
 484      *     public int m() default { return 1; }
 485      * }
 486      *
 487      * interface J {
 488      *     public int m() default { return 1; }
 489      * }
 490      *
 491      * class A implements I;
 492      *
 493      * class B extends A implements J;
 494      *
 495      * TEST: A o = new B(); o.m()I
 496      *                ICCE for all modes
 497      */
 498     public void testInvokeInterfaceMultipleDefinedClassDefaultMethod() {
 499         TestBuilder b = factory.getBuilder();
 500 
 501         Interface I = b.intf("I")
 502             .defaultMethod("m", "()I").returns(1).build()
 503             .build();
 504 
 505         Interface J = b.intf("J")
 506             .defaultMethod("m", "()I").returns(1).build()
 507             .build();
 508 
 509         ConcreteClass A = b.clazz("A").implement(I).build();
 510 
 511         ConcreteClass B = b.clazz("B").extend(A).implement(J).build();
 512 
 513         String exeMode = factory.getExecutionMode();
 514 
 515         // ICCE in direct mode due to
 516         // JVMS-5.4.3.4. Interface Method Resolution
 517         //   When resolving an interface method reference:
 518         //     If C is not an interface, interface method resolution throws an IncompatibleClassChangeError.
 519         Class expectedError = IncompatibleClassChangeError.class;
 520 
 521         b.test().interfaceCallSite(A, B, "m", "()I")
 522          .throws_(expectedError).done()
 523          .run();
 524     }
 525 
 526 }