ProxyBuilderTest.java revision 579d7739c53a2707ad711a2d2cae46d7d782f06
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
17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.google.dexmaker;
18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport junit.framework.AssertionFailedError;
20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport junit.framework.TestCase;
21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.io.File;
23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.io.IOException;
24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.lang.reflect.InvocationHandler;
25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.lang.reflect.Method;
26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.lang.reflect.UndeclaredThrowableException;
27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.Random;
28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic class ProxyBuilderTest extends TestCase {
30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private FakeInvocationHandler fakeHandler = new FakeInvocationHandler();
31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class SimpleClass {
33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public String simpleMethod() {
34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new AssertionFailedError();
35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testExampleOperation() throws Throwable {
39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult("expected");
40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        SimpleClass proxy = proxyFor(SimpleClass.class).build();
41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("expected", proxy.simpleMethod());
42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class ConstructorTakesArguments {
45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        private final String argument;
46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public ConstructorTakesArguments(String arg) {
48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            argument = arg;
49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public String method() {
52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new AssertionFailedError();
53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testConstruction_SucceedsIfCorrectArgumentsProvided() throws Throwable {
57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        ConstructorTakesArguments proxy = proxyFor(ConstructorTakesArguments.class)
58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .constructorArgTypes(String.class)
59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .constructorArgValues("hello")
60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .build();
61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("hello", proxy.argument);
62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        proxy.method();
63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testConstruction_FailsWithWrongNumberOfArguments() throws Throwable {
66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            proxyFor(ConstructorTakesArguments.class).build();
68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fail();
69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (IllegalArgumentException expected) {}
70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testClassIsNotAccessbile_FailsWithUnsupportedOperationException() throws Exception {
73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        class MethodVisibilityClass {
74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            proxyFor(MethodVisibilityClass.class).build();
77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fail();
78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (UnsupportedOperationException expected) {}
79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private static class PrivateVisibilityClass {
82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testPrivateClass_FailsWithUnsupportedOperationException() throws Exception {
85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            proxyFor(PrivateVisibilityClass.class).build();
87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fail();
88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (UnsupportedOperationException expected) {}
89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    protected static class ProtectedVisibilityClass {
92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public String foo() {
93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new AssertionFailedError();
94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testProtectedVisibility_WorksFine() throws Exception {
98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("fake result", proxyFor(ProtectedVisibilityClass.class).build().foo());
99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class HasFinalMethod {
102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public String nonFinalMethod() {
103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return "non-final method";
104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public final String finalMethod() {
107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return "final method";
108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testCanProxyClassesWithFinalMethods_WillNotCallTheFinalMethod() throws Throwable {
112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        HasFinalMethod proxy = proxyFor(HasFinalMethod.class).build();
113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("final method", proxy.finalMethod());
114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("fake result", proxy.nonFinalMethod());
115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class HasPrivateMethod {
118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        private String result() {
119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return "expected";
120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testProxyingPrivateMethods_NotIntercepted() throws Throwable {
124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("expected", proxyFor(HasPrivateMethod.class).build().result());
125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class HasPackagePrivateMethod {
128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        String result() {
129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new AssertionFailedError();
130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testProxyingPackagePrivateMethods_AreIntercepted() throws Throwable {
134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("fake result", proxyFor(HasPackagePrivateMethod.class).build().result());
135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class HasProtectedMethod {
138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        protected String result() {
139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new AssertionFailedError();
140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testProxyingProtectedMethods_AreIntercepted() throws Throwable {
144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("fake result", proxyFor(HasProtectedMethod.class).build().result());
145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class HasVoidMethod {
148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public void dangerousMethod() {
149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fail();
150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testVoidMethod_ShouldNotThrowRuntimeException() throws Throwable {
154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        proxyFor(HasVoidMethod.class).build().dangerousMethod();
155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testObjectMethodsAreAlsoProxied() throws Throwable {
158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Object proxy = proxyFor(Object.class).build();
159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult("mystring");
160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("mystring", proxy.toString());
161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult(-1);
162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(-1, proxy.hashCode());
163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult(false);
164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(false, proxy.equals(proxy));
165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class AllPrimitiveMethods {
168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public boolean getBoolean() { return true; }
169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public int getInt() { return 1; }
170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public byte getByte() { return 2; }
171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public long getLong() { return 3L; }
172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public short getShort() { return 4; }
173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public float getFloat() { return 5f; }
174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public double getDouble() { return 6.0; }
175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public char getChar() { return 'c'; }
176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testAllPrimitiveReturnTypes() throws Throwable {
179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        AllPrimitiveMethods proxy = proxyFor(AllPrimitiveMethods.class).build();
180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult(false);
181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(false, proxy.getBoolean());
182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult(8);
183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(8, proxy.getInt());
184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult((byte) 9);
185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(9, proxy.getByte());
186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult(10L);
187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(10, proxy.getLong());
188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult((short) 11);
189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(11, proxy.getShort());
190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult(12f);
191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(12f, proxy.getFloat());
192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult(13.0);
193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(13.0, proxy.getDouble());
194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult('z');
195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals('z', proxy.getChar());
196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class PassThroughAllPrimitives {
199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public boolean getBoolean(boolean input) { return input; }
200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public int getInt(int input) { return input; }
201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public byte getByte(byte input) { return input; }
202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public long getLong(long input) { return input; }
203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public short getShort(short input) { return input; }
204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public float getFloat(float input) { return input; }
205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public double getDouble(double input) { return input; }
206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public char getChar(char input) { return input; }
207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public String getString(String input) { return input; }
208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public Object getObject(Object input) { return input; }
209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public void getNothing() {}
210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class InvokeSuperHandler implements InvocationHandler {
213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
214579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return ProxyBuilder.callSuper(proxy, method, args);
215579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
217579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testPassThroughWorksForAllPrimitives() throws Exception {
219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        PassThroughAllPrimitives proxy = proxyFor(PassThroughAllPrimitives.class)
220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .handler(new InvokeSuperHandler())
221579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .build();
222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(false, proxy.getBoolean(false));
223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(true, proxy.getBoolean(true));
224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(0, proxy.getInt(0));
225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(1, proxy.getInt(1));
226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals((byte) 2, proxy.getByte((byte) 2));
227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals((byte) 3, proxy.getByte((byte) 3));
228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(4L, proxy.getLong(4L));
229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(5L, proxy.getLong(5L));
230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals((short) 6, proxy.getShort((short) 6));
231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals((short) 7, proxy.getShort((short) 7));
232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(8f, proxy.getFloat(8f));
233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(9f, proxy.getFloat(9f));
234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(10.0, proxy.getDouble(10.0));
235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(11.0, proxy.getDouble(11.0));
236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals('a', proxy.getChar('a'));
237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals('b', proxy.getChar('b'));
238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("asdf", proxy.getString("asdf"));
239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("qwer", proxy.getString("qwer"));
240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(null, proxy.getString(null));
241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Object a = new Object();
242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(a, proxy.getObject(a));
243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(null, proxy.getObject(null));
244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        proxy.getNothing();
245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class ExtendsAllPrimitiveMethods extends AllPrimitiveMethods {
248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public int example() { return 0; }
249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testProxyWorksForSuperclassMethodsAlso() throws Throwable {
252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        ExtendsAllPrimitiveMethods proxy = proxyFor(ExtendsAllPrimitiveMethods.class).build();
253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult(99);
254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(99, proxy.example());
255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(99, proxy.getInt());
256579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(99, proxy.hashCode());
257579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class HasOddParams {
260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public long method(int first, Integer second) {
261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new AssertionFailedError();
262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testMixingBoxedAndUnboxedParams() throws Throwable {
266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        HasOddParams proxy = proxyFor(HasOddParams.class).build();
267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult(99L);
268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(99L, proxy.method(1, Integer.valueOf(2)));
269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class SingleInt {
272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public String getString(int value) {
273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new AssertionFailedError();
274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testSinglePrimitiveParameter() throws Throwable {
278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        InvocationHandler handler = new InvocationHandler() {
279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return "asdf" + ((Integer) args[0]).intValue();
281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        };
283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("asdf1", proxyFor(SingleInt.class).handler(handler).build().getString(1));
284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class TwoConstructors {
287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        private final String string;
288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public TwoConstructors() {
290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            string = "no-arg";
291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
292579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
293579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public TwoConstructors(boolean unused) {
294579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            string = "one-arg";
295579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
298579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testNoConstructorArguments_CallsNoArgConstructor() throws Throwable {
299579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        TwoConstructors twoConstructors = proxyFor(TwoConstructors.class).build();
300579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("no-arg", twoConstructors.string);
301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
302579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
303579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testWithoutInvocationHandler_ThrowsIllegalArgumentException() throws Throwable {
304579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
305579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            ProxyBuilder.forClass(TwoConstructors.class)
306579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    .dexCache(DexGeneratorTest.getDataDirectory())
307579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    .build();
308579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fail();
309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (IllegalArgumentException expected) {}
310579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
311579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
312579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class HardToConstructCorrectly {
313579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public HardToConstructCorrectly() { fail(); }
314579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public HardToConstructCorrectly(Runnable ignored) { fail(); }
315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public HardToConstructCorrectly(Exception ignored) { fail(); }
316579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public HardToConstructCorrectly(Boolean ignored) { /* safe */ }
317579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public HardToConstructCorrectly(Integer ignored) { fail(); }
318579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
319579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
320579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testHardToConstruct_WorksIfYouSpecifyTheConstructorCorrectly() throws Throwable {
321579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        proxyFor(HardToConstructCorrectly.class)
322579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .constructorArgTypes(Boolean.class)
323579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .constructorArgValues(true)
324579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .build();
325579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
326579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
327579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testHardToConstruct_EvenWorksWhenArgsAreAmbiguous() throws Throwable {
328579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        proxyFor(HardToConstructCorrectly.class)
329579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .constructorArgTypes(Boolean.class)
330579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .constructorArgValues(new Object[] { null })
331579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .build();
332579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
333579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
334579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testHardToConstruct_DoesNotInferTypesFromValues() throws Throwable {
335579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
336579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            proxyFor(HardToConstructCorrectly.class)
337579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    .constructorArgValues(true)
338579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    .build();
339579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fail();
340579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (IllegalArgumentException expected) {}
341579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
342579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
343579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testDefaultProxyHasSuperMethodToAccessOriginal() throws Exception {
344579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Object objectProxy = proxyFor(Object.class).build();
345579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertNotNull(objectProxy.getClass().getMethod("super_hashCode"));
346579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
347579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
348579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class PrintsOddAndValue {
349579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public String method(int value) {
350579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return "odd " + value;
351579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
352579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
353579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
354579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testSometimesDelegateToSuper() throws Exception {
355579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        InvocationHandler delegatesOddValues = new InvocationHandler() {
356579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
357579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (method.getName().equals("method")) {
358579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    int intValue = ((Integer) args[0]).intValue();
359579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    if (intValue % 2 == 0) {
360579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        return "even " + intValue;
361579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    }
362579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
363579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return ProxyBuilder.callSuper(proxy, method, args);
364579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
365579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        };
366579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        PrintsOddAndValue proxy = proxyFor(PrintsOddAndValue.class)
367579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .handler(delegatesOddValues)
368579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .build();
369579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("even 0", proxy.method(0));
370579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("odd 1", proxy.method(1));
371579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("even 2", proxy.method(2));
372579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("odd 3", proxy.method(3));
373579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
374579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
375579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class DoubleReturn {
376579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public double getValue() {
377579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return 2.0;
378579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
379579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
380579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
381579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testUnboxedResult() throws Exception {
382579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.fakeResult = 2.0;
383579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals(2.0, proxyFor(DoubleReturn.class).build().getValue());
384579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
385579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
386579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static void staticMethod() {
387579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
388579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
389579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testDoesNotOverrideStaticMethods() throws Exception {
390579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        // Method should exist on this test class itself.
391579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        ProxyBuilderTest.class.getDeclaredMethod("staticMethod");
392579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        // Method should not exist on the subclass.
393579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
394579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            proxyFor(ProxyBuilderTest.class).build().getClass().getDeclaredMethod("staticMethod");
395579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fail();
396579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (NoSuchMethodException expected) {}
397579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
398579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
399579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testIllegalCacheDirectory() throws Exception {
400579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
401579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson          proxyFor(Object.class).dexCache(new File("//////")).build();
402579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson          fail();
403579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (DexCacheException expected) {}
404579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
405579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
406579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testInvalidConstructorSpecification() throws Exception {
407579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
408579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            proxyFor(Object.class)
409579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    .constructorArgTypes(String.class, Boolean.class)
410579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    .constructorArgValues("asdf", true)
411579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    .build();
412579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fail();
413579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (IllegalArgumentException expected) {}
414579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
415579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
416579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static abstract class AbstractClass {
417579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public abstract Object getValue();
418579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
419579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
420579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testAbstractClassBehaviour() throws Exception {
421579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertEquals("fake result", proxyFor(AbstractClass.class).build().getValue());
422579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
423579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
424579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class CtorHasDeclaredException {
425579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public CtorHasDeclaredException() throws IOException {
426579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IOException();
427579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
428579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
429579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
430579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class CtorHasRuntimeException {
431579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public CtorHasRuntimeException() {
432579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new RuntimeException("my message");
433579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
434579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
435579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
436579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class CtorHasError {
437579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public CtorHasError() {
438579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new Error("my message again");
439579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
440579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
441579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
442579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testParentConstructorThrowsDeclaredException() throws Exception {
443579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
444579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            proxyFor(CtorHasDeclaredException.class).build();
445579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fail();
446579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (UndeclaredThrowableException expected) {
447579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            assertTrue(expected.getCause() instanceof IOException);
448579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
449579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
450579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            proxyFor(CtorHasRuntimeException.class).build();
451579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fail();
452579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (RuntimeException expected) {
453579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            assertEquals("my message", expected.getMessage());
454579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
455579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
456579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            proxyFor(CtorHasError.class).build();
457579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fail();
458579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (Error expected) {
459579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            assertEquals("my message again", expected.getMessage());
460579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
461579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
462579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
463579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testGetInvocationHandler_NormalOperation() throws Exception {
464579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Object proxy = proxyFor(Object.class).build();
465579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertSame(fakeHandler, ProxyBuilder.getInvocationHandler(proxy));
466579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
467579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
468579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testGetInvocationHandler_NotAProxy() {
469579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
470579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            ProxyBuilder.getInvocationHandler(new Object());
471579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fail();
472579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (IllegalArgumentException expected) {}
473579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
474579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
475579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class ReturnsObject {
476579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public Object getValue() {
477579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return new Object();
478579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
479579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
480579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
481579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static class ReturnsString extends ReturnsObject {
482579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        @Override
483579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public String getValue() {
484579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return "a string";
485579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
486579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
487579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
488579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testCovariantReturnTypes_NormalBehaviour() throws Exception {
489579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        String expected = "some string";
490579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fakeHandler.setFakeResult(expected);
491579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertSame(expected, proxyFor(ReturnsObject.class).build().getValue());
492579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        assertSame(expected, proxyFor(ReturnsString.class).build().getValue());
493579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
494579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
495579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testCovariantReturnTypes_WrongReturnType() throws Exception {
496579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
497579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fakeHandler.setFakeResult(new Object());
498579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            proxyFor(ReturnsString.class).build().getValue();
499579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fail();
500579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (ClassCastException expected) {}
501579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
502579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
503579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testCaching_ShouldWork() {
504579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        // TODO: We're not supporting caching yet.  But we should as soon as possible.
505579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        fail();
506579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
507579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
508579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void testSubclassOfRandom() throws Exception {
509579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        proxyFor(Random.class)
510579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .handler(new InvokeSuperHandler())
511579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .build();
512579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
513579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
514579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** Simple helper to add the most common args for this test to the proxy builder. */
515579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private <T> ProxyBuilder<T> proxyFor(Class<T> clazz) throws Exception {
516579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return ProxyBuilder.forClass(clazz)
517579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .handler(fakeHandler)
518579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                .dexCache(DexGeneratorTest.getDataDirectory());
519579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
520579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
521579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private static class FakeInvocationHandler implements InvocationHandler {
522579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        private Object fakeResult = "fake result";
523579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
524579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
525579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return fakeResult;
526579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
527579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
528579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        public void setFakeResult(Object result) {
529579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            fakeResult = result;
530579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
531579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
532579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson}
533