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