ProxyBuilderTest.java revision a13e8e98b64e3f5271759dac44967f1c24c76995
1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/* 2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2011 The Android Open Source Project 3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License. 6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at 7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and 14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License. 15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 171977585657cb304a9e1ffa8a2320fa8053a7383cJesse Wilsonpackage com.google.dexmaker.stock; 18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 19ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilsonimport com.google.dexmaker.DexMakerTest; 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.io.File; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.io.IOException; 228d53a06d10c6e2b96be6857aede5e4661804611eAndrew Yousefimport java.lang.reflect.Field; 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.lang.reflect.InvocationHandler; 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.lang.reflect.Method; 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.lang.reflect.UndeclaredThrowableException; 261af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilsonimport java.util.Arrays; 278d53a06d10c6e2b96be6857aede5e4661804611eAndrew Yousefimport java.util.Map; 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.Random; 291af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilsonimport java.util.concurrent.Callable; 301af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilsonimport java.util.concurrent.atomic.AtomicInteger; 311977585657cb304a9e1ffa8a2320fa8053a7383cJesse Wilsonimport junit.framework.AssertionFailedError; 321977585657cb304a9e1ffa8a2320fa8053a7383cJesse Wilsonimport junit.framework.TestCase; 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic class ProxyBuilderTest extends TestCase { 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private FakeInvocationHandler fakeHandler = new FakeInvocationHandler(); 36054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef private File versionedDxDir = new File(DexMakerTest.getDataDirectory(), "v1"); 37054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 38054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void setUp() throws Exception { 39054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef super.setUp(); 40054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef versionedDxDir.mkdirs(); 41054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef clearVersionedDxDir(); 42054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef getGeneratedProxyClasses().clear(); 43054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 44054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 45054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void tearDown() throws Exception { 46054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef getGeneratedProxyClasses().clear(); 47054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef clearVersionedDxDir(); 48054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef super.tearDown(); 49054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 50054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 51054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef private void clearVersionedDxDir() { 52054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef for (File f : versionedDxDir.listFiles()) { 53054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef f.delete(); 54054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 55054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class SimpleClass { 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String simpleMethod() { 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionFailedError(); 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testExampleOperation() throws Throwable { 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult("expected"); 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson SimpleClass proxy = proxyFor(SimpleClass.class).build(); 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("expected", proxy.simpleMethod()); 67054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(2, versionedDxDir.listFiles().length); 68054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 69054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 70054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void testExampleOperation_DexMakerCaching() throws Throwable { 71054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef fakeHandler.setFakeResult("expected"); 72054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef SimpleClass proxy = proxyFor(SimpleClass.class).build(); 73054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(2, versionedDxDir.listFiles().length); 74054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals("expected", proxy.simpleMethod()); 75054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 76054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Force ProxyBuilder to create a DexMaker generator and call DexMaker.generateAndLoad(). 77054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef getGeneratedProxyClasses().clear(); 78054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 79054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef proxy = proxyFor(SimpleClass.class).build(); 80054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(2, versionedDxDir.listFiles().length); 81054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals("expected", proxy.simpleMethod()); 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class ConstructorTakesArguments { 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final String argument; 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public ConstructorTakesArguments(String arg) { 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson argument = arg; 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String method() { 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionFailedError(); 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testConstruction_SucceedsIfCorrectArgumentsProvided() throws Throwable { 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ConstructorTakesArguments proxy = proxyFor(ConstructorTakesArguments.class) 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgTypes(String.class) 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgValues("hello") 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("hello", proxy.argument); 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxy.method(); 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testConstruction_FailsWithWrongNumberOfArguments() throws Throwable { 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(ConstructorTakesArguments.class).build(); 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (IllegalArgumentException expected) {} 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testClassIsNotAccessbile_FailsWithUnsupportedOperationException() throws Exception { 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson class MethodVisibilityClass { 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(MethodVisibilityClass.class).build(); 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (UnsupportedOperationException expected) {} 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static class PrivateVisibilityClass { 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testPrivateClass_FailsWithUnsupportedOperationException() throws Exception { 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(PrivateVisibilityClass.class).build(); 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (UnsupportedOperationException expected) {} 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protected static class ProtectedVisibilityClass { 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String foo() { 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionFailedError(); 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testProtectedVisibility_WorksFine() throws Exception { 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("fake result", proxyFor(ProtectedVisibilityClass.class).build().foo()); 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class HasFinalMethod { 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String nonFinalMethod() { 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "non-final method"; 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final String finalMethod() { 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "final method"; 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testCanProxyClassesWithFinalMethods_WillNotCallTheFinalMethod() throws Throwable { 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson HasFinalMethod proxy = proxyFor(HasFinalMethod.class).build(); 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("final method", proxy.finalMethod()); 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("fake result", proxy.nonFinalMethod()); 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class HasPrivateMethod { 158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private String result() { 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "expected"; 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testProxyingPrivateMethods_NotIntercepted() throws Throwable { 164a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin HasPrivateMethod proxy = proxyFor(HasPrivateMethod.class).build(); 165a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin try { 166a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin proxy.getClass().getDeclaredMethod("result"); 167a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin fail(); 168a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } catch (NoSuchMethodException expected) { 169a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 170a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 171a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 172a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin assertEquals("expected", proxy.result()); 173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class HasPackagePrivateMethod { 176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson String result() { 177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionFailedError(); 178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 181a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public void testProxyingPackagePrivateMethods_NotIntercepted() 182a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin throws Throwable { 183a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin HasPackagePrivateMethod proxy = proxyFor(HasPackagePrivateMethod.class) 184a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin .build(); 185a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin try { 186a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin proxy.getClass().getDeclaredMethod("result"); 187a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin fail(); 188a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } catch (NoSuchMethodException expected) { 189a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 190a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 191a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 192a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin try { 193a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin proxy.result(); 194a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin fail(); 195a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } catch (AssertionFailedError expected) { 196a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 197a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class HasProtectedMethod { 201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protected String result() { 202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionFailedError(); 203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testProxyingProtectedMethods_AreIntercepted() throws Throwable { 207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("fake result", proxyFor(HasProtectedMethod.class).build().result()); 208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 210a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public static class MyParentClass { 211a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin String someMethod() { 212a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin return "package"; 213a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 214a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 215a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 216a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public static class MyChildClassWithProtectedMethod extends MyParentClass { 217a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin @Override 218a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin protected String someMethod() { 219a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin return "protected"; 220a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 221a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 222a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 223a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public static class MyChildClassWithPublicMethod extends MyParentClass { 224a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin @Override 225a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public String someMethod() { 226a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin return "public"; 227a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 228a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 229a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 230a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public void testProxying_ClassHierarchy() throws Throwable { 231a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin assertEquals("package", proxyFor(MyParentClass.class).build().someMethod()); 232a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin assertEquals("fake result", proxyFor(MyChildClassWithProtectedMethod.class).build().someMethod()); 233a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin assertEquals("fake result", proxyFor(MyChildClassWithPublicMethod.class).build().someMethod()); 234a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 235a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class HasVoidMethod { 237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void dangerousMethod() { 238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testVoidMethod_ShouldNotThrowRuntimeException() throws Throwable { 243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(HasVoidMethod.class).build().dangerousMethod(); 244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testObjectMethodsAreAlsoProxied() throws Throwable { 247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object proxy = proxyFor(Object.class).build(); 248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult("mystring"); 249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("mystring", proxy.toString()); 250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(-1); 251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, proxy.hashCode()); 252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(false); 253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(false, proxy.equals(proxy)); 254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 2561af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public static class AllReturnTypes { 257579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean getBoolean() { return true; } 258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int getInt() { return 1; } 259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public byte getByte() { return 2; } 260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public long getLong() { return 3L; } 261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public short getShort() { return 4; } 262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public float getFloat() { return 5f; } 263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public double getDouble() { return 6.0; } 264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public char getChar() { return 'c'; } 2651af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public int[] getIntArray() { return new int[] { 8, 9 }; } 2661af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public String[] getStringArray() { return new String[] { "d", "e" }; } 267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 2691af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testAllReturnTypes() throws Throwable { 2701af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson AllReturnTypes proxy = proxyFor(AllReturnTypes.class).build(); 271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(false); 272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(false, proxy.getBoolean()); 273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(8); 274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(8, proxy.getInt()); 275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult((byte) 9); 276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(9, proxy.getByte()); 277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(10L); 278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(10, proxy.getLong()); 279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult((short) 11); 280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(11, proxy.getShort()); 281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(12f); 282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(12f, proxy.getFloat()); 283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(13.0); 284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(13.0, proxy.getDouble()); 285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult('z'); 286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals('z', proxy.getChar()); 2871af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fakeHandler.setFakeResult(new int[] { -1, -2 }); 2881af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("[-1, -2]", Arrays.toString(proxy.getIntArray())); 2891af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fakeHandler.setFakeResult(new String[] { "x", "y" }); 2901af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("[x, y]", Arrays.toString(proxy.getStringArray())); 291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 292579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 2931af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public static class PassThroughAllTypes { 294579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean getBoolean(boolean input) { return input; } 295579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int getInt(int input) { return input; } 296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public byte getByte(byte input) { return input; } 297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public long getLong(long input) { return input; } 298579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public short getShort(short input) { return input; } 299579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public float getFloat(float input) { return input; } 300579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public double getDouble(double input) { return input; } 301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public char getChar(char input) { return input; } 302579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String getString(String input) { return input; } 303579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Object getObject(Object input) { return input; } 304579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void getNothing() {} 305579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 306579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 307579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class InvokeSuperHandler implements InvocationHandler { 308579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return ProxyBuilder.callSuper(proxy, method, args); 310579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 311579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 312579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 3131af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testPassThroughWorksForAllTypes() throws Exception { 3141af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson PassThroughAllTypes proxy = proxyFor(PassThroughAllTypes.class) 315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .handler(new InvokeSuperHandler()) 316579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 317579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(false, proxy.getBoolean(false)); 318579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(true, proxy.getBoolean(true)); 319579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, proxy.getInt(0)); 320579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, proxy.getInt(1)); 321579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((byte) 2, proxy.getByte((byte) 2)); 322579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((byte) 3, proxy.getByte((byte) 3)); 323579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(4L, proxy.getLong(4L)); 324579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(5L, proxy.getLong(5L)); 325579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((short) 6, proxy.getShort((short) 6)); 326579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((short) 7, proxy.getShort((short) 7)); 327579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(8f, proxy.getFloat(8f)); 328579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(9f, proxy.getFloat(9f)); 329579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(10.0, proxy.getDouble(10.0)); 330579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(11.0, proxy.getDouble(11.0)); 331579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals('a', proxy.getChar('a')); 332579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals('b', proxy.getChar('b')); 333579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("asdf", proxy.getString("asdf")); 334579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("qwer", proxy.getString("qwer")); 335579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(null, proxy.getString(null)); 336579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object a = new Object(); 337579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(a, proxy.getObject(a)); 338579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(null, proxy.getObject(null)); 339579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxy.getNothing(); 340579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 341579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 3421af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public static class ExtendsAllReturnTypes extends AllReturnTypes { 343579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int example() { return 0; } 344579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 345579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 346579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testProxyWorksForSuperclassMethodsAlso() throws Throwable { 3471af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson ExtendsAllReturnTypes proxy = proxyFor(ExtendsAllReturnTypes.class).build(); 348579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(99); 349579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(99, proxy.example()); 350579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(99, proxy.getInt()); 351579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(99, proxy.hashCode()); 352579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 353579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 354579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class HasOddParams { 355579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public long method(int first, Integer second) { 356579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionFailedError(); 357579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 358579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 359579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 360579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testMixingBoxedAndUnboxedParams() throws Throwable { 361579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson HasOddParams proxy = proxyFor(HasOddParams.class).build(); 362579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(99L); 363579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(99L, proxy.method(1, Integer.valueOf(2))); 364579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 365579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 366579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class SingleInt { 367579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String getString(int value) { 368579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionFailedError(); 369579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 370579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 371579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 372579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testSinglePrimitiveParameter() throws Throwable { 373579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson InvocationHandler handler = new InvocationHandler() { 374579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 375579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "asdf" + ((Integer) args[0]).intValue(); 376579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 377579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson }; 378579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("asdf1", proxyFor(SingleInt.class).handler(handler).build().getString(1)); 379579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 380579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 381579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class TwoConstructors { 382579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final String string; 383579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 384579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public TwoConstructors() { 385579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson string = "no-arg"; 386579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 387579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 388579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public TwoConstructors(boolean unused) { 389579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson string = "one-arg"; 390579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 391579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 392579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 393579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testNoConstructorArguments_CallsNoArgConstructor() throws Throwable { 394579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson TwoConstructors twoConstructors = proxyFor(TwoConstructors.class).build(); 395579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("no-arg", twoConstructors.string); 396579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 397579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 398579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testWithoutInvocationHandler_ThrowsIllegalArgumentException() throws Throwable { 399579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 400579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ProxyBuilder.forClass(TwoConstructors.class) 401ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson .dexCache(DexMakerTest.getDataDirectory()) 402579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 403579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 404579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (IllegalArgumentException expected) {} 405579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 406579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 407579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class HardToConstructCorrectly { 408579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public HardToConstructCorrectly() { fail(); } 409579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public HardToConstructCorrectly(Runnable ignored) { fail(); } 410579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public HardToConstructCorrectly(Exception ignored) { fail(); } 411579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public HardToConstructCorrectly(Boolean ignored) { /* safe */ } 412579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public HardToConstructCorrectly(Integer ignored) { fail(); } 413579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 414579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 415579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testHardToConstruct_WorksIfYouSpecifyTheConstructorCorrectly() throws Throwable { 416579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(HardToConstructCorrectly.class) 417579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgTypes(Boolean.class) 418579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgValues(true) 419579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 420579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 421579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 422579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testHardToConstruct_EvenWorksWhenArgsAreAmbiguous() throws Throwable { 423579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(HardToConstructCorrectly.class) 424579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgTypes(Boolean.class) 425579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgValues(new Object[] { null }) 426579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 427579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 428579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 429579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testHardToConstruct_DoesNotInferTypesFromValues() throws Throwable { 430579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 431579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(HardToConstructCorrectly.class) 432579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgValues(true) 433579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 434579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 435579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (IllegalArgumentException expected) {} 436579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 437579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 438579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testDefaultProxyHasSuperMethodToAccessOriginal() throws Exception { 439579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object objectProxy = proxyFor(Object.class).build(); 4401af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertNotNull(objectProxy.getClass().getMethod("super$hashCode$int")); 441579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 442579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 443579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class PrintsOddAndValue { 444579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String method(int value) { 445579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "odd " + value; 446579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 447579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 448579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 449579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testSometimesDelegateToSuper() throws Exception { 450579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson InvocationHandler delegatesOddValues = new InvocationHandler() { 451579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 452579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (method.getName().equals("method")) { 453579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int intValue = ((Integer) args[0]).intValue(); 454579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (intValue % 2 == 0) { 455579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "even " + intValue; 456579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 457579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 458579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return ProxyBuilder.callSuper(proxy, method, args); 459579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 460579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson }; 461579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson PrintsOddAndValue proxy = proxyFor(PrintsOddAndValue.class) 462579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .handler(delegatesOddValues) 463579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 464579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("even 0", proxy.method(0)); 465579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("odd 1", proxy.method(1)); 466579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("even 2", proxy.method(2)); 467579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("odd 3", proxy.method(3)); 468579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 4691af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 4701af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testCallSuperThrows() throws Exception { 4711af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson InvocationHandler handler = new InvocationHandler() { 4721af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 4731af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson return ProxyBuilder.callSuper(o, method, objects); 4741af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 4751af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson }; 4761af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 4771af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson FooThrows fooThrows = proxyFor(FooThrows.class) 4781af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .handler(handler) 4791af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 4801af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 4811af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson try { 4821af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fooThrows.foo(); 4831af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fail(); 4841af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } catch (IllegalStateException expected) { 4851af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("boom!", expected.getMessage()); 4861af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 4871af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 4881af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 4891af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public static class FooThrows { 4901af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void foo() { 4911af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson throw new IllegalStateException("boom!"); 4921af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 4931af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 494579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 495579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class DoubleReturn { 496579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public double getValue() { 497579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return 2.0; 498579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 499579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 500579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 501579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testUnboxedResult() throws Exception { 502579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.fakeResult = 2.0; 503579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(2.0, proxyFor(DoubleReturn.class).build().getValue()); 504579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 505579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 506579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static void staticMethod() { 507579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 508579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 509579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testDoesNotOverrideStaticMethods() throws Exception { 510579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Method should exist on this test class itself. 511579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ProxyBuilderTest.class.getDeclaredMethod("staticMethod"); 512579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Method should not exist on the subclass. 513579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 514579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(ProxyBuilderTest.class).build().getClass().getDeclaredMethod("staticMethod"); 515579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 516579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (NoSuchMethodException expected) {} 517579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 518579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 519579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testIllegalCacheDirectory() throws Exception { 520579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 5212e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson proxyFor(ProxyForIllegalCacheDirectory.class) 5222e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson .dexCache(new File("/poop/")) 5232e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson .build(); 524579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 5251977585657cb304a9e1ffa8a2320fa8053a7383cJesse Wilson } catch (IOException expected) { 5261977585657cb304a9e1ffa8a2320fa8053a7383cJesse Wilson } 527579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 528579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 5292e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson public static class ProxyForIllegalCacheDirectory { 5302e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson } 5312e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson 532579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testInvalidConstructorSpecification() throws Exception { 533579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 534579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(Object.class) 535579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgTypes(String.class, Boolean.class) 536579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgValues("asdf", true) 537579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 538579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 539579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (IllegalArgumentException expected) {} 540579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 541579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 542579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static abstract class AbstractClass { 543579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public abstract Object getValue(); 544579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 545579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 546579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testAbstractClassBehaviour() throws Exception { 547579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("fake result", proxyFor(AbstractClass.class).build().getValue()); 548579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 549579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 550579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class CtorHasDeclaredException { 551579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public CtorHasDeclaredException() throws IOException { 552579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IOException(); 553579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 554579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 555579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 556579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class CtorHasRuntimeException { 557579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public CtorHasRuntimeException() { 558579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException("my message"); 559579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 560579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 561579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 562579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class CtorHasError { 563579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public CtorHasError() { 564579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new Error("my message again"); 565579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 566579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 567579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 568579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testParentConstructorThrowsDeclaredException() throws Exception { 569579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 570579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(CtorHasDeclaredException.class).build(); 571579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 572579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (UndeclaredThrowableException expected) { 573579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertTrue(expected.getCause() instanceof IOException); 574579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 575579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 576579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(CtorHasRuntimeException.class).build(); 577579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 578579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (RuntimeException expected) { 579579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("my message", expected.getMessage()); 580579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 581579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 582579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(CtorHasError.class).build(); 583579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 584579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (Error expected) { 585579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("my message again", expected.getMessage()); 586579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 587579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 588579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 589579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testGetInvocationHandler_NormalOperation() throws Exception { 590579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object proxy = proxyFor(Object.class).build(); 591579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertSame(fakeHandler, ProxyBuilder.getInvocationHandler(proxy)); 592579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 593579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 594579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testGetInvocationHandler_NotAProxy() { 595579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 596579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ProxyBuilder.getInvocationHandler(new Object()); 597579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 598579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (IllegalArgumentException expected) {} 599579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 600579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 601579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class ReturnsObject { 602579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Object getValue() { 603579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return new Object(); 604579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 605579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 606579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 607579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class ReturnsString extends ReturnsObject { 608579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 609579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String getValue() { 610579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "a string"; 611579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 612579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 613579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 614579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testCovariantReturnTypes_NormalBehaviour() throws Exception { 615579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson String expected = "some string"; 616579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(expected); 617579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertSame(expected, proxyFor(ReturnsObject.class).build().getValue()); 618579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertSame(expected, proxyFor(ReturnsString.class).build().getValue()); 619579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 620579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 621579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testCovariantReturnTypes_WrongReturnType() throws Exception { 622579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 623579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(new Object()); 624579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(ReturnsString.class).build().getValue(); 625579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 626579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (ClassCastException expected) {} 627579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 628579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 6292e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson public void testCaching() throws Exception { 63031c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson SimpleClass a = proxyFor(SimpleClass.class).build(); 63131c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson SimpleClass b = proxyFor(SimpleClass.class).build(); 63231c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertSame(a.getClass(), b.getClass()); 6332e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson } 6342e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson 6352e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson public void testCachingWithMultipleConstructors() throws Exception { 63631c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson HasMultipleConstructors a = ProxyBuilder.forClass(HasMultipleConstructors.class) 63731c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .constructorArgTypes() 63831c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .constructorArgValues() 63931c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .handler(fakeHandler) 64031c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .dexCache(DexMakerTest.getDataDirectory()).build(); 64131c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertEquals("no args", a.calledConstructor); 64231c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson HasMultipleConstructors b = ProxyBuilder.forClass(HasMultipleConstructors.class) 64331c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .constructorArgTypes(int.class) 64431c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .constructorArgValues(2) 64531c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .handler(fakeHandler) 64631c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .dexCache(DexMakerTest.getDataDirectory()).build(); 64731c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertEquals("int 2", b.calledConstructor); 64831c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertEquals(a.getClass(), b.getClass()); 64931c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson 65031c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson HasMultipleConstructors c = ProxyBuilder.forClass(HasMultipleConstructors.class) 65131c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .constructorArgTypes(Integer.class) 65231c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .constructorArgValues(3) 65331c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .handler(fakeHandler) 65431c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .dexCache(DexMakerTest.getDataDirectory()).build(); 65531c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertEquals("Integer 3", c.calledConstructor); 65631c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertEquals(a.getClass(), c.getClass()); 6572e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson } 6582e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson 65931c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson public static class HasMultipleConstructors { 66031c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson private final String calledConstructor; 66131c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson public HasMultipleConstructors() { 66231c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson calledConstructor = "no args"; 66331c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson } 66431c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson public HasMultipleConstructors(int b) { 66531c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson calledConstructor = "int " + b; 66631c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson } 66731c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson public HasMultipleConstructors(Integer c) { 66831c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson calledConstructor = "Integer " + c; 66931c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson } 67031c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson } 67131c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson 67231c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson public void testClassNotCachedWithDifferentParentClassLoaders() throws Exception { 673b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson ClassLoader classLoaderA = newPathClassLoader(); 67431c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson SimpleClass a = proxyFor(SimpleClass.class) 67531c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .parentClassLoader(classLoaderA) 67631c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .build(); 67731c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertEquals(classLoaderA, a.getClass().getClassLoader().getParent()); 67831c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson 679b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson ClassLoader classLoaderB = newPathClassLoader(); 68031c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson SimpleClass b = proxyFor(SimpleClass.class) 68131c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .parentClassLoader(classLoaderB) 68231c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .build(); 68331c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertEquals(classLoaderB, b.getClass().getClassLoader().getParent()); 68431c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson 68531c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertTrue(a.getClass() != b.getClass()); 686579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 6871af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 6881af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testAbstractClassWithUndeclaredInterfaceMethod() throws Throwable { 6891af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson DeclaresInterface declaresInterface = proxyFor(DeclaresInterface.class) 6901af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 6911af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("fake result", declaresInterface.call()); 6921af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson try { 6931af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson ProxyBuilder.callSuper(declaresInterface, Callable.class.getMethod("call")); 6941af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fail(); 6951af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } catch (AbstractMethodError expected) { 6961af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 6971af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 6981af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 6991af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public static abstract class DeclaresInterface implements Callable<String> { 7001af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7011af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 7021af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testImplementingInterfaces() throws Throwable { 7031af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson SimpleClass simpleClass = proxyFor(SimpleClass.class) 7041af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .implementing(Callable.class) 7051af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .implementing(Comparable.class) 7061af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 7071af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("fake result", simpleClass.simpleMethod()); 7081af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 7091af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson Callable<?> asCallable = (Callable<?>) simpleClass; 7101af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("fake result", asCallable.call()); 7111af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 7121af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson Comparable<?> asComparable = (Comparable<?>) simpleClass; 7131af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fakeHandler.fakeResult = 3; 7141af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals(3, asComparable.compareTo(null)); 7151af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7161af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 7171af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testCallSuperWithInterfaceMethod() throws Throwable { 7181af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson SimpleClass simpleClass = proxyFor(SimpleClass.class) 7191af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .implementing(Callable.class) 7201af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 7211af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson try { 7221af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson ProxyBuilder.callSuper(simpleClass, Callable.class.getMethod("call")); 7231af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fail(); 7241af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } catch (AbstractMethodError expected) { 7251af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } catch (NoSuchMethodError expected) { 7261af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7271af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 728579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 7291af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testImplementInterfaceCallingThroughConcreteClass() throws Throwable { 7301af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson InvocationHandler invocationHandler = new InvocationHandler() { 7311af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 7321af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("a", ProxyBuilder.callSuper(o, method, objects)); 7331af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson return "b"; 7341af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7351af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson }; 7361af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson ImplementsCallable proxy = proxyFor(ImplementsCallable.class) 7371af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .implementing(Callable.class) 7381af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .handler(invocationHandler) 7391af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 7401af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("b", proxy.call()); 7411af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("a", ProxyBuilder.callSuper( 7421af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson proxy, ImplementsCallable.class.getMethod("call"))); 7431af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7441af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 7451af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson /** 7461af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * This test is a bit unintuitive because it exercises the synthetic methods 7471af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * that support covariant return types. Calling 'Object call()' on the 7481af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * interface bridges to 'String call()', and so the super method appears to 7491af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * also be proxied. 7501af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson */ 7511af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testImplementInterfaceCallingThroughInterface() throws Throwable { 7521af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson final AtomicInteger count = new AtomicInteger(); 7531af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 7541af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson InvocationHandler invocationHandler = new InvocationHandler() { 7551af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 7561af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson count.incrementAndGet(); 7571af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson return ProxyBuilder.callSuper(o, method, objects); 7581af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7591af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson }; 7601af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 7611af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson Callable<?> proxy = proxyFor(ImplementsCallable.class) 7621af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .implementing(Callable.class) 7631af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .handler(invocationHandler) 7641af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 7651af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 7661af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson // the invocation handler is called twice! 7671af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("a", proxy.call()); 7681af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals(2, count.get()); 7691af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 7701af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson // the invocation handler is called, even though this is a callSuper() call! 7711af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("a", ProxyBuilder.callSuper(proxy, Callable.class.getMethod("call"))); 7721af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals(3, count.get()); 7731af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7741af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 7751af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public static class ImplementsCallable implements Callable<String> { 7761af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public String call() throws Exception { 7771af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson return "a"; 7781af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7791af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7801af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 7811af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson /** 7821af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * This test shows that our generated proxies follow the bytecode convention 7831af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * where methods can have the same name but unrelated return types. This is 7841af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * different from javac's convention where return types must be assignable 7851af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * in one direction or the other. 7861af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson */ 7871af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testInterfacesSameNamesDifferentReturnTypes() throws Throwable { 7881af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson InvocationHandler handler = new InvocationHandler() { 7891af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 7901af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson if (method.getReturnType() == void.class) { 7911af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson return null; 7921af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } else if (method.getReturnType() == String.class) { 7931af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson return "X"; 7941af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } else if (method.getReturnType() == int.class) { 7951af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson return 3; 7961af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } else { 7971af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson throw new AssertionFailedError(); 7981af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7991af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 8001af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson }; 8011af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8021af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson Object o = proxyFor(Object.class) 8031af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .implementing(FooReturnsVoid.class, FooReturnsString.class, FooReturnsInt.class) 8041af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .handler(handler) 8051af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 8061af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8071af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson FooReturnsVoid a = (FooReturnsVoid) o; 8081af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson a.foo(); 8091af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8101af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson FooReturnsString b = (FooReturnsString) o; 8111af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("X", b.foo()); 8121af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8131af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson FooReturnsInt c = (FooReturnsInt) o; 8141af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals(3, c.foo()); 8151af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 8161af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8171af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testInterfacesSameNamesSameReturnType() throws Throwable { 8181af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson Object o = proxyFor(Object.class) 8191af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .implementing(FooReturnsInt.class, FooReturnsInt2.class) 8201af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 8211af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8221af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fakeHandler.setFakeResult(3); 8231af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8241af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson FooReturnsInt a = (FooReturnsInt) o; 8251af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals(3, a.foo()); 8261af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8271af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson FooReturnsInt2 b = (FooReturnsInt2) o; 8281af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals(3, b.foo()); 8291af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 8301af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8311af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public interface FooReturnsVoid { 8321af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson void foo(); 8331af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 8341af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8351af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public interface FooReturnsString { 8361af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson String foo(); 8371af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 8381af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8391af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public interface FooReturnsInt { 8401af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson int foo(); 8411af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 8421af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8431af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public interface FooReturnsInt2 { 8441af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson int foo(); 8451af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 8461af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 847b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson private ClassLoader newPathClassLoader() throws Exception { 848b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson return (ClassLoader) Class.forName("dalvik.system.PathClassLoader") 849b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson .getConstructor(String.class, ClassLoader.class) 850b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson .newInstance("", getClass().getClassLoader()); 851b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson 852b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson } 853b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson 854579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testSubclassOfRandom() throws Exception { 855579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(Random.class) 856579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .handler(new InvokeSuperHandler()) 857579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 858579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 859579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 86095689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy public static class FinalToString { 86195689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy @Override public final String toString() { 86295689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy return "no proxy"; 86395689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy } 86495689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy } 86595689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy 86695689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy // https://code.google.com/p/dexmaker/issues/detail?id=12 86795689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy public void testFinalToString() throws Throwable { 86895689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy assertEquals("no proxy", proxyFor(FinalToString.class).build().toString()); 86995689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy } 87095689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy 871ab38abdf175554643d40b889d58d283d358218c3Samuel Tan public static class FinalInterfaceImpl implements FooReturnsString { 872ab38abdf175554643d40b889d58d283d358218c3Samuel Tan @Override public final String foo() { 873ab38abdf175554643d40b889d58d283d358218c3Samuel Tan return "no proxy"; 874ab38abdf175554643d40b889d58d283d358218c3Samuel Tan } 875ab38abdf175554643d40b889d58d283d358218c3Samuel Tan } 876ab38abdf175554643d40b889d58d283d358218c3Samuel Tan 877ab38abdf175554643d40b889d58d283d358218c3Samuel Tan public static class ExtenstionOfFinalInterfaceImpl extends FinalInterfaceImpl 878ab38abdf175554643d40b889d58d283d358218c3Samuel Tan implements FooReturnsString { 879ab38abdf175554643d40b889d58d283d358218c3Samuel Tan } 880ab38abdf175554643d40b889d58d283d358218c3Samuel Tan 881ab38abdf175554643d40b889d58d283d358218c3Samuel Tan public void testFinalInterfaceImpl() throws Throwable { 882ab38abdf175554643d40b889d58d283d358218c3Samuel Tan assertEquals("no proxy", proxyFor(ExtenstionOfFinalInterfaceImpl.class).build().foo()); 883ab38abdf175554643d40b889d58d283d358218c3Samuel Tan } 884ab38abdf175554643d40b889d58d283d358218c3Samuel Tan 885a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin // https://code.google.com/p/dexmaker/issues/detail?id=9 886a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public interface DeclaresMethodLate { 887a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin void thisIsTheMethod(); 888a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 889a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 890a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public static class MakesMethodFinalEarly { 891a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public final void thisIsTheMethod() {} 892a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 893a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 894a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public static class YouDoNotChooseYourFamily 895a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin extends MakesMethodFinalEarly implements DeclaresMethodLate {} 896a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 897a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public void testInterfaceMethodMadeFinalBeforeActualInheritance() throws Exception { 898a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin proxyFor(YouDoNotChooseYourFamily.class).build(); 899a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 900a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 901579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** Simple helper to add the most common args for this test to the proxy builder. */ 902579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private <T> ProxyBuilder<T> proxyFor(Class<T> clazz) throws Exception { 903579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return ProxyBuilder.forClass(clazz) 904579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .handler(fakeHandler) 905ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson .dexCache(DexMakerTest.getDataDirectory()); 906579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 907579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 908579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static class FakeInvocationHandler implements InvocationHandler { 909579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private Object fakeResult = "fake result"; 910579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 911579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 912579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return fakeResult; 913579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 914579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 915579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void setFakeResult(Object result) { 916579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeResult = result; 917579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 918579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 919054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 920054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public static class TestOrderingClass { 921054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public int returnsInt() { 922054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return 0; 923054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 924054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 925054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public int returnsInt(int param1, int param2) { 926054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return 1; 927054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 928054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 929054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public String returnsString() { 930054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return "string"; 931054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 932054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 933054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public boolean returnsBoolean() { 934054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return false; 935054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 936054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 937054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public double returnsDouble() { 938054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return 1.0; 939054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 940054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 941054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public Object returnsObject() { 942054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return new Object(); 943054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 944054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 945054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 946054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef @SuppressWarnings("unchecked") 947054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void testMethodsGeneratedInDeterministicOrder() throws Exception { 948054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Grab the static methods array from the original class. 949054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Method[] methods1 = getMethodsForProxyClass(TestOrderingClass.class); 950054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertNotNull(methods1); 951054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 952054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Clear ProxyBuilder's in-memory cache of classes. This will force 953054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // it to rebuild the class and reset the static methods field. 954054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Map<Class<?>, Class<?>> map = getGeneratedProxyClasses(); 955054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertNotNull(map); 956054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef map.clear(); 957054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 958054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Grab the static methods array from the rebuilt class. 959054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Method[] methods2 = getMethodsForProxyClass(TestOrderingClass.class); 960054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertNotNull(methods2); 961054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 962054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Ensure that the two method arrays are equal. 963054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertTrue(Arrays.equals(methods1, methods2)); 964054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 965054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 966054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void testOrderingClassWithDexMakerCaching() throws Exception { 967054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef doTestOrderClassWithDexMakerCaching(); 968054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 969054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Force ProxyBuilder to call DexMaker.generateAndLoad() 970054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef getGeneratedProxyClasses().clear(); 971054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 972054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef doTestOrderClassWithDexMakerCaching(); 973054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 974054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 975054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef private void doTestOrderClassWithDexMakerCaching() throws Exception { 976054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef TestOrderingClass proxy = ProxyBuilder.forClass(TestOrderingClass.class) 977054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .handler(new InvokeSuperHandler()) 978054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .dexCache(DexMakerTest.getDataDirectory()) 979054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .build(); 980054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(0, proxy.returnsInt()); 981054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(1, proxy.returnsInt(1, 1)); 982054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals("string", proxy.returnsString()); 983054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertFalse(proxy.returnsBoolean()); 984054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(1.0, proxy.returnsDouble()); 985054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertNotNull(proxy.returnsObject()); 986054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(2, versionedDxDir.listFiles().length); 987054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 988054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 989054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Returns static methods array from a proxy class. 990054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef private Method[] getMethodsForProxyClass(Class<?> parentClass) throws Exception { 991054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Class<?> proxyClass = proxyFor(parentClass).buildProxyClass(); 992054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Method[] methods = null; 993054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef for (Field f : proxyClass.getDeclaredFields()) { 994054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef if (Method[].class.isAssignableFrom(f.getType())) { 995054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef f.setAccessible(true); 996054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef methods = (Method[]) f.get(null); 997054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef break; 998054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 999054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1000054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1001054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return methods; 1002054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1003054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1004054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef private Map<Class<?>, Class<?>> getGeneratedProxyClasses() throws Exception { 1005054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Field mapField = ProxyBuilder.class 1006054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .getDeclaredField("generatedProxyClasses"); 1007054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef mapField.setAccessible(true); 1008054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return (Map<Class<?>, Class<?>>) mapField.get(null); 1009054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1010054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1011054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public static class ConcreteClassA implements FooReturnsInt { 1012054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // from FooReturnsInt 1013054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public int foo() { 1014054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return 1; 1015054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1016054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1017054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // not from FooReturnsInt 1018054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public String bar() { 1019054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return "bar"; 1020054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1021054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1022054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1023054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public static class ConcreteClassB implements FooReturnsInt { 1024054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // from FooReturnsInt 1025054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public int foo() { 1026054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return 0; 1027054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1028054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1029054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // not from FooReturnsInt 1030054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public String bar() { 1031054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return "bahhr"; 1032054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1033054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1034054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1035054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void testTwoClassesWithIdenticalMethodSignatures_DexMakerCaching() throws Exception { 1036054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef ConcreteClassA proxyA = ProxyBuilder.forClass(ConcreteClassA.class) 1037054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .handler(new InvokeSuperHandler()) 1038054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .dexCache(DexMakerTest.getDataDirectory()) 1039054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .build(); 1040054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(1, proxyA.foo()); 1041054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals("bar", proxyA.bar()); 1042054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(2, versionedDxDir.listFiles().length); 1043054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1044054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef ConcreteClassB proxyB = ProxyBuilder.forClass(ConcreteClassB.class) 1045054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .handler(new InvokeSuperHandler()) 1046054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .dexCache(DexMakerTest.getDataDirectory()) 1047054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .build(); 1048054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(0, proxyB.foo()); 1049054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals("bahhr", proxyB.bar()); 1050054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(4, versionedDxDir.listFiles().length); 1051054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1052579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 1053