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 */
16import java.lang.reflect.*;
17
18public class ReturnsAndArgPassing {
19
20  public static final String testName = "ReturnsAndArgPassing";
21
22  static void check(boolean x) {
23    if (!x) {
24      throw new AssertionError(testName + " Check failed");
25    }
26  }
27
28  interface MyInterface {
29    void voidFoo();
30    void voidBar();
31    boolean booleanFoo();
32    boolean booleanBar();
33    byte byteFoo();
34    byte byteBar();
35    char charFoo();
36    char charBar();
37    short shortFoo();
38    short shortBar();
39    int intFoo();
40    int intBar();
41    long longFoo();
42    long longBar();
43    float floatFoo();
44    float floatBar();
45    double doubleFoo();
46    double doubleBar();
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;
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
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
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
463  public static void main(String args[]) {
464    testProxyReturns();
465    testProxyArgPassing();
466  }
467}
468