|
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 vm.runtime.defmeth.shared.builder.TestBuilder; |
|
32 import static vm.runtime.defmeth.shared.ExecutionMode.*; |
|
33 |
|
34 /* |
|
35 * Tests on invoke-super-default. |
|
36 * |
|
37 * Invoke-super-default is used by a subclass to defer to a default method |
|
38 * implementation or to disambiguate between conflicting inherited default |
|
39 * methods. |
|
40 * |
|
41 * Invoke-super-default appears in the source code as |
|
42 * "<interface-name>.super.<method-name>(<args>)". It is compiled into an |
|
43 * invokespecial instruction whose target is <interface-name>.<method-name>, |
|
44 * where the interface is a direct supertype of the current class (the current class |
|
45 * must directly implement <interface-name>). |
|
46 * |
|
47 * 0.6.3 JVMS draft for JDK8 updated. |
|
48 * Invokespecial on any superinterface method will run interface method |
|
49 * resolution, and then the selected method will be set to the resolved method. |
|
50 * super defaults no longer check for lack of shadowing, other languages |
|
51 * want this capability. |
|
52 */ |
|
53 public class SuperCallTest extends DefMethTest { |
|
54 |
|
55 @Override |
|
56 protected void configure() { |
|
57 // Since invoke-super-default relies on new semantics of invokespecial, |
|
58 // the tests are applicable only to class files of 52 version. |
|
59 if (factory.getVer() != 52) { |
|
60 getLog().warn("WARN: SuperCallTest is applicable only for class files w/ version 52."); |
|
61 getLog().warn("WARN: Overriding \"-ver " + factory.getVer() + "\" w/ \"-ver 52\"."); |
|
62 |
|
63 factory.setVer(52); |
|
64 } |
|
65 } |
|
66 |
|
67 public static void main(String[] args) { |
|
68 TestBase.runTest(new SuperCallTest(), args); |
|
69 } |
|
70 |
|
71 /* |
|
72 * Basic case |
|
73 * |
|
74 * interface I { int m() default { return 1; } } |
|
75 * interface J extends I { int m() default { return I.super.m(); } } |
|
76 * class C implements J {} |
|
77 * |
|
78 * TEST: C c = new C(); c.m() == 88; |
|
79 * TEST: I i = new C(); i.m() == 88; |
|
80 */ |
|
81 public void testSuperBasic1() { |
|
82 TestBuilder b = factory.getBuilder(); |
|
83 |
|
84 Interface I = b.intf("I") |
|
85 .defaultMethod("m", "()I").returns(1).build() |
|
86 .build(); |
|
87 |
|
88 Interface J = b.intf("J").extend(I) |
|
89 .defaultMethod("m", "()I").callSuper(I, "m", "()I").build() |
|
90 .build(); |
|
91 |
|
92 ConcreteClass C = b.clazz("C").implement(J).build(); |
|
93 |
|
94 b.test().callSite(I, C, "m", "()I").returns(1).done() |
|
95 .test().callSite(J, C, "m", "()I").returns(1).done() |
|
96 .test().callSite(C, C, "m", "()I").returns(1).done() |
|
97 |
|
98 .run(); |
|
99 } |
|
100 |
|
101 /* |
|
102 * Super Conflict Resolution |
|
103 * |
|
104 * interface K { int m() default { return 1; } } |
|
105 * interface L { int m() default { return 2; } } |
|
106 * interface I extends K,L { int m() default { K.super.m(); } } |
|
107 * class C implements I {} |
|
108 * class D implements K,L {} |
|
109 * |
|
110 * TEST: K k = new C(); k.m() == 1 |
|
111 * TEST: L l = new C(); l.m() == 1 |
|
112 * TEST: I i = new C(); i.m() == 1 |
|
113 * TEST: C c = new C(); c.m() == 1 |
|
114 * |
|
115 * TEST: K k = new D(); k.m() == 1 |
|
116 * TEST: L l = new D(); l.m() == 1 |
|
117 * TEST: D d = new D(); d.m() == 1 |
|
118 */ |
|
119 public void testSuperConflictResolution() { |
|
120 TestBuilder b = factory.getBuilder(); |
|
121 |
|
122 Interface K = b.intf("K") |
|
123 .defaultMethod("m", "()I").returns(1).build() |
|
124 .build(); |
|
125 |
|
126 Interface L = b.intf("L") |
|
127 .defaultMethod("m", "()I").returns(2).build() |
|
128 .build(); |
|
129 |
|
130 Interface I = b.intf("I").extend(K, L) |
|
131 .defaultMethod("m", "()I").callSuper(K, "m", "()I").build() |
|
132 .build(); |
|
133 |
|
134 ConcreteClass C = b.clazz("C").implement(I).build(); |
|
135 |
|
136 ConcreteClass D = b.clazz("D").implement(K,L) |
|
137 .concreteMethod("m", "()I").callSuper(K, "m", "()I").build() |
|
138 .build(); |
|
139 |
|
140 |
|
141 b.test().callSite(K, C, "m", "()I").returns(1).done() |
|
142 .test().callSite(L, C, "m", "()I").returns(1).done() |
|
143 .test().callSite(I, C, "m", "()I").returns(1).done() |
|
144 .test().callSite(C, C, "m", "()I").returns(1).done() |
|
145 |
|
146 .test().callSite(K, D, "m", "()I").returns(1).done() |
|
147 .test().callSite(L, D, "m", "()I").returns(1).done() |
|
148 .test().callSite(D, D, "m", "()I").returns(1).done() |
|
149 |
|
150 .run(); |
|
151 } |
|
152 |
|
153 /* |
|
154 * Super call of conflicting default method from different method name |
|
155 * |
|
156 * interface K { |
|
157 * default public int m(int) { return 1; } |
|
158 * } |
|
159 * interface L { |
|
160 * default public int m(int) { return 2; } |
|
161 * } |
|
162 * interface I extends K, L { |
|
163 * default public int k() { return K.super.m((int)0); } |
|
164 * default public int l() { return L.super.m((int)0); } |
|
165 * } |
|
166 * class C implements I {} |
|
167 * class D implements K, L { |
|
168 * public int k() { return K.super.m((int)0); } |
|
169 * public int l() { return L.super.m((int)0); } |
|
170 * } |
|
171 * |
|
172 * TEST: K o = new C(); o.m(I)I throws ICCE |
|
173 * TEST: L o = new C(); o.m(I)I throws ICCE |
|
174 * TEST: C o = new C(); o.m(I)I throws ICCE |
|
175 * TEST: I o = new C(); o.k()I == 1 |
|
176 * TEST: C o = new C(); o.k()I == 1 |
|
177 * TEST: I o = new C(); o.l()I == 2 |
|
178 * TEST: C o = new C(); o.l()I == 2 |
|
179 * TEST: K o = new D(); o.m(I)I throws ICCE |
|
180 * TEST: L o = new D(); o.m(I)I throws ICCE |
|
181 * TEST: D o = new D(); o.m(I)I throws ICCE |
|
182 * TEST: D o = new D(); o.k()I == 1 |
|
183 * TEST: D o = new D(); o.l()I == 2 |
|
184 */ |
|
185 public void testSuperConflictDiffMethod() { |
|
186 TestBuilder b = factory.getBuilder(); |
|
187 |
|
188 Interface K = b.intf("K") |
|
189 .defaultMethod("m", "(I)I").returns(1).build() |
|
190 .build(); |
|
191 |
|
192 Interface L = b.intf("L") |
|
193 .defaultMethod("m", "(I)I").returns(2).build() |
|
194 .build(); |
|
195 |
|
196 Interface I = b.intf("I").extend(K, L) |
|
197 .defaultMethod("k", "()I").callSuper(K, "m", "(I)I").build() |
|
198 .defaultMethod("l", "()I").callSuper(L, "m", "(I)I").build() |
|
199 .build(); |
|
200 |
|
201 ConcreteClass C = b.clazz("C").implement(I).build(); |
|
202 |
|
203 ConcreteClass D = b.clazz("D").implement(K,L) |
|
204 .concreteMethod("k", "()I").callSuper(K, "m", "(I)I").build() |
|
205 .concreteMethod("l", "()I").callSuper(L, "m", "(I)I").build() |
|
206 .build(); |
|
207 |
|
208 b.test().callSite(K, C, "m", "(I)I").throws_(IncompatibleClassChangeError.class).done() |
|
209 .test().callSite(L, C, "m", "(I)I").throws_(IncompatibleClassChangeError.class).done() |
|
210 .test().callSite(C, C, "m", "(I)I").throws_(IncompatibleClassChangeError.class).done() |
|
211 |
|
212 .test().callSite(I, C, "k", "()I").returns(1).done() |
|
213 .test().callSite(C, C, "k", "()I").returns(1).done() |
|
214 .test().callSite(I, C, "l", "()I").returns(2).done() |
|
215 .test().callSite(C, C, "l", "()I").returns(2).done() |
|
216 |
|
217 .test().callSite(K, D, "m", "(I)I").throws_(IncompatibleClassChangeError.class).done() |
|
218 .test().callSite(L, D, "m", "(I)I").throws_(IncompatibleClassChangeError.class).done() |
|
219 .test().callSite(D, D, "m", "(I)I").throws_(IncompatibleClassChangeError.class).done() |
|
220 |
|
221 .test().callSite(D, D, "k", "()I").returns(1).done() |
|
222 .test().callSite(D, D, "l", "()I").returns(2).done() |
|
223 |
|
224 .run(); |
|
225 } |
|
226 |
|
227 /* |
|
228 * SuperConflict |
|
229 * |
|
230 * interface K { int m() default { return 1; } } |
|
231 * interface L { int m() default { return 2; } } |
|
232 * interface J extends K, L {} |
|
233 * interface I extends J, K { int m() default { J.super.m(); } } |
|
234 * class C implements I {} |
|
235 * |
|
236 * TEST: K k = new C(); k.m() ==> ICCE |
|
237 * TEST: L l = new C(); l.m() ==> ICCE |
|
238 * TEST: J j = new C(); j.m() ==> ICCE |
|
239 * TEST: I i = new C(); i.m() ==> ICCE |
|
240 * TEST: C c = new C(); c.m() ==> ICCE |
|
241 */ |
|
242 public void testSuperConflict() { |
|
243 TestBuilder b = factory.getBuilder(); |
|
244 |
|
245 Interface K = b.intf("K") |
|
246 .defaultMethod("m", "()I").returns(1).build() |
|
247 .build(); |
|
248 |
|
249 Interface L = b.intf("L") |
|
250 .defaultMethod("m", "()I").returns(2).build() |
|
251 .build(); |
|
252 |
|
253 Interface J = b.intf("J").extend(K, L).build(); |
|
254 |
|
255 Interface I = b.intf("I").extend(K, J) |
|
256 .defaultMethod("m", "()I").callSuper(J, "m", "()I").build() |
|
257 .build(); |
|
258 |
|
259 ConcreteClass C = b.clazz("C").implement(I).build(); |
|
260 |
|
261 b.test().callSite(K, C, "m", "()I").throws_(IncompatibleClassChangeError.class).done() |
|
262 .test().callSite(L, C, "m", "()I").throws_(IncompatibleClassChangeError.class).done() |
|
263 .test().callSite(J, C, "m", "()I").throws_(IncompatibleClassChangeError.class).done() |
|
264 .test().callSite(I, C, "m", "()I").throws_(IncompatibleClassChangeError.class).done() |
|
265 .test().callSite(C, C, "m", "()I").throws_(IncompatibleClassChangeError.class).done() |
|
266 |
|
267 .run(); |
|
268 } |
|
269 |
|
270 /* |
|
271 * SuperDisqual |
|
272 * |
|
273 * interface I { int m() default { return 1; } } |
|
274 * interface J { int m() default { return 2; } } |
|
275 * class C implements I, J { public int m() { return I.super.m(); } } |
|
276 * |
|
277 * TEST: C c = new C(); c.m() ==> 1 |
|
278 * TEST: J j = new C(); j.m() ==> 1 |
|
279 */ |
|
280 public void testSuperDisqual() { |
|
281 TestBuilder b = factory.getBuilder(); |
|
282 |
|
283 Interface I = b.intf("I") |
|
284 .defaultMethod("m", "()I").returns(1).build() |
|
285 .build(); |
|
286 |
|
287 Interface J = b.intf("J") |
|
288 .defaultMethod("m", "()I").returns(2).build() |
|
289 .build(); |
|
290 |
|
291 ConcreteClass C = b.clazz("C").implement(I, J) |
|
292 .concreteMethod("m", "()I").callSuper(I, "m", "()I").build() |
|
293 .build(); |
|
294 |
|
295 b.test().callSite(I, C, "m", "()I").returns(1).done() |
|
296 .test().callSite(J, C, "m", "()I").returns(1).done() |
|
297 .test().callSite(C, C, "m", "()I").returns(1).done() |
|
298 |
|
299 .run(); |
|
300 } |
|
301 |
|
302 /* |
|
303 * SuperNull |
|
304 * |
|
305 * interface I { int m(); } |
|
306 * interface J extends I { int m() default { return I.super.m(); } } |
|
307 * interface K extends I { int m() default { return I.super.n(); } } |
|
308 * class C implements J {} |
|
309 * class D implements K {} |
|
310 * |
|
311 * TEST: I i = new C(); i.m() ==> AME |
|
312 * TEST: J j = new C(); j.m() ==> AME |
|
313 * TEST: C c = new C(); c.m() ==> AME |
|
314 * TEST: K k = new D(); k.m() ==> NSME |
|
315 */ |
|
316 public void testSuperNull() { |
|
317 TestBuilder b = factory.getBuilder(); |
|
318 |
|
319 Interface I = b.intf("I") |
|
320 .abstractMethod("m", "()I").build() |
|
321 .build(); |
|
322 |
|
323 Interface J = b.intf("J").extend(I) |
|
324 .defaultMethod("m", "()I").callSuper(I, "m", "()I").build() |
|
325 .build(); |
|
326 |
|
327 Interface K = b.intf("K").extend(I) |
|
328 .defaultMethod("m", "()I").callSuper(I, "n", "()I").build() |
|
329 .build(); |
|
330 |
|
331 ConcreteClass C = b.clazz("C").implement(J).build(); |
|
332 ConcreteClass D = b.clazz("D").implement(K).build(); |
|
333 |
|
334 b.test().callSite(I, C, "m", "()I").throws_(AbstractMethodError.class).done() |
|
335 .test().callSite(J, C, "m", "()I").throws_(AbstractMethodError.class).done() |
|
336 .test().callSite(C, C, "m", "()I").throws_(AbstractMethodError.class).done() |
|
337 .test().callSite(K, D, "m", "()I").throws_(NoSuchMethodError.class).done() |
|
338 |
|
339 .run(); |
|
340 } |
|
341 |
|
342 /* |
|
343 * SuperGeneric |
|
344 * |
|
345 * interface J<T> { int m(T t) default { return 1; } } |
|
346 * interface I extends J<String> { int m(String s) default { return J.super.m(); } } |
|
347 * class C implements I {} |
|
348 * |
|
349 * TEST: I i = new C(); i.m(new Object()) == 1; |
|
350 * TESTL J j = new C(); j.m(new Object()) == 1; |
|
351 * TEST: J j = new C(); j.m("") == 1; |
|
352 * TEST: C c = new C(); c.m(new Object()) == 1; |
|
353 * TEST: C c = new C(); c.m("") == 1; |
|
354 */ |
|
355 @KnownFailure(modes = { INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY }) // Test2_J_C_m: AME => IAE => ICCE instead of successful call |
|
356 public void testSuperGeneric() { |
|
357 TestBuilder b = factory.getBuilder(); |
|
358 |
|
359 // interface I<T> { |
|
360 // default int m(T t) { return 1; } |
|
361 // } |
|
362 Interface I = b.intf("I") |
|
363 .sig("<T:Ljava/lang/Object;>Ljava/lang/Object;") |
|
364 .defaultMethod("m", "(Ljava/lang/Object;)I").sig("(TT;)I").returns(1).build() |
|
365 .build(); |
|
366 |
|
367 // interface J extends I<String> { |
|
368 // default int m(String s) { return I.super.m(); } |
|
369 // } |
|
370 Interface J = b.intf("J").extend(I) |
|
371 .sig("Ljava/lang/Object;LI<Ljava/lang/String;>;") |
|
372 .defaultMethod("m", "(Ljava/lang/String;)I").callSuper(I, "m", "(Ljava/lang/Object;)I").build() |
|
373 .build(); |
|
374 |
|
375 ConcreteClass C = b.clazz("C").implement(J).build(); |
|
376 |
|
377 b.test().callSite(I, C, "m", "(Ljava/lang/Object;)I").returns(1).done() |
|
378 |
|
379 .test().callSite(J, C, "m", "(Ljava/lang/Object;)I").returns(1).done() |
|
380 .test().callSite(J, C, "m", "(Ljava/lang/String;)I").returns(1).done() |
|
381 |
|
382 .test().callSite(C, C, "m", "(Ljava/lang/Object;)I").returns(1).done() |
|
383 .test().callSite(C, C, "m", "(Ljava/lang/String;)I").returns(1).done() |
|
384 |
|
385 .run(); |
|
386 } |
|
387 |
|
388 /* |
|
389 * SuperGenericDisqual |
|
390 * |
|
391 * interface I<T> { int m(T t) default { return 1; } } |
|
392 * interface J extends I<String> { int m(String s) default { return 2; } } |
|
393 * class C implements I<String>, J { public int m(String s) { return I.super.m(s); } } |
|
394 * |
|
395 * TEST: C c = new C(); c.m("string") == 1 |
|
396 */ |
|
397 @KnownFailure(modes = { INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY }) // Test2_J_C_m: AME => IAE => ICCE instead of successful call |
|
398 public void testSuperGenericDisqual() { |
|
399 TestBuilder b = factory.getBuilder(); |
|
400 |
|
401 Interface I = b.intf("I").sig("<T:Ljava/lang/Object;>Ljava/lang/Object;") |
|
402 .defaultMethod("m", "(Ljava/lang/Object;)I").sig("(TT;)I").returns(1).build() |
|
403 .build(); |
|
404 |
|
405 Interface J = b.intf("J").extend(I) |
|
406 .sig("Ljava/lang/Object;LJ<Ljava/lang/String;>;") |
|
407 .defaultMethod("m", "(Ljava/lang/String;)I").returns(2).build() |
|
408 .build(); |
|
409 |
|
410 ConcreteClass C = b.clazz("C").implement(I,J) |
|
411 .sig("Ljava/lang/Object;LI;LJ<Ljava/lang/String;>;") |
|
412 .concreteMethod("m", "(Ljava/lang/String;)I").callSuper(I, "m", "(Ljava/lang/Object;)I").build() |
|
413 .build(); |
|
414 |
|
415 b.test().callSite(I, C, "m", "(Ljava/lang/Object;)I").returns(1).done() |
|
416 |
|
417 .test().callSite(J, C, "m", "(Ljava/lang/Object;)I").returns(1).done() |
|
418 .test().callSite(J, C, "m", "(Ljava/lang/String;)I").returns(1).done() |
|
419 |
|
420 .test().callSite(C, C, "m", "(Ljava/lang/Object;)I").returns(1).done() |
|
421 .test().callSite(C, C, "m", "(Ljava/lang/String;)I").returns(1).done() |
|
422 |
|
423 .run(); |
|
424 } |
|
425 |
|
426 /* |
|
427 * Super-call of non-default method |
|
428 * |
|
429 * class C { int m() { return 1; } } |
|
430 * class D extends C { int m() { return C.super.m(); } } |
|
431 * |
|
432 * TEST: C d = new D(); d.m() == 1 |
|
433 * TEST: D d = new D(); d.m() == 1 |
|
434 */ |
|
435 public void testSuperNonDefault() { |
|
436 TestBuilder b = factory.getBuilder(); |
|
437 |
|
438 ConcreteClass C = b.clazz("C") |
|
439 .concreteMethod("m", "()I").returns(1).build() |
|
440 .build(); |
|
441 |
|
442 ConcreteClass D = b.clazz("D").extend(C) |
|
443 .concreteMethod("m", "()I").callSuper(C, "m", "()I").build() |
|
444 .build(); |
|
445 |
|
446 b.test().callSite(C, D, "m", "()I").returns(1).done() |
|
447 .test().callSite(D, D, "m", "()I").returns(1).done() |
|
448 |
|
449 .run(); |
|
450 } |
|
451 |
|
452 /* |
|
453 * Super-call of non-default method |
|
454 * |
|
455 * interface I { int m(); } |
|
456 * class C { int m() { return 1; } } |
|
457 * class D extends C implements I { int m() { return I.super.m(); } } |
|
458 * class E extends C implements I { int m() { return C.super.m(); } } |
|
459 * |
|
460 * TEST: I d = new D(); d.m() ==> AME |
|
461 * TEST: C d = new D(); d.m() ==> AME |
|
462 * TEST: D d = new D(); d.m() ==> AME |
|
463 * TEST: I e = new E(); e.m() == 1 |
|
464 * TEST: C e = new E(); e.m() == 1 |
|
465 * TEST: E e = new E(); e.m() == 1 |
|
466 */ |
|
467 public void testSuperNonDefault1() { |
|
468 TestBuilder b = factory.getBuilder(); |
|
469 |
|
470 Interface I = b.intf("I") |
|
471 .abstractMethod("m", "()I").build() |
|
472 .build(); |
|
473 |
|
474 ConcreteClass C = b.clazz("C") |
|
475 .concreteMethod("m", "()I").returns(1).build() |
|
476 .build(); |
|
477 |
|
478 ConcreteClass D = b.clazz("D").extend(C).implement(I) |
|
479 .concreteMethod("m", "()I").callSuper(I, "m", "()I").build() |
|
480 .build(); |
|
481 |
|
482 ConcreteClass E = b.clazz("E").extend(C).implement(I) |
|
483 .concreteMethod("m", "()I").callSuper(C, "m", "()I").build() |
|
484 .build(); |
|
485 |
|
486 b.test().callSite(I, D, "m", "()I").throws_(AbstractMethodError.class).done() |
|
487 .test().callSite(C, D, "m", "()I").throws_(AbstractMethodError.class).done() |
|
488 .test().callSite(D, D, "m", "()I").throws_(AbstractMethodError.class).done() |
|
489 |
|
490 .test().callSite(I, E, "m", "()I").returns(1).done() |
|
491 .test().callSite(C, E, "m", "()I").returns(1).done() |
|
492 .test().callSite(E, E, "m", "()I").returns(1).done() |
|
493 |
|
494 .run(); |
|
495 } |
|
496 |
|
497 /* |
|
498 * Super-call of non-default method |
|
499 * |
|
500 * interface I { int m() {return 1;} } |
|
501 * class C { int m() { return 2; } } |
|
502 * class D extends C implements I { int m() { return I.super.m(); } } |
|
503 * class E extends C implements I { int m() { return C.super.m(); } } |
|
504 * |
|
505 * TEST: I d = new D(); d.m() == 1 |
|
506 * TEST: C d = new D(); d.m() == 1 |
|
507 * TEST: D d = new D(); d.m() == 1 |
|
508 * |
|
509 * TEST: I e = new E(); e.m() == 2 |
|
510 * TEST: C e = new E(); e.m() == 2 |
|
511 * TEST: E e = new E(); e.m() == 2 |
|
512 */ |
|
513 public void testSuperNonDefault2() { |
|
514 TestBuilder b = factory.getBuilder(); |
|
515 |
|
516 Interface I = b.intf("I") |
|
517 .defaultMethod("m", "()I").returns(1).build() |
|
518 .build(); |
|
519 |
|
520 ConcreteClass C = b.clazz("C") |
|
521 .concreteMethod("m", "()I").returns(2).build() |
|
522 .build(); |
|
523 |
|
524 ConcreteClass D = b.clazz("D").extend(C).implement(I) |
|
525 .concreteMethod("m", "()I").callSuper(I, "m", "()I").build() |
|
526 .build(); |
|
527 |
|
528 ConcreteClass E = b.clazz("E").extend(C).implement(I) |
|
529 .concreteMethod("m", "()I").callSuper(C, "m", "()I").build() |
|
530 .build(); |
|
531 |
|
532 b.test().callSite(I, D, "m", "()I").returns(1).done() |
|
533 .test().callSite(C, D, "m", "()I").returns(1).done() |
|
534 .test().callSite(D, D, "m", "()I").returns(1).done() |
|
535 |
|
536 .test().callSite(I, E, "m", "()I").returns(2).done() |
|
537 .test().callSite(C, E, "m", "()I").returns(2).done() |
|
538 .test().callSite(E, E, "m", "()I").returns(2).done() |
|
539 |
|
540 .run(); |
|
541 } |
|
542 |
|
543 /* |
|
544 * Disambig |
|
545 * |
|
546 * interface I { int m() default { return 1; } } |
|
547 * interface J { int m() default { return 2; } } |
|
548 * class C implements I, J { int q() { return I.super.m(); } |
|
549 * int r() { return J.super.m(); } } |
|
550 * |
|
551 * TEST: C c = new C(); c.m() == ICCE; |
|
552 * TEST: C c = new C(); c.q() == 1; |
|
553 * TEST: C c = new C(); c.r() == 2; |
|
554 */ |
|
555 public void testDisambig() { |
|
556 TestBuilder b = factory.getBuilder(); |
|
557 |
|
558 Interface I = b.intf("I") |
|
559 .defaultMethod("m", "()I").returns(1).build() |
|
560 .build(); |
|
561 |
|
562 Interface J = b.intf("J") |
|
563 .defaultMethod("m", "()I").returns(2).build() |
|
564 .build(); |
|
565 |
|
566 ConcreteClass C = b.clazz("C").implement(I,J) |
|
567 .concreteMethod("q", "()I").callSuper(I, "m", "()I").build() |
|
568 .concreteMethod("r", "()I").callSuper(J, "m", "()I").build() |
|
569 .build(); |
|
570 |
|
571 b.test().callSite(C, C, "q", "()I").returns(1).done() |
|
572 .test().callSite(C, C, "r", "()I").returns(2).done() |
|
573 .test().callSite(C, C, "m", "()I").throws_(IncompatibleClassChangeError.class).done() |
|
574 |
|
575 .run(); |
|
576 } |
|
577 |
|
578 /* |
|
579 * Disambig2 |
|
580 * |
|
581 * interface I { int m() default { return 1; } } |
|
582 * interface J { int m() default { return 2; } } |
|
583 * interface K extends I |
|
584 * interface L extends J |
|
585 * class C implements K, L { int q() { return K.super.m(); } |
|
586 * int r() { return L.super.m(); } } |
|
587 * |
|
588 * TEST: C c = new C(); c.m() == ICCE; |
|
589 * TEST: C c = new C(); c.q() == 1; |
|
590 * TEST: C c = new C(); c.r() == 2; |
|
591 */ |
|
592 public void testDisambig2() { |
|
593 TestBuilder b = factory.getBuilder(); |
|
594 |
|
595 Interface I = b.intf("I") |
|
596 .defaultMethod("m", "()I").returns(1).build() |
|
597 .build(); |
|
598 |
|
599 Interface J = b.intf("J") |
|
600 .defaultMethod("m", "()I").returns(2).build() |
|
601 .build(); |
|
602 |
|
603 Interface K = b.intf("K").extend(I).build(); |
|
604 |
|
605 Interface L = b.intf("L").extend(J).build(); |
|
606 |
|
607 ConcreteClass C = b.clazz("C").implement(K,L) |
|
608 .concreteMethod("q", "()I").callSuper(K, "m", "()I").build() |
|
609 .concreteMethod("r", "()I").callSuper(L, "m", "()I").build() |
|
610 .build(); |
|
611 |
|
612 b.test().callSite(C, C, "q", "()I").returns(1).done() |
|
613 .test().callSite(C, C, "r", "()I").returns(2).done() |
|
614 .test().callSite(C, C, "m", "()I").throws_(IncompatibleClassChangeError.class).done() |
|
615 |
|
616 .run(); |
|
617 } |
|
618 |
|
619 /* |
|
620 * testResolvedShadowed |
|
621 * |
|
622 * interface I { int m() default { return 1; } } |
|
623 * interface K extends I { int m() default { return 2; } } |
|
624 * interface J extends I { } |
|
625 * class C implements J,K { int q { J.super.m(); } } |
|
626 * |
|
627 * TEST: C c = new C(); c.m() == 2 |
|
628 * TEST: C c = new C(); c.q() == 1 |
|
629 */ |
|
630 public void testResolvedShadowed() { |
|
631 TestBuilder b = factory.getBuilder(); |
|
632 |
|
633 Interface I = b.intf("I") |
|
634 .defaultMethod("m", "()I").returns(1).build() |
|
635 .build(); |
|
636 |
|
637 Interface K = b.intf("K").extend(I) |
|
638 .defaultMethod("m", "()I").returns(2).build() |
|
639 .build(); |
|
640 |
|
641 Interface J = b.intf("J").extend(I) |
|
642 .build(); |
|
643 |
|
644 ConcreteClass C = b.clazz("C").implement(J,K) |
|
645 .concreteMethod("q", "()I").callSuper(J, "m", "()I").build() |
|
646 .build(); |
|
647 |
|
648 b.test().callSite(C, C, "m", "()I").returns(2).done() |
|
649 .test().callSite(C, C, "q", "()I").returns(1).done() |
|
650 |
|
651 .run(); |
|
652 } |
|
653 |
|
654 /* |
|
655 * testResolvedButSuperClass |
|
656 * |
|
657 * interface I { int m() default { return 1; } } |
|
658 * interface J { } |
|
659 * class A { public int m() { return 2; } } |
|
660 * class C implements J extends A { int q { J.super.m(); } } |
|
661 * |
|
662 * TEST: C c = new C(); c.q() == 1 |
|
663 * TEST: C c = new C(); c.m() == 2 |
|
664 */ |
|
665 public void testResolvedButSuperClass() { |
|
666 TestBuilder b = factory.getBuilder(); |
|
667 |
|
668 Interface I = b.intf("I") |
|
669 .defaultMethod("m", "()I").returns(1).build() |
|
670 .build(); |
|
671 |
|
672 Interface J = b.intf("J").extend(I) |
|
673 .build(); |
|
674 |
|
675 ConcreteClass A = b.clazz("A") |
|
676 .concreteMethod("m", "()I").returns(2).build() |
|
677 .build(); |
|
678 |
|
679 ConcreteClass C = b.clazz("C").implement(J).extend(A) |
|
680 .concreteMethod("q", "()I").callSuper(J, "m", "()I").build() |
|
681 .build(); |
|
682 |
|
683 b.test().callSite(C, C, "q", "()I").returns(1).done() |
|
684 .test().callSite(C, C, "m", "()I").returns(2).done() |
|
685 |
|
686 .run(); |
|
687 } |
|
688 |
|
689 /* |
|
690 * testResolved1Caller2NotShadowed |
|
691 * |
|
692 * interface I { int m() default { return 1; } } |
|
693 * interface J extends I { } |
|
694 * interface L { int m() default { return 2; } } |
|
695 * interface K extends I, L { } |
|
696 * class C implements J,K { int q { J.super.m(); } } |
|
697 * |
|
698 * TEST: C c = new C(); c.m() == ICCE |
|
699 * TEST: C c = new C(); c.q() == 1 |
|
700 */ |
|
701 public void testResolved1Caller2NotShadowed() { |
|
702 TestBuilder b = factory.getBuilder(); |
|
703 |
|
704 Interface I = b.intf("I") |
|
705 .defaultMethod("m", "()I").returns(1).build() |
|
706 .build(); |
|
707 |
|
708 Interface J = b.intf("J").extend(I).build(); |
|
709 |
|
710 Interface L = b.intf("L") |
|
711 .defaultMethod("m", "()I").returns(2).build() |
|
712 .build(); |
|
713 |
|
714 Interface K = b.intf("K").extend(I,L) |
|
715 .build(); |
|
716 |
|
717 ConcreteClass C = b.clazz("C").implement(J,K) |
|
718 .concreteMethod("q", "()I").callSuper(J, "m", "()I").build() |
|
719 .build(); |
|
720 |
|
721 b.test().callSite(C, C, "m", "()I").throws_(IncompatibleClassChangeError.class).done() |
|
722 .test().callSite(C, C, "q", "()I").returns(1).done() |
|
723 |
|
724 .run(); |
|
725 } |
|
726 |
|
727 /* |
|
728 * Test validity of invokespecial on indirect superinterface's method, |
|
729 * this test should receive a verification error. |
|
730 * |
|
731 * (JVMS draft 0.7.0) JVMS 4.9.2 Structural Constraints |
|
732 * Each invokespecial instruction must name an instance initialization |
|
733 * method (2.9), or must reference a method in the current class or interface, |
|
734 * a method in a superclass of the current class or interface, or a method |
|
735 * in a direct superinterface of the current class or interface |
|
736 * |
|
737 * Note: Normally javac would reject this test case complaining that, |
|
738 * InDirectSuper.java:5: error: not an enclosing class: I |
|
739 * interface K extends J { default public void m() { I.super.m(); } } |
|
740 * ^ |
|
741 * However, the below test case allows us to check for this structural |
|
742 * constraint on invokespecial in the JVM. |
|
743 * |
|
744 * interface I { int m() default { return 1; } } |
|
745 * interface J extends I { } |
|
746 * interface K extends J { int m() default { return I.super.m(); } } |
|
747 * class C implements K {} |
|
748 * |
|
749 * TEST: K k = new C(); k.m() == VerifyError |
|
750 */ |
|
751 @NotApplicableFor(modes = { REDEFINITION }) // Can't redefine a class that gets VerifyError |
|
752 public void testSuperInvalidIndirectInterfaceMethodInvokeSpecial() { |
|
753 TestBuilder b = factory.getBuilder(); |
|
754 |
|
755 Interface I = b.intf("I") |
|
756 .defaultMethod("m", "()I").returns(1).build() |
|
757 .build(); |
|
758 |
|
759 Interface J = b.intf("J").extend(I).build(); |
|
760 |
|
761 Interface K = b.intf("K").extend(J) |
|
762 .defaultMethod("m", "()I").callSuper(I, "m", "()I").build() |
|
763 .build(); |
|
764 |
|
765 ConcreteClass C = b.clazz("C").implement(K).build(); |
|
766 |
|
767 b.test().callSite(K, C, "m", "()I").throws_(VerifyError.class).done() |
|
768 |
|
769 .run(); |
|
770 } |
|
771 } |