diff options
Diffstat (limited to 'luni/src/test/java/libcore/java/lang/reflect/ProxyTest.java')
-rw-r--r-- | luni/src/test/java/libcore/java/lang/reflect/ProxyTest.java | 334 |
1 files changed, 333 insertions, 1 deletions
diff --git a/luni/src/test/java/libcore/java/lang/reflect/ProxyTest.java b/luni/src/test/java/libcore/java/lang/reflect/ProxyTest.java index 30d47fb..abd5851 100644 --- a/luni/src/test/java/libcore/java/lang/reflect/ProxyTest.java +++ b/luni/src/test/java/libcore/java/lang/reflect/ProxyTest.java @@ -16,14 +16,25 @@ package libcore.java.lang.reflect; +import java.io.EOFException; +import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.lang.reflect.UndeclaredThrowableException; +import java.net.SocketException; import junit.framework.TestCase; import tests.util.ClassLoaderBuilder; public final class ProxyTest extends TestCase { + private final ClassLoader loader = getClass().getClassLoader(); + private final InvocationHandler returnHandler = new TestInvocationHandler(); + private final InvocationHandler throwHandler = new InvocationHandler() { + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + throw (Throwable) args[0]; + } + }; /** * Make sure the proxy's class loader fails if it cannot see the class @@ -36,7 +47,7 @@ public final class ProxyTest extends TestCase { Class[] interfacesA = { loaderA.loadClass(prefix + "$Echo") }; try { - Proxy.newProxyInstance(loaderB, interfacesA, new TestInvocationHandler()); + Proxy.newProxyInstance(loaderB, interfacesA, returnHandler); fail(); } catch (IllegalArgumentException expected) { } @@ -55,10 +66,331 @@ public final class ProxyTest extends TestCase { assertEquals("foo", proxy.getClass().getMethod("echo", String.class).invoke(proxy, "foo")); } + public void testIncompatibleReturnTypesPrimitiveAndPrimitive() { + try { + Proxy.newProxyInstance(loader, new Class[] {ReturnsInt.class, ReturnsFloat.class}, + returnHandler); + fail(); + } catch (IllegalArgumentException expected) { + } + } + + public void testIncompatibleReturnTypesPrimitiveAndWrapper() { + try { + Proxy.newProxyInstance(loader, new Class[] {ReturnsInt.class, ReturnsInteger.class}, + returnHandler); + fail(); + } catch (IllegalArgumentException expected) { + } + } + + public void testIncompatibleReturnTypesPrimitiveAndVoid() { + try { + Proxy.newProxyInstance(loader, new Class[] {ReturnsInt.class, ReturnsVoid.class}, + returnHandler); + fail(); + } catch (IllegalArgumentException expected) { + } + } + + public void testIncompatibleReturnTypesIncompatibleObjects() { + try { + Proxy.newProxyInstance(loader, new Class[] {ReturnsInteger.class, ReturnsString.class }, + returnHandler); + fail(); + } catch (IllegalArgumentException expected) { + } + } + + public void testCompatibleReturnTypesImplementedInterface() { + Proxy.newProxyInstance(loader, new Class[] {ReturnsString.class, ReturnsCharSequence.class}, + returnHandler); + Proxy.newProxyInstance(loader, new Class[]{ReturnsObject.class, ReturnsCharSequence.class, + ReturnsString.class}, returnHandler); + Proxy.newProxyInstance(loader, new Class[]{ReturnsObject.class, ReturnsCharSequence.class, + ReturnsString.class, ReturnsSerializable.class, ReturnsComparable.class}, + returnHandler); + } + + + public void testCompatibleReturnTypesSuperclass() { + Proxy.newProxyInstance(loader, new Class[] {ReturnsString.class, ReturnsObject.class}, + returnHandler); + } + + public void testDeclaredExceptionIntersectionIsSubtype() throws Exception { + ThrowsIOException instance = (ThrowsIOException) Proxy.newProxyInstance(loader, + new Class[] {ThrowsIOException.class, ThrowsEOFException.class}, + throwHandler); + try { + instance.run(new EOFException()); + fail(); + } catch (EOFException expected) { + } + try { + instance.run(new IOException()); + fail(); + } catch (UndeclaredThrowableException expected) { + } + try { + instance.run(new Exception()); + fail(); + } catch (UndeclaredThrowableException expected) { + } + } + + public void testDeclaredExceptionIntersectionIsEmpty() throws Exception { + ThrowsEOFException instance = (ThrowsEOFException) Proxy.newProxyInstance(loader, + new Class[] {ThrowsSocketException.class, ThrowsEOFException.class}, + throwHandler); + try { + instance.run(new EOFException()); + fail(); + } catch (UndeclaredThrowableException expected) { + } + try { + instance.run(new SocketException()); + fail(); + } catch (UndeclaredThrowableException expected) { + } + } + + public void testDeclaredExceptionIntersectionIsSubset() throws Exception { + ThrowsEOFException instance = (ThrowsEOFException) Proxy.newProxyInstance(loader, + new Class[] {ThrowsEOFException.class, ThrowsSocketExceptionAndEOFException.class}, + throwHandler); + try { + instance.run(new EOFException()); + fail(); + } catch (EOFException expected) { + } + try { + instance.run(new SocketException()); + fail(); + } catch (UndeclaredThrowableException expected) { + } + try { + instance.run(new IOException()); + fail(); + } catch (UndeclaredThrowableException expected) { + } + } + + public void testDeclaredExceptionIntersectedByExactReturnTypes() throws Exception { + ThrowsIOException instance = (ThrowsIOException) Proxy.newProxyInstance(loader, + new Class[] {ThrowsIOException.class, ThrowsEOFExceptionReturnsString.class}, + throwHandler); + try { + instance.run(new EOFException()); + fail(); + } catch (EOFException expected) { + } + try { + instance.run(new IOException()); + fail(); + } catch (IOException expected) { + } + try { + ((ThrowsEOFExceptionReturnsString) instance).run(new EOFException()); + fail(); + } catch (EOFException expected) { + } + try { + ((ThrowsEOFExceptionReturnsString) instance).run(new IOException()); + fail(); + } catch (UndeclaredThrowableException expected) { + } + } + + public void test_getProxyClass_nullInterfaces() { + try { + Proxy.getProxyClass(loader, new Class<?>[] { null }); + fail(); + } catch (NullPointerException expected) { + } + + try { + Proxy.getProxyClass(loader, Echo.class, null); + fail(); + } catch (NullPointerException expected) { + } + } + + public void test_getProxyClass_duplicateInterfaces() { + try { + Proxy.getProxyClass(loader, Echo.class, Echo.class); + fail(); + } catch (IllegalArgumentException expected) { + } + } + + public void test_getProxyClass_caching() throws Exception { + Class<?> proxy1 = Proxy.getProxyClass(loader, Echo.class, ReturnsInt.class); + Class<?> proxy2 = Proxy.getProxyClass(loader, Echo.class, ReturnsInt.class); + Class<?> proxy3 = Proxy.getProxyClass(loader, ReturnsInt.class, Echo.class); + + assertSame(proxy1, proxy2); + assertTrue(!proxy2.equals(proxy3)); + } + + public void testMethodsImplementedByFarIndirectInterface() { + ExtendsExtendsDeclaresFiveMethods instance = (ExtendsExtendsDeclaresFiveMethods) + Proxy.newProxyInstance(loader, new Class[]{ExtendsExtendsDeclaresFiveMethods.class}, + returnHandler); + assertEquals("foo", instance.a("foo")); + assertEquals(0x12345678, instance.b(0x12345678)); + assertEquals(Double.MIN_VALUE, instance.c(Double.MIN_VALUE)); + assertEquals(null, instance.d(null)); + assertEquals(0x1234567890abcdefL, instance.e(0x1234567890abcdefL)); + } + + public void testEquals() { + InvocationHandler handler = new InvocationHandler() { + @Override public Object invoke(Object proxy, Method method, Object[] args) { + return args[0] == ProxyTest.class; // bogus as equals(), but good for testing + } + }; + Echo instance = (Echo) Proxy.newProxyInstance(loader, new Class[]{Echo.class}, handler); + assertTrue(instance.equals(ProxyTest.class)); + assertFalse(instance.equals(new Object())); + assertFalse(instance.equals(instance)); + assertFalse(instance.equals(null)); + } + + public void testHashCode() { + InvocationHandler handler = new InvocationHandler() { + @Override public Object invoke(Object proxy, Method method, Object[] args) { + return 0x12345678; + } + }; + Echo instance = (Echo) Proxy.newProxyInstance(loader, new Class[]{Echo.class}, handler); + assertEquals(0x12345678, instance.hashCode()); + } + + public void testToString() { + InvocationHandler handler = new InvocationHandler() { + @Override public Object invoke(Object proxy, Method method, Object[] args) { + return "foo"; + } + }; + Echo instance = (Echo) Proxy.newProxyInstance(loader, new Class[]{Echo.class}, handler); + assertEquals("foo", instance.toString()); + } + + public void testReturnTypeDoesNotSatisfyAllConstraintsWithLenientCaller() { + InvocationHandler handler = new InvocationHandler() { + @Override public Object invoke(Object proxy, Method method, Object[] args) { + assertEquals(Object.class, method.getReturnType()); + return Boolean.TRUE; // not the right type for 'ReturnsString' callers + } + }; + ReturnsObject returnsObject = (ReturnsObject) Proxy.newProxyInstance(loader, + new Class[] {ReturnsString.class, ReturnsObject.class}, handler); + assertEquals(true, returnsObject.foo()); + } + + public void testReturnTypeDoesNotSatisfyAllConstraintsWithStrictCaller() { + InvocationHandler handler = new InvocationHandler() { + @Override public Object invoke(Object proxy, Method method, Object[] args) { + assertEquals(String.class, method.getReturnType()); + return Boolean.TRUE; // not the right type for 'ReturnsString' callers + } + }; + ReturnsString returnsString = (ReturnsString) Proxy.newProxyInstance(loader, + new Class[] {ReturnsString.class, ReturnsObject.class}, handler); + try { + returnsString.foo(); + fail(); + } catch (ClassCastException expected) { + } + } + + public void testReturnsTypeAndInterfaceNotImplementedByThatType() { + try { + Proxy.newProxyInstance(loader, new Class[] {ReturnsString.class, ReturnsEcho.class}, + returnHandler); + fail(); + } catch (IllegalArgumentException expected) { + } + } + public interface Echo { String echo(String s); } + public interface ReturnsInt { + int foo(); + } + + public interface ReturnsFloat { + float foo(); + } + + public interface ReturnsInteger { + Integer foo(); + } + + public interface ReturnsString { + String foo(); + } + + public interface ReturnsCharSequence { + CharSequence foo(); + } + + public interface ReturnsSerializable { + CharSequence foo(); + } + + public interface ReturnsComparable { + CharSequence foo(); + } + + public interface ReturnsObject { + Object foo(); + } + + public interface ReturnsVoid { + void foo(); + } + + public interface ReturnsEcho { + Echo foo(); + } + + public interface ThrowsIOException { + Object run(Throwable toThrow) throws IOException; + } + + public interface ThrowsEOFException { + Object run(Throwable toThrow) throws EOFException; + } + + public interface ThrowsEOFExceptionReturnsString { + String run(Throwable toThrow) throws EOFException; + } + + public interface ThrowsSocketException { + Object run(Throwable toThrow) throws SocketException; + + } + public interface ThrowsSocketExceptionAndEOFException { + Object run(Throwable toThrow) throws SocketException, EOFException; + + } + + public interface DeclaresFiveMethods { + String a(String a); + int b(int b); + double c(double c); + Object d(Object d); + long e(long e); + } + public interface ExtendsDeclaresFiveMethods extends DeclaresFiveMethods { + } + public interface ExtendsExtendsDeclaresFiveMethods extends ExtendsDeclaresFiveMethods { + } + public static class TestInvocationHandler implements InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return args[0]; |