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      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
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
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
461  public static void main(String args[]) {
462    testProxyReturns();
463    testProxyArgPassing();
464  }
465}
466