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 java.io.File; 20054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousefimport java.io.FilenameFilter; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.io.IOException; 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.lang.reflect.Field; 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.lang.reflect.InvocationTargetException; 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.lang.reflect.Method; 255624228626d7cdf206de25a6981ba8107be61057Jesse Wilsonimport java.lang.reflect.Modifier; 26c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilsonimport static java.lang.reflect.Modifier.ABSTRACT; 2790699b97998f1582a921202fb909f17f9718d177Jesse Wilsonimport static java.lang.reflect.Modifier.FINAL; 28c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilsonimport static java.lang.reflect.Modifier.NATIVE; 2990699b97998f1582a921202fb909f17f9718d177Jesse Wilsonimport static java.lang.reflect.Modifier.PRIVATE; 3090699b97998f1582a921202fb909f17f9718d177Jesse Wilsonimport static java.lang.reflect.Modifier.PROTECTED; 3190699b97998f1582a921202fb909f17f9718d177Jesse Wilsonimport static java.lang.reflect.Modifier.PUBLIC; 3290699b97998f1582a921202fb909f17f9718d177Jesse Wilsonimport static java.lang.reflect.Modifier.STATIC; 335624228626d7cdf206de25a6981ba8107be61057Jesse Wilsonimport static java.lang.reflect.Modifier.SYNCHRONIZED; 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.Arrays; 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.List; 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.concurrent.Callable; 3790699b97998f1582a921202fb909f17f9718d177Jesse Wilsonimport junit.framework.TestCase; 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * This generates a class named 'Generated' with one or more generated methods 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * and fields. In loads the generated class into the current VM and uses 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * reflection to invoke its methods. 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <p>This test must run on a Dalvik VM. 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 46ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilsonpublic final class DexMakerTest extends TestCase { 47ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson private DexMaker dexMaker; 480e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson private static TypeId<DexMakerTest> TEST_TYPE = TypeId.get(DexMakerTest.class); 490e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson private static TypeId<?> INT_ARRAY = TypeId.get(int[].class); 500e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson private static TypeId<boolean[]> BOOLEAN_ARRAY = TypeId.get(boolean[].class); 510e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson private static TypeId<long[]> LONG_ARRAY = TypeId.get(long[].class); 520e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson private static TypeId<Object[]> OBJECT_ARRAY = TypeId.get(Object[].class); 530e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson private static TypeId<long[][]> LONG_2D_ARRAY = TypeId.get(long[][].class); 540e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson private static TypeId<?> GENERATED = TypeId.get("LGenerated;"); 550e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson private static TypeId<Callable> CALLABLE = TypeId.get(Callable.class); 560e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson private static MethodId<Callable, Object> CALL = CALLABLE.getMethod(TypeId.OBJECT, "call"); 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override protected void setUp() throws Exception { 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson super.setUp(); 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson reset(); 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * The generator is mutable. Calling reset creates a new empty generator. 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * This is necessary to generate multiple classes in the same test method. 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private void reset() { 68ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson dexMaker = new DexMaker(); 690e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 70054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef clearDataDirectory(); 71054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 72054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 73054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef private void clearDataDirectory() { 74054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef for (File f : getDataDirectory().listFiles()) { 75054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef if (f.getName().endsWith(".jar") || f.getName().endsWith(".dex")) { 76054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef f.delete(); 77054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 78054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testNewInstance() throws Exception { 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static Constructable call(long a, boolean b) { 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Constructable result = new Constructable(a, b); 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 880e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<Constructable> constructable = TypeId.get(Constructable.class); 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<?, Constructable> methodId = GENERATED.getMethod( 900e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson constructable, "call", TypeId.LONG, TypeId.BOOLEAN); 91ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 920e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Long> localA = code.getParameter(0, TypeId.LONG); 930e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Boolean> localB = code.getParameter(1, TypeId.BOOLEAN); 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<Constructable, Void> constructor 950e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson = constructable.getConstructor(TypeId.LONG, TypeId.BOOLEAN); 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<Constructable> localResult = code.newLocal(constructable); 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.newInstance(localResult, constructor, localA, localB); 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Constructable constructed = (Constructable) getMethod().invoke(null, 5L, false); 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(5L, constructed.a); 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(false, constructed.b); 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class Constructable { 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final long a; 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final boolean b; 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Constructable(long a, boolean b) { 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.a = a; 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.b = b; 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testVoidNoArgMemberMethod() throws Exception { 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public void call() { 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1190e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Void> methodId = GENERATED.getMethod(TypeId.VOID, "call"); 120ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC); 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnVoid(); 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addDefaultConstructor(); 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 125b3b96215f3dcbacb3f0d86780ac635cfc14ae9cfJesse Wilson Class<?> generatedClass = generateAndLoad(); 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object instance = generatedClass.newInstance(); 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method method = generatedClass.getMethod("call"); 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson method.invoke(instance); 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testInvokeStatic() throws Exception { 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static int call(int a) { 134ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson * int result = DexMakerTest.staticMethod(a); 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1380e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Integer> methodId = GENERATED.getMethod(TypeId.INT, "call", TypeId.INT); 139ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 1400e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localA = code.getParameter(0, TypeId.INT); 1410e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localResult = code.newLocal(TypeId.INT); 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<?, Integer> staticMethod 1430e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson = TEST_TYPE.getMethod(TypeId.INT, "staticMethod", TypeId.INT); 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.invokeStatic(staticMethod, localResult, localA); 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(10, getMethod().invoke(null, 4)); 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testCreateLocalMethodAsNull() throws Exception { 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public void call(int value) { 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Method method = null; 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1560e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Void> methodId = GENERATED.getMethod(TypeId.VOID, "call", TypeId.INT); 1570e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<Method> methodType = TypeId.get(Method.class); 158ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC); 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<Method> localMethod = code.newLocal(methodType); 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(localMethod, null); 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnVoid(); 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addDefaultConstructor(); 164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 165b3b96215f3dcbacb3f0d86780ac635cfc14ae9cfJesse Wilson Class<?> generatedClass = generateAndLoad(); 166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object instance = generatedClass.newInstance(); 167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method method = generatedClass.getMethod("call", int.class); 168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson method.invoke(instance, 0); 169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @SuppressWarnings("unused") // called by generated code 172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static int staticMethod(int a) { 173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return a + 6; 174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testInvokeVirtual() throws Exception { 177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 178ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson * public static int call(DexMakerTest test, int a) { 179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int result = test.virtualMethod(a); 180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1830e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Integer> methodId = GENERATED.getMethod(TypeId.INT, "call", TEST_TYPE, TypeId.INT); 184ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 185ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Local<DexMakerTest> localInstance = code.getParameter(0, TEST_TYPE); 1860e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localA = code.getParameter(1, TypeId.INT); 1870e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localResult = code.newLocal(TypeId.INT); 188ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson MethodId<DexMakerTest, Integer> virtualMethod 1890e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson = TEST_TYPE.getMethod(TypeId.INT, "virtualMethod", TypeId.INT); 190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.invokeVirtual(virtualMethod, localResult, localInstance, localA); 191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(9, getMethod().invoke(null, this, 4)); 194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @SuppressWarnings("unused") // called by generated code 197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int virtualMethod(int a) { 198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return a + 5; 199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public <G> void testInvokeDirect() throws Exception { 202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * private int directMethod() { 204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int a = 5; 205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return a; 206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static int call(Generated g) { 209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int b = g.directMethod(); 210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return b; 211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 2130e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<G> generated = TypeId.get("LGenerated;"); 2140e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<G, Integer> directMethodId = generated.getMethod(TypeId.INT, "directMethod"); 215ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code directCode = dexMaker.declare(directMethodId, PRIVATE); 216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson directCode.getThis(generated); // 'this' is unused 2170e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localA = directCode.newLocal(TypeId.INT); 218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson directCode.loadConstant(localA, 5); 219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson directCode.returnValue(localA); 220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 2210e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<G, Integer> methodId = generated.getMethod(TypeId.INT, "call", generated); 222ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 2230e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localB = code.newLocal(TypeId.INT); 224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<G> localG = code.getParameter(0, generated); 225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.invokeDirect(directMethodId, localB, localG); 226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localB); 227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addDefaultConstructor(); 229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 230b3b96215f3dcbacb3f0d86780ac635cfc14ae9cfJesse Wilson Class<?> generatedClass = generateAndLoad(); 231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object instance = generatedClass.newInstance(); 232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method method = generatedClass.getMethod("call", generatedClass); 233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(5, method.invoke(null, instance)); 234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public <G> void testInvokeSuper() throws Exception { 237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public int superHashCode() { 239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int result = super.hashCode(); 240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public int hashCode() { 243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return 0; 244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 2460e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<G> generated = TypeId.get("LGenerated;"); 2470e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<Object, Integer> objectHashCode = TypeId.OBJECT.getMethod(TypeId.INT, "hashCode"); 248ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code superHashCode = dexMaker.declare( 2490e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson GENERATED.getMethod(TypeId.INT, "superHashCode"), PUBLIC); 2500e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localResult = superHashCode.newLocal(TypeId.INT); 251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<G> localThis = superHashCode.getThis(generated); 252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson superHashCode.invokeSuper(objectHashCode, localResult, localThis); 253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson superHashCode.returnValue(localResult); 254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 255ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code generatedHashCode = dexMaker.declare( 2560e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson GENERATED.getMethod(TypeId.INT, "hashCode"), PUBLIC); 2570e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localZero = generatedHashCode.newLocal(TypeId.INT); 258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson generatedHashCode.loadConstant(localZero, 0); 259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson generatedHashCode.returnValue(localZero); 260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addDefaultConstructor(); 262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 263b3b96215f3dcbacb3f0d86780ac635cfc14ae9cfJesse Wilson Class<?> generatedClass = generateAndLoad(); 264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object instance = generatedClass.newInstance(); 265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method method = generatedClass.getMethod("superHashCode"); 266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(System.identityHashCode(instance), method.invoke(instance)); 267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testInvokeInterface() throws Exception { 270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static Object call(Callable c) { 272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Object result = c.call(); 273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 2760e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Object> methodId = GENERATED.getMethod(TypeId.OBJECT, "call", CALLABLE); 277ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<Callable> localC = code.getParameter(0, CALLABLE); 2790e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Object> localResult = code.newLocal(TypeId.OBJECT); 280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.invokeInterface(CALL, localResult, localC); 281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Callable<Object> callable = new Callable<Object>() { 284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Object call() throws Exception { 285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return "abc"; 286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson }; 288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("abc", getMethod().invoke(null, callable)); 289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 2915624228626d7cdf206de25a6981ba8107be61057Jesse Wilson public void testInvokeVoidMethodIgnoresTargetLocal() throws Exception { 2925624228626d7cdf206de25a6981ba8107be61057Jesse Wilson /* 2935624228626d7cdf206de25a6981ba8107be61057Jesse Wilson * public static int call() { 2945624228626d7cdf206de25a6981ba8107be61057Jesse Wilson * int result = 5; 2955624228626d7cdf206de25a6981ba8107be61057Jesse Wilson * DexMakerTest.voidMethod(); 2965624228626d7cdf206de25a6981ba8107be61057Jesse Wilson * return result; 2975624228626d7cdf206de25a6981ba8107be61057Jesse Wilson * } 2985624228626d7cdf206de25a6981ba8107be61057Jesse Wilson */ 2995624228626d7cdf206de25a6981ba8107be61057Jesse Wilson MethodId<?, Integer> methodId = GENERATED.getMethod(TypeId.INT, "call"); 3005624228626d7cdf206de25a6981ba8107be61057Jesse Wilson MethodId<?, Void> voidMethod = TEST_TYPE.getMethod(TypeId.VOID, "voidMethod"); 3015624228626d7cdf206de25a6981ba8107be61057Jesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 3025624228626d7cdf206de25a6981ba8107be61057Jesse Wilson Local<Integer> result = code.newLocal(TypeId.INT); 3035624228626d7cdf206de25a6981ba8107be61057Jesse Wilson code.loadConstant(result, 5); 3045624228626d7cdf206de25a6981ba8107be61057Jesse Wilson code.invokeStatic(voidMethod, null); 3055624228626d7cdf206de25a6981ba8107be61057Jesse Wilson code.returnValue(result); 3065624228626d7cdf206de25a6981ba8107be61057Jesse Wilson 3075624228626d7cdf206de25a6981ba8107be61057Jesse Wilson assertEquals(5, getMethod().invoke(null)); 3085624228626d7cdf206de25a6981ba8107be61057Jesse Wilson } 3095624228626d7cdf206de25a6981ba8107be61057Jesse Wilson 3105624228626d7cdf206de25a6981ba8107be61057Jesse Wilson @SuppressWarnings("unused") // called by generated code 3115624228626d7cdf206de25a6981ba8107be61057Jesse Wilson public static void voidMethod() { 3125624228626d7cdf206de25a6981ba8107be61057Jesse Wilson } 3135624228626d7cdf206de25a6981ba8107be61057Jesse Wilson 314579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testParameterMismatch() throws Exception { 3150e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<?>[] argTypes = { 3160e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId.get(Integer.class), // should fail because the code specifies int 3170e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId.OBJECT, 318579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson }; 3190e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Integer> methodId = GENERATED.getMethod(TypeId.INT, "call", argTypes); 320ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 321579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 3220e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.getParameter(0, TypeId.INT); 323579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (IllegalArgumentException e) { 324579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 325579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 3260e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.getParameter(2, TypeId.INT); 327579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (IndexOutOfBoundsException e) { 328579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 329579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 330579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 331579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testInvokeTypeSafety() throws Exception { 332579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 333ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson * public static boolean call(DexMakerTest test) { 334579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * CharSequence cs = test.toString(); 335579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * boolean result = cs.equals(test); 336579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 337579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 338579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 3390e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Boolean> methodId = GENERATED.getMethod(TypeId.BOOLEAN, "call", TEST_TYPE); 340ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 341ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Local<DexMakerTest> localTest = code.getParameter(0, TEST_TYPE); 3420e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<CharSequence> charSequenceType = TypeId.get(CharSequence.class); 3430e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<Object, String> objectToString 3440e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson = TypeId.OBJECT.getMethod(TypeId.STRING, "toString"); 345579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<Object, Boolean> objectEquals 3460e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson = TypeId.OBJECT.getMethod(TypeId.BOOLEAN, "equals", TypeId.OBJECT); 347579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<CharSequence> localCs = code.newLocal(charSequenceType); 3480e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Boolean> localResult = code.newLocal(TypeId.BOOLEAN); 349579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.invokeVirtual(objectToString, localCs, localTest); 350579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.invokeVirtual(objectEquals, localResult, localCs, localTest); 351579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 352579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 353579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(false, getMethod().invoke(null, this)); 354579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 355579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 356579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testReturnTypeMismatch() { 3570e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, String> methodId = GENERATED.getMethod(TypeId.STRING, "call"); 358ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 359579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 3600e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.returnValue(code.newLocal(TypeId.BOOLEAN)); 361579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 362579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (IllegalArgumentException expected) { 363579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 364579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 365579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnVoid(); 366579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 367579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (IllegalArgumentException expected) { 368579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 369579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 370579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 371579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testDeclareStaticFields() throws Exception { 372579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 373579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * class Generated { 374579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static int a; 375579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * protected static Object b; 376579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 377579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 3780e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson dexMaker.declare(GENERATED.getField(TypeId.INT, "a"), PUBLIC | STATIC, 3); 3790e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson dexMaker.declare(GENERATED.getField(TypeId.OBJECT, "b"), PROTECTED | STATIC, null); 380b3b96215f3dcbacb3f0d86780ac635cfc14ae9cfJesse Wilson Class<?> generatedClass = generateAndLoad(); 381579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 382579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Field a = generatedClass.getField("a"); 383579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(int.class, a.getType()); 384579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(3, a.get(null)); 385579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 386579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Field b = generatedClass.getDeclaredField("b"); 387579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Object.class, b.getType()); 388579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson b.setAccessible(true); 389579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(null, b.get(null)); 390579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 391579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 392579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testDeclareInstanceFields() throws Exception { 393579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 394579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * class Generated { 395579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public int a; 396579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * protected Object b; 397579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 398579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 3990e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson dexMaker.declare(GENERATED.getField(TypeId.INT, "a"), PUBLIC, null); 4000e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson dexMaker.declare(GENERATED.getField(TypeId.OBJECT, "b"), PROTECTED, null); 401579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 402579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson addDefaultConstructor(); 403579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 404b3b96215f3dcbacb3f0d86780ac635cfc14ae9cfJesse Wilson Class<?> generatedClass = generateAndLoad(); 405579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object instance = generatedClass.newInstance(); 406579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 407579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Field a = generatedClass.getField("a"); 408579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(int.class, a.getType()); 409579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, a.get(instance)); 410579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 411579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Field b = generatedClass.getDeclaredField("b"); 412579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Object.class, b.getType()); 413579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson b.setAccessible(true); 414579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(null, b.get(instance)); 415579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 416579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 417579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 418579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Declare a constructor that takes an int parameter and assigns it to a 419579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * field. 420579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 421579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public <G> void testDeclareConstructor() throws Exception { 422579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 423579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * class Generated { 424579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public final int a; 425579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public Generated(int a) { 426579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * this.a = a; 427579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 428579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 429579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 4300e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<G> generated = TypeId.get("LGenerated;"); 4310e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson FieldId<G, Integer> fieldId = generated.getField(TypeId.INT, "a"); 432ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson dexMaker.declare(fieldId, PUBLIC | FINAL, null); 4330e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Void> constructor = GENERATED.getConstructor(TypeId.INT); 434c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson Code code = dexMaker.declare(constructor, PUBLIC); 435579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<G> thisRef = code.getThis(generated); 4360e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> parameter = code.getParameter(0, TypeId.INT); 4370e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.invokeDirect(TypeId.OBJECT.getConstructor(), null, thisRef); 438579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.iput(fieldId, thisRef, parameter); 439579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnVoid(); 440579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 441b3b96215f3dcbacb3f0d86780ac635cfc14ae9cfJesse Wilson Class<?> generatedClass = generateAndLoad(); 442579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Field a = generatedClass.getField("a"); 443579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object instance = generatedClass.getConstructor(int.class).newInstance(0xabcd); 444579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0xabcd, a.get(instance)); 445579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 446579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 4475624228626d7cdf206de25a6981ba8107be61057Jesse Wilson public void testReturnType() throws Exception { 448579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson testReturnType(boolean.class, true); 449579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson testReturnType(byte.class, (byte) 5); 450579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson testReturnType(char.class, 'E'); 451579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson testReturnType(double.class, 5.0); 452579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson testReturnType(float.class, 5.0f); 453579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson testReturnType(int.class, 5); 454579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson testReturnType(long.class, 5L); 455579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson testReturnType(short.class, (short) 5); 456579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson testReturnType(void.class, null); 457579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson testReturnType(String.class, "foo"); 458579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson testReturnType(Class.class, List.class); 459579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 460579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 461579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private <T> void testReturnType(Class<T> javaType, T value) throws Exception { 462579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 463579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public int call() { 464579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int a = 5; 465579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return a; 466579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 467579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 468579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson reset(); 4690e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<T> returnType = TypeId.get(javaType); 470ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(GENERATED.getMethod(returnType, "call"), PUBLIC | STATIC); 471579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (value != null) { 472579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<T> i = code.newLocal(returnType); 473579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(i, value); 474579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(i); 475579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 476579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnVoid(); 477579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 478579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 479b3b96215f3dcbacb3f0d86780ac635cfc14ae9cfJesse Wilson Class<?> generatedClass = generateAndLoad(); 480579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method method = generatedClass.getMethod("call"); 481579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(javaType, method.getReturnType()); 482579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(value, method.invoke(null)); 483579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 484579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 485579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testBranching() throws Exception { 486579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method lt = branchingMethod(Comparison.LT); 487579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.TRUE, lt.invoke(null, 1, 2)); 488579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.FALSE, lt.invoke(null, 1, 1)); 489579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.FALSE, lt.invoke(null, 2, 1)); 490579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 491579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method le = branchingMethod(Comparison.LE); 492579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.TRUE, le.invoke(null, 1, 2)); 493579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.TRUE, le.invoke(null, 1, 1)); 494579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.FALSE, le.invoke(null, 2, 1)); 495579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 496579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method eq = branchingMethod(Comparison.EQ); 497579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.FALSE, eq.invoke(null, 1, 2)); 498579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.TRUE, eq.invoke(null, 1, 1)); 499579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.FALSE, eq.invoke(null, 2, 1)); 500579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 501579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method ge = branchingMethod(Comparison.GE); 502579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.FALSE, ge.invoke(null, 1, 2)); 503579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.TRUE, ge.invoke(null, 1, 1)); 504579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.TRUE, ge.invoke(null, 2, 1)); 505579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 506579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method gt = branchingMethod(Comparison.GT); 507579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.FALSE, gt.invoke(null, 1, 2)); 508579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.FALSE, gt.invoke(null, 1, 1)); 509579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.TRUE, gt.invoke(null, 2, 1)); 510579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 511579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method ne = branchingMethod(Comparison.NE); 512579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.TRUE, ne.invoke(null, 1, 2)); 513579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.FALSE, ne.invoke(null, 1, 1)); 514579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Boolean.TRUE, ne.invoke(null, 2, 1)); 515579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 516579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 517579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private Method branchingMethod(Comparison comparison) throws Exception { 518579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 519579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static boolean call(int localA, int localB) { 520579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * if (a comparison b) { 521579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return true; 522579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 523579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return false; 524579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 525579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 526579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson reset(); 527579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<?, Boolean> methodId = GENERATED.getMethod( 5280e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId.BOOLEAN, "call", TypeId.INT, TypeId.INT); 529ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 5300e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localA = code.getParameter(0, TypeId.INT); 5310e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localB = code.getParameter(1, TypeId.INT); 5320e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Boolean> result = code.newLocal(TypeId.get(boolean.class)); 53323abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label afterIf = new Label(); 53423abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label ifBody = new Label(); 5350e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.compare(comparison, ifBody, localA, localB); 536579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.jump(afterIf); 537579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 538579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(ifBody); 539579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(result, true); 540579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(result); 541579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 542579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(afterIf); 543579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(result, false); 544579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(result); 545579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return getMethod(); 546579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 547579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 548579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testCastIntegerToInteger() throws Exception { 549579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method intToLong = numericCastingMethod(int.class, long.class); 550579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0x0000000000000000L, intToLong.invoke(null, 0x00000000)); 551579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0x000000007fffffffL, intToLong.invoke(null, 0x7fffffff)); 552579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0xffffffff80000000L, intToLong.invoke(null, 0x80000000)); 553579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0xffffffffffffffffL, intToLong.invoke(null, 0xffffffff)); 554579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 555579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method longToInt = numericCastingMethod(long.class, int.class); 556579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0x1234abcd, longToInt.invoke(null, 0x000000001234abcdL)); 557579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0x1234abcd, longToInt.invoke(null, 0x123456781234abcdL)); 558579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0x1234abcd, longToInt.invoke(null, 0xffffffff1234abcdL)); 559579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 560579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method intToShort = numericCastingMethod(int.class, short.class); 561579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((short) 0x1234, intToShort.invoke(null, 0x00001234)); 562579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((short) 0x1234, intToShort.invoke(null, 0xabcd1234)); 563579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((short) 0x1234, intToShort.invoke(null, 0xffff1234)); 564579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 565579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method intToChar = numericCastingMethod(int.class, char.class); 566579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((char) 0x1234, intToChar.invoke(null, 0x00001234)); 567579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((char) 0x1234, intToChar.invoke(null, 0xabcd1234)); 568579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((char) 0x1234, intToChar.invoke(null, 0xffff1234)); 569579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 570579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method intToByte = numericCastingMethod(int.class, byte.class); 571579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((byte) 0x34, intToByte.invoke(null, 0x00000034)); 572579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((byte) 0x34, intToByte.invoke(null, 0xabcd1234)); 573579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((byte) 0x34, intToByte.invoke(null, 0xffffff34)); 574579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 575579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 576579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testCastIntegerToFloatingPoint() throws Exception { 577579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method intToFloat = numericCastingMethod(int.class, float.class); 578579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0.0f, intToFloat.invoke(null, 0)); 579579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1.0f, intToFloat.invoke(null, -1)); 580579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(16777216f, intToFloat.invoke(null, 16777216)); 581579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(16777216f, intToFloat.invoke(null, 16777217)); // precision 582579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 583579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method intToDouble = numericCastingMethod(int.class, double.class); 584579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0.0, intToDouble.invoke(null, 0)); 585579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1.0, intToDouble.invoke(null, -1)); 586579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(16777216.0, intToDouble.invoke(null, 16777216)); 587579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(16777217.0, intToDouble.invoke(null, 16777217)); 588579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 589579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method longToFloat = numericCastingMethod(long.class, float.class); 590579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0.0f, longToFloat.invoke(null, 0L)); 591579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1.0f, longToFloat.invoke(null, -1L)); 592579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(16777216f, longToFloat.invoke(null, 16777216L)); 593579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(16777216f, longToFloat.invoke(null, 16777217L)); 594579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 595579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method longToDouble = numericCastingMethod(long.class, double.class); 596579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0.0, longToDouble.invoke(null, 0L)); 597579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1.0, longToDouble.invoke(null, -1L)); 598579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(9007199254740992.0, longToDouble.invoke(null, 9007199254740992L)); 599579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(9007199254740992.0, longToDouble.invoke(null, 9007199254740993L)); // precision 600579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 601579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 602579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testCastFloatingPointToInteger() throws Exception { 603579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method floatToInt = numericCastingMethod(float.class, int.class); 604579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, floatToInt.invoke(null, 0.0f)); 605579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, floatToInt.invoke(null, -1.0f)); 606579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Integer.MAX_VALUE, floatToInt.invoke(null, 10e15f)); 607579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, floatToInt.invoke(null, 0.5f)); 608579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Integer.MIN_VALUE, floatToInt.invoke(null, Float.NEGATIVE_INFINITY)); 609579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, floatToInt.invoke(null, Float.NaN)); 610579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 611579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method floatToLong = numericCastingMethod(float.class, long.class); 612579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0L, floatToLong.invoke(null, 0.0f)); 613579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1L, floatToLong.invoke(null, -1.0f)); 614579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(10000000272564224L, floatToLong.invoke(null, 10e15f)); 615579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0L, floatToLong.invoke(null, 0.5f)); 616579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Long.MIN_VALUE, floatToLong.invoke(null, Float.NEGATIVE_INFINITY)); 617579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0L, floatToLong.invoke(null, Float.NaN)); 618579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 619579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method doubleToInt = numericCastingMethod(double.class, int.class); 620579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, doubleToInt.invoke(null, 0.0)); 621579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, doubleToInt.invoke(null, -1.0)); 622579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Integer.MAX_VALUE, doubleToInt.invoke(null, 10e15)); 623579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, doubleToInt.invoke(null, 0.5)); 624579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Integer.MIN_VALUE, doubleToInt.invoke(null, Double.NEGATIVE_INFINITY)); 625579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, doubleToInt.invoke(null, Double.NaN)); 626579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 627579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method doubleToLong = numericCastingMethod(double.class, long.class); 628579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0L, doubleToLong.invoke(null, 0.0)); 629579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1L, doubleToLong.invoke(null, -1.0)); 630579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(10000000000000000L, doubleToLong.invoke(null, 10e15)); 631579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0L, doubleToLong.invoke(null, 0.5)); 632579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Long.MIN_VALUE, doubleToLong.invoke(null, Double.NEGATIVE_INFINITY)); 633579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0L, doubleToLong.invoke(null, Double.NaN)); 634579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 635579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 636579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testCastFloatingPointToFloatingPoint() throws Exception { 637579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method floatToDouble = numericCastingMethod(float.class, double.class); 638579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0.0, floatToDouble.invoke(null, 0.0f)); 639579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1.0, floatToDouble.invoke(null, -1.0f)); 640579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0.5, floatToDouble.invoke(null, 0.5f)); 641579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Double.NEGATIVE_INFINITY, floatToDouble.invoke(null, Float.NEGATIVE_INFINITY)); 642579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Double.NaN, floatToDouble.invoke(null, Float.NaN)); 643579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 644579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method doubleToFloat = numericCastingMethod(double.class, float.class); 645579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0.0f, doubleToFloat.invoke(null, 0.0)); 646579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1.0f, doubleToFloat.invoke(null, -1.0)); 647579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0.5f, doubleToFloat.invoke(null, 0.5)); 648579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Float.NEGATIVE_INFINITY, doubleToFloat.invoke(null, Double.NEGATIVE_INFINITY)); 649579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Float.NaN, doubleToFloat.invoke(null, Double.NaN)); 650579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 651579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 652579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private Method numericCastingMethod(Class<?> source, Class<?> target) 653579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throws Exception { 654579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 655579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static short call(int source) { 656579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * short casted = (short) source; 657579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return casted; 658579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 659579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 660579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson reset(); 6610e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<?> sourceType = TypeId.get(source); 6620e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<?> targetType = TypeId.get(target); 663579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<?, ?> methodId = GENERATED.getMethod(targetType, "call", sourceType); 664ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 665579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<?> localSource = code.getParameter(0, sourceType); 666579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<?> localCasted = code.newLocal(targetType); 66797b0be6b3da9df87e9026f880b0b0bffc7242450Jesse Wilson code.cast(localCasted, localSource); 668579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localCasted); 669579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return getMethod(); 670579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 671579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 672579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testNot() throws Exception { 673579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method notInteger = notMethod(int.class); 674579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0xffffffff, notInteger.invoke(null, 0x00000000)); 675579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0x00000000, notInteger.invoke(null, 0xffffffff)); 676579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0xedcba987, notInteger.invoke(null, 0x12345678)); 677579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 678579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method notLong = notMethod(long.class); 679579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0xffffffffffffffffL, notLong.invoke(null, 0x0000000000000000L)); 680579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0x0000000000000000L, notLong.invoke(null, 0xffffffffffffffffL)); 681579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0x98765432edcba987L, notLong.invoke(null, 0x6789abcd12345678L)); 682579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 683579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 684579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private <T> Method notMethod(Class<T> source) throws Exception { 685579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 686579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static short call(int source) { 687579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * source = ~source; 688579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return not; 689579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 690579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 691579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson reset(); 6920e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<T> valueType = TypeId.get(source); 693579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<?, T> methodId = GENERATED.getMethod(valueType, "call", valueType); 694ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 695579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<T> localSource = code.getParameter(0, valueType); 696b0f6ea8cec29bd1b2453e8fd15d9c6f65ca3ea2cJesse Wilson code.op(UnaryOp.NOT, localSource, localSource); 697579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localSource); 698579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return getMethod(); 699579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 700579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 701579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testNegate() throws Exception { 702579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method negateInteger = negateMethod(int.class); 703579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, negateInteger.invoke(null, 0)); 704579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, negateInteger.invoke(null, 1)); 705579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Integer.MIN_VALUE, negateInteger.invoke(null, Integer.MIN_VALUE)); 706579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 707579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method negateLong = negateMethod(long.class); 708579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0L, negateLong.invoke(null, 0)); 709579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1L, negateLong.invoke(null, 1)); 710579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Long.MIN_VALUE, negateLong.invoke(null, Long.MIN_VALUE)); 711579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 712579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method negateFloat = negateMethod(float.class); 713579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-0.0f, negateFloat.invoke(null, 0.0f)); 714579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1.0f, negateFloat.invoke(null, 1.0f)); 715579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Float.NaN, negateFloat.invoke(null, Float.NaN)); 716579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Float.POSITIVE_INFINITY, negateFloat.invoke(null, Float.NEGATIVE_INFINITY)); 717579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 718579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method negateDouble = negateMethod(double.class); 719579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-0.0, negateDouble.invoke(null, 0.0)); 720579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1.0, negateDouble.invoke(null, 1.0)); 721579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Double.NaN, negateDouble.invoke(null, Double.NaN)); 722579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Double.POSITIVE_INFINITY, negateDouble.invoke(null, Double.NEGATIVE_INFINITY)); 723579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 724579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 725579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private <T> Method negateMethod(Class<T> source) throws Exception { 726579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 727579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static short call(int source) { 728579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * source = -source; 729579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return not; 730579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 731579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 732579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson reset(); 7330e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<T> valueType = TypeId.get(source); 734579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<?, T> methodId = GENERATED.getMethod(valueType, "call", valueType); 735ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 736579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<T> localSource = code.getParameter(0, valueType); 737b0f6ea8cec29bd1b2453e8fd15d9c6f65ca3ea2cJesse Wilson code.op(UnaryOp.NEGATE, localSource, localSource); 738579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localSource); 739579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return getMethod(); 740579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 741579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 742579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testIntBinaryOps() throws Exception { 74395689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method add = binaryOpMethod(int.class, int.class, BinaryOp.ADD); 744579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(79, add.invoke(null, 75, 4)); 745579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 74695689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method subtract = binaryOpMethod(int.class, int.class, BinaryOp.SUBTRACT); 747579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(71, subtract.invoke(null, 75, 4)); 748579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 74995689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method multiply = binaryOpMethod(int.class, int.class, BinaryOp.MULTIPLY); 750579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(300, multiply.invoke(null, 75, 4)); 751579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 75295689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method divide = binaryOpMethod(int.class, int.class, BinaryOp.DIVIDE); 753579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(18, divide.invoke(null, 75, 4)); 754579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 755579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson divide.invoke(null, 75, 0); 756579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 757579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (InvocationTargetException expected) { 758579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(ArithmeticException.class, expected.getCause().getClass()); 759579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 760579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 76195689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method remainder = binaryOpMethod(int.class, int.class, BinaryOp.REMAINDER); 762579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(3, remainder.invoke(null, 75, 4)); 763579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 764579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson remainder.invoke(null, 75, 0); 765579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 766579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (InvocationTargetException expected) { 767579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(ArithmeticException.class, expected.getCause().getClass()); 768579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 769579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 77095689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method and = binaryOpMethod(int.class, int.class, BinaryOp.AND); 771579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0xff000000, and.invoke(null, 0xff00ff00, 0xffff0000)); 772579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 77395689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method or = binaryOpMethod(int.class, int.class, BinaryOp.OR); 774579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0xffffff00, or.invoke(null, 0xff00ff00, 0xffff0000)); 775579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 77695689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method xor = binaryOpMethod(int.class, int.class, BinaryOp.XOR); 777579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0x00ffff00, xor.invoke(null, 0xff00ff00, 0xffff0000)); 778579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 77995689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method shiftLeft = binaryOpMethod(int.class, int.class, BinaryOp.SHIFT_LEFT); 780579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0xcd123400, shiftLeft.invoke(null, 0xabcd1234, 8)); 781579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 78295689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method shiftRight = binaryOpMethod(int.class, int.class, BinaryOp.SHIFT_RIGHT); 783579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0xffabcd12, shiftRight.invoke(null, 0xabcd1234, 8)); 784579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 785579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method unsignedShiftRight = binaryOpMethod(int.class, 78695689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy int.class, BinaryOp.UNSIGNED_SHIFT_RIGHT); 787579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0x00abcd12, unsignedShiftRight.invoke(null, 0xabcd1234, 8)); 788579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 789579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 790579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testLongBinaryOps() throws Exception { 79195689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method add = binaryOpMethod(long.class, long.class, BinaryOp.ADD); 79295689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy assertEquals(30000000079L, add.invoke(null, 10000000075L, 20000000004L)); 793579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 79495689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method subtract = binaryOpMethod(long.class, long.class, BinaryOp.SUBTRACT); 79595689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy assertEquals(20000000071L, subtract.invoke(null, 30000000075L, 10000000004L)); 796579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 79795689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method multiply = binaryOpMethod(long.class, long.class, BinaryOp.MULTIPLY); 79895689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy assertEquals(-8742552812415203028L, multiply.invoke(null, 30000000075L, 20000000004L)); 799579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 80095689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method divide = binaryOpMethod(long.class, long.class, BinaryOp.DIVIDE); 80195689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy assertEquals(-2L, divide.invoke(null, -8742552812415203028L, 4142552812415203028L)); 802579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 80395689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy divide.invoke(null, -8742552812415203028L, 0L); 804579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 805579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (InvocationTargetException expected) { 806579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(ArithmeticException.class, expected.getCause().getClass()); 807579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 808579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 80995689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method remainder = binaryOpMethod(long.class, long.class, BinaryOp.REMAINDER); 81095689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy assertEquals(10000000004L, remainder.invoke(null, 30000000079L, 20000000075L)); 811579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 81295689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy remainder.invoke(null, 30000000079L, 0L); 813579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 814579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (InvocationTargetException expected) { 815579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(ArithmeticException.class, expected.getCause().getClass()); 816579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 817579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 81895689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method and = binaryOpMethod(long.class, long.class, BinaryOp.AND); 819579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0xff00ff0000000000L, 820579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson and.invoke(null, 0xff00ff00ff00ff00L, 0xffffffff00000000L)); 821579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 82295689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method or = binaryOpMethod(long.class, long.class, BinaryOp.OR); 823579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0xffffffffff00ff00L, 824579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson or.invoke(null, 0xff00ff00ff00ff00L, 0xffffffff00000000L)); 825579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 82695689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method xor = binaryOpMethod(long.class, long.class, BinaryOp.XOR); 827579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0x00ff00ffff00ff00L, 828579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson xor.invoke(null, 0xff00ff00ff00ff00L, 0xffffffff00000000L)); 829579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 83095689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method shiftLeft = binaryOpMethod(long.class, int.class, BinaryOp.SHIFT_LEFT); 83195689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy assertEquals(0xcdef012345678900L, shiftLeft.invoke(null, 0xabcdef0123456789L, 8)); 832579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 83395689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method shiftRight = binaryOpMethod(long.class, int.class, BinaryOp.SHIFT_RIGHT); 83495689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy assertEquals(0xffabcdef01234567L, shiftRight.invoke(null, 0xabcdef0123456789L, 8)); 835579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 83695689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method unsignedShiftRight = binaryOpMethod( 83795689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy long.class, int.class, BinaryOp.UNSIGNED_SHIFT_RIGHT); 83895689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy assertEquals(0x00abcdef01234567L, unsignedShiftRight.invoke(null, 0xabcdef0123456789L, 8)); 839579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 840579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 841579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testFloatBinaryOps() throws Exception { 84295689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method add = binaryOpMethod(float.class, float.class, BinaryOp.ADD); 843579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(6.75f, add.invoke(null, 5.5f, 1.25f)); 844579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 84595689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method subtract = binaryOpMethod(float.class, float.class, BinaryOp.SUBTRACT); 846579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(4.25f, subtract.invoke(null, 5.5f, 1.25f)); 847579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 84895689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method multiply = binaryOpMethod(float.class, float.class, BinaryOp.MULTIPLY); 849579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(6.875f, multiply.invoke(null, 5.5f, 1.25f)); 850579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 85195689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method divide = binaryOpMethod(float.class, float.class, BinaryOp.DIVIDE); 852579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(4.4f, divide.invoke(null, 5.5f, 1.25f)); 853579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Float.POSITIVE_INFINITY, divide.invoke(null, 5.5f, 0.0f)); 854579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 85595689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method remainder = binaryOpMethod(float.class, float.class, BinaryOp.REMAINDER); 856579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0.5f, remainder.invoke(null, 5.5f, 1.25f)); 857579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Float.NaN, remainder.invoke(null, 5.5f, 0.0f)); 858579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 859579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 860579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testDoubleBinaryOps() throws Exception { 86195689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method add = binaryOpMethod(double.class, double.class, BinaryOp.ADD); 862579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(6.75, add.invoke(null, 5.5, 1.25)); 863579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 86495689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method subtract = binaryOpMethod(double.class, double.class, BinaryOp.SUBTRACT); 865579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(4.25, subtract.invoke(null, 5.5, 1.25)); 866579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 86795689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method multiply = binaryOpMethod(double.class, double.class, BinaryOp.MULTIPLY); 868579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(6.875, multiply.invoke(null, 5.5, 1.25)); 869579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 87095689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method divide = binaryOpMethod(double.class, double.class, BinaryOp.DIVIDE); 871579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(4.4, divide.invoke(null, 5.5, 1.25)); 872579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Double.POSITIVE_INFINITY, divide.invoke(null, 5.5, 0.0)); 873579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 87495689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Method remainder = binaryOpMethod(double.class, double.class, BinaryOp.REMAINDER); 875579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0.5, remainder.invoke(null, 5.5, 1.25)); 876579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(Double.NaN, remainder.invoke(null, 5.5, 0.0)); 877579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 878579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 87995689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy private <T1, T2> Method binaryOpMethod( 88095689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Class<T1> valueAClass, Class<T2> valueBClass, BinaryOp op) throws Exception { 881579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 882579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static int binaryOp(int a, int b) { 883579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int result = a + b; 884579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 885579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 886579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 887579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson reset(); 88895689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy TypeId<T1> valueAType = TypeId.get(valueAClass); 88995689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy TypeId<T2> valueBType = TypeId.get(valueBClass); 89095689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy MethodId<?, T1> methodId = GENERATED.getMethod(valueAType, "call", valueAType, valueBType); 891ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 89295689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Local<T1> localA = code.getParameter(0, valueAType); 89395689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Local<T2> localB = code.getParameter(1, valueBType); 89495689a700bfea5e2d78380a442fc2903cc40a3f2Mark Brophy Local<T1> localResult = code.newLocal(valueAType); 895579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.op(op, localResult, localA, localB); 896579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 897579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return getMethod(); 898579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 899579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 900579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testReadAndWriteInstanceFields() throws Exception { 901579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Instance instance = new Instance(); 902579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 903579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method intSwap = instanceSwapMethod(int.class, "intValue"); 904579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson instance.intValue = 5; 905579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(5, intSwap.invoke(null, instance, 10)); 906579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(10, instance.intValue); 907579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 908579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method longSwap = instanceSwapMethod(long.class, "longValue"); 909579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson instance.longValue = 500L; 910579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(500L, longSwap.invoke(null, instance, 1234L)); 911579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1234L, instance.longValue); 912579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 913579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method booleanSwap = instanceSwapMethod(boolean.class, "booleanValue"); 914579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson instance.booleanValue = false; 915579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(false, booleanSwap.invoke(null, instance, true)); 916579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(true, instance.booleanValue); 917579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 918579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method floatSwap = instanceSwapMethod(float.class, "floatValue"); 919579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson instance.floatValue = 1.5f; 920579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1.5f, floatSwap.invoke(null, instance, 0.5f)); 921579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0.5f, instance.floatValue); 922579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 923579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method doubleSwap = instanceSwapMethod(double.class, "doubleValue"); 924579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson instance.doubleValue = 155.5; 925579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(155.5, doubleSwap.invoke(null, instance, 266.6)); 926579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(266.6, instance.doubleValue); 927579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 928579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method objectSwap = instanceSwapMethod(Object.class, "objectValue"); 929579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson instance.objectValue = "before"; 930579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("before", objectSwap.invoke(null, instance, "after")); 931579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("after", instance.objectValue); 932579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 933579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method byteSwap = instanceSwapMethod(byte.class, "byteValue"); 934579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson instance.byteValue = 0x35; 935579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((byte) 0x35, byteSwap.invoke(null, instance, (byte) 0x64)); 936579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((byte) 0x64, instance.byteValue); 937579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 938579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method charSwap = instanceSwapMethod(char.class, "charValue"); 939579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson instance.charValue = 'A'; 940579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals('A', charSwap.invoke(null, instance, 'B')); 941579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals('B', instance.charValue); 942579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 943579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method shortSwap = instanceSwapMethod(short.class, "shortValue"); 944579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson instance.shortValue = (short) 0xabcd; 945579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((short) 0xabcd, shortSwap.invoke(null, instance, (short) 0x1234)); 946579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((short) 0x1234, instance.shortValue); 947579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 948579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 949579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public class Instance { 950579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int intValue; 951579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public long longValue; 952579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public float floatValue; 953579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public double doubleValue; 954579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Object objectValue; 955579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean booleanValue; 956579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public byte byteValue; 957579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public char charValue; 958579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public short shortValue; 959579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 960579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 961579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private <V> Method instanceSwapMethod( 962579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Class<V> valueClass, String fieldName) throws Exception { 963579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 964579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static int call(Instance instance, int newValue) { 965579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int oldValue = instance.intValue; 966579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance.intValue = newValue; 967579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return oldValue; 968579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 969579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 970579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson reset(); 9710e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<V> valueType = TypeId.get(valueClass); 9720e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<Instance> objectType = TypeId.get(Instance.class); 973579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson FieldId<Instance, V> fieldId = objectType.getField(valueType, fieldName); 974579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<?, V> methodId = GENERATED.getMethod(valueType, "call", objectType, valueType); 975ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 976579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<Instance> localInstance = code.getParameter(0, objectType); 977579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<V> localNewValue = code.getParameter(1, valueType); 978579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<V> localOldValue = code.newLocal(valueType); 9790e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.iget(fieldId, localOldValue, localInstance); 980579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.iput(fieldId, localInstance, localNewValue); 981579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localOldValue); 982579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return getMethod(); 983579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 984579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 985579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testReadAndWriteStaticFields() throws Exception { 986579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method intSwap = staticSwapMethod(int.class, "intValue"); 987579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Static.intValue = 5; 988579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(5, intSwap.invoke(null, 10)); 989579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(10, Static.intValue); 990579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 991579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method longSwap = staticSwapMethod(long.class, "longValue"); 992579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Static.longValue = 500L; 993579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(500L, longSwap.invoke(null, 1234L)); 994579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1234L, Static.longValue); 995579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 996579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method booleanSwap = staticSwapMethod(boolean.class, "booleanValue"); 997579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Static.booleanValue = false; 998579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(false, booleanSwap.invoke(null, true)); 999579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(true, Static.booleanValue); 1000579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1001579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method floatSwap = staticSwapMethod(float.class, "floatValue"); 1002579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Static.floatValue = 1.5f; 1003579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1.5f, floatSwap.invoke(null, 0.5f)); 1004579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0.5f, Static.floatValue); 1005579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1006579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method doubleSwap = staticSwapMethod(double.class, "doubleValue"); 1007579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Static.doubleValue = 155.5; 1008579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(155.5, doubleSwap.invoke(null, 266.6)); 1009579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(266.6, Static.doubleValue); 1010579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1011579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method objectSwap = staticSwapMethod(Object.class, "objectValue"); 1012579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Static.objectValue = "before"; 1013579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("before", objectSwap.invoke(null, "after")); 1014579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("after", Static.objectValue); 1015579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1016579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method byteSwap = staticSwapMethod(byte.class, "byteValue"); 1017579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Static.byteValue = 0x35; 1018579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((byte) 0x35, byteSwap.invoke(null, (byte) 0x64)); 1019579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((byte) 0x64, Static.byteValue); 1020579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1021579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method charSwap = staticSwapMethod(char.class, "charValue"); 1022579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Static.charValue = 'A'; 1023579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals('A', charSwap.invoke(null, 'B')); 1024579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals('B', Static.charValue); 1025579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1026579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method shortSwap = staticSwapMethod(short.class, "shortValue"); 1027579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Static.shortValue = (short) 0xabcd; 1028579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((short) 0xabcd, shortSwap.invoke(null, (short) 0x1234)); 1029579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals((short) 0x1234, Static.shortValue); 1030579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1031579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1032579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class Static { 1033579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static int intValue; 1034579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static long longValue; 1035579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static float floatValue; 1036579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static double doubleValue; 1037579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static Object objectValue; 1038579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static boolean booleanValue; 1039579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static byte byteValue; 1040579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static char charValue; 1041579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static short shortValue; 1042579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1043579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1044579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private <V> Method staticSwapMethod(Class<V> valueClass, String fieldName) 1045579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throws Exception { 1046579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1047579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static int call(int newValue) { 1048579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int oldValue = Static.intValue; 1049579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Static.intValue = newValue; 1050579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return oldValue; 1051579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1052579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1053579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson reset(); 10540e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<V> valueType = TypeId.get(valueClass); 10550e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<Static> objectType = TypeId.get(Static.class); 1056579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson FieldId<Static, V> fieldId = objectType.getField(valueType, fieldName); 1057579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<?, V> methodId = GENERATED.getMethod(valueType, "call", valueType); 1058ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 1059579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<V> localNewValue = code.getParameter(0, valueType); 1060579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<V> localOldValue = code.newLocal(valueType); 1061579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.sget(fieldId, localOldValue); 1062579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.sput(fieldId, localNewValue); 1063579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localOldValue); 1064579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return getMethod(); 1065579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1066579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1067579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testTypeCast() throws Exception { 1068579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1069579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static String call(Object o) { 1070579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * String s = (String) o; 1071579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1072579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 10730e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, String> methodId = GENERATED.getMethod(TypeId.STRING, "call", TypeId.OBJECT); 1074ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 10750e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Object> localObject = code.getParameter(0, TypeId.OBJECT); 10760e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<String> localString = code.newLocal(TypeId.STRING); 107797b0be6b3da9df87e9026f880b0b0bffc7242450Jesse Wilson code.cast(localString, localObject); 1078579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localString); 1079579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1080579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method method = getMethod(); 1081579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("s", method.invoke(null, "s")); 1082579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(null, method.invoke(null, (String) null)); 1083579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 1084579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson method.invoke(null, 5); 1085579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 1086579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (InvocationTargetException expected) { 1087579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(ClassCastException.class, expected.getCause().getClass()); 1088579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1089579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1090579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1091579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testInstanceOf() throws Exception { 1092579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1093579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static boolean call(Object o) { 1094579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * boolean result = o instanceof String; 1095579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 1096579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1097579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 10980e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Boolean> methodId = GENERATED.getMethod(TypeId.BOOLEAN, "call", TypeId.OBJECT); 1099ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 11000e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Object> localObject = code.getParameter(0, TypeId.OBJECT); 11010e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Boolean> localResult = code.newLocal(TypeId.BOOLEAN); 11020e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.instanceOfType(localResult, localObject, TypeId.STRING); 1103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 1104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method method = getMethod(); 1106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(true, method.invoke(null, "s")); 1107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(false, method.invoke(null, (String) null)); 1108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(false, method.invoke(null, 5)); 1109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 1112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Tests that we can construct a for loop. 1113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testForLoop() throws Exception { 1115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static int call(int count) { 1117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int result = 1; 1118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * for (int i = 0; i < count; i += 1) { 1119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * result = result * 2; 1120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 1122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 11240e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Integer> methodId = GENERATED.getMethod(TypeId.INT, "call", TypeId.INT); 1125ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 11260e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localCount = code.getParameter(0, TypeId.INT); 11270e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localResult = code.newLocal(TypeId.INT); 11280e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localI = code.newLocal(TypeId.INT); 11290e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> local1 = code.newLocal(TypeId.INT); 11300e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> local2 = code.newLocal(TypeId.INT); 1131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(local1, 1); 1132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(local2, 2); 1133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(localResult, 1); 1134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(localI, 0); 113523abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label loopCondition = new Label(); 113623abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label loopBody = new Label(); 113723abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label afterLoop = new Label(); 1138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(loopCondition); 11390e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.compare(Comparison.LT, loopBody, localI, localCount); 1140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.jump(afterLoop); 1141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(loopBody); 1142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.op(BinaryOp.MULTIPLY, localResult, localResult, local2); 1143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.op(BinaryOp.ADD, localI, localI, local1); 1144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.jump(loopCondition); 1145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(afterLoop); 1146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 1147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method pow2 = getMethod(); 1149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, pow2.invoke(null, 0)); 1150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(2, pow2.invoke(null, 1)); 1151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(4, pow2.invoke(null, 2)); 1152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(8, pow2.invoke(null, 3)); 1153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(16, pow2.invoke(null, 4)); 1154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 1157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Tests that we can construct a while loop. 1158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testWhileLoop() throws Exception { 1160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static int call(int max) { 1162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int result = 1; 1163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * while (result < max) { 1164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * result = result * 2; 1165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 1167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 11690e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Integer> methodId = GENERATED.getMethod(TypeId.INT, "call", TypeId.INT); 1170ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 11710e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localMax = code.getParameter(0, TypeId.INT); 11720e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localResult = code.newLocal(TypeId.INT); 11730e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> local2 = code.newLocal(TypeId.INT); 1174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(localResult, 1); 1175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(local2, 2); 117623abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label loopCondition = new Label(); 117723abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label loopBody = new Label(); 117823abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label afterLoop = new Label(); 1179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(loopCondition); 11800e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.compare(Comparison.LT, loopBody, localResult, localMax); 1181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.jump(afterLoop); 1182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(loopBody); 1183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.op(BinaryOp.MULTIPLY, localResult, localResult, local2); 1184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.jump(loopCondition); 1185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(afterLoop); 1186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 1187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method ceilPow2 = getMethod(); 1189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, ceilPow2.invoke(null, 1)); 1190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(2, ceilPow2.invoke(null, 2)); 1191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(4, ceilPow2.invoke(null, 3)); 1192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(16, ceilPow2.invoke(null, 10)); 1193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(128, ceilPow2.invoke(null, 100)); 1194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1024, ceilPow2.invoke(null, 1000)); 1195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testIfElseBlock() throws Exception { 1198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static int call(int a, int b, int c) { 1200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * if (a < b) { 1201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * if (a < c) { 1202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return a; 1203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } else { 1204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return c; 1205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } else if (b < c) { 1207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return b; 1208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } else { 1209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return c; 1210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<?, Integer> methodId = GENERATED.getMethod( 12140e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId.INT, "call", TypeId.INT, TypeId.INT, TypeId.INT); 1215ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 12160e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localA = code.getParameter(0, TypeId.INT); 12170e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localB = code.getParameter(1, TypeId.INT); 12180e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localC = code.getParameter(2, TypeId.INT); 121923abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label aLessThanB = new Label(); 122023abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label aLessThanC = new Label(); 122123abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label bLessThanC = new Label(); 12220e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.compare(Comparison.LT, aLessThanB, localA, localB); 12230e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.compare(Comparison.LT, bLessThanC, localB, localC); 1224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localC); 1225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // (a < b) 1226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(aLessThanB); 12270e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.compare(Comparison.LT, aLessThanC, localA, localC); 1228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localC); 1229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // (a < c) 1230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(aLessThanC); 1231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localA); 1232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // (b < c) 1233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(bLessThanC); 1234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localB); 1235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method min = getMethod(); 1237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, min.invoke(null, 1, 2, 3)); 1238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, min.invoke(null, 2, 3, 1)); 1239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, min.invoke(null, 2, 1, 3)); 1240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, min.invoke(null, 3, 2, 1)); 1241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testRecursion() throws Exception { 1244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static int call(int a) { 1246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * if (a < 2) { 1247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return a; 1248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * a -= 1; 1250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int x = call(a) 1251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * a -= 1; 1252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int y = call(a); 1253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int result = x + y; 1254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 1255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1256579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 12570e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Integer> methodId = GENERATED.getMethod(TypeId.INT, "call", TypeId.INT); 1258ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 12590e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localA = code.getParameter(0, TypeId.INT); 12600e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> local1 = code.newLocal(TypeId.INT); 12610e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> local2 = code.newLocal(TypeId.INT); 12620e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localX = code.newLocal(TypeId.INT); 12630e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localY = code.newLocal(TypeId.INT); 12640e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localResult = code.newLocal(TypeId.INT); 126523abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label baseCase = new Label(); 1266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(local1, 1); 1267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(local2, 2); 12680e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.compare(Comparison.LT, baseCase, localA, local2); 1269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.op(BinaryOp.SUBTRACT, localA, localA, local1); 1270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.invokeStatic(methodId, localX, localA); 1271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.op(BinaryOp.SUBTRACT, localA, localA, local1); 1272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.invokeStatic(methodId, localY, localA); 1273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.op(BinaryOp.ADD, localResult, localX, localY); 1274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 1275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(baseCase); 1276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localA); 1277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method fib = getMethod(); 1279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, fib.invoke(null, 0)); 1280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, fib.invoke(null, 1)); 1281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, fib.invoke(null, 2)); 1282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(2, fib.invoke(null, 3)); 1283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(3, fib.invoke(null, 4)); 1284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(5, fib.invoke(null, 5)); 1285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(8, fib.invoke(null, 6)); 1286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testCatchExceptions() throws Exception { 1289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static String call(int i) { 1291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * try { 1292ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson * DexMakerTest.thrower(i); 1293579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return "NONE"; 1294579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } catch (IllegalArgumentException e) { 1295579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return "IAE"; 1296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } catch (IllegalStateException e) { 1297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return "ISE"; 1298579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } catch (RuntimeException e) { 1299579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return "RE"; 1300579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 13020e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, String> methodId = GENERATED.getMethod(TypeId.STRING, "call", TypeId.INT); 1303ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 13040e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localI = code.getParameter(0, TypeId.INT); 13050e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<String> result = code.newLocal(TypeId.STRING); 130623abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label catchIae = new Label(); 130723abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label catchIse = new Label(); 130823abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label catchRe = new Label(); 1309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 13100e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.addCatchClause(TypeId.get(IllegalArgumentException.class), catchIae); 13110e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.addCatchClause(TypeId.get(IllegalStateException.class), catchIse); 13120e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.addCatchClause(TypeId.get(RuntimeException.class), catchRe); 13130e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, ?> thrower = TEST_TYPE.getMethod(TypeId.VOID, "thrower", TypeId.INT); 1314579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.invokeStatic(thrower, null, localI); 1315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(result, "NONE"); 1316579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(result); 1317579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1318579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(catchIae); 1319579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(result, "IAE"); 1320579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(result); 1321579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1322579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(catchIse); 1323579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(result, "ISE"); 1324579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(result); 1325579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1326579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(catchRe); 1327579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(result, "RE"); 1328579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(result); 1329579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1330579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method method = getMethod(); 1331579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("NONE", method.invoke(null, 0)); 1332579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("IAE", method.invoke(null, 1)); 1333579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("ISE", method.invoke(null, 2)); 1334579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("RE", method.invoke(null, 3)); 1335579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 1336579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson method.invoke(null, 4); 1337579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 1338579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (InvocationTargetException expected) { 1339579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(IOException.class, expected.getCause().getClass()); 1340579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1341579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1342579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1343579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @SuppressWarnings("unused") // called by generated code 1344579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static void thrower(int a) throws Exception { 1345579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson switch (a) { 1346579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case 0: 1347579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return; 1348579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case 1: 1349579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IllegalArgumentException(); 1350579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case 2: 1351579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IllegalStateException(); 1352579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case 3: 1353579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new UnsupportedOperationException(); 1354579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case 4: 1355579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IOException(); 1356579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson default: 1357579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new AssertionError(); 1358579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1359579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1360579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1361579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testNestedCatchClauses() throws Exception { 1362579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1363579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static String call(int a, int b, int c) { 1364579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * try { 1365ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson * DexMakerTest.thrower(a); 1366579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * try { 1367ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson * DexMakerTest.thrower(b); 1368579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } catch (IllegalArgumentException) { 1369579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return "INNER"; 1370579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1371ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson * DexMakerTest.thrower(c); 1372579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return "NONE"; 1373579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } catch (IllegalArgumentException e) { 1374579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return "OUTER"; 1375579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1376579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1377579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<?, String> methodId = GENERATED.getMethod( 13780e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId.STRING, "call", TypeId.INT, TypeId.INT, TypeId.INT); 1379ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 13800e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localA = code.getParameter(0, TypeId.INT); 13810e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localB = code.getParameter(1, TypeId.INT); 13820e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localC = code.getParameter(2, TypeId.INT); 13830e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<String> localResult = code.newLocal(TypeId.STRING); 138423abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label catchInner = new Label(); 138523abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson Label catchOuter = new Label(); 1386579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 13870e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<IllegalArgumentException> iaeType = TypeId.get(IllegalArgumentException.class); 1388579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.addCatchClause(iaeType, catchOuter); 1389579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 13900e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, ?> thrower = TEST_TYPE.getMethod(TypeId.VOID, "thrower", TypeId.INT); 1391579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.invokeStatic(thrower, null, localA); 1392579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1393579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // for the inner catch clause, we stash the old label and put it back afterwards. 1394579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Label previousLabel = code.removeCatchClause(iaeType); 1395579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.addCatchClause(iaeType, catchInner); 1396579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.invokeStatic(thrower, null, localB); 1397579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.removeCatchClause(iaeType); 1398579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.addCatchClause(iaeType, previousLabel); 1399579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.invokeStatic(thrower, null, localC); 1400579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(localResult, "NONE"); 1401579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 1402579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1403579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(catchInner); 1404579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(localResult, "INNER"); 1405579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 1406579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1407579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.mark(catchOuter); 1408579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.loadConstant(localResult, "OUTER"); 1409579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 1410579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1411579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method method = getMethod(); 1412579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("OUTER", method.invoke(null, 1, 0, 0)); 1413579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("INNER", method.invoke(null, 0, 1, 0)); 1414579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("OUTER", method.invoke(null, 0, 0, 1)); 1415579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("NONE", method.invoke(null, 0, 0, 0)); 1416579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1417579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1418579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testThrow() throws Exception { 1419579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1420579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static void call() { 1421579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * throw new IllegalStateException(); 1422579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1423579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 14240e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Void> methodId = GENERATED.getMethod(TypeId.VOID, "call"); 1425ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 14260e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<IllegalStateException> iseType = TypeId.get(IllegalStateException.class); 1427579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<IllegalStateException, Void> iseConstructor = iseType.getConstructor(); 1428579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<IllegalStateException> localIse = code.newLocal(iseType); 1429579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.newInstance(localIse, iseConstructor); 1430579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.throwValue(localIse); 1431579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1432579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson try { 1433579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson getMethod().invoke(null); 1434579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson fail(); 1435579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } catch (InvocationTargetException expected) { 1436579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(IllegalStateException.class, expected.getCause().getClass()); 1437579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1438579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1439579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1440579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testUnusedParameters() throws Exception { 1441579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1442579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static void call(int unused1, long unused2, long unused3) {} 1443579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1444579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<?, Void> methodId = GENERATED.getMethod( 14450e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId.VOID, "call", TypeId.INT, TypeId.LONG, TypeId.LONG); 1446ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 1447579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnVoid(); 1448579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson getMethod().invoke(null, 1, 2, 3); 1449579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1450579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1451579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testFloatingPointCompare() throws Exception { 14520e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Method floatG = floatingPointCompareMethod(TypeId.FLOAT, 1); 1453579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, floatG.invoke(null, 1.0f, Float.POSITIVE_INFINITY)); 1454579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, floatG.invoke(null, 1.0f, 2.0f)); 1455579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, floatG.invoke(null, 1.0f, 1.0f)); 1456579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, floatG.invoke(null, 2.0f, 1.0f)); 1457579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, floatG.invoke(null, 1.0f, Float.NaN)); 1458579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, floatG.invoke(null, Float.NaN, 1.0f)); 1459579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, floatG.invoke(null, Float.NaN, Float.NaN)); 1460579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, floatG.invoke(null, Float.NaN, Float.POSITIVE_INFINITY)); 1461579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 14620e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Method floatL = floatingPointCompareMethod(TypeId.FLOAT, -1); 1463579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, floatG.invoke(null, 1.0f, Float.POSITIVE_INFINITY)); 1464579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, floatL.invoke(null, 1.0f, 2.0f)); 1465579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, floatL.invoke(null, 1.0f, 1.0f)); 1466579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, floatL.invoke(null, 2.0f, 1.0f)); 1467579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, floatL.invoke(null, 1.0f, Float.NaN)); 1468579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, floatL.invoke(null, Float.NaN, 1.0f)); 1469579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, floatL.invoke(null, Float.NaN, Float.NaN)); 1470579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, floatL.invoke(null, Float.NaN, Float.POSITIVE_INFINITY)); 1471579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 14720e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Method doubleG = floatingPointCompareMethod(TypeId.DOUBLE, 1); 1473579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, doubleG.invoke(null, 1.0, Double.POSITIVE_INFINITY)); 1474579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, doubleG.invoke(null, 1.0, 2.0)); 1475579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, doubleG.invoke(null, 1.0, 1.0)); 1476579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, doubleG.invoke(null, 2.0, 1.0)); 1477579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, doubleG.invoke(null, 1.0, Double.NaN)); 1478579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, doubleG.invoke(null, Double.NaN, 1.0)); 1479579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, doubleG.invoke(null, Double.NaN, Double.NaN)); 1480579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, doubleG.invoke(null, Double.NaN, Double.POSITIVE_INFINITY)); 1481579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 14820e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Method doubleL = floatingPointCompareMethod(TypeId.DOUBLE, -1); 1483579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, doubleL.invoke(null, 1.0, Double.POSITIVE_INFINITY)); 1484579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, doubleL.invoke(null, 1.0, 2.0)); 1485579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, doubleL.invoke(null, 1.0, 1.0)); 1486579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, doubleL.invoke(null, 2.0, 1.0)); 1487579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, doubleL.invoke(null, 1.0, Double.NaN)); 1488579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, doubleL.invoke(null, Double.NaN, 1.0)); 1489579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, doubleL.invoke(null, Double.NaN, Double.NaN)); 1490579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, doubleL.invoke(null, Double.NaN, Double.POSITIVE_INFINITY)); 1491579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1492579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1493579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private <T extends Number> Method floatingPointCompareMethod( 14940e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId<T> valueType, int nanValue) throws Exception { 1495579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1496579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static int call(float a, float b) { 1497579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int result = a <=> b; 1498579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 1499579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1500579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1501579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson reset(); 15020e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Integer> methodId = GENERATED.getMethod( 15030e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson TypeId.INT, "call", valueType, valueType); 1504ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 1505579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<T> localA = code.getParameter(0, valueType); 1506579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<T> localB = code.getParameter(1, valueType); 15070e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localResult = code.newLocal(TypeId.INT); 1508d6c77efc0b187577dd7956070adfc7c335f65698Jesse Wilson code.compareFloatingPoint(localResult, localA, localB, nanValue); 1509579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 1510579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return getMethod(); 1511579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1512579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1513579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testLongCompare() throws Exception { 1514579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1515579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static int call(long a, long b) { 1516579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int result = a <=> b; 1517579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 1518579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1519579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 15200e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Integer> methodId = GENERATED.getMethod(TypeId.INT, "call", TypeId.LONG, TypeId.LONG); 1521ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 15220e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Long> localA = code.getParameter(0, TypeId.LONG); 15230e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Long> localB = code.getParameter(1, TypeId.LONG); 15240e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localResult = code.newLocal(TypeId.INT); 1525d6c77efc0b187577dd7956070adfc7c335f65698Jesse Wilson code.compareLongs(localResult, localA, localB); 1526579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 1527579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1528579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method method = getMethod(); 1529579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, method.invoke(null, Long.MIN_VALUE, Long.MIN_VALUE)); 1530579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, method.invoke(null, Long.MIN_VALUE, 0)); 1531579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, method.invoke(null, Long.MIN_VALUE, Long.MAX_VALUE)); 1532579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, method.invoke(null, 0, Long.MIN_VALUE)); 1533579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, method.invoke(null, 0, 0)); 1534579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(-1, method.invoke(null, 0, Long.MAX_VALUE)); 1535579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, method.invoke(null, Long.MAX_VALUE, Long.MIN_VALUE)); 1536579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(1, method.invoke(null, Long.MAX_VALUE, 0)); 1537579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, method.invoke(null, Long.MAX_VALUE, Long.MAX_VALUE)); 1538579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1539579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1540579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testArrayLength() throws Exception { 1541579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method booleanArrayLength = arrayLengthMethod(BOOLEAN_ARRAY); 1542579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, booleanArrayLength.invoke(null, new Object[] { new boolean[0] })); 1543579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(5, booleanArrayLength.invoke(null, new Object[] { new boolean[5] })); 1544579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1545579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method intArrayLength = arrayLengthMethod(INT_ARRAY); 1546579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, intArrayLength.invoke(null, new Object[] { new int[0] })); 1547579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(5, intArrayLength.invoke(null, new Object[] { new int[5] })); 1548579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1549579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method longArrayLength = arrayLengthMethod(LONG_ARRAY); 1550242b6fb150cd9fc4e0b871b9595bc1bdd84cceabJesse Wilson assertEquals(0, longArrayLength.invoke(null, new Object[] { new long[0] })); 1551579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(5, longArrayLength.invoke(null, new Object[] { new long[5] })); 1552579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1553579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method objectArrayLength = arrayLengthMethod(OBJECT_ARRAY); 1554579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, objectArrayLength.invoke(null, new Object[] { new Object[0] })); 1555579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(5, objectArrayLength.invoke(null, new Object[] { new Object[5] })); 1556579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1557579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method long2dArrayLength = arrayLengthMethod(LONG_2D_ARRAY); 1558579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, long2dArrayLength.invoke(null, new Object[] { new long[0][0] })); 1559579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(5, long2dArrayLength.invoke(null, new Object[] { new long[5][10] })); 1560579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1561579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 15620e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson private <T> Method arrayLengthMethod(TypeId<T> valueType) throws Exception { 1563579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1564579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static int call(long[] array) { 1565579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * int result = array.length; 1566579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 1567579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1568579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1569579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson reset(); 15700e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, Integer> methodId = GENERATED.getMethod(TypeId.INT, "call", valueType); 1571ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 1572579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<T> localArray = code.getParameter(0, valueType); 15730e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localResult = code.newLocal(TypeId.INT); 15740e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.arrayLength(localResult, localArray); 1575579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 1576579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return getMethod(); 1577579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1578579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1579579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testNewArray() throws Exception { 1580579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method newBooleanArray = newArrayMethod(BOOLEAN_ARRAY); 1581579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[]", Arrays.toString((boolean[]) newBooleanArray.invoke(null, 0))); 1582579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[false, false, false]", 1583579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Arrays.toString((boolean[]) newBooleanArray.invoke(null, 3))); 1584579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1585579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method newIntArray = newArrayMethod(INT_ARRAY); 1586579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[]", Arrays.toString((int[]) newIntArray.invoke(null, 0))); 1587579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[0, 0, 0]", Arrays.toString((int[]) newIntArray.invoke(null, 3))); 1588579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1589579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method newLongArray = newArrayMethod(LONG_ARRAY); 1590579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[]", Arrays.toString((long[]) newLongArray.invoke(null, 0))); 1591579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[0, 0, 0]", Arrays.toString((long[]) newLongArray.invoke(null, 3))); 1592579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1593579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method newObjectArray = newArrayMethod(OBJECT_ARRAY); 1594579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[]", Arrays.toString((Object[]) newObjectArray.invoke(null, 0))); 1595579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[null, null, null]", 1596579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Arrays.toString((Object[]) newObjectArray.invoke(null, 3))); 1597579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1598579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method new2dLongArray = newArrayMethod(LONG_2D_ARRAY); 1599579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[]", Arrays.deepToString((long[][]) new2dLongArray.invoke(null, 0))); 1600579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[null, null, null]", 1601579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Arrays.deepToString((long[][]) new2dLongArray.invoke(null, 3))); 1602579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1603579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 16040e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson private <T> Method newArrayMethod(TypeId<T> valueType) throws Exception { 1605579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1606579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static long[] call(int length) { 1607579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * long[] result = new long[length]; 1608579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 1609579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1610579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1611579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson reset(); 16120e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson MethodId<?, T> methodId = GENERATED.getMethod(valueType, "call", TypeId.INT); 1613ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 16140e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localLength = code.getParameter(0, TypeId.INT); 1615579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<T> localResult = code.newLocal(valueType); 16160e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.newArray(localResult, localLength); 1617579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 1618579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return getMethod(); 1619579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1620579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1621579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void testReadAndWriteArray() throws Exception { 16220e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Method swapBooleanArray = arraySwapMethod(BOOLEAN_ARRAY, TypeId.BOOLEAN); 1623579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson boolean[] booleans = new boolean[3]; 1624579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(false, swapBooleanArray.invoke(null, booleans, 1, true)); 1625579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[false, true, false]", Arrays.toString(booleans)); 1626579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 16270e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Method swapIntArray = arraySwapMethod(INT_ARRAY, TypeId.INT); 1628579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int[] ints = new int[3]; 1629579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0, swapIntArray.invoke(null, ints, 1, 5)); 1630579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[0, 5, 0]", Arrays.toString(ints)); 1631579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 16320e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Method swapLongArray = arraySwapMethod(LONG_ARRAY, TypeId.LONG); 1633579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson long[] longs = new long[3]; 1634579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(0L, swapLongArray.invoke(null, longs, 1, 6L)); 1635579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[0, 6, 0]", Arrays.toString(longs)); 1636579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 16370e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Method swapObjectArray = arraySwapMethod(OBJECT_ARRAY, TypeId.OBJECT); 1638579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Object[] objects = new Object[3]; 1639579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(null, swapObjectArray.invoke(null, objects, 1, "X")); 1640579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[null, X, null]", Arrays.toString(objects)); 1641579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1642579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Method swapLong2dArray = arraySwapMethod(LONG_2D_ARRAY, LONG_ARRAY); 1643579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson long[][] longs2d = new long[3][]; 1644579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals(null, swapLong2dArray.invoke(null, longs2d, 1, new long[] { 7 })); 1645579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assertEquals("[null, [7], null]", Arrays.deepToString(longs2d)); 1646579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1647579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 16480e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson private <A, T> Method arraySwapMethod(TypeId<A> arrayType, TypeId<T> singleType) 1649579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throws Exception { 1650579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 1651579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * public static long swap(long[] array, int index, long newValue) { 1652579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * long result = array[index]; 1653579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * array[index] = newValue; 1654579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * return result; 1655579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * } 1656579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1657579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson reset(); 1658579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson MethodId<?, T> methodId = GENERATED.getMethod( 16590e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson singleType, "call", arrayType, TypeId.INT, singleType); 1660ab220f004db90fa94ef9349ca1adde5f89012e8dJesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 1661579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<A> localArray = code.getParameter(0, arrayType); 16620e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson Local<Integer> localIndex = code.getParameter(1, TypeId.INT); 1663579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<T> localNewValue = code.getParameter(2, singleType); 1664579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<T> localResult = code.newLocal(singleType); 16650e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.aget(localResult, localArray, localIndex); 1666579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.aput(localArray, localIndex, localNewValue); 1667579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnValue(localResult); 1668579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return getMethod(); 1669579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1670579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 16715624228626d7cdf206de25a6981ba8107be61057Jesse Wilson public void testSynchronizedFlagImpactsDeclarationOnly() throws Exception { 16725624228626d7cdf206de25a6981ba8107be61057Jesse Wilson /* 16735624228626d7cdf206de25a6981ba8107be61057Jesse Wilson * public synchronized void call() { 16745624228626d7cdf206de25a6981ba8107be61057Jesse Wilson * wait(100L); 16755624228626d7cdf206de25a6981ba8107be61057Jesse Wilson * } 16765624228626d7cdf206de25a6981ba8107be61057Jesse Wilson */ 16775624228626d7cdf206de25a6981ba8107be61057Jesse Wilson MethodId<?, Void> methodId = GENERATED.getMethod(TypeId.VOID, "call"); 16785624228626d7cdf206de25a6981ba8107be61057Jesse Wilson MethodId<Object, Void> wait = TypeId.OBJECT.getMethod(TypeId.VOID, "wait", TypeId.LONG); 16795624228626d7cdf206de25a6981ba8107be61057Jesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | SYNCHRONIZED); 16805624228626d7cdf206de25a6981ba8107be61057Jesse Wilson Local<?> thisLocal = code.getThis(GENERATED); 16815624228626d7cdf206de25a6981ba8107be61057Jesse Wilson Local<Long> timeout = code.newLocal(TypeId.LONG); 16825624228626d7cdf206de25a6981ba8107be61057Jesse Wilson code.loadConstant(timeout, 100L); 16835624228626d7cdf206de25a6981ba8107be61057Jesse Wilson code.invokeVirtual(wait, null, thisLocal, timeout); 16845624228626d7cdf206de25a6981ba8107be61057Jesse Wilson code.returnVoid(); 16855624228626d7cdf206de25a6981ba8107be61057Jesse Wilson 16865624228626d7cdf206de25a6981ba8107be61057Jesse Wilson addDefaultConstructor(); 16875624228626d7cdf206de25a6981ba8107be61057Jesse Wilson 16885624228626d7cdf206de25a6981ba8107be61057Jesse Wilson Class<?> generatedClass = generateAndLoad(); 16895624228626d7cdf206de25a6981ba8107be61057Jesse Wilson Object instance = generatedClass.newInstance(); 16905624228626d7cdf206de25a6981ba8107be61057Jesse Wilson Method method = generatedClass.getMethod("call"); 16915624228626d7cdf206de25a6981ba8107be61057Jesse Wilson assertTrue(Modifier.isSynchronized(method.getModifiers())); 16925624228626d7cdf206de25a6981ba8107be61057Jesse Wilson try { 16935624228626d7cdf206de25a6981ba8107be61057Jesse Wilson method.invoke(instance); 16945624228626d7cdf206de25a6981ba8107be61057Jesse Wilson fail(); 16955624228626d7cdf206de25a6981ba8107be61057Jesse Wilson } catch (InvocationTargetException expected) { 16965624228626d7cdf206de25a6981ba8107be61057Jesse Wilson assertTrue(expected.getCause() instanceof IllegalMonitorStateException); 16975624228626d7cdf206de25a6981ba8107be61057Jesse Wilson } 16985624228626d7cdf206de25a6981ba8107be61057Jesse Wilson } 16995624228626d7cdf206de25a6981ba8107be61057Jesse Wilson 17005624228626d7cdf206de25a6981ba8107be61057Jesse Wilson public void testMonitorEnterMonitorExit() throws Exception { 17015624228626d7cdf206de25a6981ba8107be61057Jesse Wilson /* 17025624228626d7cdf206de25a6981ba8107be61057Jesse Wilson * public synchronized void call() { 17035624228626d7cdf206de25a6981ba8107be61057Jesse Wilson * synchronized (this) { 17045624228626d7cdf206de25a6981ba8107be61057Jesse Wilson * wait(100L); 17055624228626d7cdf206de25a6981ba8107be61057Jesse Wilson * } 17065624228626d7cdf206de25a6981ba8107be61057Jesse Wilson * } 17075624228626d7cdf206de25a6981ba8107be61057Jesse Wilson */ 17085624228626d7cdf206de25a6981ba8107be61057Jesse Wilson MethodId<?, Void> methodId = GENERATED.getMethod(TypeId.VOID, "call"); 17095624228626d7cdf206de25a6981ba8107be61057Jesse Wilson MethodId<Object, Void> wait = TypeId.OBJECT.getMethod(TypeId.VOID, "wait", TypeId.LONG); 17105624228626d7cdf206de25a6981ba8107be61057Jesse Wilson Code code = dexMaker.declare(methodId, PUBLIC); 17115624228626d7cdf206de25a6981ba8107be61057Jesse Wilson Local<?> thisLocal = code.getThis(GENERATED); 17125624228626d7cdf206de25a6981ba8107be61057Jesse Wilson Local<Long> timeout = code.newLocal(TypeId.LONG); 17135624228626d7cdf206de25a6981ba8107be61057Jesse Wilson code.monitorEnter(thisLocal); 17145624228626d7cdf206de25a6981ba8107be61057Jesse Wilson code.loadConstant(timeout, 100L); 17155624228626d7cdf206de25a6981ba8107be61057Jesse Wilson code.invokeVirtual(wait, null, thisLocal, timeout); 17165624228626d7cdf206de25a6981ba8107be61057Jesse Wilson code.monitorExit(thisLocal); 17175624228626d7cdf206de25a6981ba8107be61057Jesse Wilson code.returnVoid(); 17185624228626d7cdf206de25a6981ba8107be61057Jesse Wilson 17195624228626d7cdf206de25a6981ba8107be61057Jesse Wilson addDefaultConstructor(); 17205624228626d7cdf206de25a6981ba8107be61057Jesse Wilson 17215624228626d7cdf206de25a6981ba8107be61057Jesse Wilson Class<?> generatedClass = generateAndLoad(); 17225624228626d7cdf206de25a6981ba8107be61057Jesse Wilson Object instance = generatedClass.newInstance(); 17235624228626d7cdf206de25a6981ba8107be61057Jesse Wilson Method method = generatedClass.getMethod("call"); 17245624228626d7cdf206de25a6981ba8107be61057Jesse Wilson assertFalse(Modifier.isSynchronized(method.getModifiers())); 17255624228626d7cdf206de25a6981ba8107be61057Jesse Wilson method.invoke(instance); // will take 100ms 17265624228626d7cdf206de25a6981ba8107be61057Jesse Wilson } 17275624228626d7cdf206de25a6981ba8107be61057Jesse Wilson 17284838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson public void testMoveInt() throws Exception { 17294838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson /* 17304838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson * public static int call(int a) { 17314838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson * int b = a; 17324838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson * int c = a + b; 17334838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson * return c; 17344838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson * } 17354838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson */ 17364838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson MethodId<?, Integer> methodId = GENERATED.getMethod(TypeId.INT, "call", TypeId.INT); 17374838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 17384838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson Local<Integer> a = code.getParameter(0, TypeId.INT); 17394838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson Local<Integer> b = code.newLocal(TypeId.INT); 17404838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson Local<Integer> c = code.newLocal(TypeId.INT); 17414838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson code.move(b, a); 17424838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson code.op(BinaryOp.ADD, c, a, b); 17434838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson code.returnValue(c); 17444838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson 17454838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson assertEquals(6, getMethod().invoke(null, 3)); 17464838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson } 17474838105a39ae6c608c2a0e242ead249d8683a5d0Jesse Wilson 1748c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson public void testPrivateClassesAreUnsupported() { 1749c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson try { 1750c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson dexMaker.declare(TypeId.get("LPrivateClass;"), "PrivateClass.generated", PRIVATE, 1751c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson TypeId.OBJECT); 1752c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson fail(); 1753c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } catch (IllegalArgumentException expected) { 1754c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } 1755c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } 1756c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson 1757c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson public void testAbstractMethodsAreUnsupported() { 1758c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson MethodId<?, Void> methodId = GENERATED.getMethod(TypeId.VOID, "call"); 1759c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson try { 1760c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson dexMaker.declare(methodId, ABSTRACT); 1761c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson fail(); 1762c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } catch (IllegalArgumentException expected) { 1763c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } 1764c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } 1765c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson 1766c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson public void testNativeMethodsAreUnsupported() { 1767c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson MethodId<?, Void> methodId = GENERATED.getMethod(TypeId.VOID, "call"); 1768c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson try { 1769c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson dexMaker.declare(methodId, NATIVE); 1770c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson fail(); 1771c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } catch (IllegalArgumentException expected) { 1772c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } 1773c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } 1774c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson 1775c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson public void testSynchronizedFieldsAreUnsupported() { 1776c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson try { 1777c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson FieldId<?, ?> fieldId = GENERATED.getField(TypeId.OBJECT, "synchronizedField"); 1778c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson dexMaker.declare(fieldId, SYNCHRONIZED, null); 1779c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson fail(); 1780c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } catch (IllegalArgumentException expected) { 1781c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } 1782c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } 1783c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson 1784c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson public void testInitialValueWithNonStaticField() { 1785c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson try { 1786c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson FieldId<?, ?> fieldId = GENERATED.getField(TypeId.OBJECT, "nonStaticField"); 1787c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson dexMaker.declare(fieldId, 0, 1); 1788c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson fail(); 1789c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } catch (IllegalArgumentException expected) { 1790c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } 1791c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson } 1792c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson 179397b0be6b3da9df87e9026f880b0b0bffc7242450Jesse Wilson // TODO: cast primitive to non-primitive 179497b0be6b3da9df87e9026f880b0b0bffc7242450Jesse Wilson // TODO: cast non-primitive to primitive 179597b0be6b3da9df87e9026f880b0b0bffc7242450Jesse Wilson // TODO: cast byte to integer 179697b0be6b3da9df87e9026f880b0b0bffc7242450Jesse Wilson // TODO: cast byte to long 179797b0be6b3da9df87e9026f880b0b0bffc7242450Jesse Wilson // TODO: cast long to byte 1798579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // TODO: fail if a label is unreachable (never navigated to) 1799579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // TODO: more strict type parameters: Integer on methods 1800579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // TODO: don't generate multiple times (?) 180197b0be6b3da9df87e9026f880b0b0bffc7242450Jesse Wilson // TODO: test array types 180297b0be6b3da9df87e9026f880b0b0bffc7242450Jesse Wilson // TODO: test generating an interface 180323abc2fe89ec3713645d64bdb74415a9090084f4Jesse Wilson // TODO: declare native method or abstract method 1804d6c77efc0b187577dd7956070adfc7c335f65698Jesse Wilson // TODO: get a thrown exception 'e' into a local 1805d6c77efc0b187577dd7956070adfc7c335f65698Jesse Wilson // TODO: move a primitive or reference 1806d6c77efc0b187577dd7956070adfc7c335f65698Jesse Wilson 1807579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private void addDefaultConstructor() { 1808c0271e9981ddd85a13ed88defd0b5b1a5ccc6f46Jesse Wilson Code code = dexMaker.declare(GENERATED.getConstructor(), PUBLIC); 1809579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Local<?> thisRef = code.getThis(GENERATED); 18100e49fb9243b7463835ab80ef7cc62435f55846ceJesse Wilson code.invokeDirect(TypeId.OBJECT.getConstructor(), null, thisRef); 1811579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson code.returnVoid(); 1812579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 1813579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 1814054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void testCaching_Methods() throws Exception { 1815054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef int origSize = getDataDirectory().listFiles().length; 1816054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef final String defaultMethodName = "call"; 1817054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1818054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1819054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1820054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.INT); 1821054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1822054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // DexMaker writes two files to disk at a time: Generated_XXXX.jar and Generated_XXXX.dex. 1823054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 2, getDataDirectory().listFiles().length); 1824054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1825054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef long lastModified = getJarFiles()[0].lastModified(); 1826054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1827054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Create new dexmaker generator with same method signature. 1828054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1829054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1830054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.INT); 1831054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1832054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 2, getDataDirectory().listFiles().length); 1833054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(lastModified, getJarFiles()[0].lastModified()); 1834054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1835054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Create new dexmaker generators with different params. 1836054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1837054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1838054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.DOUBLE); 1839054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1840054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 4, getDataDirectory().listFiles().length); 1841054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1842054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1843054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1844054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.INT, TypeId.DOUBLE); 1845054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1846054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 6, getDataDirectory().listFiles().length); 1847054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1848054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Create new dexmaker generator with different return types. 1849054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1850054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1851054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.DOUBLE, defaultMethodName, TypeId.INT); 1852054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1853054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 8, getDataDirectory().listFiles().length); 1854054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1855054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Create new dexmaker generators with multiple methods. 1856054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1857054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1858054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.INT); 1859054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.INT, TypeId.BOOLEAN); // new method 1860054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1861054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 10, getDataDirectory().listFiles().length); 1862054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1863054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1864054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1865054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.INT, TypeId.BOOLEAN); 1866054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.INT); 1867054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1868054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 10, getDataDirectory().listFiles().length); // should already be cached. 1869054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1870054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1871054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1872054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.INT); 1873054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.INT, TypeId.INT, TypeId.BOOLEAN); // new method 1874054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1875054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 12, getDataDirectory().listFiles().length); 1876054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1877054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1878054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1879054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.INT); 1880054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.INT, TypeId.INT); // new method 1881054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1882054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 14, getDataDirectory().listFiles().length); 1883054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1884054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1885054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1886054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, "differentName", TypeId.INT); // new method 1887054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.INT, TypeId.BOOLEAN); 1888054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1889054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 16, getDataDirectory().listFiles().length); 1890054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1891054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1892054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public static class BlankClassA { 1893054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1894054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1895054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1896054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public static class BlankClassB { 1897054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1898054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1899054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1900054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void testCaching_DifferentParentClasses() throws Exception { 1901054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef int origSize = getDataDirectory().listFiles().length; 1902054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef final String defaultMethodName = "call"; 1903054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1904054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Create new dexmaker generator with BlankClassA as supertype. 1905054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1906054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.get(BlankClassA.class)); 1907054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.INT); 1908054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1909054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // DexMaker writes two files to disk at a time: Generated_XXXX.jar and Generated_XXXX.dex. 1910054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 2, getDataDirectory().listFiles().length); 1911054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1912054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Create new dexmaker generator with BlankClassB as supertype. 1913054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1914054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.get(BlankClassB.class)); 1915054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addMethodToDexMakerGenerator(TypeId.INT, defaultMethodName, TypeId.INT); 1916054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1917054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 4, getDataDirectory().listFiles().length); 1918054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1919054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1920054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1921054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef private void addMethodToDexMakerGenerator(TypeId<?> typeId, String methodName, TypeId<?>... params) throws Exception { 1922054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef MethodId<?, ?> methodId = GENERATED.getMethod(typeId, methodName, params); 1923054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Code code = dexMaker.declare(methodId, PUBLIC | STATIC); 1924054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef TypeId<IllegalStateException> iseType = TypeId.get(IllegalStateException.class); 1925054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Local<IllegalStateException> localIse = code.newLocal(iseType); 1926054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef if (params.length > 0) { 1927054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef if (params[0] == typeId) { 1928054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Local<?> localResult = code.getParameter(0, TypeId.INT); 1929054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef code.returnValue(localResult); 1930054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } else { 1931054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef code.throwValue(localIse); 1932054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1933054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } else { 1934054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef code.throwValue(localIse); 1935054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1936054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1937054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1938054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public void testCaching_Constructors() throws Exception { 1939054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef int origSize = getDataDirectory().listFiles().length; 1940054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1941054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Create new dexmaker generator with Generated(int) constructor. 1942054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1943054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1944054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addConstructorToDexMakerGenerator(TypeId.INT); 1945054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1946054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // DexMaker writes two files to disk at a time: Generated_XXXX.jar and Generated_XXXX.dex. 1947054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 2, getDataDirectory().listFiles().length); 1948054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1949054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef long lastModified = getJarFiles()[0].lastModified(); 1950054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1951054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1952054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1953054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addConstructorToDexMakerGenerator(TypeId.INT); 1954054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1955054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 2, getDataDirectory().listFiles().length); 1956054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(lastModified, getJarFiles()[0].lastModified()); 1957054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1958054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Create new dexmaker generator with Generated(boolean) constructor. 1959054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1960054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1961054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addConstructorToDexMakerGenerator(TypeId.BOOLEAN); 1962054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1963054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 4, getDataDirectory().listFiles().length); 1964054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1965054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Create new dexmaker generator with multiple constructors. 1966054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1967054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1968054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addConstructorToDexMakerGenerator(TypeId.INT); 1969054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addConstructorToDexMakerGenerator(TypeId.BOOLEAN); 1970054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1971054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 6, getDataDirectory().listFiles().length); 1972054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1973054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef // Ensure that order of constructors does not affect caching decision. 1974054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker = new DexMaker(); 1975054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef dexMaker.declare(GENERATED, "Generated.java", PUBLIC, TypeId.OBJECT); 1976054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addConstructorToDexMakerGenerator(TypeId.BOOLEAN); 1977054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef addConstructorToDexMakerGenerator(TypeId.INT); 1978054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef generateAndLoad(); 1979054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef assertEquals(origSize + 6, getDataDirectory().listFiles().length); 1980054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1981054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1982054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef private void addConstructorToDexMakerGenerator(TypeId<?>... params) throws Exception { 1983054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef MethodId<?, Void> constructor = GENERATED.getConstructor(params); 1984054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef Code code = dexMaker.declare(constructor, PUBLIC); 1985054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef code.returnVoid(); 1986054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1987054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1988054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef private File[] getJarFiles() { 1989054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return getDataDirectory().listFiles(new FilenameFilter() { 1990054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef public boolean accept(File dir, String name) { 1991054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef return name.endsWith(".jar"); 1992054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1993054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef }); 1994054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef } 1995054604d4c95cb530bea955718d79dbe3dc0962cfAndrew Yousef 1996579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 1997579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns the generated method. 1998579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 1999579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private Method getMethod() throws Exception { 2000b3b96215f3dcbacb3f0d86780ac635cfc14ae9cfJesse Wilson Class<?> generated = generateAndLoad(); 2001579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (Method method : generated.getMethods()) { 2002579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (method.getName().equals("call")) { 2003579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return method; 2004579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 2005579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 2006579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IllegalStateException("no call() method"); 2007579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 2008579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 20097ff2c5291c7e0840ef62842372df0c2ecd5979f4Andrew Yousef public static File getDataDirectory() { 20107ff2c5291c7e0840ef62842372df0c2ecd5979f4Andrew Yousef String envVariable = "ANDROID_DATA"; 20117ff2c5291c7e0840ef62842372df0c2ecd5979f4Andrew Yousef String defaultLoc = "/data"; 20127ff2c5291c7e0840ef62842372df0c2ecd5979f4Andrew Yousef String path = System.getenv(envVariable); 20137ff2c5291c7e0840ef62842372df0c2ecd5979f4Andrew Yousef return path == null ? new File(defaultLoc) : new File(path); 2014579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 2015579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 2016b3b96215f3dcbacb3f0d86780ac635cfc14ae9cfJesse Wilson private Class<?> generateAndLoad() throws Exception { 2017ff314e1f06b974be78de3356a71072dbf0a450cdJesse Wilson return dexMaker.generateAndLoad(getClass().getClassLoader(), getDataDirectory()) 2018ff314e1f06b974be78de3356a71072dbf0a450cdJesse Wilson .loadClass("Generated"); 2019579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 2020579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 2021