2121 * questions.
2222 */
2323
24+ import java .io .IOException ;
2425import java .lang .reflect .InvocationHandler ;
26+ import java .lang .reflect .InvocationTargetException ;
2527import java .lang .reflect .Method ;
2628import java .lang .reflect .Proxy ;
2729import java .util .Arrays ;
@@ -87,6 +89,12 @@ default Object[] concat(Object first, Object... rest) {
8789 }
8890 }
8991
92+ public interface IX {
93+ default void doThrow (Throwable exception ) throws Throwable {
94+ throw exception ;
95+ }
96+ }
97+
9098 private static Method findDefaultMethod (Class <?> refc , Method m ) {
9199 try {
92100 assertTrue (refc .isInterface ());
@@ -113,15 +121,15 @@ public void test() {
113121 // a default method is declared in one of the proxy interfaces
114122 @ DataProvider (name = "defaultMethods" )
115123 private Object [][] defaultMethods () {
116- return new Object [][] {
117- new Object [] { new Class <?>[] { I1 .class , I2 .class }, true , 10 },
118- new Object [] { new Class <?>[] { I1 .class , I3 .class }, true , 10 },
119- new Object [] { new Class <?>[] { I1 .class , I12 .class }, true , 10 },
120- new Object [] { new Class <?>[] { I2 .class , I12 .class }, true , 20 },
121- new Object [] { new Class <?>[] { I4 .class }, true , 40 },
122- new Object [] { new Class <?>[] { I4 .class , I3 .class }, true , 40 },
123- new Object [] { new Class <?>[] { I12 .class }, false , -1 },
124- new Object [] { new Class <?>[] { I12 .class , I1 .class , I2 .class }, false , -1 },
124+ return new Object [][]{
125+ new Object []{ new Class <?>[]{ I1 .class , I2 .class }, true , 10 },
126+ new Object []{ new Class <?>[]{ I1 .class , I3 .class }, true , 10 },
127+ new Object []{ new Class <?>[]{ I1 .class , I12 .class }, true , 10 },
128+ new Object []{ new Class <?>[]{ I2 .class , I12 .class }, true , 20 },
129+ new Object []{ new Class <?>[]{ I4 .class }, true , 40 },
130+ new Object []{ new Class <?>[]{ I4 .class , I3 .class }, true , 40 },
131+ new Object []{ new Class <?>[]{ I12 .class }, false , -1 },
132+ new Object []{ new Class <?>[]{ I12 .class , I1 .class , I2 .class }, false , -1 }
125133 };
126134 }
127135
@@ -155,28 +163,28 @@ public void testDefaultMethod(Class<?>[] intfs, boolean isDefault, int expected)
155163 // inherited from a superinterface of a proxy interface
156164 @ DataProvider (name = "supers" )
157165 private Object [][] supers () {
158- return new Object [][] {
159- // invoke "m" implemented in the first proxy interface
160- // same as the method passed to InvocationHandler::invoke
161- new Object []{new Class <?>[]{ I1 .class }, I1 .class , 10 },
162- new Object []{new Class <?>[]{ I2 .class }, I2 .class , 20 },
163- new Object []{new Class <?>[]{ I1 .class , I2 .class }, I1 .class , 10 },
164- // "m" is implemented in I2, an indirect superinterface of I3
165- new Object []{new Class <?>[]{ I3 .class }, I3 .class , 20 },
166- // "m" is implemented in I1, I2 and overridden in I4
167- new Object []{new Class <?>[]{ I4 .class }, I4 .class , 40 },
168- // invoke "m" implemented in the second proxy interface
169- // different from the method passed to InvocationHandler::invoke
170- new Object []{new Class <?>[]{ I1 .class , I2 .class }, I2 .class , 20 },
171- new Object []{new Class <?>[]{ I1 .class , I3 .class }, I3 .class , 20 },
172- // I2::m is implemented in more than one proxy interface directly or indirectly
173- // I3::m resolves to I2::m (indirect superinterface)
174- // I2 is the superinterface of I4 and I4 overrides m
175- // the proxy class can invoke I4::m and I2::m
176- new Object []{new Class <?>[]{ I3 .class , I4 .class }, I3 .class , 20 },
177- new Object []{new Class <?>[]{ I3 .class , I4 .class }, I4 .class , 40 },
178- new Object []{new Class <?>[]{ I4 .class , I3 .class }, I3 .class , 20 },
179- new Object []{new Class <?>[]{ I4 .class , I3 .class }, I4 .class , 40 },
166+ return new Object [][]{
167+ // invoke "m" implemented in the first proxy interface
168+ // same as the method passed to InvocationHandler::invoke
169+ new Object []{new Class <?>[]{I1 .class }, I1 .class , 10 },
170+ new Object []{new Class <?>[]{I2 .class }, I2 .class , 20 },
171+ new Object []{new Class <?>[]{I1 .class , I2 .class }, I1 .class , 10 },
172+ // "m" is implemented in I2, an indirect superinterface of I3
173+ new Object []{new Class <?>[]{I3 .class }, I3 .class , 20 },
174+ // "m" is implemented in I1, I2 and overridden in I4
175+ new Object []{new Class <?>[]{I4 .class }, I4 .class , 40 },
176+ // invoke "m" implemented in the second proxy interface
177+ // different from the method passed to InvocationHandler::invoke
178+ new Object []{new Class <?>[]{I1 .class , I2 .class }, I2 .class , 20 },
179+ new Object []{new Class <?>[]{I1 .class , I3 .class }, I3 .class , 20 },
180+ // I2::m is implemented in more than one proxy interface directly or indirectly
181+ // I3::m resolves to I2::m (indirect superinterface)
182+ // I2 is the superinterface of I4 and I4 overrides m
183+ // the proxy class can invoke I4::m and I2::m
184+ new Object []{new Class <?>[]{I3 .class , I4 .class }, I3 .class , 20 },
185+ new Object []{new Class <?>[]{I3 .class , I4 .class }, I4 .class , 40 },
186+ new Object []{new Class <?>[]{I4 .class , I3 .class }, I3 .class , 20 },
187+ new Object []{new Class <?>[]{I4 .class , I3 .class }, I4 .class , 40 }
180188 };
181189 }
182190
@@ -291,24 +299,24 @@ public void invokeNonProxyMethod() throws Exception {
291299 // negative cases
292300 @ DataProvider (name = "negativeCases" )
293301 private Object [][] negativeCases () {
294- return new Object [][] {
295- // I4::m overrides I1::m and I2::m
296- new Object [] { new Class <?>[]{ I4 .class }, I1 .class , "m" },
297- new Object [] { new Class <?>[]{ I4 .class }, I2 .class , "m" },
298- // I12::m is not a default method
299- new Object [] { new Class <?>[]{ I12 .class }, I12 .class , "m" },
300- // non-proxy default method
301- new Object [] { new Class <?>[]{ I3 .class }, I1 .class , "m" },
302- // not a default method and not a proxy interface
303- new Object [] { new Class <?>[]{ I12 .class }, DefaultMethods .class , "test" },
304- new Object [] { new Class <?>[]{ I12 .class }, Runnable .class , "run" },
305- // I2::privateMethod is a private method
306- new Object [] { new Class <?>[]{ I3 .class }, I2 .class , "privateMethod" },
302+ return new Object [][]{
303+ // I4::m overrides I1::m and I2::m
304+ new Object []{ new Class <?>[]{I4 .class }, I1 .class , "m" },
305+ new Object []{ new Class <?>[]{I4 .class }, I2 .class , "m" },
306+ // I12::m is not a default method
307+ new Object []{ new Class <?>[]{I12 .class }, I12 .class , "m" },
308+ // non-proxy default method
309+ new Object []{ new Class <?>[]{I3 .class }, I1 .class , "m" },
310+ // not a default method and not a proxy interface
311+ new Object []{ new Class <?>[]{I12 .class }, DefaultMethods .class , "test" },
312+ new Object []{ new Class <?>[]{I12 .class }, Runnable .class , "run" },
313+ // I2::privateMethod is a private method
314+ new Object []{ new Class <?>[]{I3 .class }, I2 .class , "privateMethod" }
307315 };
308316 }
309317
310318 @ Test (dataProvider = "negativeCases" , expectedExceptions = {IllegalArgumentException .class })
311- public void testIllegalArgument (Class <?>[] interfaces , Class <?> defc , String name )
319+ public void testNegativeCase (Class <?>[] interfaces , Class <?> defc , String name )
312320 throws Exception {
313321 ClassLoader loader = DefaultMethods .class .getClassLoader ();
314322 Object proxy = Proxy .newProxyInstance (loader , interfaces , HANDLER );
@@ -322,31 +330,53 @@ public void testIllegalArgument(Class<?>[] interfaces, Class<?> defc, String nam
322330 }
323331 }
324332
325- @ DataProvider (name = "arguments " )
326- private Object [][] arguments () {
333+ @ DataProvider (name = "illegalArguments " )
334+ private Object [][] illegalArguments () {
327335 return new Object [][] {
328- new Object [] {},
329- new Object [] { 100 , "foo" , 100 },
330- new Object [] { "foo" , 100 },
336+ new Object [] {},
337+ new Object [] { 100 },
338+ new Object [] { 100 , "foo" , 100 },
339+ new Object [] { 100L , "foo" },
340+ new Object [] { "foo" , 100 },
341+ new Object [] { null , "foo" }
331342 };
332343 }
333344
334- @ Test (dataProvider = "arguments " , expectedExceptions = {IllegalArgumentException .class })
335- public void testWrongArguments (Object ... args ) throws Exception {
345+ @ Test (dataProvider = "illegalArguments " , expectedExceptions = {IllegalArgumentException .class })
346+ public void testIllegalArgument (Object ... args ) throws Exception {
336347 ClassLoader loader = DefaultMethods .class .getClassLoader ();
337348 I4 proxy = (I4 )Proxy .newProxyInstance (loader , new Class <?>[]{I4 .class }, HANDLER );
338349 Method m = I4 .class .getMethod ("mix" , int .class , String .class );
339350 assertTrue (m .isDefault ());
351+ if (args .length == 0 ) {
352+ // substitute empty args with null since @DataProvider doesn't allow null array
353+ args = null ;
354+ }
340355 Proxy .invokeDefaultMethod (proxy , m , args );
341356 }
342357
343- @ Test (expectedExceptions = {IllegalArgumentException .class })
344- public void testNullArguments () throws Exception {
358+ @ DataProvider (name = "invocationTargetExceptions" )
359+ private Object [][] invocationTargetExceptions () {
360+ return new Object [][] {
361+ new Object [] { new IOException () },
362+ new Object [] { new IllegalArgumentException () },
363+ new Object [] { new ClassCastException () },
364+ new Object [] { new NullPointerException () },
365+ new Object [] { new AssertionError () },
366+ new Object [] { new Throwable () }
367+ };
368+ }
369+
370+ @ Test (dataProvider = "invocationTargetExceptions" )
371+ public void testInvocationTargetException (Throwable exception ) throws Exception {
345372 ClassLoader loader = DefaultMethods .class .getClassLoader ();
346- I4 proxy = (I4 )Proxy .newProxyInstance (loader , new Class <?>[]{I4 .class }, HANDLER );
347- Method m = I4 .class .getMethod ("mix" , int .class , String .class );
348- assertTrue (m .isDefault ());
349- Proxy .invokeDefaultMethod (proxy , m , (Object [])null );
373+ IX proxy = (IX )Proxy .newProxyInstance (loader , new Class <?>[]{IX .class }, HANDLER );
374+ Method m = IX .class .getMethod ("doThrow" , Throwable .class );
375+ try {
376+ Proxy .invokeDefaultMethod (proxy , m , exception );
377+ } catch (InvocationTargetException e ) {
378+ assertEquals (e .getCause (), exception );
379+ }
350380 }
351381
352382 private static final InvocationHandler HANDLER = (proxy , method , params ) -> {
0 commit comments