1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 import java.lang.reflect.*;
17 
18 public class ReturnsAndArgPassing {
19 
20   public static final String testName = "ReturnsAndArgPassing";
21 
check(boolean x)22   static void check(boolean x) {
23     if (!x) {
24       throw new AssertionError(testName + " Check failed");
25     }
26   }
27 
28   interface MyInterface {
voidFoo()29     void voidFoo();
voidBar()30     void voidBar();
booleanFoo()31     boolean booleanFoo();
booleanBar()32     boolean booleanBar();
byteFoo()33     byte byteFoo();
byteBar()34     byte byteBar();
charFoo()35     char charFoo();
charBar()36     char charBar();
shortFoo()37     short shortFoo();
shortBar()38     short shortBar();
intFoo()39     int intFoo();
intBar()40     int intBar();
longFoo()41     long longFoo();
longBar()42     long longBar();
floatFoo()43     float floatFoo();
floatBar()44     float floatBar();
doubleFoo()45     double doubleFoo();
doubleBar()46     double doubleBar();
selectArg(int select, int a, long b, float c, double d, Object x)47     Object selectArg(int select, int a, long b, float c, double d, Object x);
48   }
49 
50   static int fooInvocations = 0;
51   static int barInvocations = 0;
52 
53   static class MyInvocationHandler implements InvocationHandler {
54     boolean causeNpeOnReturn = false;
55     Class<?> returnType = null;
invoke(Object proxy, Method method, Object[] args)56     public Object invoke(Object proxy, Method method, Object[] args) {
57       check(proxy instanceof Proxy);
58       check(method.getDeclaringClass() == MyInterface.class);
59       String name = method.getName();
60       if (name.endsWith("Foo")) {
61         check(args == null);
62         fooInvocations++;
63       } else if (name.endsWith("Bar")) {
64         check(args == null);
65         barInvocations++;
66       }
67       if (causeNpeOnReturn) {
68         return null;
69       } else if (name.equals("voidFoo") || name.equals("voidBar")) {
70         return null;
71       } else if (name.equals("booleanFoo")) {
72         return true;
73       } else if (name.equals("booleanBar")) {
74         return false;
75       } else if (name.equals("selectArg")) {
76         check(args.length == 6);
77         int select = (Integer)args[0];
78         return args[select];
79       } else {
80         try {
81           if (name.endsWith("Foo")) {
82             return returnType.getField("MAX_VALUE").get(null);
83           } else {
84             check(name.endsWith("Bar"));
85             return returnType.getField("MIN_VALUE").get(null);
86           }
87         } catch (Exception e) {
88           throw new Error("return type = " + returnType, e);
89         }
90       }
91     }
92   }
93 
testProxyReturns()94   static void testProxyReturns() {
95     System.out.println(testName + ".testProxyReturns RUNNING");
96     MyInvocationHandler myHandler = new MyInvocationHandler();
97     MyInterface proxyMyInterface =
98         (MyInterface)Proxy.newProxyInstance(ReturnsAndArgPassing.class.getClassLoader(),
99                                             new Class[] { MyInterface.class },
100                                             myHandler);
101     check(fooInvocations == 0);
102     proxyMyInterface.voidFoo();
103     check(fooInvocations == 1);
104 
105     check(barInvocations == 0);
106     proxyMyInterface.voidBar();
107     check(barInvocations == 1);
108 
109     check(fooInvocations == 1);
110     myHandler.returnType = Boolean.class;
111     check(proxyMyInterface.booleanFoo() == true);
112     check(fooInvocations == 2);
113 
114     check(barInvocations == 1);
115     check(proxyMyInterface.booleanBar() == false);
116     check(barInvocations == 2);
117 
118     check(fooInvocations == 2);
119     myHandler.returnType = Byte.class;
120     check(proxyMyInterface.byteFoo() == Byte.MAX_VALUE);
121     check(fooInvocations == 3);
122 
123     check(barInvocations == 2);
124     check(proxyMyInterface.byteBar() == Byte.MIN_VALUE);
125     check(barInvocations == 3);
126 
127     check(fooInvocations == 3);
128     myHandler.returnType = Character.class;
129     check(proxyMyInterface.charFoo() == Character.MAX_VALUE);
130     check(fooInvocations == 4);
131 
132     check(barInvocations == 3);
133     check(proxyMyInterface.charBar() == Character.MIN_VALUE);
134     check(barInvocations == 4);
135 
136     check(fooInvocations == 4);
137     myHandler.returnType = Short.class;
138     check(proxyMyInterface.shortFoo() == Short.MAX_VALUE);
139     check(fooInvocations == 5);
140 
141     check(barInvocations == 4);
142     check(proxyMyInterface.shortBar() == Short.MIN_VALUE);
143     check(barInvocations == 5);
144 
145     check(fooInvocations == 5);
146     myHandler.returnType = Integer.class;
147     check(proxyMyInterface.intFoo() == Integer.MAX_VALUE);
148     check(fooInvocations == 6);
149 
150     check(barInvocations == 5);
151     check(proxyMyInterface.intBar() == Integer.MIN_VALUE);
152     check(barInvocations == 6);
153 
154     check(fooInvocations == 6);
155     myHandler.returnType = Long.class;
156     check(proxyMyInterface.longFoo() == Long.MAX_VALUE);
157     check(fooInvocations == 7);
158 
159     check(barInvocations == 6);
160     check(proxyMyInterface.longBar() == Long.MIN_VALUE);
161     check(barInvocations == 7);
162 
163     check(fooInvocations == 7);
164     myHandler.returnType = Float.class;
165     check(proxyMyInterface.floatFoo() == Float.MAX_VALUE);
166     check(fooInvocations == 8);
167 
168     check(barInvocations == 7);
169     check(proxyMyInterface.floatBar() == Float.MIN_VALUE);
170     check(barInvocations == 8);
171 
172     check(fooInvocations == 8);
173     myHandler.returnType = Double.class;
174     check(proxyMyInterface.doubleFoo() == Double.MAX_VALUE);
175     check(fooInvocations == 9);
176 
177     check(barInvocations == 8);
178     check(proxyMyInterface.doubleBar() == Double.MIN_VALUE);
179     check(barInvocations == 9);
180 
181     // Toggle flag to get return values to cause NPEs
182     myHandler.causeNpeOnReturn = true;
183 
184     check(fooInvocations == 9);
185     try {
186         proxyMyInterface.booleanFoo();
187         throw new AssertionError("Expected NPE");
188     } catch (NullPointerException e) {
189     }
190     check(fooInvocations == 10);
191 
192     check(barInvocations == 9);
193     try {
194         proxyMyInterface.booleanBar();
195         throw new AssertionError("Expected NPE");
196     } catch (NullPointerException e) {
197     }
198     check(barInvocations == 10);
199 
200     check(fooInvocations == 10);
201     try {
202         proxyMyInterface.byteFoo();
203         throw new AssertionError("Expected NPE");
204     } catch (NullPointerException e) {
205     }
206     check(fooInvocations == 11);
207 
208     check(barInvocations == 10);
209     try {
210         proxyMyInterface.byteBar();
211         throw new AssertionError("Expected NPE");
212     } catch (NullPointerException e) {
213     }
214     check(barInvocations == 11);
215 
216     check(fooInvocations == 11);
217     try {
218         proxyMyInterface.charFoo();
219         throw new AssertionError("Expected NPE");
220     } catch (NullPointerException e) {
221     }
222     check(fooInvocations == 12);
223 
224     check(barInvocations == 11);
225     try {
226         proxyMyInterface.charBar();
227         throw new AssertionError("Expected NPE");
228     } catch (NullPointerException e) {
229     }
230     check(barInvocations == 12);
231 
232     check(fooInvocations == 12);
233     try {
234         proxyMyInterface.shortFoo();
235         throw new AssertionError("Expected NPE");
236     } catch (NullPointerException e) {
237     }
238     check(fooInvocations == 13);
239 
240     check(barInvocations == 12);
241     try {
242         proxyMyInterface.shortBar();
243         throw new AssertionError("Expected NPE");
244     } catch (NullPointerException e) {
245     }
246     check(barInvocations == 13);
247 
248     check(fooInvocations == 13);
249     try {
250         proxyMyInterface.intFoo();
251         throw new AssertionError("Expected NPE");
252     } catch (NullPointerException e) {
253     }
254     check(fooInvocations == 14);
255 
256     check(barInvocations == 13);
257     try {
258         proxyMyInterface.intBar();
259         throw new AssertionError("Expected NPE");
260     } catch (NullPointerException e) {
261     }
262     check(barInvocations == 14);
263 
264     check(fooInvocations == 14);
265     try {
266         proxyMyInterface.longFoo();
267         throw new AssertionError("Expected NPE");
268     } catch (NullPointerException e) {
269     }
270     check(fooInvocations == 15);
271 
272     check(barInvocations == 14);
273     try {
274         proxyMyInterface.longBar();
275         throw new AssertionError("Expected NPE");
276     } catch (NullPointerException e) {
277     }
278     check(barInvocations == 15);
279 
280     check(fooInvocations == 15);
281     try {
282         proxyMyInterface.floatFoo();
283         throw new AssertionError("Expected NPE");
284     } catch (NullPointerException e) {
285     }
286     check(fooInvocations == 16);
287 
288     check(barInvocations == 15);
289     try {
290         proxyMyInterface.floatBar();
291         throw new AssertionError("Expected NPE");
292     } catch (NullPointerException e) {
293     }
294     check(barInvocations == 16);
295 
296     check(fooInvocations == 16);
297     try {
298         proxyMyInterface.doubleFoo();
299         throw new AssertionError("Expected NPE");
300     } catch (NullPointerException e) {
301     }
302     check(fooInvocations == 17);
303 
304     check(barInvocations == 16);
305     try {
306         proxyMyInterface.doubleBar();
307         throw new AssertionError("Expected NPE");
308     } catch (NullPointerException e) {
309     }
310     check(barInvocations == 17);
311 
312     // Toggle flag to stop NPEs
313     myHandler.causeNpeOnReturn = false;
314 
315     check(fooInvocations == 17);
316     myHandler.returnType = Double.class;  // Double -> byte == fail
317     try {
318         proxyMyInterface.byteFoo();
319         throw new AssertionError("Expected ClassCastException");
320     } catch (ClassCastException e) {
321     }
322     check(fooInvocations == 18);
323 
324     check(barInvocations == 17);
325     try {
326         proxyMyInterface.byteBar();
327         throw new AssertionError("Expected NPE");
328     } catch (ClassCastException e) {
329     }
330     check(barInvocations == 18);
331 
332     check(fooInvocations == 18);
333     myHandler.returnType = Float.class;  // Float -> byte == fail
334     try {
335         proxyMyInterface.byteFoo();
336         throw new AssertionError("Expected ClassCastException");
337     } catch (ClassCastException e) {
338     }
339     check(fooInvocations == 19);
340 
341     check(barInvocations == 18);
342     try {
343         proxyMyInterface.byteBar();
344         throw new AssertionError("Expected NPE");
345     } catch (ClassCastException e) {
346     }
347     check(barInvocations == 19);
348 
349     check(fooInvocations == 19);
350     myHandler.returnType = Long.class;  // Long -> byte == fail
351     try {
352         proxyMyInterface.byteFoo();
353         throw new AssertionError("Expected ClassCastException");
354     } catch (ClassCastException e) {
355     }
356     check(fooInvocations == 20);
357 
358     check(barInvocations == 19);
359     try {
360         proxyMyInterface.byteBar();
361         throw new AssertionError("Expected NPE");
362     } catch (ClassCastException e) {
363     }
364     check(barInvocations == 20);
365 
366     check(fooInvocations == 20);
367     myHandler.returnType = Integer.class;  // Int -> byte == fail
368     try {
369         proxyMyInterface.byteFoo();
370         throw new AssertionError("Expected ClassCastException");
371     } catch (ClassCastException e) {
372     }
373     check(fooInvocations == 21);
374 
375     check(barInvocations == 20);
376     try {
377         proxyMyInterface.byteBar();
378         throw new AssertionError("Expected NPE");
379     } catch (ClassCastException e) {
380     }
381     check(barInvocations == 21);
382 
383     check(fooInvocations == 21);
384     myHandler.returnType = Short.class;  // Short -> byte == fail
385     try {
386         proxyMyInterface.byteFoo();
387         throw new AssertionError("Expected ClassCastException");
388     } catch (ClassCastException e) {
389     }
390     check(fooInvocations == 22);
391 
392     check(barInvocations == 21);
393     try {
394         proxyMyInterface.byteBar();
395         throw new AssertionError("Expected NPE");
396     } catch (ClassCastException e) {
397     }
398     check(barInvocations == 22);
399 
400     check(fooInvocations == 22);
401     myHandler.returnType = Character.class;  // Char -> byte == fail
402     try {
403         proxyMyInterface.byteFoo();
404         throw new AssertionError("Expected ClassCastException");
405     } catch (ClassCastException e) {
406     }
407     check(fooInvocations == 23);
408 
409     check(barInvocations == 22);
410     try {
411         proxyMyInterface.byteBar();
412         throw new AssertionError("Expected NPE");
413     } catch (ClassCastException e) {
414     }
415     check(barInvocations == 23);
416 
417     check(fooInvocations == 23);
418     myHandler.returnType = Character.class;  // Char -> short == fail
419     try {
420         proxyMyInterface.shortFoo();
421         throw new AssertionError("Expected ClassCastException");
422     } catch (ClassCastException e) {
423     }
424     check(fooInvocations == 24);
425 
426     check(barInvocations == 23);
427     try {
428         proxyMyInterface.shortBar();
429         throw new AssertionError("Expected NPE");
430     } catch (ClassCastException e) {
431     }
432     check(barInvocations == 24);
433 
434     System.out.println(testName + ".testProxyReturns PASSED");
435   }
436 
testProxyArgPassing()437   static void testProxyArgPassing() {
438     System.out.println(testName + ".testProxyArgPassing RUNNING");
439     MyInvocationHandler myHandler = new MyInvocationHandler();
440     MyInterface proxyMyInterface =
441         (MyInterface)Proxy.newProxyInstance(ReturnsAndArgPassing.class.getClassLoader(),
442                                             new Class[] { MyInterface.class },
443                                             myHandler);
444 
445     check((Integer)proxyMyInterface.selectArg(0, Integer.MAX_VALUE, Long.MAX_VALUE,
446         Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == 0);
447     check((Integer)proxyMyInterface.selectArg(1, Integer.MAX_VALUE, Long.MAX_VALUE,
448         Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Integer.MAX_VALUE);
449     check((Long)proxyMyInterface.selectArg(2, Integer.MAX_VALUE, Long.MAX_VALUE,
450         Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Long.MAX_VALUE);
451     check((Float)proxyMyInterface.selectArg(3, Integer.MAX_VALUE, Long.MAX_VALUE,
452         Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Float.MAX_VALUE);
453     check((Double)proxyMyInterface.selectArg(4, Integer.MAX_VALUE, Long.MAX_VALUE,
454         Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Double.MAX_VALUE);
455     check(proxyMyInterface.selectArg(5, Integer.MAX_VALUE, Long.MAX_VALUE,
456         Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Object.class);
457 
458     System.out.println(testName + ".testProxyArgPassing PASSED");
459   }
460 
main(String args[])461   public static void main(String args[]) {
462     testProxyReturns();
463     testProxyArgPassing();
464   }
465 }
466