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.data.*; 30 import vm.runtime.defmeth.shared.data.method.param.NewInstanceParam; 31 import vm.runtime.defmeth.shared.builder.TestBuilder; 32 import static vm.runtime.defmeth.shared.ExecutionMode.*; 33 import static vm.runtime.defmeth.shared.data.method.body.CallMethod.Invoke.*; 34 import static vm.runtime.defmeth.shared.data.method.body.CallMethod.IndexbyteOp.*; 35 36 /** 37 * Tests on interaction of default methods with abstract methods 38 * 39 * The rule: "the superclass always wins." 40 * 41 * In searching the superclass hierarchy, a declaration in a superclass is 42 * preferred to a default in an interface. This preference includes abstract 43 * methods in superclasses as well; the defaults are only considered when 44 * the entire implementation hierarchy is silent on the status of the method 45 * in question. 46 */ 47 public class DefaultVsAbstractTest extends DefMethTest { 48 49 public static void main(String[] args) { 50 TestBase.runTest(new DefaultVsAbstractTest(), args); 51 } 52 53 /* 54 * interface I { public int m() default { return 1; } } 55 * class C implements I { public abstract int m(); } 56 * 57 * TEST: new C() throws InstantiationError 58 */ 59 public void test0() { 60 TestBuilder b = factory.getBuilder(); 61 62 Interface I = b.intf("I") 63 .defaultMethod("m", "()I").returns(1).build() 64 .build(); 65 66 ConcreteClass C = b.clazz("C").implement(I) 67 .abstractMethod("m", "()I").build() 68 .build(); 69 70 b.test() 71 .callSite(I, C, "m", "()I") 72 .throws_(InstantiationError.class) 73 .done() 74 .run(); 75 } 76 77 /* 78 * interface I { 79 * public int m() default { return 1; } 80 * } 81 * class C implements I { 82 * public abstract int m(); 83 * } 84 * class D extends C {} 85 * 86 * TEST: I i = new D(); i.m() ==> AME 87 * TEST: C c = new D(); c.m() ==> AME 88 * TEST: D d = new D(); d.m() ==> AME 89 */ 90 @KnownFailure(modes = {INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY }) // Test1_I_D_m: NPE instead of AME 91 // Test3_D_D_m: AME => IAE => ICCE instead of AME 92 public void test1() { 93 TestBuilder b = factory.getBuilder(); 94 95 Interface I = b.intf("I") 96 .defaultMethod("m", "()I").returns(1).build() 97 .build(); 98 99 ConcreteClass C = b.clazz("C").implement(I) 100 .abstractMethod("m", "()I").build() 101 .build(); 102 103 ConcreteClass D = b.clazz("D").extend(C).build(); 104 105 b.test() 106 .callSite(I, D, "m", "()I") 107 .throws_(AbstractMethodError.class) 108 .done() 109 .test() 110 .callSite(C, D, "m", "()I") 111 .throws_(AbstractMethodError.class) 112 .done() 113 .test() 114 .callSite(D, D, "m", "()I") 115 .throws_(AbstractMethodError.class) 116 .done() 117 .run(); 118 } 119 120 /* 121 * interface I { 122 * default public int m() { return 1; } 123 * } 124 * class C { 125 * abstract public int m(); 126 * } 127 * class D extends C implements I {} 128 * 129 * TEST: I o = new D(); o.m()I throws AME 130 * TEST: C o = new D(); o.m()I throws AME 131 * TEST: D o = new D(); o.m()I throws AME 132 */ 133 @KnownFailure(modes = { INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY }) // Test1_I_D_m: NPE instead of AME 134 // Test3_D_D_m: AME => IAE => ICCE instead of AME 135 public void test2() { 136 TestBuilder b = factory.getBuilder(); 137 138 Interface I = b.intf("I") 139 .defaultMethod("m", "()I").returns(1).build() 140 .build(); 141 142 ConcreteClass C = b.clazz("C") 143 .abstractMethod("m", "()I").build() 144 .build(); 145 146 ConcreteClass D = b.clazz("D").extend(C).implement(I).build(); 147 148 b.test() 149 .callSite(I, D, "m", "()I") 150 .throws_(AbstractMethodError.class) 151 .done() 152 .test() 153 .callSite(C, D, "m", "()I") 154 .throws_(AbstractMethodError.class) 155 .done() 156 .test() 157 .callSite(D, D, "m", "()I") 158 .throws_(AbstractMethodError.class) 159 .done() 160 .run(); 161 } 162 163 /* 164 * interface I { 165 * default public int m() { return 1; } 166 * } 167 * class C { 168 * abstract public int m(); 169 * } 170 * class D extends C implements I { 171 * public int m() { return 2; } 172 * } 173 * 174 * TEST: I o = new D(); o.m()I == 2 175 * TEST: C o = new D(); o.m()I == 2 176 * TEST: D o = new D(); o.m()I == 2 177 */ 178 public void test3() { 179 TestBuilder b = factory.getBuilder(); 180 181 Interface I = b.intf("I") 182 .defaultMethod("m", "()I").returns(1).build() 183 .build(); 184 185 ConcreteClass C = b.clazz("C") 186 .abstractMethod("m", "()I").build() 187 .build(); 188 189 ConcreteClass D = b.clazz("D").extend(C).implement(I) 190 .concreteMethod("m", "()I").returns(2) 191 .build() 192 .build(); 193 194 b.test() // I i = new D(); ... 195 .callSite(I, D, "m", "()I").returns(2) 196 .done() 197 .test() // C c = new D(); ... 198 .callSite(C, D, "m", "()I").returns(2) 199 .done() 200 .test() // D d = new C(); ... 201 .callSite(D, D, "m", "()I").returns(2) 202 .done() 203 .run(); 204 } 205 206 /* 207 * interface I { 208 * default public int m() { return 1; } 209 * } 210 * class E { 211 * abstract public int m(); 212 * } 213 * class D extends E {} 214 * class C extends D implements I {} 215 * 216 * TEST: I o = new C(); o.m()I throws AME 217 * TEST: E o = new C(); o.m()I throws AME 218 * TEST: D o = new C(); o.m()I throws AME 219 * TEST: C o = new C(); o.m()I throws AME 220 */ 221 @KnownFailure(modes = { 222 INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY // Test1_I_C_m: NPE instead of AME 223 // Test3_D_C_m: AME => IAE => ICCE instead of AME 224 // Test4_C_C_m: AME => IAE => ICCE instead of AME 225 }) 226 public void test4() { 227 TestBuilder b = factory.getBuilder(); 228 229 Interface I = b.intf("I") 230 .defaultMethod("m", "()I").returns(1).build() 231 .build(); 232 233 ConcreteClass E = b.clazz("E") 234 .abstractMethod("m", "()I").build() 235 .build(); 236 237 ConcreteClass D = b.clazz("D").extend(E).build(); 238 239 ConcreteClass C = b.clazz("C").extend(D).implement(I).build(); 240 241 b.test() // I i = new C(); ... 242 .callSite(I, C, "m", "()I") 243 .throws_(AbstractMethodError.class) 244 .done() 245 .test() // E e = new C(); ... 246 .callSite(E, C, "m", "()I") 247 .throws_(AbstractMethodError.class) 248 .done() 249 .test() // D d = new C(); ... 250 .callSite(D, C, "m", "()I") 251 .throws_(AbstractMethodError.class) 252 .done() 253 .test() // C c = new C(); ... 254 .callSite(C, C, "m", "()I") 255 .throws_(AbstractMethodError.class) 256 .done() 257 .run(); 258 } 259 260 /* 261 * interface I { 262 * default public int m() { return 1; } 263 * } 264 * class E { 265 * abstract public int m(); 266 * } 267 * class D extends E { 268 * public int m() { return 2; } 269 * } 270 * class C extends D implements I {} 271 * 272 * TEST: I o = new C(); o.m()I == 2 273 * TEST: I o = new C(); o.m()I == 2 274 * TEST: I o = new C(); o.m()I == 2 275 * TEST: I o = new C(); o.m()I == 2 276 */ 277 public void test5() { 278 TestBuilder b = factory.getBuilder(); 279 280 Interface I = b.intf("I") 281 .defaultMethod("m", "()I").returns(1).build() 282 .build(); 283 284 ConcreteClass E = b.clazz("E") 285 .abstractMethod("m", "()I").build() 286 .build(); 287 288 ConcreteClass D = b.clazz("D").extend(E) 289 .concreteMethod("m", "()I").returns(2).build() 290 .build(); 291 292 ConcreteClass C = b.clazz("C").extend(D).implement(I).build(); 293 294 b.test() // I i = new C(); ... 295 .callSite(I, C, "m", "()I") 296 .returns(2) 297 .done() 298 .test() // E e = new C(); ... 299 .callSite(I, C, "m", "()I") 300 .returns(2) 301 .done() 302 .test() // D d = new C(); ... 303 .callSite(I, C, "m", "()I") 304 .returns(2) 305 .done() 306 .test() // C c = new C(); ... 307 .callSite(I, C, "m", "()I") 308 .returns(2) 309 .done() 310 .run(); 311 } 312 313 /* 314 * interface I { 315 * default public int m() { return 1; } 316 * } 317 * interface J { 318 * default public int m() { return 2; } 319 * } 320 * class E { 321 * abstract public int m(); 322 * } 323 * class D extends E { 324 * public int m() { return 3; } 325 * } 326 * class C extends D implements I, J {} 327 * 328 * TEST: I o = new C(); o.m()I == 3 329 * TEST: J o = new C(); o.m()I == 3 330 * TEST: E o = new C(); o.m()I == 3 331 * TEST: D o = new C(); o.m()I == 3 332 * TEST: J o = new C(); o.m()I == 3 333 */ 334 public void test6() { 335 TestBuilder b = factory.getBuilder(); 336 337 Interface I = b.intf("I") 338 .defaultMethod("m", "()I").returns(1).build() 339 .build(); 340 341 Interface J = b.intf("J") 342 .defaultMethod("m", "()I").returns(2).build() 343 .build(); 344 345 ConcreteClass E = b.clazz("E") 346 .abstractMethod("m", "()I").build() 347 .build(); 348 349 ConcreteClass D = b.clazz("D").extend(E) 350 .concreteMethod("m", "()I").returns(3).build() 351 .build(); 352 353 ConcreteClass C = b.clazz("C").extend(D).implement(I, J).build(); 354 355 356 b.test() // I i = new C(); ... 357 .callSite(I, C, "m", "()I").returns(3) 358 .done() 359 .test() // J j = new C(); ... 360 .callSite(J, C, "m", "()I").returns(3) 361 .done() 362 .test() // E e = new C(); ... 363 .callSite(E, C, "m", "()I").returns(3) 364 .done() 365 .test() // D d = new C(); ... 366 .callSite(D, C, "m", "()I").returns(3) 367 .done() 368 .test() // C c = new C(); ... 369 .callSite(J, C, "m", "()I").returns(3) 370 .done() 371 .run(); 372 } 373 374 /* 375 * interface I { 376 * abstract public int m(); 377 * } 378 * 379 * interface J { 380 * default public int m() { return 1; } 381 * } 382 * 383 * class A implements I; 384 * 385 * class B extends A implements J; 386 * 387 * TEST: A o = new B(); o.m()I 388 * returns 1 for REFLECTION and INVOKE_WITH_ARGS 389 * ICCE for other modes 390 */ 391 public void testInvokeInterfaceClassDefaultMethod() { 392 TestBuilder b = factory.getBuilder(); 393 394 Interface I = b.intf("I") 395 .abstractMethod("m", "()I").build() 396 .build(); 397 398 Interface J = b.intf("J") 399 .extend(I) 400 .defaultMethod("m", "()I").returns(1).build() 401 .build(); 402 403 ConcreteClass A = b.clazz("A").implement(I).build(); 404 405 ConcreteClass B = b.clazz("B").extend(A).implement(J).build(); 406 407 String exeMode = factory.getExecutionMode(); 408 409 // the test passes in the reflection mode because there's no way to 410 // express invokeinterface on a class using Reflection API 411 // In the test generator, vm.runtime.defmeth.shared.executor.ReflectionTest, 412 // the invokeinterface is switched to invokevirtual. 413 // 414 // the test passes in the INVOKE_WITH_ARGS mode due to the fix for 415 // JDK-8032010 to conform with the removal of the following check 416 // during method resolution in JVMS-5.4.3.3 Method Resolution 417 // "If method lookup succeeds and the method is abstract, but C is not 418 // abstract, method resolution throws an AbstractMethodError." 419 if (exeMode.equals("REFLECTION") || 420 exeMode.equals("INVOKE_WITH_ARGS")) { 421 b.test().interfaceCallSite(A, B, "m", "()I") 422 .returns(1).done() 423 .run(); 424 } else { 425 // ICCE in other modes due to 426 // JVMS-5.4.3.4. Interface Method Resolution 427 // When resolving an interface method reference: 428 // If C is not an interface, interface method resolution throws an IncompatibleClassChangeError. 429 b.test().interfaceCallSite(A, B, "m", "()I") 430 .throws_(IncompatibleClassChangeError.class).done() 431 .run(); 432 } 433 } 434 435 /* 436 * interface I { 437 * abstract public int m(); 438 * } 439 * 440 * interface J { 441 * abstract public int m(); 442 * } 443 * 444 * class A implements I; 445 * 446 * class B extends A implements J; 447 * 448 * TEST: A o = new B(); o.m()I 449 * ICCE for DIRECT mode 450 * AME for REFLECTION and INVOKE_WITH_ARGS modes 451 * IAE for other modes 452 */ 453 public void testInvokeInterfaceClassAbstractMethod() { 454 TestBuilder b = factory.getBuilder(); 455 456 Interface I = b.intf("I") 457 .abstractMethod("m", "()I").build() 458 .build(); 459 460 Interface J = b.intf("J") 461 .abstractMethod("m", "()I").build() 462 .build(); 463 464 ConcreteClass A = b.clazz("A").implement(I).build(); 465 466 ConcreteClass B = b.clazz("B").extend(A).implement(J).build(); 467 468 String exeMode = factory.getExecutionMode(); 469 470 // ICCE in direct mode due to 471 // JVMS-5.4.3.4. Interface Method Resolution 472 // When resolving an interface method reference: 473 // If C is not an interface, interface method resolution throws an IncompatibleClassChangeError. 474 Class expectedError = IncompatibleClassChangeError.class;; 475 476 b.test().interfaceCallSite(A, B, "m", "()I") 477 .throws_(expectedError).done() 478 .run(); 479 480 } 481 482 /* 483 * interface I { 484 * public int m() default { return 1; } 485 * } 486 * 487 * interface J { 488 * public int m() default { return 1; } 489 * } 490 * 491 * class A implements I; 492 * 493 * class B extends A implements J; 494 * 495 * TEST: A o = new B(); o.m()I 496 * ICCE for all modes 497 */ 498 public void testInvokeInterfaceMultipleDefinedClassDefaultMethod() { 499 TestBuilder b = factory.getBuilder(); 500 501 Interface I = b.intf("I") 502 .defaultMethod("m", "()I").returns(1).build() 503 .build(); 504 505 Interface J = b.intf("J") 506 .defaultMethod("m", "()I").returns(1).build() 507 .build(); 508 509 ConcreteClass A = b.clazz("A").implement(I).build(); 510 511 ConcreteClass B = b.clazz("B").extend(A).implement(J).build(); 512 513 String exeMode = factory.getExecutionMode(); 514 515 // ICCE in direct mode due to 516 // JVMS-5.4.3.4. Interface Method Resolution 517 // When resolving an interface method reference: 518 // If C is not an interface, interface method resolution throws an IncompatibleClassChangeError. 519 Class expectedError = IncompatibleClassChangeError.class; 520 521 b.test().interfaceCallSite(A, B, "m", "()I") 522 .throws_(expectedError).done() 523 .run(); 524 } 525 526 }