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