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 17b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinpackage com.android.dx.stock; 18b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 19b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinimport com.android.dx.DexMakerTest; 20b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinimport junit.framework.AssertionFailedError; 21b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinimport org.junit.After; 22b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinimport org.junit.Before; 23b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinimport org.junit.Test; 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.io.File; 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.io.IOException; 278d53a06d10c6e2b96be6857aede5e4661804611eAndrew Yousefimport java.lang.reflect.Field; 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.lang.reflect.InvocationHandler; 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.lang.reflect.Method; 30171f097997993b84053f643dc275ce66364315caPhilip P. Moltmannimport java.lang.reflect.Modifier; 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.lang.reflect.UndeclaredThrowableException; 32171f097997993b84053f643dc275ce66364315caPhilip P. Moltmannimport java.util.ArrayList; 331af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilsonimport java.util.Arrays; 348d53a06d10c6e2b96be6857aede5e4661804611eAndrew Yousefimport java.util.Map; 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.Random; 361af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilsonimport java.util.concurrent.Callable; 371af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilsonimport java.util.concurrent.atomic.AtomicInteger; 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 39b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinimport static com.android.dx.util.TestUtil.DELTA_DOUBLE; 40b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinimport static com.android.dx.util.TestUtil.DELTA_FLOAT; 41b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinimport static junit.framework.Assert.assertFalse; 42b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinimport static junit.framework.Assert.assertNotNull; 43b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinimport static junit.framework.Assert.assertSame; 44b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinimport static junit.framework.Assert.assertTrue; 45b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinimport static junit.framework.Assert.fail; 46b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinimport static org.junit.Assert.assertEquals; 47b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 48b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffinpublic class ProxyBuilderTest { 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private FakeInvocationHandler fakeHandler = new FakeInvocationHandler(); 50054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef private File versionedDxDir = new File(DexMakerTest.getDataDirectory(), "v1"); 51054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 52b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Before 53054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void setUp() throws Exception { 54b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin versionedDxDir.mkdirs(); 55054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef clearVersionedDxDir(); 56054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef getGeneratedProxyClasses().clear(); 57054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 58054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 59b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @After 60054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void tearDown() throws Exception { 61054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef getGeneratedProxyClasses().clear(); 62054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef clearVersionedDxDir(); 63054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 64054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 65054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef private void clearVersionedDxDir() { 66b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin for (File file : versionedDxDir.listFiles()) { 67b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin file.delete(); 68054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 69054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class SimpleClass { 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String simpleMethod() { 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionFailedError(); 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 77b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin public static class ExampleClass { 78b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin public String exampleMethod() { 79b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin throw new AssertionFailedError(); 80b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin } 81b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin } 82b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 83b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin public static class ExampleOperationClass { 84b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin public String exampleMethod() { 85b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin throw new AssertionFailedError(); 86b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin } 87b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin } 88b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 89b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testExampleOperation() throws Throwable { 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult("expected"); 92b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin ExampleClass proxy = proxyFor(ExampleClass.class).build(); 93b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin assertEquals("expected", proxy.exampleMethod()); 94054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(2, versionedDxDir.listFiles().length); 95054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 96054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 97b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 98054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void testExampleOperation_DexMakerCaching() throws Throwable { 99054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef fakeHandler.setFakeResult("expected"); 100b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin ExampleOperationClass proxy = proxyFor(ExampleOperationClass.class).build(); 101054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(2, versionedDxDir.listFiles().length); 102b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin assertEquals("expected", proxy.exampleMethod()); 103054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 104054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Force ProxyBuilder to create a DexMaker generator and call DexMaker.generateAndLoad(). 105054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef getGeneratedProxyClasses().clear(); 106054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 107b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin proxy = proxyFor(ExampleOperationClass.class).build(); 108054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(2, versionedDxDir.listFiles().length); 109b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin assertEquals("expected", proxy.exampleMethod()); 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class ConstructorTakesArguments { 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final String argument; 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public ConstructorTakesArguments(String arg) { 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson argument = arg; 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String method() { 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionFailedError(); 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 124b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testConstruction_SucceedsIfCorrectArgumentsProvided() throws Throwable { 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ConstructorTakesArguments proxy = proxyFor(ConstructorTakesArguments.class) 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgTypes(String.class) 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgValues("hello") 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("hello", proxy.argument); 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxy.method(); 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 134b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test(expected = IllegalArgumentException.class) 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testConstruction_FailsWithWrongNumberOfArguments() throws Throwable { 136b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin proxyFor(ConstructorTakesArguments.class).build(); 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 139b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test(expected = UnsupportedOperationException.class) 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testClassIsNotAccessbile_FailsWithUnsupportedOperationException() throws Exception { 141b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin class MethodVisibilityClass {} 142b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin proxyFor(MethodVisibilityClass.class).build(); 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 145b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin private static class PrivateVisibilityClass {} 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 147b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test(expected = UnsupportedOperationException.class) 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testPrivateClass_FailsWithUnsupportedOperationException() throws Exception { 149b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin proxyFor(PrivateVisibilityClass.class).build(); 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protected static class ProtectedVisibilityClass { 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String foo() { 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionFailedError(); 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 158b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testProtectedVisibility_WorksFine() throws Exception { 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("fake result", proxyFor(ProtectedVisibilityClass.class).build().foo()); 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class HasFinalMethod { 164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String nonFinalMethod() { 165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "non-final method"; 166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final String finalMethod() { 169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "final method"; 170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 173b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testCanProxyClassesWithFinalMethods_WillNotCallTheFinalMethod() throws Throwable { 175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson HasFinalMethod proxy = proxyFor(HasFinalMethod.class).build(); 176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("final method", proxy.finalMethod()); 177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("fake result", proxy.nonFinalMethod()); 178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class HasPrivateMethod { 181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private String result() { 182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "expected"; 183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 186b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testProxyingPrivateMethods_NotIntercepted() throws Throwable { 188a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin HasPrivateMethod proxy = proxyFor(HasPrivateMethod.class).build(); 189a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin try { 190a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin proxy.getClass().getDeclaredMethod("result"); 191a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin fail(); 192a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } catch (NoSuchMethodException expected) { 193a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 194a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 195a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 196a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin assertEquals("expected", proxy.result()); 197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class HasPackagePrivateMethod { 200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson String result() { 201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionFailedError(); 202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 205a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public void testProxyingPackagePrivateMethods_NotIntercepted() 206a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin throws Throwable { 207a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin HasPackagePrivateMethod proxy = proxyFor(HasPackagePrivateMethod.class) 208a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin .build(); 209a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin try { 210a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin proxy.getClass().getDeclaredMethod("result"); 211a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin fail(); 212a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } catch (NoSuchMethodException expected) { 213a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 214a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 215a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 216a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin try { 217a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin proxy.result(); 218a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin fail(); 219a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } catch (AssertionFailedError expected) { 220a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 221a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class HasProtectedMethod { 225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protected String result() { 226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionFailedError(); 227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 230b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testProxyingProtectedMethods_AreIntercepted() throws Throwable { 232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("fake result", proxyFor(HasProtectedMethod.class).build().result()); 233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 235a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public static class MyParentClass { 236a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin String someMethod() { 237a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin return "package"; 238a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 239a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 240a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 241a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public static class MyChildClassWithProtectedMethod extends MyParentClass { 242a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin @Override 243a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin protected String someMethod() { 244a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin return "protected"; 245a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 246a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 247a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 248a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public static class MyChildClassWithPublicMethod extends MyParentClass { 249a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin @Override 250a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public String someMethod() { 251a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin return "public"; 252a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 253a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 254a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 255b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 256a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin public void testProxying_ClassHierarchy() throws Throwable { 257a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin assertEquals("package", proxyFor(MyParentClass.class).build().someMethod()); 258a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin assertEquals("fake result", proxyFor(MyChildClassWithProtectedMethod.class).build().someMethod()); 259a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin assertEquals("fake result", proxyFor(MyChildClassWithPublicMethod.class).build().someMethod()); 260a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin } 261a13e8e98b64e3f5271759dac44967f1c24c76995Paul Duffin 262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class HasVoidMethod { 263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void dangerousMethod() { 264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 268b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testVoidMethod_ShouldNotThrowRuntimeException() throws Throwable { 270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(HasVoidMethod.class).build().dangerousMethod(); 271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 273b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 274b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @SuppressWarnings("EqualsWithItself") 275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testObjectMethodsAreAlsoProxied() throws Throwable { 276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object proxy = proxyFor(Object.class).build(); 277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult("mystring"); 278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("mystring", proxy.toString()); 279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(-1); 280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, proxy.hashCode()); 281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(false); 282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(false, proxy.equals(proxy)); 283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 2851af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public static class AllReturnTypes { 286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean getBoolean() { return true; } 287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int getInt() { return 1; } 288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public byte getByte() { return 2; } 289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public long getLong() { return 3L; } 290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public short getShort() { return 4; } 291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public float getFloat() { return 5f; } 292579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public double getDouble() { return 6.0; } 293579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public char getChar() { return 'c'; } 2941af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public int[] getIntArray() { return new int[] { 8, 9 }; } 2951af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public String[] getStringArray() { return new String[] { "d", "e" }; } 296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 298b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 2991af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testAllReturnTypes() throws Throwable { 3001af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson AllReturnTypes proxy = proxyFor(AllReturnTypes.class).build(); 301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(false); 302579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(false, proxy.getBoolean()); 303579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(8); 304579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(8, proxy.getInt()); 305579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult((byte) 9); 306579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(9, proxy.getByte()); 307579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(10L); 308579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(10, proxy.getLong()); 309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult((short) 11); 310579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(11, proxy.getShort()); 311579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(12f); 312b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin assertEquals(12f, proxy.getFloat(), DELTA_FLOAT); 313579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(13.0); 314b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin assertEquals(13.0, proxy.getDouble(), DELTA_FLOAT); 315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult('z'); 316579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals('z', proxy.getChar()); 3171af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fakeHandler.setFakeResult(new int[] { -1, -2 }); 3181af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("[-1, -2]", Arrays.toString(proxy.getIntArray())); 3191af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fakeHandler.setFakeResult(new String[] { "x", "y" }); 3201af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("[x, y]", Arrays.toString(proxy.getStringArray())); 321579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 322579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 3231af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public static class PassThroughAllTypes { 324579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean getBoolean(boolean input) { return input; } 325579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int getInt(int input) { return input; } 326579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public byte getByte(byte input) { return input; } 327579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public long getLong(long input) { return input; } 328579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public short getShort(short input) { return input; } 329579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public float getFloat(float input) { return input; } 330579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public double getDouble(double input) { return input; } 331579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public char getChar(char input) { return input; } 332579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String getString(String input) { return input; } 333579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Object getObject(Object input) { return input; } 334579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void getNothing() {} 335579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 336579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 337579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class InvokeSuperHandler implements InvocationHandler { 338579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 339579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return ProxyBuilder.callSuper(proxy, method, args); 340579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 341579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 342579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 343b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 3441af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testPassThroughWorksForAllTypes() throws Exception { 3451af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson PassThroughAllTypes proxy = proxyFor(PassThroughAllTypes.class) 346579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .handler(new InvokeSuperHandler()) 347579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 348579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(false, proxy.getBoolean(false)); 349579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(true, proxy.getBoolean(true)); 350579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, proxy.getInt(0)); 351579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, proxy.getInt(1)); 352579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((byte) 2, proxy.getByte((byte) 2)); 353579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((byte) 3, proxy.getByte((byte) 3)); 354579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(4L, proxy.getLong(4L)); 355579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(5L, proxy.getLong(5L)); 356579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((short) 6, proxy.getShort((short) 6)); 357579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((short) 7, proxy.getShort((short) 7)); 358b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin assertEquals(8f, proxy.getFloat(8f), DELTA_FLOAT); 359b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin assertEquals(9f, proxy.getFloat(9f), DELTA_FLOAT); 360b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin assertEquals(10.0, proxy.getDouble(10.0), DELTA_DOUBLE); 361b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin assertEquals(11.0, proxy.getDouble(11.0), DELTA_DOUBLE); 362579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals('a', proxy.getChar('a')); 363579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals('b', proxy.getChar('b')); 364579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("asdf", proxy.getString("asdf")); 365579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("qwer", proxy.getString("qwer")); 366579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(null, proxy.getString(null)); 367579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object a = new Object(); 368579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(a, proxy.getObject(a)); 369579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(null, proxy.getObject(null)); 370579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxy.getNothing(); 371579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 372579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 3731af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public static class ExtendsAllReturnTypes extends AllReturnTypes { 374579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int example() { return 0; } 375579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 376579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 377b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 378579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testProxyWorksForSuperclassMethodsAlso() throws Throwable { 3791af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson ExtendsAllReturnTypes proxy = proxyFor(ExtendsAllReturnTypes.class).build(); 380579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(99); 381579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(99, proxy.example()); 382579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(99, proxy.getInt()); 383579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(99, proxy.hashCode()); 384579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 385579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 386579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class HasOddParams { 387579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public long method(int first, Integer second) { 388579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionFailedError(); 389579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 390579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 391579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 392b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 393579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testMixingBoxedAndUnboxedParams() throws Throwable { 394579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson HasOddParams proxy = proxyFor(HasOddParams.class).build(); 395579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(99L); 396579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(99L, proxy.method(1, Integer.valueOf(2))); 397579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 398579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 399579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class SingleInt { 400579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String getString(int value) { 401579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionFailedError(); 402579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 403579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 404579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 405b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 406579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testSinglePrimitiveParameter() throws Throwable { 407579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson InvocationHandler handler = new InvocationHandler() { 408579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 409579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "asdf" + ((Integer) args[0]).intValue(); 410579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 411579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson }; 412579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("asdf1", proxyFor(SingleInt.class).handler(handler).build().getString(1)); 413579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 414579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 415579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class TwoConstructors { 416579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final String string; 417579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 418579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public TwoConstructors() { 419579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson string = "no-arg"; 420579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 421579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 422579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public TwoConstructors(boolean unused) { 423579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson string = "one-arg"; 424579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 425579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 426579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 427b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 428579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testNoConstructorArguments_CallsNoArgConstructor() throws Throwable { 429579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson TwoConstructors twoConstructors = proxyFor(TwoConstructors.class).build(); 430579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("no-arg", twoConstructors.string); 431579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 432579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 433b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 434579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testWithoutInvocationHandler_ThrowsIllegalArgumentException() throws Throwable { 435579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 436579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ProxyBuilder.forClass(TwoConstructors.class) 437ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson .dexCache(DexMakerTest.getDataDirectory()) 438579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 439579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 440579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (IllegalArgumentException expected) {} 441579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 442579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 443579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class HardToConstructCorrectly { 444579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public HardToConstructCorrectly() { fail(); } 445579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public HardToConstructCorrectly(Runnable ignored) { fail(); } 446579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public HardToConstructCorrectly(Exception ignored) { fail(); } 447579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public HardToConstructCorrectly(Boolean ignored) { /* safe */ } 448579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public HardToConstructCorrectly(Integer ignored) { fail(); } 449579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 450579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 451b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 452579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testHardToConstruct_WorksIfYouSpecifyTheConstructorCorrectly() throws Throwable { 453579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(HardToConstructCorrectly.class) 454579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgTypes(Boolean.class) 455579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgValues(true) 456579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 457579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 458579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 459b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 460579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testHardToConstruct_EvenWorksWhenArgsAreAmbiguous() throws Throwable { 461579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(HardToConstructCorrectly.class) 462579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgTypes(Boolean.class) 463579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .constructorArgValues(new Object[] { null }) 464579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 465579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 466579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 467b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test(expected = IllegalArgumentException.class) 468579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testHardToConstruct_DoesNotInferTypesFromValues() throws Throwable { 469b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin proxyFor(HardToConstructCorrectly.class) 470b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin .constructorArgValues(true) 471b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin .build(); 472579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 473579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 474b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 475579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testDefaultProxyHasSuperMethodToAccessOriginal() throws Exception { 476579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object objectProxy = proxyFor(Object.class).build(); 4771af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertNotNull(objectProxy.getClass().getMethod("super$hashCode$int")); 478579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 479579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 480579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class PrintsOddAndValue { 481579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String method(int value) { 482579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "odd " + value; 483579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 484579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 485579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 486b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 487579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testSometimesDelegateToSuper() throws Exception { 488579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson InvocationHandler delegatesOddValues = new InvocationHandler() { 489579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 490579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (method.getName().equals("method")) { 491579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int intValue = ((Integer) args[0]).intValue(); 492579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (intValue % 2 == 0) { 493579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "even " + intValue; 494579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 495579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 496579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return ProxyBuilder.callSuper(proxy, method, args); 497579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 498579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson }; 499579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson PrintsOddAndValue proxy = proxyFor(PrintsOddAndValue.class) 500579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .handler(delegatesOddValues) 501579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 502579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("even 0", proxy.method(0)); 503579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("odd 1", proxy.method(1)); 504579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("even 2", proxy.method(2)); 505579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("odd 3", proxy.method(3)); 506579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 507b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 508b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 5091af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testCallSuperThrows() throws Exception { 5101af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson InvocationHandler handler = new InvocationHandler() { 5111af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 5121af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson return ProxyBuilder.callSuper(o, method, objects); 5131af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 5141af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson }; 5151af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 5161af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson FooThrows fooThrows = proxyFor(FooThrows.class) 5171af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .handler(handler) 5181af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 5191af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 5201af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson try { 5211af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fooThrows.foo(); 5221af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fail(); 5231af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } catch (IllegalStateException expected) { 5241af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("boom!", expected.getMessage()); 5251af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 5261af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 527b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 5281af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public static class FooThrows { 5291af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void foo() { 5301af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson throw new IllegalStateException("boom!"); 5311af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 5321af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 533579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 534579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class DoubleReturn { 535579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public double getValue() { 536579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return 2.0; 537579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 538579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 539579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 540b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 541579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testUnboxedResult() throws Exception { 542579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.fakeResult = 2.0; 543b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin assertEquals(2.0, proxyFor(DoubleReturn.class).build().getValue(), DELTA_DOUBLE); 544579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 545579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 546b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin public static void staticMethod() {} 547579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 548b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 549579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testDoesNotOverrideStaticMethods() throws Exception { 550579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Method should exist on this test class itself. 551579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ProxyBuilderTest.class.getDeclaredMethod("staticMethod"); 552579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Method should not exist on the subclass. 553579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 554579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(ProxyBuilderTest.class).build().getClass().getDeclaredMethod("staticMethod"); 555579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 556579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (NoSuchMethodException expected) {} 557579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 558579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 559b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test(expected = IOException.class) 560579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testIllegalCacheDirectory() throws Exception { 561b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin proxyFor(ProxyForIllegalCacheDirectory.class) 562b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin .dexCache(new File("/poop/")) 563b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin .build(); 564579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 565579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 566b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin public static class ProxyForIllegalCacheDirectory {} 5672e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson 568b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test(expected = IllegalArgumentException.class) 569579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testInvalidConstructorSpecification() throws Exception { 570b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin proxyFor(Object.class) 571b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin .constructorArgTypes(String.class, Boolean.class) 572b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin .constructorArgValues("asdf", true) 573b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin .build(); 574579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 575579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 576579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static abstract class AbstractClass { 577579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public abstract Object getValue(); 578579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 579579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 580b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 581579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testAbstractClassBehaviour() throws Exception { 582579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("fake result", proxyFor(AbstractClass.class).build().getValue()); 583579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 584579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 585579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class CtorHasDeclaredException { 586579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public CtorHasDeclaredException() throws IOException { 587579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IOException(); 588579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 589579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 590579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 591579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class CtorHasRuntimeException { 592579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public CtorHasRuntimeException() { 593579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new RuntimeException("my message"); 594579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 595579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 596579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 597579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class CtorHasError { 598579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public CtorHasError() { 599579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new Error("my message again"); 600579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 601579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 602579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 603b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 604579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testParentConstructorThrowsDeclaredException() throws Exception { 605579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 606579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(CtorHasDeclaredException.class).build(); 607579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 608579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (UndeclaredThrowableException expected) { 609579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertTrue(expected.getCause() instanceof IOException); 610579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 611579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 612579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(CtorHasRuntimeException.class).build(); 613579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 614579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (RuntimeException expected) { 615579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("my message", expected.getMessage()); 616579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 617579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 618579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(CtorHasError.class).build(); 619579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 620579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (Error expected) { 621579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("my message again", expected.getMessage()); 622579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 623579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 624579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 625b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 626579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testGetInvocationHandler_NormalOperation() throws Exception { 627579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object proxy = proxyFor(Object.class).build(); 628579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertSame(fakeHandler, ProxyBuilder.getInvocationHandler(proxy)); 629579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 630579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 631b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test(expected = IllegalArgumentException.class) 632579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testGetInvocationHandler_NotAProxy() { 633b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin ProxyBuilder.getInvocationHandler(new Object()); 634579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 635579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 636579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class ReturnsObject { 637579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Object getValue() { 638579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return new Object(); 639579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 640579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 641579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 642579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class ReturnsString extends ReturnsObject { 643579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 644579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String getValue() { 645579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "a string"; 646579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 647579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 648579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 649b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 650579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testCovariantReturnTypes_NormalBehaviour() throws Exception { 651579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson String expected = "some string"; 652579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(expected); 653579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertSame(expected, proxyFor(ReturnsObject.class).build().getValue()); 654579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertSame(expected, proxyFor(ReturnsString.class).build().getValue()); 655579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 656579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 657b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 658579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testCovariantReturnTypes_WrongReturnType() throws Exception { 659579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 660579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeHandler.setFakeResult(new Object()); 661579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(ReturnsString.class).build().getValue(); 662579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 663579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (ClassCastException expected) {} 664579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 665579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 666b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 6672e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson public void testCaching() throws Exception { 66831c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson SimpleClass a = proxyFor(SimpleClass.class).build(); 66931c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson SimpleClass b = proxyFor(SimpleClass.class).build(); 67031c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertSame(a.getClass(), b.getClass()); 6712e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson } 6722e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson 673b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 6742e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson public void testCachingWithMultipleConstructors() throws Exception { 67531c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson HasMultipleConstructors a = ProxyBuilder.forClass(HasMultipleConstructors.class) 67631c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .constructorArgTypes() 67731c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .constructorArgValues() 67831c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .handler(fakeHandler) 67931c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .dexCache(DexMakerTest.getDataDirectory()).build(); 68031c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertEquals("no args", a.calledConstructor); 68131c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson HasMultipleConstructors b = ProxyBuilder.forClass(HasMultipleConstructors.class) 68231c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .constructorArgTypes(int.class) 68331c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .constructorArgValues(2) 68431c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .handler(fakeHandler) 68531c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .dexCache(DexMakerTest.getDataDirectory()).build(); 68631c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertEquals("int 2", b.calledConstructor); 68731c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertEquals(a.getClass(), b.getClass()); 68831c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson 68931c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson HasMultipleConstructors c = ProxyBuilder.forClass(HasMultipleConstructors.class) 69031c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .constructorArgTypes(Integer.class) 69131c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .constructorArgValues(3) 69231c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .handler(fakeHandler) 69331c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .dexCache(DexMakerTest.getDataDirectory()).build(); 69431c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertEquals("Integer 3", c.calledConstructor); 69531c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertEquals(a.getClass(), c.getClass()); 6962e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson } 6972e28a229885e9ba7fec9ef42cbf30fdcf8a0c939Jesse Wilson 69831c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson public static class HasMultipleConstructors { 69931c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson private final String calledConstructor; 70031c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson public HasMultipleConstructors() { 70131c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson calledConstructor = "no args"; 70231c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson } 70331c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson public HasMultipleConstructors(int b) { 70431c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson calledConstructor = "int " + b; 70531c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson } 70631c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson public HasMultipleConstructors(Integer c) { 70731c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson calledConstructor = "Integer " + c; 70831c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson } 70931c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson } 71031c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson 711b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 71231c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson public void testClassNotCachedWithDifferentParentClassLoaders() throws Exception { 713b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson ClassLoader classLoaderA = newPathClassLoader(); 71431c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson SimpleClass a = proxyFor(SimpleClass.class) 71531c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .parentClassLoader(classLoaderA) 71631c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .build(); 71731c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertEquals(classLoaderA, a.getClass().getClassLoader().getParent()); 71831c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson 719b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson ClassLoader classLoaderB = newPathClassLoader(); 72031c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson SimpleClass b = proxyFor(SimpleClass.class) 72131c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .parentClassLoader(classLoaderB) 72231c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson .build(); 72331c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertEquals(classLoaderB, b.getClass().getClassLoader().getParent()); 72431c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson 72531c34ef392ca364c845f71b4cc8f84de2739426bJesse Wilson assertTrue(a.getClass() != b.getClass()); 726579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 727b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 728b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 7291af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testAbstractClassWithUndeclaredInterfaceMethod() throws Throwable { 7301af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson DeclaresInterface declaresInterface = proxyFor(DeclaresInterface.class) 7311af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 7321af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("fake result", declaresInterface.call()); 7331af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson try { 7341af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson ProxyBuilder.callSuper(declaresInterface, Callable.class.getMethod("call")); 7351af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fail(); 736b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin } catch (IncompatibleClassChangeError expected) { 7371af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7381af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7391af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 740b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin public static abstract class DeclaresInterface implements Callable<String> {} 741b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 742b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 7431af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testImplementingInterfaces() throws Throwable { 7441af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson SimpleClass simpleClass = proxyFor(SimpleClass.class) 7451af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .implementing(Callable.class) 7461af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .implementing(Comparable.class) 7471af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 7481af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("fake result", simpleClass.simpleMethod()); 7491af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 7501af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson Callable<?> asCallable = (Callable<?>) simpleClass; 7511af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("fake result", asCallable.call()); 7521af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 7531af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson Comparable<?> asComparable = (Comparable<?>) simpleClass; 7541af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fakeHandler.fakeResult = 3; 7551af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals(3, asComparable.compareTo(null)); 7561af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7571af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 758b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 7591af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testCallSuperWithInterfaceMethod() throws Throwable { 7601af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson SimpleClass simpleClass = proxyFor(SimpleClass.class) 7611af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .implementing(Callable.class) 7621af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 7631af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson try { 7641af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson ProxyBuilder.callSuper(simpleClass, Callable.class.getMethod("call")); 7651af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fail(); 7661af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } catch (AbstractMethodError expected) { 7671af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } catch (NoSuchMethodError expected) { 7681af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7691af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 770579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 771b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 7721af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testImplementInterfaceCallingThroughConcreteClass() throws Throwable { 7731af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson InvocationHandler invocationHandler = new InvocationHandler() { 7741af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 7751af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("a", ProxyBuilder.callSuper(o, method, objects)); 7761af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson return "b"; 7771af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 7781af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson }; 7791af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson ImplementsCallable proxy = proxyFor(ImplementsCallable.class) 7801af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .implementing(Callable.class) 7811af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .handler(invocationHandler) 7821af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 7831af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("b", proxy.call()); 7841af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("a", ProxyBuilder.callSuper( 7851af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson proxy, ImplementsCallable.class.getMethod("call"))); 7861af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 787b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 7881af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson /** 7891af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * This test is a bit unintuitive because it exercises the synthetic methods 7901af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * that support covariant return types. Calling 'Object call()' on the 7911af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * interface bridges to 'String call()', and so the super method appears to 7921af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * also be proxied. 7931af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson */ 794b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 7951af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testImplementInterfaceCallingThroughInterface() throws Throwable { 7961af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson final AtomicInteger count = new AtomicInteger(); 7971af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 7981af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson InvocationHandler invocationHandler = new InvocationHandler() { 7991af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 8001af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson count.incrementAndGet(); 8011af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson return ProxyBuilder.callSuper(o, method, objects); 8021af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 8031af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson }; 8041af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8051af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson Callable<?> proxy = proxyFor(ImplementsCallable.class) 8061af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .implementing(Callable.class) 8071af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .handler(invocationHandler) 8081af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 8091af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8101af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson // the invocation handler is called twice! 8111af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("a", proxy.call()); 8121af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals(2, count.get()); 8131af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8141af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson // the invocation handler is called, even though this is a callSuper() call! 8151af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("a", ProxyBuilder.callSuper(proxy, Callable.class.getMethod("call"))); 8161af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals(3, count.get()); 8171af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 818b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 8191af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public static class ImplementsCallable implements Callable<String> { 8201af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public String call() throws Exception { 8211af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson return "a"; 8221af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 8231af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 8241af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8251af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson /** 8261af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * This test shows that our generated proxies follow the bytecode convention 8271af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * where methods can have the same name but unrelated return types. This is 8281af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * different from javac's convention where return types must be assignable 8291af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson * in one direction or the other. 8301af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson */ 831b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 8321af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testInterfacesSameNamesDifferentReturnTypes() throws Throwable { 8331af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson InvocationHandler handler = new InvocationHandler() { 8341af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 8351af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson if (method.getReturnType() == void.class) { 8361af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson return null; 8371af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } else if (method.getReturnType() == String.class) { 8381af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson return "X"; 8391af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } else if (method.getReturnType() == int.class) { 8401af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson return 3; 8411af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } else { 8421af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson throw new AssertionFailedError(); 8431af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 8441af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 8451af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson }; 846b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 8471af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson Object o = proxyFor(Object.class) 8481af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .implementing(FooReturnsVoid.class, FooReturnsString.class, FooReturnsInt.class) 8491af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .handler(handler) 8501af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 851b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 8521af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson FooReturnsVoid a = (FooReturnsVoid) o; 8531af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson a.foo(); 854b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 8551af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson FooReturnsString b = (FooReturnsString) o; 8561af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals("X", b.foo()); 857b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 8581af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson FooReturnsInt c = (FooReturnsInt) o; 8591af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals(3, c.foo()); 8601af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 861b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 862b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 8631af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public void testInterfacesSameNamesSameReturnType() throws Throwable { 8641af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson Object o = proxyFor(Object.class) 8651af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .implementing(FooReturnsInt.class, FooReturnsInt2.class) 8661af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson .build(); 867b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 8681af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson fakeHandler.setFakeResult(3); 8691af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8701af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson FooReturnsInt a = (FooReturnsInt) o; 8711af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals(3, a.foo()); 8721af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8731af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson FooReturnsInt2 b = (FooReturnsInt2) o; 8741af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson assertEquals(3, b.foo()); 8751af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 876b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 8771af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public interface FooReturnsVoid { 8781af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson void foo(); 8791af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 8801af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8811af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public interface FooReturnsString { 8821af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson String foo(); 8831af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 8841af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson 8851af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public interface FooReturnsInt { 8861af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson int foo(); 8871af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 888b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 8891af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson public interface FooReturnsInt2 { 8901af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson int foo(); 8911af1da6af1f59f0bc1f9d048f31279ce5e614c3dJesse Wilson } 892b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin 893b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson private ClassLoader newPathClassLoader() throws Exception { 894b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson return (ClassLoader) Class.forName("dalvik.system.PathClassLoader") 895b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson .getConstructor(String.class, ClassLoader.class) 896b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson .newInstance("", getClass().getClassLoader()); 897b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson 898b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson } 899b4fdb175545f178c642194bc43a3fad31af3f0e9Jesse Wilson 900b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 901579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testSubclassOfRandom() throws Exception { 902579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson proxyFor(Random.class) 903579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .handler(new InvokeSuperHandler()) 904579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .build(); 905579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 906579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 90795689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy public static class FinalToString { 908b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Override 909b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin public final String toString() { 91095689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy return "no proxy"; 91195689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy } 91295689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy } 91395689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy 91495689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy // https://code.google.com/p/dexmaker/issues/detail?id=12 915b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 91695689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy public void testFinalToString() throws Throwable { 91795689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy assertEquals("no proxy", proxyFor(FinalToString.class).build().toString()); 91895689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy } 91995689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy 920ab38abdf175554643d40b889d58d283d358218c3Samuel Tan public static class FinalInterfaceImpl implements FooReturnsString { 921b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Override 922b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin public final String foo() { 923ab38abdf175554643d40b889d58d283d358218c3Samuel Tan return "no proxy"; 924ab38abdf175554643d40b889d58d283d358218c3Samuel Tan } 925ab38abdf175554643d40b889d58d283d358218c3Samuel Tan } 926ab38abdf175554643d40b889d58d283d358218c3Samuel Tan 927ab38abdf175554643d40b889d58d283d358218c3Samuel Tan public static class ExtenstionOfFinalInterfaceImpl extends FinalInterfaceImpl 928ab38abdf175554643d40b889d58d283d358218c3Samuel Tan implements FooReturnsString { 929ab38abdf175554643d40b889d58d283d358218c3Samuel Tan } 930ab38abdf175554643d40b889d58d283d358218c3Samuel Tan 931b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 932ab38abdf175554643d40b889d58d283d358218c3Samuel Tan public void testFinalInterfaceImpl() throws Throwable { 933ab38abdf175554643d40b889d58d283d358218c3Samuel Tan assertEquals("no proxy", proxyFor(ExtenstionOfFinalInterfaceImpl.class).build().foo()); 934ab38abdf175554643d40b889d58d283d358218c3Samuel Tan } 935ab38abdf175554643d40b889d58d283d358218c3Samuel Tan 936cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin // https://code.google.com/p/dexmaker/issues/detail?id=9 937cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin public interface DeclaresMethodLate { 938cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin void thisIsTheMethod(); 939cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin } 940cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin 941cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin public static class MakesMethodFinalEarly { 942cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin public final void thisIsTheMethod() {} 943cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin } 944cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin 945cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin public static class YouDoNotChooseYourFamily 946cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin extends MakesMethodFinalEarly implements DeclaresMethodLate {} 947cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin 948b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 949cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin public void testInterfaceMethodMadeFinalBeforeActualInheritance() throws Exception { 950cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin proxyFor(YouDoNotChooseYourFamily.class).build(); 951cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin } 952cb6e5223823f9f9ad04da51c63548659062a4f43Paul Duffin 953309cc66e50aaac713a5c2c72e3ea6b236716b036Paul Duffin public interface ExtendsAnotherInterface extends FooReturnsString { 954309cc66e50aaac713a5c2c72e3ea6b236716b036Paul Duffin 955309cc66e50aaac713a5c2c72e3ea6b236716b036Paul Duffin } 956309cc66e50aaac713a5c2c72e3ea6b236716b036Paul Duffin 957309cc66e50aaac713a5c2c72e3ea6b236716b036Paul Duffin @Test 958309cc66e50aaac713a5c2c72e3ea6b236716b036Paul Duffin public void testExtraInterfaceExtendsInterface() throws Exception { 959309cc66e50aaac713a5c2c72e3ea6b236716b036Paul Duffin ExtendsAnotherInterface proxy = (ExtendsAnotherInterface) 960309cc66e50aaac713a5c2c72e3ea6b236716b036Paul Duffin proxyFor(SimpleClass.class) 961309cc66e50aaac713a5c2c72e3ea6b236716b036Paul Duffin .implementing(ExtendsAnotherInterface.class) 962309cc66e50aaac713a5c2c72e3ea6b236716b036Paul Duffin .build(); 963309cc66e50aaac713a5c2c72e3ea6b236716b036Paul Duffin fakeHandler.setFakeResult(ExtendsAnotherInterface.class.getName()); 964309cc66e50aaac713a5c2c72e3ea6b236716b036Paul Duffin assertEquals(ExtendsAnotherInterface.class.getName(), proxy.foo()); 965309cc66e50aaac713a5c2c72e3ea6b236716b036Paul Duffin } 966309cc66e50aaac713a5c2c72e3ea6b236716b036Paul Duffin 967579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** Simple helper to add the most common args for this test to the proxy builder. */ 968579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private <T> ProxyBuilder<T> proxyFor(Class<T> clazz) throws Exception { 969579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return ProxyBuilder.forClass(clazz) 970579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson .handler(fakeHandler) 971ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson .dexCache(DexMakerTest.getDataDirectory()); 972579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 973579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 974579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static class FakeInvocationHandler implements InvocationHandler { 975579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private Object fakeResult = "fake result"; 976579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 977579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 978579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return fakeResult; 979579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 980579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 981579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void setFakeResult(Object result) { 982579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fakeResult = result; 983579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 984579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 985054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 986054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public static class TestOrderingClass { 987054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public int returnsInt() { 988054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return 0; 989054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 990054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 991054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public int returnsInt(int param1, int param2) { 992054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return 1; 993054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 994054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 995054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public String returnsString() { 996054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return "string"; 997054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 998054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 999054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public boolean returnsBoolean() { 1000054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return false; 1001054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1002054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1003054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public double returnsDouble() { 1004054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return 1.0; 1005054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1006054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1007054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public Object returnsObject() { 1008054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return new Object(); 1009054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1010054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1011054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1012b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 1013054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef @SuppressWarnings("unchecked") 1014054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void testMethodsGeneratedInDeterministicOrder() throws Exception { 1015054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Grab the static methods array from the original class. 1016054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Method[] methods1 = getMethodsForProxyClass(TestOrderingClass.class); 1017054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertNotNull(methods1); 1018054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1019054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Clear ProxyBuilder's in-memory cache of classes. This will force 1020054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // it to rebuild the class and reset the static methods field. 1021054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Map<Class<?>, Class<?>> map = getGeneratedProxyClasses(); 1022054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertNotNull(map); 1023054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef map.clear(); 1024054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1025054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Grab the static methods array from the rebuilt class. 1026054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Method[] methods2 = getMethodsForProxyClass(TestOrderingClass.class); 1027054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertNotNull(methods2); 1028054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1029054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Ensure that the two method arrays are equal. 1030054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertTrue(Arrays.equals(methods1, methods2)); 1031054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1032054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1033b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 1034054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void testOrderingClassWithDexMakerCaching() throws Exception { 1035054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef doTestOrderClassWithDexMakerCaching(); 1036054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1037054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Force ProxyBuilder to call DexMaker.generateAndLoad() 1038054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef getGeneratedProxyClasses().clear(); 1039054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1040054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef doTestOrderClassWithDexMakerCaching(); 1041054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1042054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1043054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef private void doTestOrderClassWithDexMakerCaching() throws Exception { 1044054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef TestOrderingClass proxy = ProxyBuilder.forClass(TestOrderingClass.class) 1045054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .handler(new InvokeSuperHandler()) 1046054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .dexCache(DexMakerTest.getDataDirectory()) 1047054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .build(); 1048054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(0, proxy.returnsInt()); 1049054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(1, proxy.returnsInt(1, 1)); 1050054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals("string", proxy.returnsString()); 1051054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertFalse(proxy.returnsBoolean()); 1052b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin assertEquals(1.0, proxy.returnsDouble(), DELTA_DOUBLE); 1053054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertNotNull(proxy.returnsObject()); 1054b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin assertTrue(versionedDxDir.listFiles().length != 0); 1055054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1056054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1057054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Returns static methods array from a proxy class. 1058054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef private Method[] getMethodsForProxyClass(Class<?> parentClass) throws Exception { 1059054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Class<?> proxyClass = proxyFor(parentClass).buildProxyClass(); 1060054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Method[] methods = null; 1061054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef for (Field f : proxyClass.getDeclaredFields()) { 1062054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef if (Method[].class.isAssignableFrom(f.getType())) { 1063054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef f.setAccessible(true); 1064054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef methods = (Method[]) f.get(null); 1065054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef break; 1066054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1067054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1068054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1069054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return methods; 1070054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1071054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1072054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef private Map<Class<?>, Class<?>> getGeneratedProxyClasses() throws Exception { 1073054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Field mapField = ProxyBuilder.class 1074054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .getDeclaredField("generatedProxyClasses"); 1075054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef mapField.setAccessible(true); 1076054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return (Map<Class<?>, Class<?>>) mapField.get(null); 1077054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1078054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1079054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public static class ConcreteClassA implements FooReturnsInt { 1080054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // from FooReturnsInt 1081054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public int foo() { 1082054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return 1; 1083054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1084054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1085054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // not from FooReturnsInt 1086054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public String bar() { 1087054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return "bar"; 1088054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1089054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1090054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1091054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public static class ConcreteClassB implements FooReturnsInt { 1092054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // from FooReturnsInt 1093054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public int foo() { 1094054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return 0; 1095054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1096054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1097054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // not from FooReturnsInt 1098054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public String bar() { 1099054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return "bahhr"; 1100054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1101054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1102054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1103b8a5896885d4da2b798888b688a46df1adbf5b89Paul Duffin @Test 1104054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void testTwoClassesWithIdenticalMethodSignatures_DexMakerCaching() throws Exception { 1105054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef ConcreteClassA proxyA = ProxyBuilder.forClass(ConcreteClassA.class) 1106054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .handler(new InvokeSuperHandler()) 1107054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .dexCache(DexMakerTest.getDataDirectory()) 1108054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .build(); 1109054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(1, proxyA.foo()); 1110054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals("bar", proxyA.bar()); 1111171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann int numFiles = versionedDxDir.listFiles().length; 1112171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann assertTrue(numFiles > 0); 1113054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1114054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef ConcreteClassB proxyB = ProxyBuilder.forClass(ConcreteClassB.class) 1115054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .handler(new InvokeSuperHandler()) 1116054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .dexCache(DexMakerTest.getDataDirectory()) 1117054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef .build(); 1118054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(0, proxyB.foo()); 1119054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals("bahhr", proxyB.bar()); 1120171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann assertTrue(numFiles < versionedDxDir.listFiles().length); 1121171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann } 1122171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann 1123171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann public static abstract class PartiallyFinalClass { 1124171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann public String returnA() { 1125171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann return "A"; 1126171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann } 1127171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann 1128171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann public String returnB() { 1129171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann return "B"; 1130171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann } 1131171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann 1132171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann public String returnC() { 1133171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann return "C"; 1134171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann } 1135171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann 1136171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann public final String returnD() { 1137171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann return "D"; 1138171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann } 1139171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann 1140171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann public abstract String returnE(); 1141171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann } 1142171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann 1143171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann @Test 1144171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann public void testProxyingSomeMethods() throws Throwable { 1145171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann ArrayList<Method> methodsToOverride = new ArrayList<>(); 1146171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann for (Method method : PartiallyFinalClass.class.getDeclaredMethods()) { 1147171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann if (!Modifier.isFinal(method.getModifiers()) && !method.getName().equals("returnC")) { 1148171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann methodsToOverride.add(method); 1149171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann } 1150171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann } 1151171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann 1152171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann InvocationHandler handler = new InvokeSuperHandler() { 1153171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 1154171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann if (method.getName().equals("returnA")) { 1155171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann return "fake A"; 1156171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann } else if (method.getName().equals("returnC")) { 1157171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann // This will never trigger as "returnC" is not overridden 1158171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann return "fake C"; 1159171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann } else if (method.getName().equals("returnE")) { 1160171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann return "fake E"; 1161171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann } else { 1162171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann return super.invoke(proxy, method, args); 1163171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann } 1164171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann } 1165171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann }; 1166171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann 1167171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann PartiallyFinalClass proxy = ProxyBuilder.forClass(PartiallyFinalClass.class) 1168171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann .handler(handler).onlyMethods(methodsToOverride.toArray(new Method[]{})).build(); 1169171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann 1170171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann assertEquals("fake A", proxy.returnA()); 1171171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann assertEquals("B", proxy.returnB()); 1172171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann assertEquals("C", proxy.returnC()); 1173171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann assertEquals("D", proxy.returnD()); 1174171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann assertEquals("fake E", proxy.returnE()); 1175171f097997993b84053f643dc275ce66364315caPhilip P. Moltmann 1176054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 1178