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 * @bug 8029674 27 * @summary Verify that the right interface methods are returned by 28 * Class.getMethod() and Class.getMethods() 29 * @run testng FilterNotMostSpecific 30 */ 31 32 import java.lang.reflect.*; 33 import java.lang.annotation.*; 34 35 import java.util.Arrays; 36 import java.util.List; 37 import java.util.Map; 38 import java.util.HashMap; 39 import java.util.HashSet; 40 import java.util.Set; 41 import java.util.stream.Collectors; 42 43 import org.testng.annotations.DataProvider; 44 import org.testng.annotations.Test; 45 46 import static org.testng.Assert.*; 47 48 public class FilterNotMostSpecific { 49 50 @Test(dataProvider="getCases") 51 public void testGetMethod(Class<?> iface) { 52 boolean match = false; 53 MethodDesc[] expectedMethods = iface.getAnnotationsByType(MethodDesc.class); 54 55 for (MethodDesc expected : expectedMethods) { 56 if (expected.isGetMethodReturn()) { 57 try { 58 Method m = iface.getMethod(expected.name()); 59 if (!assertMatch(expected, m)) 60 fail(failMsg(expected, m, iface)); 61 else 62 match = true; 63 } catch (NoSuchMethodException e) { 64 fail("expected: " + toMethodString(expected), e); 65 } 66 } 67 } 68 assert(match); 69 } 70 71 @Test(dataProvider="getCases") 72 public void testGetMethods(Class<?> iface) { 73 List<Method> foundMethods = filterObjectMethods(iface.getMethods()); 74 MethodDesc[] expectedMethods = iface.getAnnotationsByType(MethodDesc.class); 75 Set<Method> used = new HashSet<>(); 76 77 for (MethodDesc expected : expectedMethods) { 78 boolean found = false; 79 80 for (Method m : foundMethods) { 81 if (used.contains(m)) 82 continue; 83 84 if(expected.name().equals(m.getName()) && 85 expected.declaringClass() ==m.getDeclaringClass()) { 86 87 found = true; 88 assertMatch(expected, m); 89 used.add(m); 90 break; 91 } 92 } 93 if (! found) 94 fail("On: "+ iface +"\nDid not find " + toMethodString(expected) + " among " + foundMethods); 95 } 96 assertEquals(foundMethods.size(), expectedMethods.length, 97 "\non: " + iface + 98 "\nexpected: " + toMethodStrings(expectedMethods) + 99 "\nfound: " + foundMethods + "\n"); 100 } 101 102 private boolean assertMatch(MethodDesc expected, Method m) { 103 if (!expected.name().equals(m.getName())) 104 return false; 105 if (expected.declaringClass() != m.getDeclaringClass()) 106 return false; 107 108 if (expected.kind() == MethodKind.ABSTRACT) 109 assertTrue(Modifier.isAbstract(m.getModifiers()), m + " should be ABSTRACT"); 110 else if (expected.kind() == MethodKind.CONCRETE) 111 assertTrue(!Modifier.isAbstract(m.getModifiers()) && !m.isDefault(), m + " should be CONCRETE"); 112 else if (expected.kind() == MethodKind.DEFAULT) 113 assertTrue(m.isDefault(), m + " should be DEFAULT"); 114 115 return true; 116 } 117 118 private String failMsg(MethodDesc expected, Method m, Class<?> iface) { 119 return "\nOn interface: " + iface + 120 "\nexpected: " + toMethodString(expected) + 121 "\nfound: " + m; 122 } 123 124 private static List<Method> filterObjectMethods(Method[] in) { 125 return Arrays.stream(in). 126 filter(m -> (m.getDeclaringClass() != java.lang.Object.class)). 127 collect(Collectors.toList()); 128 } 129 130 private String toMethodString(MethodDesc m) { 131 return m.declaringClass().getSimpleName().toString() + "." + 132 m.name() + "()"; 133 } 134 135 private List<String> toMethodStrings(MethodDesc[] m) { 136 return Arrays.stream(m). 137 map(this::toMethodString) 138 .collect(Collectors.toList()); 139 } 140 141 @Retention(RetentionPolicy.RUNTIME) 142 @Repeatable(MethodDescs.class) 143 public @interface MethodDesc { 144 String name(); 145 Class<?> declaringClass(); 146 MethodKind kind() default MethodKind.ABSTRACT; 147 boolean isGetMethodReturn() default false; 148 } 149 150 @Retention(RetentionPolicy.RUNTIME) 151 public @interface MethodDescs { 152 MethodDesc[] value(); 153 } 154 155 public static enum MethodKind { 156 ABSTRACT, 157 CONCRETE, 158 DEFAULT, 159 } 160 // base interfaces 161 interface I { void nonDefault(); } 162 interface J extends I { void nonDefault(); } 163 164 interface Jprim extends I {} 165 interface Jbis extends Jprim { void nonDefault(); } 166 167 // interesting cases 168 169 @MethodDesc(name="nonDefault", declaringClass=Jbis.class, 170 isGetMethodReturn=true) 171 interface P1 extends Jbis {} 172 173 @MethodDesc(name="nonDefault", declaringClass=Jbis.class, 174 isGetMethodReturn=true) 175 @MethodDesc(name="nonDefault", declaringClass=I.class) 176 interface P2 extends Jbis, Jprim {} 177 178 @MethodDesc(name="nonDefault", declaringClass=Jbis.class, 179 isGetMethodReturn=true) 180 @MethodDesc(name="nonDefault", declaringClass=I.class) 181 interface P3 extends Jbis, Jprim, I {} 182 183 @MethodDesc(name="nonDefault", declaringClass=I.class, 184 isGetMethodReturn=true) 185 @MethodDesc(name="nonDefault", declaringClass=J.class) 186 interface P4 extends I, J {} 187 188 @MethodDesc(name="nonDefault", declaringClass=J.class, 189 isGetMethodReturn=true) 190 @MethodDesc(name="nonDefault", declaringClass=I.class) 191 interface P5 extends J, I {} 192 193 @MethodDesc(name="nonDefault", declaringClass=J.class, 194 isGetMethodReturn=true) 195 interface K1 extends J {} 196 197 @MethodDesc(name="nonDefault", declaringClass=K1M.class, 198 isGetMethodReturn=true) 199 interface K1M extends J { void nonDefault(); } 200 201 @MethodDesc(name="nonDefault", declaringClass=I.class, 202 isGetMethodReturn=true) 203 @MethodDesc(name="nonDefault", declaringClass=J.class) 204 interface K2 extends I, J {} 205 206 @MethodDesc(name="nonDefault", declaringClass=J.class, 207 isGetMethodReturn=true) 208 @MethodDesc(name="nonDefault", declaringClass=I.class) 209 interface K2O extends J, I {} 210 211 @MethodDesc(name="nonDefault", declaringClass=K2M.class, 212 isGetMethodReturn=true) 213 interface K2M extends J, I { void nonDefault(); } 214 215 // base interfaces default methods 216 interface L { default void isDefault() {} void nonDefault(); } 217 interface M extends L { default void isDefault() {} void nonDefault(); } 218 219 // test cases default methods 220 221 @MethodDesc(name="nonDefault", declaringClass=M.class, 222 isGetMethodReturn=true) 223 @MethodDesc(name="isDefault", declaringClass=M.class, 224 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 225 interface N1 extends M {} 226 227 @MethodDesc(name="isDefault", declaringClass=N1D.class, 228 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 229 @MethodDesc(name="nonDefault", declaringClass=M.class, 230 isGetMethodReturn=true) 231 interface N1D extends M { default void isDefault() {}} 232 233 @MethodDesc(name="nonDefault", declaringClass=N1N.class, 234 isGetMethodReturn=true) 235 @MethodDesc(name="isDefault", declaringClass=M.class, 236 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 237 interface N1N extends M { void nonDefault(); } 238 239 @MethodDesc(name="isDefault", declaringClass=N1DN.class, 240 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 241 @MethodDesc(name="nonDefault", declaringClass=N1DN.class, 242 isGetMethodReturn=true) 243 interface N1DN extends M { default void isDefault() {} void nonDefault(); } 244 245 @MethodDesc(name="isDefault", declaringClass=M.class, 246 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 247 @MethodDesc(name="nonDefault", declaringClass=L.class) 248 @MethodDesc(name="nonDefault", declaringClass=M.class, 249 isGetMethodReturn=true) 250 interface N2 extends M, L {} 251 252 @MethodDesc(name="isDefault", declaringClass=M.class, 253 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 254 @MethodDesc(name="nonDefault", declaringClass=L.class, 255 isGetMethodReturn=true) 256 @MethodDesc(name="nonDefault", declaringClass=M.class) 257 interface N22 extends L, M {} 258 259 @MethodDesc(name="isDefault", declaringClass=N2D.class, 260 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 261 @MethodDesc(name="nonDefault", declaringClass=L.class) 262 @MethodDesc(name="nonDefault", declaringClass=M.class, 263 isGetMethodReturn=true) 264 interface N2D extends M, L { default void isDefault() {}} 265 266 @MethodDesc(name="isDefault", declaringClass=M.class, 267 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 268 @MethodDesc(name="nonDefault", declaringClass=N2N.class, 269 isGetMethodReturn=true) 270 interface N2N extends M, L { void nonDefault(); } 271 272 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 273 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 274 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 275 isGetMethodReturn=true) 276 interface N2DN extends M, L { default void isDefault() {} void nonDefault(); } 277 278 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 279 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 280 @MethodDesc(name="nonDefault", declaringClass=L.class, 281 isGetMethodReturn=true) 282 @MethodDesc(name="nonDefault", declaringClass=M.class) 283 @MethodDesc(name="nonDefault", declaringClass=N2DN.class) 284 interface O1 extends L, M, N2DN {} 285 286 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 287 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 288 @MethodDesc(name="nonDefault", declaringClass=L.class) 289 @MethodDesc(name="nonDefault", declaringClass=M.class, 290 isGetMethodReturn=true) 291 @MethodDesc(name="nonDefault", declaringClass=N2DN.class) 292 interface O2 extends M, N2DN, L {} 293 294 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 295 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 296 @MethodDesc(name="nonDefault", declaringClass=L.class) 297 @MethodDesc(name="nonDefault", declaringClass=M.class) 298 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 299 isGetMethodReturn=true) 300 interface O3 extends N2DN, L, M {} 301 302 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 303 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 304 @MethodDesc(name="nonDefault", declaringClass=L.class, 305 isGetMethodReturn=true) 306 @MethodDesc(name="nonDefault", declaringClass=M.class) 307 @MethodDesc(name="nonDefault", declaringClass=N2DN.class) 308 abstract class C1 implements L, M, N2DN {} 309 310 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 311 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 312 @MethodDesc(name="nonDefault", declaringClass=L.class) 313 @MethodDesc(name="nonDefault", declaringClass=M.class, 314 isGetMethodReturn=true) 315 @MethodDesc(name="nonDefault", declaringClass=N2DN.class) 316 abstract class C2 implements M, N2DN, L {} 317 318 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 319 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 320 @MethodDesc(name="nonDefault", declaringClass=L.class) 321 @MethodDesc(name="nonDefault", declaringClass=M.class) 322 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 323 isGetMethodReturn=true) 324 abstract class C3 implements N2DN, L, M {} 325 326 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 327 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 328 @MethodDesc(name="nonDefault", declaringClass=C4.class, 329 kind=MethodKind.CONCRETE, isGetMethodReturn=true) 330 class C4 implements L, M, N2DN { public void nonDefault() {} } 331 332 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 333 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 334 @MethodDesc(name="nonDefault", declaringClass=C5.class, 335 kind=MethodKind.CONCRETE, isGetMethodReturn=true) 336 class C5 implements M, N2DN, L { public void nonDefault() {} } 337 338 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 339 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 340 @MethodDesc(name="nonDefault", declaringClass=C6.class, 341 kind=MethodKind.CONCRETE, isGetMethodReturn=true) 342 class C6 implements N2DN, L, M { public void nonDefault() {} } 343 344 // reabstraction 345 346 @MethodDesc(name="isDefault", declaringClass=R1.class, 347 isGetMethodReturn=true) 348 @MethodDesc(name="nonDefault", declaringClass=L.class, 349 isGetMethodReturn=true) 350 @MethodDesc(name="nonDefault", declaringClass=M.class) 351 @MethodDesc(name="nonDefault", declaringClass=N2DN.class) 352 interface R1 extends L, M, N2DN { void isDefault(); } 353 354 @MethodDesc(name="isDefault", declaringClass=R2.class, 355 isGetMethodReturn=true) 356 @MethodDesc(name="nonDefault", declaringClass=L.class) 357 @MethodDesc(name="nonDefault", declaringClass=M.class, 358 isGetMethodReturn=true) 359 @MethodDesc(name="nonDefault", declaringClass=N2DN.class) 360 interface R2 extends M, N2DN, L { void isDefault(); } 361 362 @MethodDesc(name="isDefault", declaringClass=R3.class, 363 isGetMethodReturn=true) 364 @MethodDesc(name="nonDefault", declaringClass=L.class) 365 @MethodDesc(name="nonDefault", declaringClass=M.class) 366 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 367 isGetMethodReturn=true) 368 interface R3 extends N2DN, L, M { void isDefault(); } 369 370 // this one is strange but logical, getMethod finds N2DN first, which is 371 // default but not the most specific 372 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 373 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 374 @MethodDesc(name="isDefault", declaringClass=R1.class) 375 @MethodDesc(name="nonDefault", declaringClass=L.class, 376 isGetMethodReturn=true) 377 @MethodDesc(name="nonDefault", declaringClass=M.class) 378 @MethodDesc(name="nonDefault", declaringClass=N2DN.class) 379 interface R4 extends L, M, N2DN, R1 {} 380 381 // this one is strange but logical, getMethod finds N2DN first, which is 382 // default but not the most specific 383 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 384 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 385 @MethodDesc(name="isDefault", declaringClass=R2.class) 386 @MethodDesc(name="nonDefault", declaringClass=L.class) 387 @MethodDesc(name="nonDefault", declaringClass=M.class, 388 isGetMethodReturn=true) 389 @MethodDesc(name="nonDefault", declaringClass=N2DN.class) 390 interface R5 extends M, N2DN, R2, L {} 391 392 // this one is strange but logical, getMethod finds N2DN first, which is 393 // default but not the most specific 394 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 395 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 396 @MethodDesc(name="isDefault", declaringClass=R3.class) 397 @MethodDesc(name="nonDefault", declaringClass=L.class) 398 @MethodDesc(name="nonDefault", declaringClass=M.class) 399 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 400 isGetMethodReturn=true) 401 interface R6 extends N2DN, R3, L, M {} 402 403 // the following three finds the "right" one 404 @MethodDesc(name="isDefault", declaringClass=R1.class, 405 isGetMethodReturn=true) 406 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 407 kind=MethodKind.DEFAULT) 408 @MethodDesc(name="nonDefault", declaringClass=L.class, 409 isGetMethodReturn=true) 410 @MethodDesc(name="nonDefault", declaringClass=M.class) 411 @MethodDesc(name="nonDefault", declaringClass=N2DN.class) 412 interface R7 extends L, M, R1, N2DN {} 413 414 @MethodDesc(name="isDefault", declaringClass=R2.class, 415 isGetMethodReturn=true) 416 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 417 kind=MethodKind.DEFAULT) 418 @MethodDesc(name="nonDefault", declaringClass=L.class) 419 @MethodDesc(name="nonDefault", declaringClass=M.class, 420 isGetMethodReturn=true) 421 @MethodDesc(name="nonDefault", declaringClass=N2DN.class) 422 interface R8 extends M, R2, N2DN, L {} 423 424 @MethodDesc(name="isDefault", declaringClass=R3.class, 425 isGetMethodReturn=true) 426 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 427 kind=MethodKind.DEFAULT) 428 @MethodDesc(name="nonDefault", declaringClass=L.class) 429 @MethodDesc(name="nonDefault", declaringClass=M.class) 430 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 431 isGetMethodReturn=true) 432 interface R9 extends R3, N2DN, L, M {} 433 434 // More reabstraction 435 interface Z1 { void z(); } 436 interface Z2 extends Z1 { default void z() {} } 437 438 @MethodDesc(name="z", declaringClass=Z2.class, 439 isGetMethodReturn=true, kind=MethodKind.DEFAULT) 440 interface Z31 extends Z1, Z2 {} 441 442 @MethodDesc(name="z", declaringClass=Z2.class, 443 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 444 interface Z32 extends Z2, Z1 {} 445 446 interface Z3 extends Z2, Z1 { void z(); } 447 448 @MethodDesc(name="z", declaringClass=Z2.class, 449 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 450 @MethodDesc(name="z", declaringClass=Z3.class) 451 interface Z41 extends Z1, Z2, Z3 { } 452 453 @MethodDesc(name="z", declaringClass=Z2.class, 454 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 455 @MethodDesc(name="z", declaringClass=Z3.class) 456 interface Z42 extends Z2, Z3, Z1 { } 457 458 @MethodDesc(name="z", declaringClass=Z3.class, 459 isGetMethodReturn=true) 460 @MethodDesc(name="z", declaringClass=Z2.class, 461 kind=MethodKind.DEFAULT) 462 interface Z43 extends Z3, Z1, Z2 { } 463 464 @MethodDesc(name="z", declaringClass=Z2.class, 465 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 466 @MethodDesc(name="z", declaringClass=Z3.class) 467 abstract class ZC41 implements Z1, Z2, Z3 { } 468 469 @MethodDesc(name="z", declaringClass=Z2.class, 470 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 471 @MethodDesc(name="z", declaringClass=Z3.class) 472 abstract class ZC42 implements Z2, Z3, Z1 { } 473 474 @MethodDesc(name="z", declaringClass=Z3.class, 475 isGetMethodReturn=true) 476 @MethodDesc(name="z", declaringClass=Z2.class, 477 kind=MethodKind.DEFAULT) 478 abstract class ZC43 implements Z3, Z1, Z2 { } 479 480 // More reabstraction + concretization 481 interface X1 { default void x() {} } 482 interface X2 extends X1 { void x(); } 483 484 @MethodDesc(name="x", declaringClass=X1.class, 485 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 486 @MethodDesc(name="x", declaringClass=X2.class) 487 interface X31 extends X1, X2 {} 488 489 @MethodDesc(name="x", declaringClass=X2.class, 490 isGetMethodReturn=true) 491 @MethodDesc(name="x", declaringClass=X1.class, 492 kind=MethodKind.DEFAULT) 493 interface X32 extends X2, X1 {} 494 495 @MethodDesc(name="x", declaringClass=X3.class, 496 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 497 interface X3 extends X2, X1 { default void x() {} } 498 499 // order shouldn't matter here 500 @MethodDesc(name="x", declaringClass=X3.class, 501 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 502 interface X41 extends X1, X2, X3 { } 503 504 @MethodDesc(name="x", declaringClass=X3.class, 505 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 506 interface X42 extends X2, X3, X1 { } 507 508 @MethodDesc(name="x", declaringClass=X3.class, 509 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 510 interface X43 extends X3, X1, X2 { } 511 512 // order shouldn't matter here 513 @MethodDesc(name="x", declaringClass=X3.class, 514 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 515 abstract class XC41 implements X1, X2, X3 { } 516 517 @MethodDesc(name="x", declaringClass=X3.class, 518 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 519 abstract class XC42 implements X2, X3, X1 { } 520 521 @MethodDesc(name="x", declaringClass=X3.class, 522 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 523 abstract class XC43 implements X3, X1, X2 { } 524 525 interface K extends I, J { void nonDefault(); } 526 527 @MethodDesc(name="nonDefault", declaringClass=I.class, 528 isGetMethodReturn=true) 529 @MethodDesc(name="nonDefault", declaringClass=J.class) 530 @MethodDesc(name="nonDefault", declaringClass=K.class) 531 abstract class ZZ1 implements I, J, K {} 532 533 @MethodDesc(name="nonDefault", declaringClass=I.class, 534 isGetMethodReturn=true) 535 @MethodDesc(name="nonDefault", declaringClass=J.class) 536 @MethodDesc(name="nonDefault", declaringClass=K.class) 537 abstract class ZZ2 extends ZZ1 implements K, I, J {} 538 539 @MethodDesc(name="nonDefault", declaringClass=I.class, 540 isGetMethodReturn=true) 541 @MethodDesc(name="nonDefault", declaringClass=J.class) 542 @MethodDesc(name="nonDefault", declaringClass=K.class) 543 abstract class ZZ3 extends ZZ2 implements J, K, I {} 544 545 // bridges 546 interface B1A { Object m(); } 547 interface B1B extends B1A { Map m(); } 548 549 @MethodDesc(name="m", declaringClass=B1C.class, 550 isGetMethodReturn=true) 551 @MethodDesc(name="m", declaringClass=B1C.class, 552 kind=MethodKind.DEFAULT) 553 @MethodDesc(name="m", declaringClass=B1C.class, 554 kind=MethodKind.DEFAULT) 555 interface B1C extends B1B { HashMap m(); } 556 557 @MethodDesc(name="m", declaringClass=B2.class, 558 isGetMethodReturn=true) 559 @MethodDesc(name="m", declaringClass=B2.class, 560 kind=MethodKind.DEFAULT) 561 @MethodDesc(name="m", declaringClass=B2.class, 562 kind=MethodKind.DEFAULT) 563 interface B2 extends B1C { HashMap m(); } 564 565 @MethodDesc(name="m", declaringClass=B2.class, //HahsMap 566 isGetMethodReturn=true) 567 @MethodDesc(name="m", declaringClass=B2.class, //Map 568 kind=MethodKind.DEFAULT) 569 @MethodDesc(name="m", declaringClass=B2.class, //Object 570 kind=MethodKind.DEFAULT) 571 interface B3A extends B2, B1A {} 572 573 // this one is funny since HashMap isn't a bridge thus not a default 574 @MethodDesc(name="m", declaringClass=B2.class, //HashMap 575 isGetMethodReturn=true) 576 @MethodDesc(name="m", declaringClass=B2.class, //Map 577 kind=MethodKind.DEFAULT) 578 @MethodDesc(name="m", declaringClass=B2.class, //Object 579 kind=MethodKind.DEFAULT) 580 @MethodDesc(name="m", declaringClass=B1C.class) //HashMap 581 interface B3B extends B2, B1C {} 582 583 // same name different params type 584 interface A1 { void m(); void m(int i); void m(int i, int j); } 585 interface A2A extends A1 { void m(); void m(int i); void m(int i, int j); } 586 interface A2B extends A1 { void m(); void m(int i); default void m(int i, int j) {} } 587 588 @MethodDesc(name="m", declaringClass=A1.class, 589 isGetMethodReturn=true) 590 @MethodDesc(name="m", declaringClass=A1.class) 591 @MethodDesc(name="m", declaringClass=A1.class) 592 @MethodDesc(name="m", declaringClass=A2A.class) 593 @MethodDesc(name="m", declaringClass=A2A.class) 594 @MethodDesc(name="m", declaringClass=A2A.class) 595 interface A3A extends A1, A2A {} 596 597 @MethodDesc(name="m", declaringClass=A1.class, 598 isGetMethodReturn=true) 599 @MethodDesc(name="m", declaringClass=A1.class) 600 @MethodDesc(name="m", declaringClass=A2B.class) 601 @MethodDesc(name="m", declaringClass=A2B.class) 602 @MethodDesc(name="m", declaringClass=A2B.class, 603 kind=MethodKind.DEFAULT) 604 interface A3B extends A1, A2B {} 605 606 @DataProvider 607 public Object[][] getCases() { return CASES; } 608 public static final Class<?>[][] CASES = { 609 { K1.class }, 610 { K1M.class }, 611 { K2.class }, 612 { K2O.class }, 613 { K2M.class }, 614 615 { N1.class }, 616 { N1D.class }, 617 { N1N.class }, 618 { N1DN.class }, 619 620 { N2.class }, 621 { N22.class }, 622 { N2D.class }, 623 { N2N.class }, 624 { N2DN.class }, 625 663 { ZC41.class }, 664 { ZC42.class }, 665 { ZC43.class }, 666 667 { ZZ1.class }, 668 { ZZ2.class }, 669 { ZZ3.class }, 670 671 { X3.class }, 672 { X31.class }, 673 { X32.class }, 674 675 { X41.class }, 676 { X42.class }, 677 { X43.class }, 678 679 { XC41.class }, 680 { XC42.class }, 681 { XC43.class }, 682 683 { B1C.class }, 684 { B2.class }, 685 { B3A.class }, 686 { B3B.class }, 687 688 { A3A.class }, 689 { A3B.class }, 690 }; 691 } | 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 * @bug 8029674 27 * @summary Verify that the right interface methods are returned by 28 * Class.getMethod() and Class.getMethods() 29 * @run testng FilterNotMostSpecific 30 */ 31 32 import java.lang.reflect.*; 33 import java.lang.annotation.*; 34 35 import java.util.Arrays; 36 import java.util.List; 37 import java.util.Map; 38 import java.util.HashMap; 39 import java.util.stream.Collectors; 40 import java.util.stream.Stream; 41 42 import org.testng.annotations.DataProvider; 43 import org.testng.annotations.Test; 44 45 import static org.testng.Assert.*; 46 47 public class FilterNotMostSpecific { 48 49 @Test(dataProvider="getCases") 50 public void testGetMethod(Class<?> iface) { 51 boolean match = false; 52 MethodDesc[] expectedMethods = iface.getAnnotationsByType(MethodDesc.class); 53 54 for (MethodDesc expected : expectedMethods) { 55 if (expected.isGetMethodReturn()) { 56 try { 57 Method m = iface.getMethod(expected.name(), expected.parameterTypes()); 58 if (!assertMatch(expected, m)) 59 fail(failMsg(expected, m, iface)); 60 else 61 match = true; 62 } catch (NoSuchMethodException e) { 63 fail("expected: " + toMethodString(expected), e); 64 } 65 } 66 } 67 assert(match); 68 } 69 70 @Test(dataProvider="getCases") 71 public void testGetMethods(Class<?> iface) { 72 List<Method> foundMethods = filterObjectMethods(iface.getMethods()); 73 MethodDesc[] expectedMethods = iface.getAnnotationsByType(MethodDesc.class); 74 75 for (MethodDesc expected : expectedMethods) { 76 boolean found = false; 77 for (Method m : foundMethods) { 78 if (assertMatch(expected, m)) { 79 found = true; 80 break; 81 } 82 } 83 if (!found) 84 fail("On: "+ iface +"\nDid not find " + toMethodString(expected) + 85 " among " + foundMethods); 86 } 87 assertEquals(foundMethods.size(), expectedMethods.length, 88 "\non: " + iface + 89 "\nexpected: " + toMethodStrings(expectedMethods) + 90 "\nfound: " + foundMethods + "\n"); 91 } 92 93 private boolean assertMatch(MethodDesc expected, Method m) { 94 if (!expected.name().equals(m.getName())) 95 return false; 96 if (expected.declaringClass() != m.getDeclaringClass()) 97 return false; 98 if (!Arrays.equals(expected.parameterTypes(), m.getParameterTypes())) 99 return false; 100 if (expected.returnType() != NotSpecified.class && 101 expected.returnType() != m.getReturnType()) 102 return false; 103 104 if (expected.kind() == MethodKind.ABSTRACT) 105 assertTrue(Modifier.isAbstract(m.getModifiers()), m + " should be ABSTRACT"); 106 else if (expected.kind() == MethodKind.CONCRETE) 107 assertTrue(!Modifier.isAbstract(m.getModifiers()) && !m.isDefault(), m + " should be CONCRETE"); 108 else if (expected.kind() == MethodKind.DEFAULT) 109 assertTrue(m.isDefault(), m + " should be DEFAULT"); 110 111 return true; 112 } 113 114 private String failMsg(MethodDesc expected, Method m, Class<?> iface) { 115 return "\nOn interface: " + iface + 116 "\nexpected: " + toMethodString(expected) + 117 "\nfound: " + m; 118 } 119 120 private static List<Method> filterObjectMethods(Method[] in) { 121 return Arrays.stream(in). 122 filter(m -> (m.getDeclaringClass() != java.lang.Object.class)). 123 collect(Collectors.toList()); 124 } 125 126 private String toMethodString(MethodDesc m) { 127 return (m.returnType() != NotSpecified.class 128 ? m.returnType().getSimpleName() + " " 129 : "") + 130 m.declaringClass().getSimpleName().toString() + "." + 131 m.name() + Stream.of(m.parameterTypes()) 132 .map(cl -> cl.getSimpleName()) 133 .collect(Collectors.joining(", ", "(", ")")); 134 } 135 136 private List<String> toMethodStrings(MethodDesc[] m) { 137 return Arrays.stream(m). 138 map(this::toMethodString) 139 .collect(Collectors.toList()); 140 } 141 142 @Retention(RetentionPolicy.RUNTIME) 143 @Repeatable(MethodDescs.class) 144 public @interface MethodDesc { 145 String name(); 146 Class<?> returnType() default NotSpecified.class; 147 Class<?>[] parameterTypes() default {}; 148 Class<?> declaringClass(); 149 MethodKind kind() default MethodKind.ABSTRACT; 150 boolean isGetMethodReturn() default false; 151 } 152 153 // special type marking a not-specified return type in @MethodDesc 154 interface NotSpecified {} 155 156 @Retention(RetentionPolicy.RUNTIME) 157 public @interface MethodDescs { 158 MethodDesc[] value(); 159 } 160 161 public static enum MethodKind { 162 ABSTRACT, 163 CONCRETE, 164 DEFAULT, 165 } 166 // base interfaces 167 interface I { void nonDefault(); } 168 interface J extends I { void nonDefault(); } 169 170 interface Jprim extends I {} 171 interface Jbis extends Jprim { void nonDefault(); } 172 173 // interesting cases 174 175 @MethodDesc(name="nonDefault", declaringClass=Jbis.class, 176 isGetMethodReturn=true) 177 interface P1 extends Jbis {} 178 179 @MethodDesc(name="nonDefault", declaringClass=Jbis.class, 180 isGetMethodReturn=true) 181 interface P2 extends Jbis, Jprim {} 182 183 @MethodDesc(name="nonDefault", declaringClass=Jbis.class, 184 isGetMethodReturn=true) 185 interface P3 extends Jbis, Jprim, I {} 186 187 @MethodDesc(name="nonDefault", declaringClass=J.class, 188 isGetMethodReturn=true) 189 interface P4 extends I, J {} 190 191 @MethodDesc(name="nonDefault", declaringClass=J.class, 192 isGetMethodReturn=true) 193 interface P5 extends J, I {} 194 195 @MethodDesc(name="nonDefault", declaringClass=J.class, 196 isGetMethodReturn=true) 197 interface K1 extends J {} 198 199 @MethodDesc(name="nonDefault", declaringClass=K1M.class, 200 isGetMethodReturn=true) 201 interface K1M extends J { void nonDefault(); } 202 203 @MethodDesc(name="nonDefault", declaringClass=J.class, 204 isGetMethodReturn=true) 205 interface K2 extends I, J {} 206 207 @MethodDesc(name="nonDefault", declaringClass=J.class, 208 isGetMethodReturn=true) 209 interface K2O extends J, I {} 210 211 @MethodDesc(name="nonDefault", declaringClass=K2M.class, 212 isGetMethodReturn=true) 213 interface K2M extends J, I { void nonDefault(); } 214 215 // base interfaces default methods 216 interface L { default void isDefault() {} void nonDefault(); } 217 interface M extends L { default void isDefault() {} void nonDefault(); } 218 219 // test cases default methods 220 221 @MethodDesc(name="nonDefault", declaringClass=M.class, 222 isGetMethodReturn=true) 223 @MethodDesc(name="isDefault", declaringClass=M.class, 224 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 225 interface N1 extends M {} 226 227 @MethodDesc(name="isDefault", declaringClass=N1D.class, 228 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 229 @MethodDesc(name="nonDefault", declaringClass=M.class, 230 isGetMethodReturn=true) 231 interface N1D extends M { default void isDefault() {}} 232 233 @MethodDesc(name="nonDefault", declaringClass=N1N.class, 234 isGetMethodReturn=true) 235 @MethodDesc(name="isDefault", declaringClass=M.class, 236 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 237 interface N1N extends M { void nonDefault(); } 238 239 @MethodDesc(name="isDefault", declaringClass=N1DN.class, 240 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 241 @MethodDesc(name="nonDefault", declaringClass=N1DN.class, 242 isGetMethodReturn=true) 243 interface N1DN extends M { default void isDefault() {} void nonDefault(); } 244 245 @MethodDesc(name="isDefault", declaringClass=M.class, 246 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 247 @MethodDesc(name="nonDefault", declaringClass=M.class, 248 isGetMethodReturn=true) 249 interface N2 extends M, L {} 250 251 @MethodDesc(name="isDefault", declaringClass=M.class, 252 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 253 @MethodDesc(name="nonDefault", declaringClass=M.class, 254 isGetMethodReturn=true) 255 interface N22 extends L, M {} 256 257 @MethodDesc(name="isDefault", declaringClass=N2D.class, 258 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 259 @MethodDesc(name="nonDefault", declaringClass=M.class, 260 isGetMethodReturn=true) 261 interface N2D extends M, L { default void isDefault() {}} 262 263 @MethodDesc(name="isDefault", declaringClass=M.class, 264 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 265 @MethodDesc(name="nonDefault", declaringClass=N2N.class, 266 isGetMethodReturn=true) 267 interface N2N extends M, L { void nonDefault(); } 268 269 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 270 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 271 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 272 isGetMethodReturn=true) 273 interface N2DN extends M, L { default void isDefault() {} void nonDefault(); } 274 275 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 276 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 277 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 278 isGetMethodReturn=true) 279 interface O1 extends L, M, N2DN {} 280 281 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 282 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 283 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 284 isGetMethodReturn=true) 285 interface O2 extends M, N2DN, L {} 286 287 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 288 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 289 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 290 isGetMethodReturn=true) 291 interface O3 extends N2DN, L, M {} 292 293 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 294 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 295 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 296 isGetMethodReturn=true) 297 abstract class C1 implements L, M, N2DN {} 298 299 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 300 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 301 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 302 isGetMethodReturn=true) 303 abstract class C2 implements M, N2DN, L {} 304 305 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 306 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 307 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 308 isGetMethodReturn=true) 309 abstract class C3 implements N2DN, L, M {} 310 311 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 312 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 313 @MethodDesc(name="nonDefault", declaringClass=C4.class, 314 kind=MethodKind.CONCRETE, isGetMethodReturn=true) 315 class C4 implements L, M, N2DN { public void nonDefault() {} } 316 317 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 318 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 319 @MethodDesc(name="nonDefault", declaringClass=C5.class, 320 kind=MethodKind.CONCRETE, isGetMethodReturn=true) 321 class C5 implements M, N2DN, L { public void nonDefault() {} } 322 323 @MethodDesc(name="isDefault", declaringClass=N2DN.class, 324 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 325 @MethodDesc(name="nonDefault", declaringClass=C6.class, 326 kind=MethodKind.CONCRETE, isGetMethodReturn=true) 327 class C6 implements N2DN, L, M { public void nonDefault() {} } 328 329 // reabstraction 330 331 @MethodDesc(name="isDefault", declaringClass=R1.class, 332 isGetMethodReturn=true) 333 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 334 isGetMethodReturn=true) 335 interface R1 extends L, M, N2DN { void isDefault(); } 336 337 @MethodDesc(name="isDefault", declaringClass=R2.class, 338 isGetMethodReturn=true) 339 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 340 isGetMethodReturn=true) 341 interface R2 extends M, N2DN, L { void isDefault(); } 342 343 @MethodDesc(name="isDefault", declaringClass=R3.class, 344 isGetMethodReturn=true) 345 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 346 isGetMethodReturn=true) 347 interface R3 extends N2DN, L, M { void isDefault(); } 348 349 @MethodDesc(name="isDefault", declaringClass=R1.class, 350 isGetMethodReturn=true) 351 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 352 isGetMethodReturn=true) 353 interface R4 extends L, M, N2DN, R1 {} 354 355 @MethodDesc(name="isDefault", declaringClass=R2.class, 356 isGetMethodReturn=true) 357 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 358 isGetMethodReturn=true) 359 interface R5 extends M, N2DN, R2, L {} 360 361 @MethodDesc(name="isDefault", declaringClass=R3.class, 362 isGetMethodReturn=true) 363 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 364 isGetMethodReturn=true) 365 interface R6 extends N2DN, R3, L, M {} 366 367 @MethodDesc(name="isDefault", declaringClass=R1.class, 368 isGetMethodReturn=true) 369 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 370 isGetMethodReturn=true) 371 interface R7 extends L, M, R1, N2DN {} 372 373 @MethodDesc(name="isDefault", declaringClass=R2.class, 374 isGetMethodReturn=true) 375 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 376 isGetMethodReturn=true) 377 interface R8 extends M, R2, N2DN, L {} 378 379 @MethodDesc(name="isDefault", declaringClass=R3.class, 380 isGetMethodReturn=true) 381 @MethodDesc(name="nonDefault", declaringClass=N2DN.class, 382 isGetMethodReturn=true) 383 interface R9 extends R3, N2DN, L, M {} 384 385 // More reabstraction 386 interface Z1 { void z(); } 387 interface Z2 extends Z1 { default void z() {} } 388 389 @MethodDesc(name="z", declaringClass=Z2.class, 390 isGetMethodReturn=true, kind=MethodKind.DEFAULT) 391 interface Z31 extends Z1, Z2 {} 392 393 @MethodDesc(name="z", declaringClass=Z2.class, 394 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 395 interface Z32 extends Z2, Z1 {} 396 397 interface Z3 extends Z2, Z1 { void z(); } 398 399 @MethodDesc(name="z", declaringClass=Z3.class, 400 isGetMethodReturn = true) 401 interface Z41 extends Z1, Z2, Z3 { } 402 403 @MethodDesc(name="z", declaringClass=Z3.class, 404 isGetMethodReturn = true) 405 interface Z42 extends Z2, Z3, Z1 { } 406 407 @MethodDesc(name="z", declaringClass=Z3.class, 408 isGetMethodReturn = true) 409 interface Z43 extends Z3, Z1, Z2 { } 410 411 @MethodDesc(name="z", declaringClass=Z3.class, 412 isGetMethodReturn = true) 413 abstract class ZC41 implements Z1, Z2, Z3 { } 414 415 @MethodDesc(name="z", declaringClass=Z3.class, 416 isGetMethodReturn = true) 417 abstract class ZC42 implements Z2, Z3, Z1 { } 418 419 @MethodDesc(name="z", declaringClass=Z3.class, 420 isGetMethodReturn = true) 421 abstract class ZC43 implements Z3, Z1, Z2 { } 422 423 // More reabstraction + concretization 424 interface X1 { default void x() {} } 425 interface X2 extends X1 { void x(); } 426 427 @MethodDesc(name="x", declaringClass=X2.class, 428 isGetMethodReturn=true) 429 interface X31 extends X1, X2 {} 430 431 @MethodDesc(name="x", declaringClass=X2.class, 432 isGetMethodReturn=true) 433 interface X32 extends X2, X1 {} 434 435 @MethodDesc(name="x", declaringClass=X3.class, 436 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 437 interface X3 extends X2, X1 { default void x() {} } 438 439 // order shouldn't matter here 440 @MethodDesc(name="x", declaringClass=X3.class, 441 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 442 interface X41 extends X1, X2, X3 { } 443 444 @MethodDesc(name="x", declaringClass=X3.class, 445 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 446 interface X42 extends X2, X3, X1 { } 447 448 @MethodDesc(name="x", declaringClass=X3.class, 449 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 450 interface X43 extends X3, X1, X2 { } 451 452 // order shouldn't matter here 453 @MethodDesc(name="x", declaringClass=X3.class, 454 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 455 abstract class XC41 implements X1, X2, X3 { } 456 457 @MethodDesc(name="x", declaringClass=X3.class, 458 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 459 abstract class XC42 implements X2, X3, X1 { } 460 461 @MethodDesc(name="x", declaringClass=X3.class, 462 kind=MethodKind.DEFAULT, isGetMethodReturn=true) 463 abstract class XC43 implements X3, X1, X2 { } 464 465 interface K extends I, J { void nonDefault(); } 466 467 @MethodDesc(name="nonDefault", declaringClass=K.class, 468 isGetMethodReturn=true) 469 abstract class ZZ1 implements I, J, K {} 470 471 @MethodDesc(name="nonDefault", declaringClass=K.class, 472 isGetMethodReturn=true) 473 abstract class ZZ2 extends ZZ1 implements K, I, J {} 474 475 @MethodDesc(name="nonDefault", declaringClass=K.class, 476 isGetMethodReturn=true) 477 abstract class ZZ3 extends ZZ2 implements J, K, I {} 478 479 // bridges... 480 481 interface B1 { Object m(); } 482 interface B2A extends B1 { Map m(); } 483 interface B2B extends B1 { HashMap m(); } 484 485 @MethodDesc(name="m", returnType=Object.class, declaringClass=B3A.class, 486 kind = MethodKind.DEFAULT) 487 @MethodDesc(name="m", returnType=Map.class, declaringClass=B3A.class, 488 kind = MethodKind.DEFAULT) 489 @MethodDesc(name="m", returnType=HashMap.class, declaringClass=B3A.class, 490 isGetMethodReturn=true) 491 interface B3A extends B2A { HashMap m(); } 492 493 @MethodDesc(name="m", returnType=Object.class, declaringClass=B4A.class, 494 kind = MethodKind.DEFAULT) 495 @MethodDesc(name="m", returnType=Map.class, declaringClass=B4A.class, 496 kind = MethodKind.DEFAULT) 497 @MethodDesc(name="m", returnType=HashMap.class, declaringClass= B4A.class, 498 isGetMethodReturn=true) 499 interface B4A extends B3A { HashMap m(); } 500 501 @MethodDesc(name="m", returnType=Object.class, declaringClass=B4A.class, 502 kind = MethodKind.DEFAULT) 503 @MethodDesc(name="m", returnType=Map.class, declaringClass=B4A.class, 504 kind = MethodKind.DEFAULT) 505 @MethodDesc(name="m", returnType=HashMap.class, declaringClass= B4A.class, 506 isGetMethodReturn=true) 507 interface B5A2 extends B4A, B1 {} 508 509 @MethodDesc(name="m", returnType=Object.class, declaringClass=B4A.class, 510 kind = MethodKind.DEFAULT) 511 @MethodDesc(name="m", returnType=Map.class, declaringClass=B4A.class, 512 kind = MethodKind.DEFAULT) 513 @MethodDesc(name="m", returnType=HashMap.class, declaringClass= B4A.class, 514 isGetMethodReturn=true) 515 interface B5A4A extends B4A, B3A {} 516 517 // ... + most specific return type for getMethod from two unrelated interfaces 518 519 @MethodDesc(name="m", returnType=Object.class, declaringClass=B2A.class, 520 kind = MethodKind.DEFAULT) 521 @MethodDesc(name="m", returnType=Object.class, declaringClass=B2B.class, 522 kind = MethodKind.DEFAULT) 523 @MethodDesc(name="m", returnType=Map.class, declaringClass=B2A.class) 524 @MethodDesc(name="m", returnType=HashMap.class, declaringClass=B2B.class, 525 isGetMethodReturn=true) 526 interface B3AB extends B2A, B2B {} 527 528 @MethodDesc(name="m", returnType=Object.class, declaringClass=B2A.class, 529 kind = MethodKind.DEFAULT) 530 @MethodDesc(name="m", returnType=Object.class, declaringClass=B2B.class, 531 kind = MethodKind.DEFAULT) 532 @MethodDesc(name="m", returnType=Map.class, declaringClass=B2A.class) 533 @MethodDesc(name="m", returnType=HashMap.class, declaringClass=B2B.class, 534 isGetMethodReturn=true) 535 interface B3BA extends B2B, B2A {} 536 537 // same name different params type 538 interface A1 { void m(); void m(int i); void m(int i, int j); } 539 interface A2A extends A1 { void m(); void m(int i); void m(int i, int j); } 540 interface A2B extends A1 { void m(); void m(int i); default void m(int i, int j) {} } 541 542 @MethodDesc(name="m", parameterTypes = {}, declaringClass=A2A.class, 543 isGetMethodReturn=true) 544 @MethodDesc(name="m", parameterTypes = {int.class}, declaringClass=A2A.class, 545 isGetMethodReturn=true) 546 @MethodDesc(name="m", parameterTypes = {int.class, int.class}, declaringClass=A2A.class, 547 isGetMethodReturn=true) 548 interface A3A extends A1, A2A {} 549 550 @MethodDesc(name="m", parameterTypes = {}, declaringClass=A2B.class, 551 isGetMethodReturn=true) 552 @MethodDesc(name="m", parameterTypes = {int.class}, declaringClass=A2B.class, 553 isGetMethodReturn=true) 554 @MethodDesc(name="m", parameterTypes = {int.class, int.class}, declaringClass=A2B.class, 555 kind = MethodKind.DEFAULT, isGetMethodReturn=true) 556 interface A3B extends A1, A2B {} 557 558 // method in directly implemented interface overrides interface method 559 // inherited by superclass 560 561 interface E { void m(); } 562 interface F extends E { void m(); } 563 abstract class G implements E {} 564 565 @MethodDesc(name="m", declaringClass=F.class, isGetMethodReturn=true) 566 abstract class H extends G implements F {} 567 568 @DataProvider 569 public Object[][] getCases() { return CASES; } 570 public static final Class<?>[][] CASES = { 571 { K1.class }, 572 { K1M.class }, 573 { K2.class }, 574 { K2O.class }, 575 { K2M.class }, 576 577 { N1.class }, 578 { N1D.class }, 579 { N1N.class }, 580 { N1DN.class }, 581 582 { N2.class }, 583 { N22.class }, 584 { N2D.class }, 585 { N2N.class }, 586 { N2DN.class }, 587 625 { ZC41.class }, 626 { ZC42.class }, 627 { ZC43.class }, 628 629 { ZZ1.class }, 630 { ZZ2.class }, 631 { ZZ3.class }, 632 633 { X3.class }, 634 { X31.class }, 635 { X32.class }, 636 637 { X41.class }, 638 { X42.class }, 639 { X43.class }, 640 641 { XC41.class }, 642 { XC42.class }, 643 { XC43.class }, 644 645 { B3A.class }, 646 { B4A.class }, 647 { B5A2.class }, 648 { B5A4A.class }, 649 { B3AB.class }, 650 { B3BA.class }, 651 652 { A3A.class }, 653 { A3B.class }, 654 655 { H.class }, 656 }; 657 } |