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