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
32import java.lang.reflect.*;
33import java.lang.annotation.*;
34
35import java.util.Arrays;
36import java.util.List;
37import java.util.Map;
38import java.util.HashMap;
39import java.util.stream.Collectors;
40import java.util.stream.Stream;
41
42import org.testng.annotations.DataProvider;
43import org.testng.annotations.Test;
44
45import static org.testng.Assert.*;
46
47public 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
588        { P1.class },
589        { P2.class },
590        { P3.class },
591        { P4.class },
592        { P5.class },
593
594        { O1.class },
595        { O2.class },
596        { O3.class },
597
598        { C1.class },
599        { C2.class },
600        { C3.class },
601
602        { C4.class },
603        { C5.class },
604        { C6.class },
605
606        { R1.class },
607        { R2.class },
608        { R3.class },
609
610        { R4.class },
611        { R5.class },
612        { R6.class },
613
614        { R7.class },
615        { R8.class },
616        { R9.class },
617
618        { Z31.class },
619        { Z32.class },
620
621        { Z41.class },
622        { Z42.class },
623        { Z43.class },
624
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}
658