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.annotation.KnownFailure; 28 import vm.runtime.defmeth.shared.data.*; 29 import vm.runtime.defmeth.shared.data.method.param.*; 30 import static jdk.internal.org.objectweb.asm.Opcodes.*; 31 import vm.runtime.defmeth.shared.DefMethTest; 32 import vm.runtime.defmeth.shared.builder.TestBuilder; 33 import static vm.runtime.defmeth.shared.ExecutionMode.*; 34 35 /** 36 * Tests on method resolution in presence of default methods in the hierarchy. 37 * 38 * Because default methods reside in interfaces, and interfaces do not have 39 * the constraint of being single-inheritance, it is possible to inherit 40 * multiple conflicting default methods, or even inherit the same default method 41 * from many different inheritance paths. 42 * 43 * There is an algorithm to select which method to use in the case that a 44 * concrete class does not provide an implementation. Informally, the algorithm 45 * works as follows: 46 * 47 * (1) If there is a adequate implementation in the class itself or in a 48 * superclass (not an interface), then that implementation should be used 49 * (i.e., class methods always "win"). 50 * 51 * (2) Failing that, create the set of methods consisting of all methods in the 52 * type hierarchy which satisfy the slot to be filled, where in this case 53 * 'satisfy' means that the methods have the same name, the same language- 54 * level representation of the parameters, and covariant return values. Both 55 * default methods and abstract methods will be part of this set. 56 * 57 * (3) Remove from this set, any method which has a "more specific" version 58 * anywhere in the hierarchy. That is, if C implements I,J and I extends J, 59 * then if both I and J have a suitable methods, J's method is eliminated 60 * from the set since I is a subtype of J -- there exist a more specific 61 * method than J's method, so that is eliminated. 62 * 63 * (4) If the remaining set contains only a single entry, then that method is 64 * selected. Note that the method may be abstract, in which case an 65 * IncompatibleClassChangeError is thrown when/if the method is called. If there are 66 * multiple entries in the set, or no entries, then this also results in an 67 * IncompatibleClassChangeError when called. 68 */ 69 public class MethodResolutionTest extends DefMethTest { 70 main(String[] args)71 public static void main(String[] args) { 72 TestBase.runTest(new MethodResolutionTest(), args); 73 } 74 75 /* 76 * Basic 77 * 78 * interface I { int m(); } 79 * class C implements I { public int m() { return 1; } } 80 * 81 * TEST: C c = new C(); c.m() == 1; 82 * TEST: I i = new C(); i.m() == 1; 83 */ testBasic()84 public void testBasic() { 85 TestBuilder b = factory.getBuilder(); 86 87 Interface I = 88 b.intf("I") 89 .abstractMethod("m", "()I").build() 90 .build(); 91 92 ConcreteClass C = 93 b.clazz("C").implement(I) 94 .concreteMethod("m", "()I").returns(1).build() 95 .build(); 96 97 b.test() 98 .callSite(I, C, "m", "()I") 99 .returns(1) 100 .done() 101 .test() 102 .callSite(C, C, "m", "()I") 103 .returns(1) 104 .done() 105 .run(); 106 } 107 108 /* 109 * Basic Default 110 * 111 * interface I { int m() default { return 1; } } 112 * class C implements I {} 113 * 114 * TEST: C c = new C(); c.m() == 1; 115 * TEST: I i = new C(); i.m() == 1; 116 */ testBasicDefault()117 public void testBasicDefault() { 118 TestBuilder b = factory.getBuilder(); 119 120 Interface I = 121 b.intf("I") 122 .defaultMethod("m", "()I").returns(1) 123 .build() 124 .build(); 125 126 ConcreteClass C = 127 b.clazz("C").implement(I) 128 .build(); 129 130 b.test() 131 .callSite(I, C, "m", "()I") 132 .returns(1) 133 .done() 134 .test().callSite(C, C, "m", "()I") 135 .returns(1) 136 .done() 137 138 .run(); 139 } 140 141 /* 142 * Far Default 143 * 144 * interface I { int m() default { return 1; } } 145 * interface J extends I {} 146 * interface K extends J {} 147 * class C implements K {} 148 * 149 * TEST: [I|J|K|C] i = new C(); i.m() == 1; 150 */ 151 @KnownFailure(modes = { INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY }) // Test2_J_C_m, Test3_K_C_m: AME => IAE => ICCE instead of successful call testFarDefault()152 public void testFarDefault() { 153 TestBuilder b = factory.getBuilder(); 154 155 Interface I = 156 b.intf("I") 157 .defaultMethod("m", "()I").returns(1) 158 .build() 159 .build(); 160 161 Interface J = b.intf("J").extend(I).build(); 162 Interface K = b.intf("K").extend(J).build(); 163 164 ConcreteClass C = 165 b.clazz("C").implement(K) 166 .build(); 167 168 b.test() 169 .callSite(I, C, "m", "()I") 170 .returns(1) 171 .done() 172 .test().callSite(J, C, "m", "()I") 173 .returns(1) 174 .done() 175 .test().callSite(K, C, "m", "()I") 176 .returns(1) 177 .done() 178 .test().callSite(C, C, "m", "()I") 179 .returns(1) 180 .done() 181 182 .run(); 183 } 184 185 /* 186 * Override Abstract 187 * 188 * interface I { int m(); } 189 * interface J extends I { int m() default { return 1; } } 190 * interface K extends J {} 191 * class C implements K {} 192 * 193 * TEST: C c = new C(); c.m() == 1; 194 * TEST: K k = new C(); k.m() == 1; 195 */ 196 @KnownFailure(modes = { INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY }) // Test3_K_C_m: AME => IAE => ICCE instead of successful call testOverrideAbstract()197 public void testOverrideAbstract() { 198 TestBuilder b = factory.getBuilder(); 199 200 Interface I = b.intf("I") 201 .abstractMethod("m", "()I").build() 202 .build(); 203 204 Interface J = b.intf("J").extend(I) 205 .defaultMethod("m", "()I").returns(1).build() 206 .build(); 207 208 Interface K = b.intf("K").extend(J).build(); 209 210 ConcreteClass C = b.clazz("C").implement(K).build(); 211 212 b.test() 213 .callSite(I, C, "m", "()I") 214 .returns(1) 215 .done() 216 .test() 217 .callSite(J, C, "m", "()I") 218 .returns(1) 219 .done() 220 .test() 221 .callSite(K, C, "m", "()I") 222 .returns(1) 223 .done() 224 .test() 225 .callSite(C, C, "m", "()I") 226 .returns(1) 227 .done() 228 229 .run(); 230 } 231 232 /* 233 * Default vs Concrete 234 * 235 * interface I { int m() default { return 1; } } 236 * class C implements I { public int m() { return 2; } } 237 * 238 * TEST: [C|I] c = new C(); c.m() == 2; 239 */ testDefaultVsConcrete()240 public void testDefaultVsConcrete() { 241 TestBuilder b = factory.getBuilder(); 242 243 Interface I = b.intf("I") 244 .defaultMethod("m", "()I").returns(1).build() 245 .build(); 246 247 ConcreteClass C = b.clazz("C").implement(I) 248 .concreteMethod("m", "()I").returns(2).build() 249 .build(); 250 251 b.test() 252 .callSite(I, C, "m", "()I") 253 .returns(2) 254 .done() 255 .test() 256 .callSite(C, C, "m", "()I") 257 .returns(2) 258 .done() 259 260 .run(); 261 } 262 263 /* 264 * InheritedDefault 265 * 266 * interface I { int m() default { return 1; } } 267 * class B implements I {} 268 * class C extends B {} 269 * 270 * TEST: [I|B|C] v = new C(); v.m() == 1; 271 */ testInheritedDefault()272 public void testInheritedDefault() { 273 TestBuilder b = factory.getBuilder(); 274 275 Interface I = b.intf("I") 276 .defaultMethod("m", "()I").returns(1).build() 277 .build(); 278 279 ConcreteClass B = b.clazz("B").implement(I).build(); 280 ConcreteClass C = b.clazz("C").extend(B).build(); 281 282 b.test() 283 .callSite(I, C, "m","()I") 284 .returns(1) 285 .done() 286 .test() 287 .callSite(B, C, "m","()I") 288 .returns(1) 289 .done() 290 .test() 291 .callSite(C, C, "m","()I") 292 .returns(1) 293 .done() 294 295 .run(); 296 } 297 298 /* 299 * ExistingInherited 300 * 301 * interface I { int m() default { return 1; } } 302 * class B { public int m() { return 2; } } 303 * class C extends B implements I {} 304 * 305 * TEST: [I|B|C] v = new C(); v.m() == 2; 306 */ testExistingInherited()307 public void testExistingInherited() { 308 TestBuilder b = factory.getBuilder(); 309 310 Interface I = b.intf("I") 311 .defaultMethod("m", "()I").returns(1).build() 312 .build(); 313 314 ConcreteClass B = b.clazz("B") 315 .concreteMethod("m", "()I").returns(2).build() 316 .build(); 317 318 ConcreteClass C = b.clazz("C").extend(B).implement(I).build(); 319 320 b.test() 321 .callSite(I, C, "m","()I") 322 .returns(2) 323 .done() 324 .test() 325 .callSite(B, C, "m","()I") 326 .returns(2) 327 .done() 328 .test() 329 .callSite(C, C, "m","()I") 330 .returns(2) 331 .done() 332 333 .run(); 334 } 335 336 /* 337 * ExistingInheritedOverride 338 * 339 * interface I { int m() default { return 1; } } 340 * class B implements I { public int m() { return 2; } } 341 * class C extends B { public int m() { return 3; } } 342 * 343 * TEST: [I|B|D] v = new C(); v.m() == 3; 344 */ testExistingInheritedOverride()345 public void testExistingInheritedOverride() { 346 TestBuilder b = factory.getBuilder(); 347 348 Interface I = b.intf("I") 349 .defaultMethod("m", "()I").returns(1).build() 350 .build(); 351 352 ConcreteClass B = b.clazz("B").implement(I) 353 .concreteMethod("m", "()I").returns(2).build() 354 .build(); 355 356 ConcreteClass C = b.clazz("C").extend(B) 357 .concreteMethod("m", "()I").returns(3).build() 358 .build(); 359 360 b.test() 361 .callSite(I, C, "m","()I") 362 .returns(3) 363 .done() 364 .test() 365 .callSite(B, C, "m","()I") 366 .returns(3) 367 .done() 368 .test() 369 .callSite(C, C, "m","()I") 370 .returns(3) 371 .done() 372 373 .run(); 374 } 375 376 /* 377 * ExistingInheritedPlusDefault 378 * 379 * interface I { int m() default { return 11; } } 380 * interface J { int m() default { return 12; } } 381 * class C implements I { public int m() { return 21; } } 382 * class D extends C { public int m() { return 22; } } 383 * class E extends D implements J {} 384 * 385 * TEST: [I|J|C|D|J] v = new E(); v.m() == 22; 386 */ testExistingInheritedPlusDefault()387 public void testExistingInheritedPlusDefault() { 388 TestBuilder b = factory.getBuilder(); 389 390 Interface I = b.intf("I") 391 .defaultMethod("m", "()I").returns(11).build() 392 .build(); 393 394 Interface J = b.intf("J") 395 .defaultMethod("m", "()I").returns(12).build() 396 .build(); 397 398 ConcreteClass C = b.clazz("C").implement(I) 399 .concreteMethod("m","()I").returns(21).build() 400 .build(); 401 402 ConcreteClass D = b.clazz("D").extend(C) 403 .concreteMethod("m", "()I").returns(22).build() 404 .build(); 405 406 ConcreteClass E = b.clazz("E").extend(D).implement(J) 407 .build(); 408 409 b.test() 410 .callSite(I, E, "m","()I") 411 .returns(22) 412 .done() 413 .test() 414 .callSite(J, E, "m","()I") 415 .returns(22) 416 .done() 417 .test() 418 .callSite(C, E, "m","()I") 419 .returns(22) 420 .done() 421 .test() 422 .callSite(D, E, "m","()I") 423 .returns(22) 424 .done() 425 .test() 426 .callSite(E, E, "m","()I") 427 .returns(22) 428 .done() 429 430 .run(); 431 } 432 433 /* 434 * InheritedWithConcrete 435 * 436 * interface I { int m() default { return 1; } } 437 * class B implements I {} 438 * class C extends B { public int m() { return 2; } } 439 * 440 * TEST: [I|B|C] v = new C(); v.m() == 2; 441 */ testInheritedWithConcrete()442 public void testInheritedWithConcrete() { 443 TestBuilder b = factory.getBuilder(); 444 445 Interface I = b.intf("I") 446 .defaultMethod("m", "()I").returns(1).build() 447 .build(); 448 449 ConcreteClass B = b.clazz("B").implement(I).build(); 450 451 ConcreteClass C = b.clazz("C").extend(B) 452 .concreteMethod("m", "()I").returns(2).build() 453 .build(); 454 455 b.test() 456 .callSite(I, C, "m","()I") 457 .returns(2) 458 .done() 459 .test() 460 .callSite(B, C, "m","()I") 461 .returns(2) 462 .done() 463 .test() 464 .callSite(C, C, "m","()I") 465 .returns(2) 466 .done() 467 468 .run(); 469 } 470 471 /* 472 * InheritedWithConcreteAndImpl 473 * 474 * interface I { int m() default { return 1; } } 475 * class B implements I {} 476 * class C extends B implements I { public int m() { return 2; } } 477 * 478 * TEST: [I|B|C] v = new C(); v.m() == 2; 479 */ testInheritedWithConcreteAndImpl()480 public void testInheritedWithConcreteAndImpl() { 481 TestBuilder b = factory.getBuilder(); 482 483 Interface I = b.intf("I") 484 .defaultMethod("m", "()I").returns(1).build() 485 .build(); 486 487 ConcreteClass B = b.clazz("B").implement(I).build(); 488 489 ConcreteClass C = b.clazz("C").extend(B) 490 .concreteMethod("m", "()I").returns(2).build() 491 .build(); 492 493 b.test() 494 .callSite(I, C, "m","()I") 495 .returns(2) 496 .done() 497 .test() 498 .callSite(B, C, "m","()I") 499 .returns(2) 500 .done() 501 .test() 502 .callSite(C, C, "m","()I") 503 .returns(2) 504 .done() 505 506 .run(); 507 } 508 509 /* 510 * Diamond 511 * 512 * interface I { int m() default { return 1; } } 513 * interface J extends I {} 514 * interface K extends I {} 515 * class C implements J, K {} 516 * 517 * TEST: [I|J|K|C] c = new C(); c.m() == 99 518 */ 519 @KnownFailure(modes = { INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY }) // Test2_J_C_m, Test3_K_C_m: AME => IAE => ICCE instead of successful call testDiamond()520 public void testDiamond() { 521 TestBuilder b = factory.getBuilder(); 522 523 Interface I = b.intf("I") 524 .defaultMethod("m", "()I").returns(1).build() 525 .build(); 526 527 Interface J = b.intf("J").extend(I).build(); 528 Interface K = b.intf("K").extend(I).build(); 529 530 ConcreteClass C = b.clazz("C").implement(J,K) 531 .build(); 532 533 b.test() 534 .callSite(I, C, "m","()I") 535 .returns(1) 536 .done() 537 .test() 538 .callSite(J, C, "m","()I") 539 .returns(1) 540 .done() 541 .test() 542 .callSite(K, C, "m","()I") 543 .returns(1) 544 .done() 545 .test() 546 .callSite(C, C, "m","()I") 547 .returns(1) 548 .done() 549 550 .run(); 551 } 552 553 /* 554 * ExpandedDiamond 555 * 556 * interface I { int m() default { return 1; } } 557 * interface J extends I {} 558 * interface K extends I {} 559 * interface L extends I {} 560 * interface M extends I {} 561 * class C implements J, K, L, M {} 562 * 563 * TEST: [I|J|K|L|M|C] c = new C(); c.m() == 1 564 */ 565 @KnownFailure(modes = { INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY }) // Test2_J_C_m, Test3_K_C_m, Test4_L_C_m, Test5_M_C_m: 566 // AME => IAE => ICCE instead of successful call testExpandedDiamond()567 public void testExpandedDiamond() { 568 TestBuilder b = factory.getBuilder(); 569 570 Interface I = b.intf("I") 571 .defaultMethod("m", "()I").returns(1).build() 572 .build(); 573 574 Interface J = b.intf("J").extend(I).build(); 575 Interface K = b.intf("K").extend(I).build(); 576 Interface L = b.intf("L").extend(I).build(); 577 Interface M = b.intf("M").extend(I).build(); 578 579 ConcreteClass C = b.clazz("C").implement(J,K,L,M) 580 .build(); 581 582 b.test() 583 .callSite(I, C, "m","()I") 584 .returns(1) 585 .done() 586 .test() 587 .callSite(J, C, "m","()I") 588 .returns(1) 589 .done() 590 .test() 591 .callSite(K, C, "m","()I") 592 .returns(1) 593 .done() 594 .test() 595 .callSite(L, C, "m","()I") 596 .returns(1) 597 .done() 598 .test() 599 .callSite(M, C, "m","()I") 600 .returns(1) 601 .done() 602 .test() 603 .callSite(C, C, "m","()I") 604 .returns(1) 605 .done() 606 607 .run(); 608 } 609 610 /* 611 * SelfFill w/ explicit bridge 612 * 613 * interface I<T> { int m(T t) default { return 1; } } 614 * class C implements I<C> { 615 * public int m(C s) { return 2; } 616 * public int m(Object o) { ... } 617 * } 618 * 619 * TEST: I i = new C(); i.m((Object)null) == 2; 620 * TEST: C c = new C(); c.m((Object)null) == 2; 621 * TEST: C c = new C(); c.m((C)null) == 2; 622 */ testSelfFillWithExplicitBridge()623 public void testSelfFillWithExplicitBridge() { 624 TestBuilder b = factory.getBuilder(); 625 626 /* interface I<T> { ... */ 627 Interface I = b.intf("I").sig("<T:Ljava/lang/Object;>Ljava/lang/Object;") 628 /* default int m(T t) { return 1; } */ 629 .defaultMethod("m", "(Ljava/lang/Object;)I") 630 .sig("(TT;)I") 631 .returns(1) 632 .build() 633 .build(); 634 635 /* class C implements I<C> { ... */ 636 ConcreteClass C = b.clazz("C").implement(I) 637 .sig("Ljava/lang/Object;LI<LC;>;") 638 639 /* public int m(I i) { return 2; } */ 640 .concreteMethod("m","(LC;)I").returns(2).build() 641 642 /* bridge method for m(LI;)I */ 643 .concreteMethod("m","(Ljava/lang/Object;)I") 644 .flags(ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC) 645 .returns(2) 646 .build() 647 .build(); 648 649 // I i = new C(); ... 650 b.test() 651 .callSite(I, C, "m", "(Ljava/lang/Object;)I") 652 .params(new NullParam()) 653 .returns(2) 654 .done() 655 // C c = new C(); ... 656 .test() 657 .callSite(C, C, "m", "(Ljava/lang/Object;)I") 658 .params(new NullParam()) 659 .returns(2) 660 .done() 661 .test() 662 .callSite(C, C, "m", "(LC;)I") 663 .params(new NullParam()) 664 .returns(2) 665 .done() 666 667 .run(); 668 } 669 670 /* 671 * interface I { int m() default { return 1; } } 672 * class C implements I { int m(int i) { return 2; } } 673 * 674 * TEST: C c = new C(); c.m(0) == 2; 675 * TEST: I i = new C(); i.m() == 1; 676 */ testMixedArity()677 public void testMixedArity() { 678 TestBuilder b = factory.getBuilder(); 679 680 Interface I = 681 b.intf("I") 682 .defaultMethod("m", "()I").returns(1) 683 .build() 684 .build(); 685 686 ConcreteClass C = 687 b.clazz("C").implement(I) 688 .concreteMethod("m", "(I)I").returns(2) 689 .build() 690 .build(); 691 692 b.test().callSite(I, C, "m", "()I") 693 .returns(1) 694 .build(); 695 b.test().callSite(C, C, "m", "(I)I").params(ICONST_0) 696 .returns(2) 697 .build(); 698 699 b.run(); 700 } 701 702 /* 703 * interface I { int m() default { return 1; } } 704 * interface J { int m(int i) default { return 2; } } 705 * class C implements I, J {} 706 * 707 * TEST: I i = new C(); i.m() == 1; i.m(0) ==> NSME 708 * TEST: J j = new C(); j.m() ==> NSME; j.m(0) == 2 709 * TEST: C c = new C(); c.m() == 1; c.m(0) == 2 710 */ 711 @KnownFailure(modes = { INVOKE_EXACT, INVOKE_GENERIC, INDY }) //Test2_I_C_m, Test3_J_C_m: NSMError => NSMException => ICCE instead of NSME testConflictingDefaultMixedArity1()712 public void testConflictingDefaultMixedArity1() { 713 TestBuilder b = factory.getBuilder(); 714 715 Interface I = b.intf("I") 716 .defaultMethod("m", "()I").returns(1) 717 .build() 718 .build(); 719 720 Interface J = b.intf("J") 721 .defaultMethod("m", "(I)I").returns(2) 722 .build() 723 .build(); 724 725 ConcreteClass C = b.clazz("C").implement(I,J).build(); 726 727 728 // I i = new C(); ... 729 b.test().callSite(I, C, "m", "()I") 730 .returns(1) 731 .build(); 732 b.test().callSite(I, C, "m", "(I)I").params(ICONST_0) 733 .throws_(NoSuchMethodError.class) 734 .build(); 735 736 // J j = new C(); ... 737 b.test().callSite(J, C, "m", "()I") 738 .throws_(NoSuchMethodError.class) 739 .build(); 740 b.test().callSite(J, C, "m", "(I)I").params(ICONST_0) 741 .returns(2) 742 .build(); 743 744 // C c = new C(); ... 745 b.test().callSite(C, C, "m", "()I") 746 .returns(1) 747 .build(); 748 b.test().callSite(C, C, "m", "(I)I").params(ICONST_0) 749 .returns(2) 750 .build(); 751 752 b.run(); 753 } 754 755 /* 756 * interface I { int m() default { return 1; } } 757 * interface J { int m() default { return 2; } } 758 * class C implements I, J { 759 * int m(int i) { return 3; } 760 * } 761 * 762 * TEST: I i = new C(); i.m(0) ==> ICCE 763 * TEST: J j = new C(); j.m(0) ==> ICCE 764 * TEST: C c = new C(); c.m() ==> ICCE; c.m(0) == 3 765 */ 766 @KnownFailure(modes = { INVOKE_EXACT, INVOKE_GENERIC, INDY }) 767 //Test2_I_C_m, Test3_J_C_m: NSMError => NSMException => ICCE instead of NSME testConflictingDefaultMixedArity2()768 public void testConflictingDefaultMixedArity2() { 769 TestBuilder b = factory.getBuilder(); 770 771 Interface I = b.intf("I") 772 .defaultMethod("m", "()I").returns(1) 773 .build() 774 .build(); 775 776 Interface J = b.intf("J") 777 .defaultMethod("m", "()I").returns(2) 778 .build() 779 .build(); 780 781 ConcreteClass C = b.clazz("C").implement(I, J) 782 .concreteMethod("m", "(I)I").returns(3) 783 .build() 784 .build(); 785 786 // I i = new C(); ... 787 b.test().callSite(I, C, "m", "()I") 788 .throws_(IncompatibleClassChangeError.class) 789 .build(); 790 b.test().callSite(I, C, "m", "(I)I").params(ICONST_0) 791 .throws_(NoSuchMethodError.class) 792 .build(); 793 794 // J j = new C(); ... 795 b.test().callSite(J, C, "m", "()I") 796 .throws_(IncompatibleClassChangeError.class) 797 .build(); 798 b.test().callSite(J, C, "m", "(I)I").params(ICONST_0) 799 .throws_(NoSuchMethodError.class) 800 .build(); 801 802 // C c = new C(); ... 803 b.test().callSite(C, C, "m", "()I") 804 .throws_(IncompatibleClassChangeError.class) 805 .build(); 806 b.test().callSite(C, C, "m", "(I)I").params(ICONST_0) 807 .returns(3) 808 .build(); 809 810 b.run(); 811 } 812 813 /* In package1: 814 * package p1; 815 * interface I { 816 * default int m() { return 10; }; 817 * } 818 * public interface J extends I {}; 819 * 820 * In package2: 821 * class A implements p1.J {} 822 * A myA = new A; 823 * myA.m(); // should return 10 except for reflect mode, 824 * // throw IllegalAccessException with reflect mode 825 * B myB = new B; // not related 826 */ 827 testMethodResolvedInDifferentPackage()828 public void testMethodResolvedInDifferentPackage() { 829 TestBuilder b = factory.getBuilder(); 830 Interface I = b.intf("p1.I").flags(~ACC_PUBLIC & ACC_PUBLIC) // make it package private 831 .defaultMethod("m", "()I").returns(10) 832 .build() 833 .build(); 834 835 Interface J = b.intf("p1.J").extend(I) 836 .build(); 837 838 ConcreteClass myA = b.clazz("p2.A").implement(J) 839 .build(); 840 if (!factory.getExecutionMode().equals("REFLECTION")) { 841 b.test() 842 .callSite(myA, myA, "m", "()I") 843 .returns(10) 844 .done() 845 .run(); 846 // -mode reflect will fail with IAE as expected 847 } else { 848 b.test() 849 .callSite(myA, myA, "m", "()I") 850 .throws_(IllegalAccessException.class) 851 .done() 852 .run(); 853 } 854 855 ConcreteClass myB = b.clazz("p2.B").build(); 856 } 857 858 /* In package p1: 859 * package p1; 860 * interface I { 861 * public default int m() { return 12; }; 862 * } 863 * 864 * public class A implements I {} 865 * 866 * In package p2: 867 * package p2; 868 * public interface J { int m(); } 869 * 870 * public class B extends p1.A implements J { 871 * public int m() { return 13; } 872 * } 873 * 874 * Then: 875 * A myA = new B; 876 * myA.m(); // should return 13, not throw IllegalAccessError 877 */ 878 testMethodResolvedInLocalFirst()879 public void testMethodResolvedInLocalFirst() { 880 TestBuilder b = factory.getBuilder(); 881 Interface I = b.intf("p1.I") 882 .defaultMethod("m", "()I").returns(12) 883 .build() 884 .build(); 885 886 ConcreteClass myA = b.clazz("p1.A").implement(I) 887 .build(); 888 889 Interface J = b.intf("p2.J").abstractMethod("m", "()I") 890 .build() 891 .build(); 892 893 ConcreteClass myB = b.clazz("p2.B").extend(myA).implement(J) 894 .concreteMethod("m", "()I").returns(13) 895 .build() 896 .build(); 897 898 b.test() 899 .callSite(myB, myB, "m", "()I") 900 .returns(13) 901 .done() 902 .run(); 903 } 904 } 905