1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @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 
 626         { P1.class },
 627         { P2.class },
 628         { P3.class },
 629         { P4.class },
 630         { P5.class },
 631 
 632         { O1.class },
 633         { O2.class },
 634         { O3.class },
 635 
 636         { C1.class },
 637         { C2.class },
 638         { C3.class },
 639 
 640         { C4.class },
 641         { C5.class },
 642         { C6.class },
 643 
 644         { R1.class },
 645         { R2.class },
 646         { R3.class },
 647 
 648         { R4.class },
 649         { R5.class },
 650         { R6.class },
 651 
 652         { R7.class },
 653         { R8.class },
 654         { R9.class },
 655 
 656         { Z31.class },
 657         { Z32.class },
 658 
 659         { Z41.class },
 660         { Z42.class },
 661         { Z43.class },
 662 
 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 }