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       // Check for moving GC bugs in proxy stubs.
61       Runtime.getRuntime().gc();
62       if (name.endsWith("Foo")) {
63         check(args == null);
64         fooInvocations++;
65       } else if (name.endsWith("Bar")) {
66         check(args == null);
67         barInvocations++;
68       }
69       if (causeNpeOnReturn) {
70         return null;
71       } else if (name.equals("voidFoo") || name.equals("voidBar")) {
72         return null;
73       } else if (name.equals("booleanFoo")) {
74         return true;
75       } else if (name.equals("booleanBar")) {
76         return false;
77       } else if (name.equals("selectArg")) {
78         check(args.length == 6);
79         int select = (Integer)args[0];
80         return args[select];
81       } else {
82         try {
83           if (name.endsWith("Foo")) {
84             return returnType.getField("MAX_VALUE").get(null);
85           } else {
86             check(name.endsWith("Bar"));
87             return returnType.getField("MIN_VALUE").get(null);
88           }
89         } catch (Exception e) {
90           throw new Error("return type = " + returnType, e);
91         }
92       }
93     }
94   }
95 
testProxyReturns()96   static void testProxyReturns() {
97     System.out.println(testName + ".testProxyReturns RUNNING");
98     MyInvocationHandler myHandler = new MyInvocationHandler();
99     MyInterface proxyMyInterface =
100         (MyInterface)Proxy.newProxyInstance(ReturnsAndArgPassing.class.getClassLoader(),
101                                             new Class<?>[] { MyInterface.class },
102                                             myHandler);
103     check(fooInvocations == 0);
104     proxyMyInterface.voidFoo();
105     check(fooInvocations == 1);
106 
107     check(barInvocations == 0);
108     proxyMyInterface.voidBar();
109     check(barInvocations == 1);
110 
111     check(fooInvocations == 1);
112     myHandler.returnType = Boolean.class;
113     check(proxyMyInterface.booleanFoo() == true);
114     check(fooInvocations == 2);
115 
116     check(barInvocations == 1);
117     check(proxyMyInterface.booleanBar() == false);
118     check(barInvocations == 2);
119 
120     check(fooInvocations == 2);
121     myHandler.returnType = Byte.class;
122     check(proxyMyInterface.byteFoo() == Byte.MAX_VALUE);
123     check(fooInvocations == 3);
124 
125     check(barInvocations == 2);
126     check(proxyMyInterface.byteBar() == Byte.MIN_VALUE);
127     check(barInvocations == 3);
128 
129     check(fooInvocations == 3);
130     myHandler.returnType = Character.class;
131     check(proxyMyInterface.charFoo() == Character.MAX_VALUE);
132     check(fooInvocations == 4);
133 
134     check(barInvocations == 3);
135     check(proxyMyInterface.charBar() == Character.MIN_VALUE);
136     check(barInvocations == 4);
137 
138     check(fooInvocations == 4);
139     myHandler.returnType = Short.class;
140     check(proxyMyInterface.shortFoo() == Short.MAX_VALUE);
141     check(fooInvocations == 5);
142 
143     check(barInvocations == 4);
144     check(proxyMyInterface.shortBar() == Short.MIN_VALUE);
145     check(barInvocations == 5);
146 
147     check(fooInvocations == 5);
148     myHandler.returnType = Integer.class;
149     check(proxyMyInterface.intFoo() == Integer.MAX_VALUE);
150     check(fooInvocations == 6);
151 
152     check(barInvocations == 5);
153     check(proxyMyInterface.intBar() == Integer.MIN_VALUE);
154     check(barInvocations == 6);
155 
156     check(fooInvocations == 6);
157     myHandler.returnType = Long.class;
158     check(proxyMyInterface.longFoo() == Long.MAX_VALUE);
159     check(fooInvocations == 7);
160 
161     check(barInvocations == 6);
162     check(proxyMyInterface.longBar() == Long.MIN_VALUE);
163     check(barInvocations == 7);
164 
165     check(fooInvocations == 7);
166     myHandler.returnType = Float.class;
167     check(proxyMyInterface.floatFoo() == Float.MAX_VALUE);
168     check(fooInvocations == 8);
169 
170     check(barInvocations == 7);
171     check(proxyMyInterface.floatBar() == Float.MIN_VALUE);
172     check(barInvocations == 8);
173 
174     check(fooInvocations == 8);
175     myHandler.returnType = Double.class;
176     check(proxyMyInterface.doubleFoo() == Double.MAX_VALUE);
177     check(fooInvocations == 9);
178 
179     check(barInvocations == 8);
180     check(proxyMyInterface.doubleBar() == Double.MIN_VALUE);
181     check(barInvocations == 9);
182 
183     // Toggle flag to get return values to cause NPEs
184     myHandler.causeNpeOnReturn = true;
185 
186     check(fooInvocations == 9);
187     try {
188         proxyMyInterface.booleanFoo();
189         throw new AssertionError("Expected NPE");
190     } catch (NullPointerException e) {
191     }
192     check(fooInvocations == 10);
193 
194     check(barInvocations == 9);
195     try {
196         proxyMyInterface.booleanBar();
197         throw new AssertionError("Expected NPE");
198     } catch (NullPointerException e) {
199     }
200     check(barInvocations == 10);
201 
202     check(fooInvocations == 10);
203     try {
204         proxyMyInterface.byteFoo();
205         throw new AssertionError("Expected NPE");
206     } catch (NullPointerException e) {
207     }
208     check(fooInvocations == 11);
209 
210     check(barInvocations == 10);
211     try {
212         proxyMyInterface.byteBar();
213         throw new AssertionError("Expected NPE");
214     } catch (NullPointerException e) {
215     }
216     check(barInvocations == 11);
217 
218     check(fooInvocations == 11);
219     try {
220         proxyMyInterface.charFoo();
221         throw new AssertionError("Expected NPE");
222     } catch (NullPointerException e) {
223     }
224     check(fooInvocations == 12);
225 
226     check(barInvocations == 11);
227     try {
228         proxyMyInterface.charBar();
229         throw new AssertionError("Expected NPE");
230     } catch (NullPointerException e) {
231     }
232     check(barInvocations == 12);
233 
234     check(fooInvocations == 12);
235     try {
236         proxyMyInterface.shortFoo();
237         throw new AssertionError("Expected NPE");
238     } catch (NullPointerException e) {
239     }
240     check(fooInvocations == 13);
241 
242     check(barInvocations == 12);
243     try {
244         proxyMyInterface.shortBar();
245         throw new AssertionError("Expected NPE");
246     } catch (NullPointerException e) {
247     }
248     check(barInvocations == 13);
249 
250     check(fooInvocations == 13);
251     try {
252         proxyMyInterface.intFoo();
253         throw new AssertionError("Expected NPE");
254     } catch (NullPointerException e) {
255     }
256     check(fooInvocations == 14);
257 
258     check(barInvocations == 13);
259     try {
260         proxyMyInterface.intBar();
261         throw new AssertionError("Expected NPE");
262     } catch (NullPointerException e) {
263     }
264     check(barInvocations == 14);
265 
266     check(fooInvocations == 14);
267     try {
268         proxyMyInterface.longFoo();
269         throw new AssertionError("Expected NPE");
270     } catch (NullPointerException e) {
271     }
272     check(fooInvocations == 15);
273 
274     check(barInvocations == 14);
275     try {
276         proxyMyInterface.longBar();
277         throw new AssertionError("Expected NPE");
278     } catch (NullPointerException e) {
279     }
280     check(barInvocations == 15);
281 
282     check(fooInvocations == 15);
283     try {
284         proxyMyInterface.floatFoo();
285         throw new AssertionError("Expected NPE");
286     } catch (NullPointerException e) {
287     }
288     check(fooInvocations == 16);
289 
290     check(barInvocations == 15);
291     try {
292         proxyMyInterface.floatBar();
293         throw new AssertionError("Expected NPE");
294     } catch (NullPointerException e) {
295     }
296     check(barInvocations == 16);
297 
298     check(fooInvocations == 16);
299     try {
300         proxyMyInterface.doubleFoo();
301         throw new AssertionError("Expected NPE");
302     } catch (NullPointerException e) {
303     }
304     check(fooInvocations == 17);
305 
306     check(barInvocations == 16);
307     try {
308         proxyMyInterface.doubleBar();
309         throw new AssertionError("Expected NPE");
310     } catch (NullPointerException e) {
311     }
312     check(barInvocations == 17);
313 
314     // Toggle flag to stop NPEs
315     myHandler.causeNpeOnReturn = false;
316 
317     check(fooInvocations == 17);
318     myHandler.returnType = Double.class;  // Double -> byte == fail
319     try {
320         proxyMyInterface.byteFoo();
321         throw new AssertionError("Expected ClassCastException");
322     } catch (ClassCastException e) {
323     }
324     check(fooInvocations == 18);
325 
326     check(barInvocations == 17);
327     try {
328         proxyMyInterface.byteBar();
329         throw new AssertionError("Expected NPE");
330     } catch (ClassCastException e) {
331     }
332     check(barInvocations == 18);
333 
334     check(fooInvocations == 18);
335     myHandler.returnType = Float.class;  // Float -> byte == fail
336     try {
337         proxyMyInterface.byteFoo();
338         throw new AssertionError("Expected ClassCastException");
339     } catch (ClassCastException e) {
340     }
341     check(fooInvocations == 19);
342 
343     check(barInvocations == 18);
344     try {
345         proxyMyInterface.byteBar();
346         throw new AssertionError("Expected NPE");
347     } catch (ClassCastException e) {
348     }
349     check(barInvocations == 19);
350 
351     check(fooInvocations == 19);
352     myHandler.returnType = Long.class;  // Long -> byte == fail
353     try {
354         proxyMyInterface.byteFoo();
355         throw new AssertionError("Expected ClassCastException");
356     } catch (ClassCastException e) {
357     }
358     check(fooInvocations == 20);
359 
360     check(barInvocations == 19);
361     try {
362         proxyMyInterface.byteBar();
363         throw new AssertionError("Expected NPE");
364     } catch (ClassCastException e) {
365     }
366     check(barInvocations == 20);
367 
368     check(fooInvocations == 20);
369     myHandler.returnType = Integer.class;  // Int -> byte == fail
370     try {
371         proxyMyInterface.byteFoo();
372         throw new AssertionError("Expected ClassCastException");
373     } catch (ClassCastException e) {
374     }
375     check(fooInvocations == 21);
376 
377     check(barInvocations == 20);
378     try {
379         proxyMyInterface.byteBar();
380         throw new AssertionError("Expected NPE");
381     } catch (ClassCastException e) {
382     }
383     check(barInvocations == 21);
384 
385     check(fooInvocations == 21);
386     myHandler.returnType = Short.class;  // Short -> byte == fail
387     try {
388         proxyMyInterface.byteFoo();
389         throw new AssertionError("Expected ClassCastException");
390     } catch (ClassCastException e) {
391     }
392     check(fooInvocations == 22);
393 
394     check(barInvocations == 21);
395     try {
396         proxyMyInterface.byteBar();
397         throw new AssertionError("Expected NPE");
398     } catch (ClassCastException e) {
399     }
400     check(barInvocations == 22);
401 
402     check(fooInvocations == 22);
403     myHandler.returnType = Character.class;  // Char -> byte == fail
404     try {
405         proxyMyInterface.byteFoo();
406         throw new AssertionError("Expected ClassCastException");
407     } catch (ClassCastException e) {
408     }
409     check(fooInvocations == 23);
410 
411     check(barInvocations == 22);
412     try {
413         proxyMyInterface.byteBar();
414         throw new AssertionError("Expected NPE");
415     } catch (ClassCastException e) {
416     }
417     check(barInvocations == 23);
418 
419     check(fooInvocations == 23);
420     myHandler.returnType = Character.class;  // Char -> short == fail
421     try {
422         proxyMyInterface.shortFoo();
423         throw new AssertionError("Expected ClassCastException");
424     } catch (ClassCastException e) {
425     }
426     check(fooInvocations == 24);
427 
428     check(barInvocations == 23);
429     try {
430         proxyMyInterface.shortBar();
431         throw new AssertionError("Expected NPE");
432     } catch (ClassCastException e) {
433     }
434     check(barInvocations == 24);
435 
436     System.out.println(testName + ".testProxyReturns PASSED");
437   }
438 
testProxyArgPassing()439   static void testProxyArgPassing() {
440     System.out.println(testName + ".testProxyArgPassing RUNNING");
441     MyInvocationHandler myHandler = new MyInvocationHandler();
442     MyInterface proxyMyInterface =
443         (MyInterface)Proxy.newProxyInstance(ReturnsAndArgPassing.class.getClassLoader(),
444                                             new Class<?>[] { MyInterface.class },
445                                             myHandler);
446 
447     check((Integer)proxyMyInterface.selectArg(0, Integer.MAX_VALUE, Long.MAX_VALUE,
448         Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == 0);
449     check((Integer)proxyMyInterface.selectArg(1, Integer.MAX_VALUE, Long.MAX_VALUE,
450         Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Integer.MAX_VALUE);
451     check((Long)proxyMyInterface.selectArg(2, Integer.MAX_VALUE, Long.MAX_VALUE,
452         Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Long.MAX_VALUE);
453     check((Float)proxyMyInterface.selectArg(3, Integer.MAX_VALUE, Long.MAX_VALUE,
454         Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Float.MAX_VALUE);
455     check((Double)proxyMyInterface.selectArg(4, Integer.MAX_VALUE, Long.MAX_VALUE,
456         Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Double.MAX_VALUE);
457     check(proxyMyInterface.selectArg(5, Integer.MAX_VALUE, Long.MAX_VALUE,
458         Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Object.class);
459 
460     System.out.println(testName + ".testProxyArgPassing PASSED");
461   }
462 
main(String args[])463   public static void main(String args[]) {
464     testProxyReturns();
465     testProxyArgPassing();
466   }
467 }
468