/*
* 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();
}
}