/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.lang.reflect.*; public class ReturnsAndArgPassing { public static final String testName = "ReturnsAndArgPassing"; static void check(boolean x) { if (!x) { throw new AssertionError(testName + " Check failed"); } } interface MyInterface { void voidFoo(); void voidBar(); boolean booleanFoo(); boolean booleanBar(); byte byteFoo(); byte byteBar(); char charFoo(); char charBar(); short shortFoo(); short shortBar(); int intFoo(); int intBar(); long longFoo(); long longBar(); float floatFoo(); float floatBar(); double doubleFoo(); double doubleBar(); Object selectArg(int select, int a, long b, float c, double d, Object x); } static int fooInvocations = 0; static int barInvocations = 0; static class MyInvocationHandler implements InvocationHandler { boolean causeNpeOnReturn = false; Class<?> returnType = null; public Object invoke(Object proxy, Method method, Object[] args) { check(proxy instanceof Proxy); check(method.getDeclaringClass() == MyInterface.class); String name = method.getName(); // Check for moving GC bugs in proxy stubs. Runtime.getRuntime().gc(); if (name.endsWith("Foo")) { check(args == null); fooInvocations++; } else if (name.endsWith("Bar")) { check(args == null); barInvocations++; } if (causeNpeOnReturn) { return null; } else if (name.equals("voidFoo") || name.equals("voidBar")) { return null; } else if (name.equals("booleanFoo")) { return true; } else if (name.equals("booleanBar")) { return false; } else if (name.equals("selectArg")) { check(args.length == 6); int select = (Integer)args[0]; return args[select]; } else { try { if (name.endsWith("Foo")) { return returnType.getField("MAX_VALUE").get(null); } else { check(name.endsWith("Bar")); return returnType.getField("MIN_VALUE").get(null); } } catch (Exception e) { throw new Error("return type = " + returnType, e); } } } } static void testProxyReturns() { System.out.println(testName + ".testProxyReturns RUNNING"); MyInvocationHandler myHandler = new MyInvocationHandler(); MyInterface proxyMyInterface = (MyInterface)Proxy.newProxyInstance(ReturnsAndArgPassing.class.getClassLoader(), new Class[] { MyInterface.class }, myHandler); check(fooInvocations == 0); proxyMyInterface.voidFoo(); check(fooInvocations == 1); check(barInvocations == 0); proxyMyInterface.voidBar(); check(barInvocations == 1); check(fooInvocations == 1); myHandler.returnType = Boolean.class; check(proxyMyInterface.booleanFoo() == true); check(fooInvocations == 2); check(barInvocations == 1); check(proxyMyInterface.booleanBar() == false); check(barInvocations == 2); check(fooInvocations == 2); myHandler.returnType = Byte.class; check(proxyMyInterface.byteFoo() == Byte.MAX_VALUE); check(fooInvocations == 3); check(barInvocations == 2); check(proxyMyInterface.byteBar() == Byte.MIN_VALUE); check(barInvocations == 3); check(fooInvocations == 3); myHandler.returnType = Character.class; check(proxyMyInterface.charFoo() == Character.MAX_VALUE); check(fooInvocations == 4); check(barInvocations == 3); check(proxyMyInterface.charBar() == Character.MIN_VALUE); check(barInvocations == 4); check(fooInvocations == 4); myHandler.returnType = Short.class; check(proxyMyInterface.shortFoo() == Short.MAX_VALUE); check(fooInvocations == 5); check(barInvocations == 4); check(proxyMyInterface.shortBar() == Short.MIN_VALUE); check(barInvocations == 5); check(fooInvocations == 5); myHandler.returnType = Integer.class; check(proxyMyInterface.intFoo() == Integer.MAX_VALUE); check(fooInvocations == 6); check(barInvocations == 5); check(proxyMyInterface.intBar() == Integer.MIN_VALUE); check(barInvocations == 6); check(fooInvocations == 6); myHandler.returnType = Long.class; check(proxyMyInterface.longFoo() == Long.MAX_VALUE); check(fooInvocations == 7); check(barInvocations == 6); check(proxyMyInterface.longBar() == Long.MIN_VALUE); check(barInvocations == 7); check(fooInvocations == 7); myHandler.returnType = Float.class; check(proxyMyInterface.floatFoo() == Float.MAX_VALUE); check(fooInvocations == 8); check(barInvocations == 7); check(proxyMyInterface.floatBar() == Float.MIN_VALUE); check(barInvocations == 8); check(fooInvocations == 8); myHandler.returnType = Double.class; check(proxyMyInterface.doubleFoo() == Double.MAX_VALUE); check(fooInvocations == 9); check(barInvocations == 8); check(proxyMyInterface.doubleBar() == Double.MIN_VALUE); check(barInvocations == 9); // Toggle flag to get return values to cause NPEs myHandler.causeNpeOnReturn = true; check(fooInvocations == 9); try { proxyMyInterface.booleanFoo(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(fooInvocations == 10); check(barInvocations == 9); try { proxyMyInterface.booleanBar(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(barInvocations == 10); check(fooInvocations == 10); try { proxyMyInterface.byteFoo(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(fooInvocations == 11); check(barInvocations == 10); try { proxyMyInterface.byteBar(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(barInvocations == 11); check(fooInvocations == 11); try { proxyMyInterface.charFoo(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(fooInvocations == 12); check(barInvocations == 11); try { proxyMyInterface.charBar(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(barInvocations == 12); check(fooInvocations == 12); try { proxyMyInterface.shortFoo(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(fooInvocations == 13); check(barInvocations == 12); try { proxyMyInterface.shortBar(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(barInvocations == 13); check(fooInvocations == 13); try { proxyMyInterface.intFoo(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(fooInvocations == 14); check(barInvocations == 13); try { proxyMyInterface.intBar(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(barInvocations == 14); check(fooInvocations == 14); try { proxyMyInterface.longFoo(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(fooInvocations == 15); check(barInvocations == 14); try { proxyMyInterface.longBar(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(barInvocations == 15); check(fooInvocations == 15); try { proxyMyInterface.floatFoo(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(fooInvocations == 16); check(barInvocations == 15); try { proxyMyInterface.floatBar(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(barInvocations == 16); check(fooInvocations == 16); try { proxyMyInterface.doubleFoo(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(fooInvocations == 17); check(barInvocations == 16); try { proxyMyInterface.doubleBar(); throw new AssertionError("Expected NPE"); } catch (NullPointerException e) { } check(barInvocations == 17); // Toggle flag to stop NPEs myHandler.causeNpeOnReturn = false; check(fooInvocations == 17); myHandler.returnType = Double.class; // Double -> byte == fail try { proxyMyInterface.byteFoo(); throw new AssertionError("Expected ClassCastException"); } catch (ClassCastException e) { } check(fooInvocations == 18); check(barInvocations == 17); try { proxyMyInterface.byteBar(); throw new AssertionError("Expected NPE"); } catch (ClassCastException e) { } check(barInvocations == 18); check(fooInvocations == 18); myHandler.returnType = Float.class; // Float -> byte == fail try { proxyMyInterface.byteFoo(); throw new AssertionError("Expected ClassCastException"); } catch (ClassCastException e) { } check(fooInvocations == 19); check(barInvocations == 18); try { proxyMyInterface.byteBar(); throw new AssertionError("Expected NPE"); } catch (ClassCastException e) { } check(barInvocations == 19); check(fooInvocations == 19); myHandler.returnType = Long.class; // Long -> byte == fail try { proxyMyInterface.byteFoo(); throw new AssertionError("Expected ClassCastException"); } catch (ClassCastException e) { } check(fooInvocations == 20); check(barInvocations == 19); try { proxyMyInterface.byteBar(); throw new AssertionError("Expected NPE"); } catch (ClassCastException e) { } check(barInvocations == 20); check(fooInvocations == 20); myHandler.returnType = Integer.class; // Int -> byte == fail try { proxyMyInterface.byteFoo(); throw new AssertionError("Expected ClassCastException"); } catch (ClassCastException e) { } check(fooInvocations == 21); check(barInvocations == 20); try { proxyMyInterface.byteBar(); throw new AssertionError("Expected NPE"); } catch (ClassCastException e) { } check(barInvocations == 21); check(fooInvocations == 21); myHandler.returnType = Short.class; // Short -> byte == fail try { proxyMyInterface.byteFoo(); throw new AssertionError("Expected ClassCastException"); } catch (ClassCastException e) { } check(fooInvocations == 22); check(barInvocations == 21); try { proxyMyInterface.byteBar(); throw new AssertionError("Expected NPE"); } catch (ClassCastException e) { } check(barInvocations == 22); check(fooInvocations == 22); myHandler.returnType = Character.class; // Char -> byte == fail try { proxyMyInterface.byteFoo(); throw new AssertionError("Expected ClassCastException"); } catch (ClassCastException e) { } check(fooInvocations == 23); check(barInvocations == 22); try { proxyMyInterface.byteBar(); throw new AssertionError("Expected NPE"); } catch (ClassCastException e) { } check(barInvocations == 23); check(fooInvocations == 23); myHandler.returnType = Character.class; // Char -> short == fail try { proxyMyInterface.shortFoo(); throw new AssertionError("Expected ClassCastException"); } catch (ClassCastException e) { } check(fooInvocations == 24); check(barInvocations == 23); try { proxyMyInterface.shortBar(); throw new AssertionError("Expected NPE"); } catch (ClassCastException e) { } check(barInvocations == 24); System.out.println(testName + ".testProxyReturns PASSED"); } static void testProxyArgPassing() { System.out.println(testName + ".testProxyArgPassing RUNNING"); MyInvocationHandler myHandler = new MyInvocationHandler(); MyInterface proxyMyInterface = (MyInterface)Proxy.newProxyInstance(ReturnsAndArgPassing.class.getClassLoader(), new Class[] { MyInterface.class }, myHandler); check((Integer)proxyMyInterface.selectArg(0, Integer.MAX_VALUE, Long.MAX_VALUE, Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == 0); check((Integer)proxyMyInterface.selectArg(1, Integer.MAX_VALUE, Long.MAX_VALUE, Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Integer.MAX_VALUE); check((Long)proxyMyInterface.selectArg(2, Integer.MAX_VALUE, Long.MAX_VALUE, Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Long.MAX_VALUE); check((Float)proxyMyInterface.selectArg(3, Integer.MAX_VALUE, Long.MAX_VALUE, Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Float.MAX_VALUE); check((Double)proxyMyInterface.selectArg(4, Integer.MAX_VALUE, Long.MAX_VALUE, Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Double.MAX_VALUE); check(proxyMyInterface.selectArg(5, Integer.MAX_VALUE, Long.MAX_VALUE, Float.MAX_VALUE, Double.MAX_VALUE, Object.class) == Object.class); System.out.println(testName + ".testProxyArgPassing PASSED"); } public static void main(String args[]) { testProxyReturns(); testProxyArgPassing(); } }