diff options
Diffstat (limited to 'dx')
73 files changed, 156 insertions, 7200 deletions
diff --git a/dx/Android.mk b/dx/Android.mk index 3abf21af8..b31b23b3b 100644 --- a/dx/Android.mk +++ b/dx/Android.mk @@ -67,6 +67,7 @@ INTERNAL_DALVIK_MODULES += $(LOCAL_INSTALLED_MODULE) # the other stuff # ============================================================ subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \ + junit-tests \ src \ )) diff --git a/dx/junit-tests/Android.mk b/dx/junit-tests/Android.mk new file mode 100644 index 000000000..e1f3c4182 --- /dev/null +++ b/dx/junit-tests/Android.mk @@ -0,0 +1,10 @@ +# Copyright 2011 The Android Open Source Project + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(call all-subdir-java-files) +LOCAL_JAVA_LIBRARIES := dx junit +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_TAGS := tests +LOCAL_MODULE:= dx-tests +include $(BUILD_HOST_JAVA_LIBRARY) diff --git a/dx/junit-tests/HelloWorldMaker.java b/dx/junit-tests/HelloWorldMaker.java deleted file mode 100644 index 001f31a90..000000000 --- a/dx/junit-tests/HelloWorldMaker.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import com.android.dx.gen.BinaryOp; -import com.android.dx.gen.Code; -import com.android.dx.gen.DexGenerator; -import com.android.dx.gen.FieldId; -import com.android.dx.gen.Local; -import com.android.dx.gen.MethodId; -import com.android.dx.gen.Type; -import com.android.dx.rop.code.AccessFlags; -import java.io.PrintStream; - -public class HelloWorldMaker { - private static final Type<PrintStream> PRINT_STREAM = Type.get(PrintStream.class); - private static final FieldId<System, PrintStream> SYSTEM_OUT - = Type.get(System.class).getField(PRINT_STREAM, "out"); - private static final MethodId<Integer, String> TO_HEX_STRING - = Type.get(Integer.class).getMethod(Type.STRING, "toHexString", Type.INT); - private static final MethodId<PrintStream, Void> PRINTLN - = PRINT_STREAM.getMethod(Type.VOID, "println", Type.STRING); - - public static void main(String[] args) throws Exception { - - /* - * This code generates Dalvik bytecode equivalent to the following - * program. - * - * public class HelloWorld { - * public static void hello() { - * int a = 0xabcd; - * int b = 0xaaaa; - * int c = a - b; - * String s = Integer.toHexString(c); - * System.out.println(s); - * } - * } - */ - - DexGenerator generator = new DexGenerator(); - - // lookup the symbols of interest - Type<?> helloWorld = Type.get("LHelloWorld;"); - MethodId hello = helloWorld.getMethod(Type.VOID, "hello"); - - // create some registers - // (I'd like a better syntax for this) - Code code = generator.declare(hello, AccessFlags.ACC_STATIC | AccessFlags.ACC_PUBLIC); - Local<Integer> a = code.newLocal(Type.INT); - Local<Integer> b = code.newLocal(Type.INT); - Local<Integer> c = code.newLocal(Type.INT); - Local<String> s = code.newLocal(Type.STRING); - Local<PrintStream> localSystemOut = code.newLocal(PRINT_STREAM); - - // specify the code instruction-by-instruction (approximately) - code.loadConstant(a, 0xabcd); - code.loadConstant(b, 0xaaaa); - code.op(BinaryOp.SUBTRACT, c, a, b); - code.invokeStatic(TO_HEX_STRING, s, c); - code.sget(SYSTEM_OUT, localSystemOut); - code.invokeVirtual(PRINTLN, null, localSystemOut, s); - code.returnVoid(); - - // TODO: create the constructor - - generator.declare(helloWorld, "Generated.java", AccessFlags.ACC_PUBLIC, Type.OBJECT); - - // load the dex - ClassLoader loader = generator.load(HelloWorldMaker.class.getClassLoader()); - Class<?> helloWorldClass = loader.loadClass("HelloWorld"); - helloWorldClass.getMethod("hello").invoke(null); - } -} diff --git a/dx/junit-tests/com/android/dx/gen/DexGeneratorTest.java b/dx/junit-tests/com/android/dx/gen/DexGeneratorTest.java deleted file mode 100644 index 99eea855e..000000000 --- a/dx/junit-tests/com/android/dx/gen/DexGeneratorTest.java +++ /dev/null @@ -1,1628 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.gen; - -import static com.android.dx.rop.code.AccessFlags.ACC_CONSTRUCTOR; -import static com.android.dx.rop.code.AccessFlags.ACC_FINAL; -import static com.android.dx.rop.code.AccessFlags.ACC_PRIVATE; -import static com.android.dx.rop.code.AccessFlags.ACC_PROTECTED; -import static com.android.dx.rop.code.AccessFlags.ACC_PUBLIC; -import static com.android.dx.rop.code.AccessFlags.ACC_STATIC; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.Callable; -import junit.framework.TestCase; - -/** - * This generates a class named 'Generated' with one or more generated methods - * and fields. In loads the generated class into the current VM and uses - * reflection to invoke its methods. - * - * <p>This test must run on a Dalvik VM. - */ -public final class DexGeneratorTest extends TestCase { - private DexGenerator generator; - private static Type<DexGeneratorTest> TEST_TYPE = Type.get(DexGeneratorTest.class); - private static Type<?> INT_ARRAY = Type.get(int[].class); - private static Type<boolean[]> BOOLEAN_ARRAY = Type.get(boolean[].class); - private static Type<long[]> LONG_ARRAY = Type.get(long[].class); - private static Type<Object[]> OBJECT_ARRAY = Type.get(Object[].class); - private static Type<long[][]> LONG_2D_ARRAY = Type.get(long[][].class); - private static Type<?> GENERATED = Type.get("LGenerated;"); - private static Type<Callable> CALLABLE = Type.get(Callable.class); - private static MethodId<Callable, Object> CALL = CALLABLE.getMethod(Type.OBJECT, "call"); - - @Override protected void setUp() throws Exception { - super.setUp(); - reset(); - } - - /** - * The generator is mutable. Calling reset creates a new empty generator. - * This is necessary to generate multiple classes in the same test method. - */ - private void reset() { - generator = new DexGenerator(); - generator.declare(GENERATED, "Generated.java", ACC_PUBLIC, Type.OBJECT); - } - - public void testNewInstance() throws Exception { - /* - * public static Constructable call(long a, boolean b) { - * Constructable result = new Constructable(a, b); - * return result; - * } - */ - Type<Constructable> constructable = Type.get(Constructable.class); - MethodId<?, Constructable> methodId = GENERATED.getMethod( - constructable, "call", Type.LONG, Type.BOOLEAN); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Long> localA = code.getParameter(0, Type.LONG); - Local<Boolean> localB = code.getParameter(1, Type.BOOLEAN); - MethodId<Constructable, Void> constructor - = constructable.getConstructor(Type.LONG, Type.BOOLEAN); - Local<Constructable> localResult = code.newLocal(constructable); - code.newInstance(localResult, constructor, localA, localB); - code.returnValue(localResult); - - Constructable constructed = (Constructable) getMethod().invoke(null, 5L, false); - assertEquals(5L, constructed.a); - assertEquals(false, constructed.b); - } - - public static class Constructable { - private final long a; - private final boolean b; - public Constructable(long a, boolean b) { - this.a = a; - this.b = b; - } - } - - public void testInvokeStatic() throws Exception { - /* - * public static int call(int a) { - * int result = DexGeneratorTest.staticMethod(a); - * return result; - * } - */ - MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", Type.INT); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Integer> localA = code.getParameter(0, Type.INT); - Local<Integer> localResult = code.newLocal(Type.INT); - MethodId<?, Integer> staticMethod - = TEST_TYPE.getMethod(Type.INT, "staticMethod", Type.INT); - code.invokeStatic(staticMethod, localResult, localA); - code.returnValue(localResult); - - assertEquals(10, getMethod().invoke(null, 4)); - } - - @SuppressWarnings("unused") // called by generated code - public static int staticMethod(int a) { - return a + 6; - } - - public void testInvokeVirtual() throws Exception { - /* - * public static int call(DexGeneratorTest test, int a) { - * int result = test.virtualMethod(a); - * return result; - * } - */ - MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", TEST_TYPE, Type.INT); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<DexGeneratorTest> localInstance = code.getParameter(0, TEST_TYPE); - Local<Integer> localA = code.getParameter(1, Type.INT); - Local<Integer> localResult = code.newLocal(Type.INT); - MethodId<DexGeneratorTest, Integer> virtualMethod - = TEST_TYPE.getMethod(Type.INT, "virtualMethod", Type.INT); - code.invokeVirtual(virtualMethod, localResult, localInstance, localA); - code.returnValue(localResult); - - assertEquals(9, getMethod().invoke(null, this, 4)); - } - - @SuppressWarnings("unused") // called by generated code - public int virtualMethod(int a) { - return a + 5; - } - - public <G> void testInvokeDirect() throws Exception { - /* - * private int directMethod() { - * int a = 5; - * return a; - * } - * - * public static int call(Generated g) { - * int b = g.directMethod(); - * return b; - * } - */ - Type<G> generated = Type.get("LGenerated;"); - MethodId<G, Integer> directMethodId = generated.getMethod(Type.INT, "directMethod"); - Code directCode = generator.declare(directMethodId, ACC_PRIVATE); - directCode.getThis(generated); // 'this' is unused - Local<Integer> localA = directCode.newLocal(Type.INT); - directCode.loadConstant(localA, 5); - directCode.returnValue(localA); - - MethodId<G, Integer> methodId = generated.getMethod(Type.INT, "call", generated); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Integer> localB = code.newLocal(Type.INT); - Local<G> localG = code.getParameter(0, generated); - code.invokeDirect(directMethodId, localB, localG); - code.returnValue(localB); - - addDefaultConstructor(); - - Class<?> generatedClass = loadAndGenerate(); - Object instance = generatedClass.newInstance(); - Method method = generatedClass.getMethod("call", generatedClass); - assertEquals(5, method.invoke(null, instance)); - } - - public <G> void testInvokeSuper() throws Exception { - /* - * public int superHashCode() { - * int result = super.hashCode(); - * return result; - * } - * public int hashCode() { - * return 0; - * } - */ - Type<G> generated = Type.get("LGenerated;"); - MethodId<Object, Integer> objectHashCode = Type.OBJECT.getMethod(Type.INT, "hashCode"); - Code superHashCode = generator.declare( - GENERATED.getMethod(Type.INT, "superHashCode"), ACC_PUBLIC); - Local<Integer> localResult = superHashCode.newLocal(Type.INT); - Local<G> localThis = superHashCode.getThis(generated); - superHashCode.invokeSuper(objectHashCode, localResult, localThis); - superHashCode.returnValue(localResult); - - Code generatedHashCode = generator.declare( - GENERATED.getMethod(Type.INT, "hashCode"), ACC_PUBLIC); - Local<Integer> localZero = generatedHashCode.newLocal(Type.INT); - generatedHashCode.loadConstant(localZero, 0); - generatedHashCode.returnValue(localZero); - - addDefaultConstructor(); - - Class<?> generatedClass = loadAndGenerate(); - Object instance = generatedClass.newInstance(); - Method method = generatedClass.getMethod("superHashCode"); - assertEquals(System.identityHashCode(instance), method.invoke(instance)); - } - - @SuppressWarnings("unused") // called by generated code - public int superMethod(int a) { - return a + 4; - } - - public void testInvokeInterface() throws Exception { - /* - * public static Object call(Callable c) { - * Object result = c.call(); - * return result; - * } - */ - MethodId<?, Object> methodId = GENERATED.getMethod(Type.OBJECT, "call", CALLABLE); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Callable> localC = code.getParameter(0, CALLABLE); - Local<Object> localResult = code.newLocal(Type.OBJECT); - code.invokeInterface(CALL, localResult, localC); - code.returnValue(localResult); - - Callable<Object> callable = new Callable<Object>() { - public Object call() throws Exception { - return "abc"; - } - }; - assertEquals("abc", getMethod().invoke(null, callable)); - } - - public void testParameterMismatch() throws Exception { - Type<?>[] argTypes = { - Type.get(Integer.class), // should fail because the code specifies int - Type.OBJECT, - }; - MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", argTypes); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - try { - code.getParameter(0, Type.INT); - } catch (IllegalArgumentException e) { - } - try { - code.getParameter(2, Type.INT); - } catch (IndexOutOfBoundsException e) { - } - } - - public void testInvokeTypeSafety() throws Exception { - /* - * public static boolean call(DexGeneratorTest test) { - * CharSequence cs = test.toString(); - * boolean result = cs.equals(test); - * return result; - * } - */ - MethodId<?, Boolean> methodId = GENERATED.getMethod(Type.BOOLEAN, "call", TEST_TYPE); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<DexGeneratorTest> localTest = code.getParameter(0, TEST_TYPE); - Type<CharSequence> charSequenceType = Type.get(CharSequence.class); - MethodId<Object, String> objectToString = Type.OBJECT.getMethod(Type.STRING, "toString"); - MethodId<Object, Boolean> objectEquals - = Type.OBJECT.getMethod(Type.BOOLEAN, "equals", Type.OBJECT); - Local<CharSequence> localCs = code.newLocal(charSequenceType); - Local<Boolean> localResult = code.newLocal(Type.BOOLEAN); - code.invokeVirtual(objectToString, localCs, localTest); - code.invokeVirtual(objectEquals, localResult, localCs, localTest); - code.returnValue(localResult); - - assertEquals(false, getMethod().invoke(null, this)); - } - - public void testReturnTypeMismatch() { - MethodId<?, String> methodId = GENERATED.getMethod(Type.STRING, "call"); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - try { - code.returnValue(code.newLocal(Type.BOOLEAN)); - fail(); - } catch (IllegalArgumentException expected) { - } - try { - code.returnVoid(); - fail(); - } catch (IllegalArgumentException expected) { - } - } - - public void testDeclareStaticFields() throws Exception { - /* - * class Generated { - * public static int a; - * protected static Object b; - * } - */ - generator.declare(GENERATED.getField(Type.INT, "a"), ACC_PUBLIC | ACC_STATIC, 3); - generator.declare(GENERATED.getField(Type.OBJECT, "b"), ACC_PROTECTED | ACC_STATIC, null); - Class<?> generatedClass = loadAndGenerate(); - - Field a = generatedClass.getField("a"); - assertEquals(int.class, a.getType()); - assertEquals(3, a.get(null)); - - Field b = generatedClass.getDeclaredField("b"); - assertEquals(Object.class, b.getType()); - b.setAccessible(true); - assertEquals(null, b.get(null)); - } - - public void testDeclareInstanceFields() throws Exception { - /* - * class Generated { - * public int a; - * protected Object b; - * } - */ - generator.declare(GENERATED.getField(Type.INT, "a"), ACC_PUBLIC, null); - generator.declare(GENERATED.getField(Type.OBJECT, "b"), ACC_PROTECTED, null); - - addDefaultConstructor(); - - Class<?> generatedClass = loadAndGenerate(); - Object instance = generatedClass.newInstance(); - - Field a = generatedClass.getField("a"); - assertEquals(int.class, a.getType()); - assertEquals(0, a.get(instance)); - - Field b = generatedClass.getDeclaredField("b"); - assertEquals(Object.class, b.getType()); - b.setAccessible(true); - assertEquals(null, b.get(instance)); - } - - /** - * Declare a constructor that takes an int parameter and assigns it to a - * field. - */ - public <G> void testDeclareConstructor() throws Exception { - /* - * class Generated { - * public final int a; - * public Generated(int a) { - * this.a = a; - * } - * } - */ - Type<G> generated = Type.get("LGenerated;"); - FieldId<G, Integer> fieldId = generated.getField(Type.INT, "a"); - generator.declare(fieldId, ACC_PUBLIC | ACC_FINAL, null); - MethodId<?, Void> constructor = GENERATED.getConstructor(Type.INT); - Code code = generator.declare(constructor, ACC_PUBLIC | ACC_CONSTRUCTOR); - Local<G> thisRef = code.getThis(generated); - Local<Integer> parameter = code.getParameter(0, Type.INT); - code.invokeDirect(Type.OBJECT.getConstructor(), null, thisRef); - code.iput(fieldId, thisRef, parameter); - code.returnVoid(); - - Class<?> generatedClass = loadAndGenerate(); - Field a = generatedClass.getField("a"); - Object instance = generatedClass.getConstructor(int.class).newInstance(0xabcd); - assertEquals(0xabcd, a.get(instance)); - } - - public void testReturnBoolean() throws Exception { - testReturnType(boolean.class, true); - testReturnType(byte.class, (byte) 5); - testReturnType(char.class, 'E'); - testReturnType(double.class, 5.0); - testReturnType(float.class, 5.0f); - testReturnType(int.class, 5); - testReturnType(long.class, 5L); - testReturnType(short.class, (short) 5); - testReturnType(void.class, null); - testReturnType(String.class, "foo"); - testReturnType(Class.class, List.class); - } - - private <T> void testReturnType(Class<T> javaType, T value) throws Exception { - /* - * public int call() { - * int a = 5; - * return a; - * } - */ - reset(); - Type<T> returnType = Type.get(javaType); - Code code = generator.declare(GENERATED.getMethod(returnType, "call"), - ACC_PUBLIC | ACC_STATIC); - if (value != null) { - Local<T> i = code.newLocal(returnType); - code.loadConstant(i, value); - code.returnValue(i); - } else { - code.returnVoid(); - } - - Class<?> generatedClass = loadAndGenerate(); - Method method = generatedClass.getMethod("call"); - assertEquals(javaType, method.getReturnType()); - assertEquals(value, method.invoke(null)); - } - - public void testBranching() throws Exception { - Method lt = branchingMethod(Comparison.LT); - assertEquals(Boolean.TRUE, lt.invoke(null, 1, 2)); - assertEquals(Boolean.FALSE, lt.invoke(null, 1, 1)); - assertEquals(Boolean.FALSE, lt.invoke(null, 2, 1)); - - Method le = branchingMethod(Comparison.LE); - assertEquals(Boolean.TRUE, le.invoke(null, 1, 2)); - assertEquals(Boolean.TRUE, le.invoke(null, 1, 1)); - assertEquals(Boolean.FALSE, le.invoke(null, 2, 1)); - - Method eq = branchingMethod(Comparison.EQ); - assertEquals(Boolean.FALSE, eq.invoke(null, 1, 2)); - assertEquals(Boolean.TRUE, eq.invoke(null, 1, 1)); - assertEquals(Boolean.FALSE, eq.invoke(null, 2, 1)); - - Method ge = branchingMethod(Comparison.GE); - assertEquals(Boolean.FALSE, ge.invoke(null, 1, 2)); - assertEquals(Boolean.TRUE, ge.invoke(null, 1, 1)); - assertEquals(Boolean.TRUE, ge.invoke(null, 2, 1)); - - Method gt = branchingMethod(Comparison.GT); - assertEquals(Boolean.FALSE, gt.invoke(null, 1, 2)); - assertEquals(Boolean.FALSE, gt.invoke(null, 1, 1)); - assertEquals(Boolean.TRUE, gt.invoke(null, 2, 1)); - - Method ne = branchingMethod(Comparison.NE); - assertEquals(Boolean.TRUE, ne.invoke(null, 1, 2)); - assertEquals(Boolean.FALSE, ne.invoke(null, 1, 1)); - assertEquals(Boolean.TRUE, ne.invoke(null, 2, 1)); - } - - private Method branchingMethod(Comparison comparison) throws Exception { - /* - * public static boolean call(int localA, int localB) { - * if (a comparison b) { - * return true; - * } - * return false; - * } - */ - reset(); - MethodId<?, Boolean> methodId = GENERATED.getMethod( - Type.BOOLEAN, "call", Type.INT, Type.INT); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Integer> localA = code.getParameter(0, Type.INT); - Local<Integer> localB = code.getParameter(1, Type.INT); - Local<Boolean> result = code.newLocal(Type.get(boolean.class)); - Label afterIf = code.newLabel(); - Label ifBody = code.newLabel(); - code.compare(comparison, localA, localB, ifBody); - code.jump(afterIf); - - code.mark(ifBody); - code.loadConstant(result, true); - code.returnValue(result); - - code.mark(afterIf); - code.loadConstant(result, false); - code.returnValue(result); - return getMethod(); - } - - public void testCastIntegerToInteger() throws Exception { - Method intToLong = numericCastingMethod(int.class, long.class); - assertEquals(0x0000000000000000L, intToLong.invoke(null, 0x00000000)); - assertEquals(0x000000007fffffffL, intToLong.invoke(null, 0x7fffffff)); - assertEquals(0xffffffff80000000L, intToLong.invoke(null, 0x80000000)); - assertEquals(0xffffffffffffffffL, intToLong.invoke(null, 0xffffffff)); - - Method longToInt = numericCastingMethod(long.class, int.class); - assertEquals(0x1234abcd, longToInt.invoke(null, 0x000000001234abcdL)); - assertEquals(0x1234abcd, longToInt.invoke(null, 0x123456781234abcdL)); - assertEquals(0x1234abcd, longToInt.invoke(null, 0xffffffff1234abcdL)); - - Method intToShort = numericCastingMethod(int.class, short.class); - assertEquals((short) 0x1234, intToShort.invoke(null, 0x00001234)); - assertEquals((short) 0x1234, intToShort.invoke(null, 0xabcd1234)); - assertEquals((short) 0x1234, intToShort.invoke(null, 0xffff1234)); - - Method intToChar = numericCastingMethod(int.class, char.class); - assertEquals((char) 0x1234, intToChar.invoke(null, 0x00001234)); - assertEquals((char) 0x1234, intToChar.invoke(null, 0xabcd1234)); - assertEquals((char) 0x1234, intToChar.invoke(null, 0xffff1234)); - - Method intToByte = numericCastingMethod(int.class, byte.class); - assertEquals((byte) 0x34, intToByte.invoke(null, 0x00000034)); - assertEquals((byte) 0x34, intToByte.invoke(null, 0xabcd1234)); - assertEquals((byte) 0x34, intToByte.invoke(null, 0xffffff34)); - } - - public void testCastIntegerToFloatingPoint() throws Exception { - Method intToFloat = numericCastingMethod(int.class, float.class); - assertEquals(0.0f, intToFloat.invoke(null, 0)); - assertEquals(-1.0f, intToFloat.invoke(null, -1)); - assertEquals(16777216f, intToFloat.invoke(null, 16777216)); - assertEquals(16777216f, intToFloat.invoke(null, 16777217)); // precision - - Method intToDouble = numericCastingMethod(int.class, double.class); - assertEquals(0.0, intToDouble.invoke(null, 0)); - assertEquals(-1.0, intToDouble.invoke(null, -1)); - assertEquals(16777216.0, intToDouble.invoke(null, 16777216)); - assertEquals(16777217.0, intToDouble.invoke(null, 16777217)); - - Method longToFloat = numericCastingMethod(long.class, float.class); - assertEquals(0.0f, longToFloat.invoke(null, 0L)); - assertEquals(-1.0f, longToFloat.invoke(null, -1L)); - assertEquals(16777216f, longToFloat.invoke(null, 16777216L)); - assertEquals(16777216f, longToFloat.invoke(null, 16777217L)); - - Method longToDouble = numericCastingMethod(long.class, double.class); - assertEquals(0.0, longToDouble.invoke(null, 0L)); - assertEquals(-1.0, longToDouble.invoke(null, -1L)); - assertEquals(9007199254740992.0, longToDouble.invoke(null, 9007199254740992L)); - assertEquals(9007199254740992.0, longToDouble.invoke(null, 9007199254740993L)); // precision - } - - public void testCastFloatingPointToInteger() throws Exception { - Method floatToInt = numericCastingMethod(float.class, int.class); - assertEquals(0, floatToInt.invoke(null, 0.0f)); - assertEquals(-1, floatToInt.invoke(null, -1.0f)); - assertEquals(Integer.MAX_VALUE, floatToInt.invoke(null, 10e15f)); - assertEquals(0, floatToInt.invoke(null, 0.5f)); - assertEquals(Integer.MIN_VALUE, floatToInt.invoke(null, Float.NEGATIVE_INFINITY)); - assertEquals(0, floatToInt.invoke(null, Float.NaN)); - - Method floatToLong = numericCastingMethod(float.class, long.class); - assertEquals(0L, floatToLong.invoke(null, 0.0f)); - assertEquals(-1L, floatToLong.invoke(null, -1.0f)); - assertEquals(10000000272564224L, floatToLong.invoke(null, 10e15f)); - assertEquals(0L, floatToLong.invoke(null, 0.5f)); - assertEquals(Long.MIN_VALUE, floatToLong.invoke(null, Float.NEGATIVE_INFINITY)); - assertEquals(0L, floatToLong.invoke(null, Float.NaN)); - - Method doubleToInt = numericCastingMethod(double.class, int.class); - assertEquals(0, doubleToInt.invoke(null, 0.0)); - assertEquals(-1, doubleToInt.invoke(null, -1.0)); - assertEquals(Integer.MAX_VALUE, doubleToInt.invoke(null, 10e15)); - assertEquals(0, doubleToInt.invoke(null, 0.5)); - assertEquals(Integer.MIN_VALUE, doubleToInt.invoke(null, Double.NEGATIVE_INFINITY)); - assertEquals(0, doubleToInt.invoke(null, Double.NaN)); - - Method doubleToLong = numericCastingMethod(double.class, long.class); - assertEquals(0L, doubleToLong.invoke(null, 0.0)); - assertEquals(-1L, doubleToLong.invoke(null, -1.0)); - assertEquals(10000000000000000L, doubleToLong.invoke(null, 10e15)); - assertEquals(0L, doubleToLong.invoke(null, 0.5)); - assertEquals(Long.MIN_VALUE, doubleToLong.invoke(null, Double.NEGATIVE_INFINITY)); - assertEquals(0L, doubleToLong.invoke(null, Double.NaN)); - } - - public void testCastFloatingPointToFloatingPoint() throws Exception { - Method floatToDouble = numericCastingMethod(float.class, double.class); - assertEquals(0.0, floatToDouble.invoke(null, 0.0f)); - assertEquals(-1.0, floatToDouble.invoke(null, -1.0f)); - assertEquals(0.5, floatToDouble.invoke(null, 0.5f)); - assertEquals(Double.NEGATIVE_INFINITY, floatToDouble.invoke(null, Float.NEGATIVE_INFINITY)); - assertEquals(Double.NaN, floatToDouble.invoke(null, Float.NaN)); - - Method doubleToFloat = numericCastingMethod(double.class, float.class); - assertEquals(0.0f, doubleToFloat.invoke(null, 0.0)); - assertEquals(-1.0f, doubleToFloat.invoke(null, -1.0)); - assertEquals(0.5f, doubleToFloat.invoke(null, 0.5)); - assertEquals(Float.NEGATIVE_INFINITY, doubleToFloat.invoke(null, Double.NEGATIVE_INFINITY)); - assertEquals(Float.NaN, doubleToFloat.invoke(null, Double.NaN)); - } - - private Method numericCastingMethod(Class<?> source, Class<?> target) - throws Exception { - /* - * public static short call(int source) { - * short casted = (short) source; - * return casted; - * } - */ - reset(); - Type<?> sourceType = Type.get(source); - Type<?> targetType = Type.get(target); - MethodId<?, ?> methodId = GENERATED.getMethod(targetType, "call", sourceType); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<?> localSource = code.getParameter(0, sourceType); - Local<?> localCasted = code.newLocal(targetType); - code.numericCast(localSource, localCasted); - code.returnValue(localCasted); - return getMethod(); - } - - public void testNot() throws Exception { - Method notInteger = notMethod(int.class); - assertEquals(0xffffffff, notInteger.invoke(null, 0x00000000)); - assertEquals(0x00000000, notInteger.invoke(null, 0xffffffff)); - assertEquals(0xedcba987, notInteger.invoke(null, 0x12345678)); - - Method notLong = notMethod(long.class); - assertEquals(0xffffffffffffffffL, notLong.invoke(null, 0x0000000000000000L)); - assertEquals(0x0000000000000000L, notLong.invoke(null, 0xffffffffffffffffL)); - assertEquals(0x98765432edcba987L, notLong.invoke(null, 0x6789abcd12345678L)); - } - - private <T> Method notMethod(Class<T> source) throws Exception { - /* - * public static short call(int source) { - * source = ~source; - * return not; - * } - */ - reset(); - Type<T> valueType = Type.get(source); - MethodId<?, T> methodId = GENERATED.getMethod(valueType, "call", valueType); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<T> localSource = code.getParameter(0, valueType); - code.not(localSource, localSource); - code.returnValue(localSource); - return getMethod(); - } - - public void testNegate() throws Exception { - Method negateInteger = negateMethod(int.class); - assertEquals(0, negateInteger.invoke(null, 0)); - assertEquals(-1, negateInteger.invoke(null, 1)); - assertEquals(Integer.MIN_VALUE, negateInteger.invoke(null, Integer.MIN_VALUE)); - - Method negateLong = negateMethod(long.class); - assertEquals(0L, negateLong.invoke(null, 0)); - assertEquals(-1L, negateLong.invoke(null, 1)); - assertEquals(Long.MIN_VALUE, negateLong.invoke(null, Long.MIN_VALUE)); - - Method negateFloat = negateMethod(float.class); - assertEquals(-0.0f, negateFloat.invoke(null, 0.0f)); - assertEquals(-1.0f, negateFloat.invoke(null, 1.0f)); - assertEquals(Float.NaN, negateFloat.invoke(null, Float.NaN)); - assertEquals(Float.POSITIVE_INFINITY, negateFloat.invoke(null, Float.NEGATIVE_INFINITY)); - - Method negateDouble = negateMethod(double.class); - assertEquals(-0.0, negateDouble.invoke(null, 0.0)); - assertEquals(-1.0, negateDouble.invoke(null, 1.0)); - assertEquals(Double.NaN, negateDouble.invoke(null, Double.NaN)); - assertEquals(Double.POSITIVE_INFINITY, negateDouble.invoke(null, Double.NEGATIVE_INFINITY)); - } - - private <T> Method negateMethod(Class<T> source) throws Exception { - /* - * public static short call(int source) { - * source = -source; - * return not; - * } - */ - reset(); - Type<T> valueType = Type.get(source); - MethodId<?, T> methodId = GENERATED.getMethod(valueType, "call", valueType); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<T> localSource = code.getParameter(0, valueType); - code.negate(localSource, localSource); - code.returnValue(localSource); - return getMethod(); - } - - public void testIntBinaryOps() throws Exception { - Method add = binaryOpMethod(int.class, BinaryOp.ADD); - assertEquals(79, add.invoke(null, 75, 4)); - - Method subtract = binaryOpMethod(int.class, BinaryOp.SUBTRACT); - assertEquals(71, subtract.invoke(null, 75, 4)); - - Method multiply = binaryOpMethod(int.class, BinaryOp.MULTIPLY); - assertEquals(300, multiply.invoke(null, 75, 4)); - - Method divide = binaryOpMethod(int.class, BinaryOp.DIVIDE); - assertEquals(18, divide.invoke(null, 75, 4)); - try { - divide.invoke(null, 75, 0); - fail(); - } catch (InvocationTargetException expected) { - assertEquals(ArithmeticException.class, expected.getCause().getClass()); - } - - Method remainder = binaryOpMethod(int.class, BinaryOp.REMAINDER); - assertEquals(3, remainder.invoke(null, 75, 4)); - try { - remainder.invoke(null, 75, 0); - fail(); - } catch (InvocationTargetException expected) { - assertEquals(ArithmeticException.class, expected.getCause().getClass()); - } - - Method and = binaryOpMethod(int.class, BinaryOp.AND); - assertEquals(0xff000000, and.invoke(null, 0xff00ff00, 0xffff0000)); - - Method or = binaryOpMethod(int.class, BinaryOp.OR); - assertEquals(0xffffff00, or.invoke(null, 0xff00ff00, 0xffff0000)); - - Method xor = binaryOpMethod(int.class, BinaryOp.XOR); - assertEquals(0x00ffff00, xor.invoke(null, 0xff00ff00, 0xffff0000)); - - Method shiftLeft = binaryOpMethod(int.class, BinaryOp.SHIFT_LEFT); - assertEquals(0xcd123400, shiftLeft.invoke(null, 0xabcd1234, 8)); - - Method shiftRight = binaryOpMethod(int.class, BinaryOp.SHIFT_RIGHT); - assertEquals(0xffabcd12, shiftRight.invoke(null, 0xabcd1234, 8)); - - Method unsignedShiftRight = binaryOpMethod(int.class, - BinaryOp.UNSIGNED_SHIFT_RIGHT); - assertEquals(0x00abcd12, unsignedShiftRight.invoke(null, 0xabcd1234, 8)); - } - - public void testLongBinaryOps() throws Exception { - Method add = binaryOpMethod(long.class, BinaryOp.ADD); - assertEquals(79L, add.invoke(null, 75L, 4L)); - - Method subtract = binaryOpMethod(long.class, BinaryOp.SUBTRACT); - assertEquals(71L, subtract.invoke(null, 75L, 4L)); - - Method multiply = binaryOpMethod(long.class, BinaryOp.MULTIPLY); - assertEquals(300L, multiply.invoke(null, 75L, 4L)); - - Method divide = binaryOpMethod(long.class, BinaryOp.DIVIDE); - assertEquals(18L, divide.invoke(null, 75L, 4L)); - try { - divide.invoke(null, 75L, 0L); - fail(); - } catch (InvocationTargetException expected) { - assertEquals(ArithmeticException.class, expected.getCause().getClass()); - } - - Method remainder = binaryOpMethod(long.class, BinaryOp.REMAINDER); - assertEquals(3L, remainder.invoke(null, 75L, 4L)); - try { - remainder.invoke(null, 75L, 0L); - fail(); - } catch (InvocationTargetException expected) { - assertEquals(ArithmeticException.class, expected.getCause().getClass()); - } - - Method and = binaryOpMethod(long.class, BinaryOp.AND); - assertEquals(0xff00ff0000000000L, - and.invoke(null, 0xff00ff00ff00ff00L, 0xffffffff00000000L)); - - Method or = binaryOpMethod(long.class, BinaryOp.OR); - assertEquals(0xffffffffff00ff00L, - or.invoke(null, 0xff00ff00ff00ff00L, 0xffffffff00000000L)); - - Method xor = binaryOpMethod(long.class, BinaryOp.XOR); - assertEquals(0x00ff00ffff00ff00L, - xor.invoke(null, 0xff00ff00ff00ff00L, 0xffffffff00000000L)); - - Method shiftLeft = binaryOpMethod(long.class, BinaryOp.SHIFT_LEFT); - assertEquals(0xcdef012345678900L, shiftLeft.invoke(null, 0xabcdef0123456789L, 8L)); - - Method shiftRight = binaryOpMethod(long.class, BinaryOp.SHIFT_RIGHT); - assertEquals(0xffabcdef01234567L, shiftRight.invoke(null, 0xabcdef0123456789L, 8L)); - - Method unsignedShiftRight = binaryOpMethod(long.class, - BinaryOp.UNSIGNED_SHIFT_RIGHT); - assertEquals(0x00abcdef01234567L, unsignedShiftRight.invoke(null, 0xabcdef0123456789L, 8L)); - } - - public void testFloatBinaryOps() throws Exception { - Method add = binaryOpMethod(float.class, BinaryOp.ADD); - assertEquals(6.75f, add.invoke(null, 5.5f, 1.25f)); - - Method subtract = binaryOpMethod(float.class, BinaryOp.SUBTRACT); - assertEquals(4.25f, subtract.invoke(null, 5.5f, 1.25f)); - - Method multiply = binaryOpMethod(float.class, BinaryOp.MULTIPLY); - assertEquals(6.875f, multiply.invoke(null, 5.5f, 1.25f)); - - Method divide = binaryOpMethod(float.class, BinaryOp.DIVIDE); - assertEquals(4.4f, divide.invoke(null, 5.5f, 1.25f)); - assertEquals(Float.POSITIVE_INFINITY, divide.invoke(null, 5.5f, 0.0f)); - - Method remainder = binaryOpMethod(float.class, BinaryOp.REMAINDER); - assertEquals(0.5f, remainder.invoke(null, 5.5f, 1.25f)); - assertEquals(Float.NaN, remainder.invoke(null, 5.5f, 0.0f)); - } - - public void testDoubleBinaryOps() throws Exception { - Method add = binaryOpMethod(double.class, BinaryOp.ADD); - assertEquals(6.75, add.invoke(null, 5.5, 1.25)); - - Method subtract = binaryOpMethod(double.class, BinaryOp.SUBTRACT); - assertEquals(4.25, subtract.invoke(null, 5.5, 1.25)); - - Method multiply = binaryOpMethod(double.class, BinaryOp.MULTIPLY); - assertEquals(6.875, multiply.invoke(null, 5.5, 1.25)); - - Method divide = binaryOpMethod(double.class, BinaryOp.DIVIDE); - assertEquals(4.4, divide.invoke(null, 5.5, 1.25)); - assertEquals(Double.POSITIVE_INFINITY, divide.invoke(null, 5.5, 0.0)); - - Method remainder = binaryOpMethod(double.class, BinaryOp.REMAINDER); - assertEquals(0.5, remainder.invoke(null, 5.5, 1.25)); - assertEquals(Double.NaN, remainder.invoke(null, 5.5, 0.0)); - } - - private <T> Method binaryOpMethod(Class<T> valueClass, BinaryOp op) - throws Exception { - /* - * public static int binaryOp(int a, int b) { - * int result = a + b; - * return result; - * } - */ - reset(); - Type<T> valueType = Type.get(valueClass); - MethodId<?, T> methodId = GENERATED.getMethod(valueType, "call", valueType, valueType); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<T> localA = code.getParameter(0, valueType); - Local<T> localB = code.getParameter(1, valueType); - Local<T> localResult = code.newLocal(valueType); - code.op(op, localResult, localA, localB); - code.returnValue(localResult); - return getMethod(); - } - - public void testReadAndWriteInstanceFields() throws Exception { - Instance instance = new Instance(); - - Method intSwap = instanceSwapMethod(int.class, "intValue"); - instance.intValue = 5; - assertEquals(5, intSwap.invoke(null, instance, 10)); - assertEquals(10, instance.intValue); - - Method longSwap = instanceSwapMethod(long.class, "longValue"); - instance.longValue = 500L; - assertEquals(500L, longSwap.invoke(null, instance, 1234L)); - assertEquals(1234L, instance.longValue); - - Method booleanSwap = instanceSwapMethod(boolean.class, "booleanValue"); - instance.booleanValue = false; - assertEquals(false, booleanSwap.invoke(null, instance, true)); - assertEquals(true, instance.booleanValue); - - Method floatSwap = instanceSwapMethod(float.class, "floatValue"); - instance.floatValue = 1.5f; - assertEquals(1.5f, floatSwap.invoke(null, instance, 0.5f)); - assertEquals(0.5f, instance.floatValue); - - Method doubleSwap = instanceSwapMethod(double.class, "doubleValue"); - instance.doubleValue = 155.5; - assertEquals(155.5, doubleSwap.invoke(null, instance, 266.6)); - assertEquals(266.6, instance.doubleValue); - - Method objectSwap = instanceSwapMethod(Object.class, "objectValue"); - instance.objectValue = "before"; - assertEquals("before", objectSwap.invoke(null, instance, "after")); - assertEquals("after", instance.objectValue); - - Method byteSwap = instanceSwapMethod(byte.class, "byteValue"); - instance.byteValue = 0x35; - assertEquals((byte) 0x35, byteSwap.invoke(null, instance, (byte) 0x64)); - assertEquals((byte) 0x64, instance.byteValue); - - Method charSwap = instanceSwapMethod(char.class, "charValue"); - instance.charValue = 'A'; - assertEquals('A', charSwap.invoke(null, instance, 'B')); - assertEquals('B', instance.charValue); - - Method shortSwap = instanceSwapMethod(short.class, "shortValue"); - instance.shortValue = (short) 0xabcd; - assertEquals((short) 0xabcd, shortSwap.invoke(null, instance, (short) 0x1234)); - assertEquals((short) 0x1234, instance.shortValue); - } - - public class Instance { - public int intValue; - public long longValue; - public float floatValue; - public double doubleValue; - public Object objectValue; - public boolean booleanValue; - public byte byteValue; - public char charValue; - public short shortValue; - } - - private <V> Method instanceSwapMethod( - Class<V> valueClass, String fieldName) throws Exception { - /* - * public static int call(Instance instance, int newValue) { - * int oldValue = instance.intValue; - * instance.intValue = newValue; - * return oldValue; - * } - */ - reset(); - Type<V> valueType = Type.get(valueClass); - Type<Instance> objectType = Type.get(Instance.class); - FieldId<Instance, V> fieldId = objectType.getField(valueType, fieldName); - MethodId<?, V> methodId = GENERATED.getMethod(valueType, "call", objectType, valueType); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Instance> localInstance = code.getParameter(0, objectType); - Local<V> localNewValue = code.getParameter(1, valueType); - Local<V> localOldValue = code.newLocal(valueType); - code.iget(fieldId, localInstance, localOldValue); - code.iput(fieldId, localInstance, localNewValue); - code.returnValue(localOldValue); - return getMethod(); - } - - public void testReadAndWriteStaticFields() throws Exception { - Method intSwap = staticSwapMethod(int.class, "intValue"); - Static.intValue = 5; - assertEquals(5, intSwap.invoke(null, 10)); - assertEquals(10, Static.intValue); - - Method longSwap = staticSwapMethod(long.class, "longValue"); - Static.longValue = 500L; - assertEquals(500L, longSwap.invoke(null, 1234L)); - assertEquals(1234L, Static.longValue); - - Method booleanSwap = staticSwapMethod(boolean.class, "booleanValue"); - Static.booleanValue = false; - assertEquals(false, booleanSwap.invoke(null, true)); - assertEquals(true, Static.booleanValue); - - Method floatSwap = staticSwapMethod(float.class, "floatValue"); - Static.floatValue = 1.5f; - assertEquals(1.5f, floatSwap.invoke(null, 0.5f)); - assertEquals(0.5f, Static.floatValue); - - Method doubleSwap = staticSwapMethod(double.class, "doubleValue"); - Static.doubleValue = 155.5; - assertEquals(155.5, doubleSwap.invoke(null, 266.6)); - assertEquals(266.6, Static.doubleValue); - - Method objectSwap = staticSwapMethod(Object.class, "objectValue"); - Static.objectValue = "before"; - assertEquals("before", objectSwap.invoke(null, "after")); - assertEquals("after", Static.objectValue); - - Method byteSwap = staticSwapMethod(byte.class, "byteValue"); - Static.byteValue = 0x35; - assertEquals((byte) 0x35, byteSwap.invoke(null, (byte) 0x64)); - assertEquals((byte) 0x64, Static.byteValue); - - Method charSwap = staticSwapMethod(char.class, "charValue"); - Static.charValue = 'A'; - assertEquals('A', charSwap.invoke(null, 'B')); - assertEquals('B', Static.charValue); - - Method shortSwap = staticSwapMethod(short.class, "shortValue"); - Static.shortValue = (short) 0xabcd; - assertEquals((short) 0xabcd, shortSwap.invoke(null, (short) 0x1234)); - assertEquals((short) 0x1234, Static.shortValue); - } - - public static class Static { - public static int intValue; - public static long longValue; - public static float floatValue; - public static double doubleValue; - public static Object objectValue; - public static boolean booleanValue; - public static byte byteValue; - public static char charValue; - public static short shortValue; - } - - private <V> Method staticSwapMethod(Class<V> valueClass, String fieldName) - throws Exception { - /* - * public static int call(int newValue) { - * int oldValue = Static.intValue; - * Static.intValue = newValue; - * return oldValue; - * } - */ - reset(); - Type<V> valueType = Type.get(valueClass); - Type<Static> objectType = Type.get(Static.class); - FieldId<Static, V> fieldId = objectType.getField(valueType, fieldName); - MethodId<?, V> methodId = GENERATED.getMethod(valueType, "call", valueType); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<V> localNewValue = code.getParameter(0, valueType); - Local<V> localOldValue = code.newLocal(valueType); - code.sget(fieldId, localOldValue); - code.sput(fieldId, localNewValue); - code.returnValue(localOldValue); - return getMethod(); - } - - public void testTypeCast() throws Exception { - /* - * public static String call(Object o) { - * String s = (String) o; - * } - */ - MethodId<?, String> methodId = GENERATED.getMethod(Type.STRING, "call", Type.OBJECT); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Object> localObject = code.getParameter(0, Type.OBJECT); - Local<String> localString = code.newLocal(Type.STRING); - code.typeCast(localObject, localString); - code.returnValue(localString); - - Method method = getMethod(); - assertEquals("s", method.invoke(null, "s")); - assertEquals(null, method.invoke(null, (String) null)); - try { - method.invoke(null, 5); - fail(); - } catch (InvocationTargetException expected) { - assertEquals(ClassCastException.class, expected.getCause().getClass()); - } - } - - public void testInstanceOf() throws Exception { - /* - * public static boolean call(Object o) { - * boolean result = o instanceof String; - * return result; - * } - */ - MethodId<?, Boolean> methodId = GENERATED.getMethod(Type.BOOLEAN, "call", Type.OBJECT); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Object> localObject = code.getParameter(0, Type.OBJECT); - Local<Boolean> localResult = code.newLocal(Type.BOOLEAN); - code.instanceOfType(localResult, localObject, Type.STRING); - code.returnValue(localResult); - - Method method = getMethod(); - assertEquals(true, method.invoke(null, "s")); - assertEquals(false, method.invoke(null, (String) null)); - assertEquals(false, method.invoke(null, 5)); - } - - /** - * Tests that we can construct a for loop. - */ - public void testForLoop() throws Exception { - /* - * public static int call(int count) { - * int result = 1; - * for (int i = 0; i < count; i += 1) { - * result = result * 2; - * } - * return result; - * } - */ - MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", Type.INT); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Integer> localCount = code.getParameter(0, Type.INT); - Local<Integer> localResult = code.newLocal(Type.INT); - Local<Integer> localI = code.newLocal(Type.INT); - Local<Integer> local1 = code.newLocal(Type.INT); - Local<Integer> local2 = code.newLocal(Type.INT); - code.loadConstant(local1, 1); - code.loadConstant(local2, 2); - code.loadConstant(localResult, 1); - code.loadConstant(localI, 0); - Label loopCondition = code.newLabel(); - Label loopBody = code.newLabel(); - Label afterLoop = code.newLabel(); - code.mark(loopCondition); - code.compare(Comparison.LT, localI, localCount, loopBody); - code.jump(afterLoop); - code.mark(loopBody); - code.op(BinaryOp.MULTIPLY, localResult, localResult, local2); - code.op(BinaryOp.ADD, localI, localI, local1); - code.jump(loopCondition); - code.mark(afterLoop); - code.returnValue(localResult); - - Method pow2 = getMethod(); - assertEquals(1, pow2.invoke(null, 0)); - assertEquals(2, pow2.invoke(null, 1)); - assertEquals(4, pow2.invoke(null, 2)); - assertEquals(8, pow2.invoke(null, 3)); - assertEquals(16, pow2.invoke(null, 4)); - } - - /** - * Tests that we can construct a while loop. - */ - public void testWhileLoop() throws Exception { - /* - * public static int call(int max) { - * int result = 1; - * while (result < max) { - * result = result * 2; - * } - * return result; - * } - */ - MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", Type.INT); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Integer> localMax = code.getParameter(0, Type.INT); - Local<Integer> localResult = code.newLocal(Type.INT); - Local<Integer> local2 = code.newLocal(Type.INT); - code.loadConstant(localResult, 1); - code.loadConstant(local2, 2); - Label loopCondition = code.newLabel(); - Label loopBody = code.newLabel(); - Label afterLoop = code.newLabel(); - code.mark(loopCondition); - code.compare(Comparison.LT, localResult, localMax, loopBody); - code.jump(afterLoop); - code.mark(loopBody); - code.op(BinaryOp.MULTIPLY, localResult, localResult, local2); - code.jump(loopCondition); - code.mark(afterLoop); - code.returnValue(localResult); - - Method ceilPow2 = getMethod(); - assertEquals(1, ceilPow2.invoke(null, 1)); - assertEquals(2, ceilPow2.invoke(null, 2)); - assertEquals(4, ceilPow2.invoke(null, 3)); - assertEquals(16, ceilPow2.invoke(null, 10)); - assertEquals(128, ceilPow2.invoke(null, 100)); - assertEquals(1024, ceilPow2.invoke(null, 1000)); - } - - public void testIfElseBlock() throws Exception { - /* - * public static int call(int a, int b, int c) { - * if (a < b) { - * if (a < c) { - * return a; - * } else { - * return c; - * } - * } else if (b < c) { - * return b; - * } else { - * return c; - * } - * } - */ - MethodId<?, Integer> methodId = GENERATED.getMethod( - Type.INT, "call", Type.INT, Type.INT, Type.INT); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Integer> localA = code.getParameter(0, Type.INT); - Local<Integer> localB = code.getParameter(1, Type.INT); - Local<Integer> localC = code.getParameter(2, Type.INT); - Label aLessThanB = code.newLabel(); - Label aLessThanC = code.newLabel(); - Label bLessThanC = code.newLabel(); - code.compare(Comparison.LT, localA, localB, aLessThanB); - code.compare(Comparison.LT, localB, localC, bLessThanC); - code.returnValue(localC); - // (a < b) - code.mark(aLessThanB); - code.compare(Comparison.LT, localA, localC, aLessThanC); - code.returnValue(localC); - // (a < c) - code.mark(aLessThanC); - code.returnValue(localA); - // (b < c) - code.mark(bLessThanC); - code.returnValue(localB); - - Method min = getMethod(); - assertEquals(1, min.invoke(null, 1, 2, 3)); - assertEquals(1, min.invoke(null, 2, 3, 1)); - assertEquals(1, min.invoke(null, 2, 1, 3)); - assertEquals(1, min.invoke(null, 3, 2, 1)); - } - - public void testRecursion() throws Exception { - /* - * public static int call(int a) { - * if (a < 2) { - * return a; - * } - * a -= 1; - * int x = call(a) - * a -= 1; - * int y = call(a); - * int result = x + y; - * return result; - * } - */ - MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", Type.INT); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Integer> localA = code.getParameter(0, Type.INT); - Local<Integer> local1 = code.newLocal(Type.INT); - Local<Integer> local2 = code.newLocal(Type.INT); - Local<Integer> localX = code.newLocal(Type.INT); - Local<Integer> localY = code.newLocal(Type.INT); - Local<Integer> localResult = code.newLocal(Type.INT); - Label baseCase = code.newLabel(); - code.loadConstant(local1, 1); - code.loadConstant(local2, 2); - code.compare(Comparison.LT, localA, local2, baseCase); - code.op(BinaryOp.SUBTRACT, localA, localA, local1); - code.invokeStatic(methodId, localX, localA); - code.op(BinaryOp.SUBTRACT, localA, localA, local1); - code.invokeStatic(methodId, localY, localA); - code.op(BinaryOp.ADD, localResult, localX, localY); - code.returnValue(localResult); - code.mark(baseCase); - code.returnValue(localA); - - Method fib = getMethod(); - assertEquals(0, fib.invoke(null, 0)); - assertEquals(1, fib.invoke(null, 1)); - assertEquals(1, fib.invoke(null, 2)); - assertEquals(2, fib.invoke(null, 3)); - assertEquals(3, fib.invoke(null, 4)); - assertEquals(5, fib.invoke(null, 5)); - assertEquals(8, fib.invoke(null, 6)); - } - - public void testCatchExceptions() throws Exception { - /* - * public static String call(int i) { - * try { - * DexGeneratorTest.thrower(i); - * return "NONE"; - * } catch (IllegalArgumentException e) { - * return "IAE"; - * } catch (IllegalStateException e) { - * return "ISE"; - * } catch (RuntimeException e) { - * return "RE"; - * } - */ - MethodId<?, String> methodId = GENERATED.getMethod(Type.STRING, "call", Type.INT); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Integer> localI = code.getParameter(0, Type.INT); - Local<String> result = code.newLocal(Type.STRING); - Label catchIae = code.newLabel(); - Label catchIse = code.newLabel(); - Label catchRe = code.newLabel(); - - code.addCatchClause(Type.get(IllegalArgumentException.class), catchIae); - code.addCatchClause(Type.get(IllegalStateException.class), catchIse); - code.addCatchClause(Type.get(RuntimeException.class), catchRe); - MethodId<?, ?> thrower = TEST_TYPE.getMethod(Type.VOID, "thrower", Type.INT); - code.invokeStatic(thrower, null, localI); - code.loadConstant(result, "NONE"); - code.returnValue(result); - - code.mark(catchIae); - code.loadConstant(result, "IAE"); - code.returnValue(result); - - code.mark(catchIse); - code.loadConstant(result, "ISE"); - code.returnValue(result); - - code.mark(catchRe); - code.loadConstant(result, "RE"); - code.returnValue(result); - - Method method = getMethod(); - assertEquals("NONE", method.invoke(null, 0)); - assertEquals("IAE", method.invoke(null, 1)); - assertEquals("ISE", method.invoke(null, 2)); - assertEquals("RE", method.invoke(null, 3)); - try { - method.invoke(null, 4); - fail(); - } catch (InvocationTargetException expected) { - assertEquals(IOException.class, expected.getCause().getClass()); - } - } - - @SuppressWarnings("unused") // called by generated code - public static void thrower(int a) throws Exception { - switch (a) { - case 0: - return; - case 1: - throw new IllegalArgumentException(); - case 2: - throw new IllegalStateException(); - case 3: - throw new UnsupportedOperationException(); - case 4: - throw new IOException(); - default: - throw new AssertionError(); - } - } - - public void testNestedCatchClauses() throws Exception { - /* - * public static String call(int a, int b, int c) { - * try { - * DexGeneratorTest.thrower(a); - * try { - * DexGeneratorTest.thrower(b); - * } catch (IllegalArgumentException) { - * return "INNER"; - * } - * DexGeneratorTest.thrower(c); - * return "NONE"; - * } catch (IllegalArgumentException e) { - * return "OUTER"; - * } - */ - MethodId<?, String> methodId = GENERATED.getMethod( - Type.STRING, "call", Type.INT, Type.INT, Type.INT); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Integer> localA = code.getParameter(0, Type.INT); - Local<Integer> localB = code.getParameter(1, Type.INT); - Local<Integer> localC = code.getParameter(2, Type.INT); - Local<String> localResult = code.newLocal(Type.STRING); - Label catchInner = code.newLabel(); - Label catchOuter = code.newLabel(); - - Type<IllegalArgumentException> iaeType = Type.get(IllegalArgumentException.class); - code.addCatchClause(iaeType, catchOuter); - - MethodId<?, ?> thrower = TEST_TYPE.getMethod(Type.VOID, "thrower", Type.INT); - code.invokeStatic(thrower, null, localA); - - // for the inner catch clause, we stash the old label and put it back afterwards. - Label previousLabel = code.removeCatchClause(iaeType); - code.addCatchClause(iaeType, catchInner); - code.invokeStatic(thrower, null, localB); - code.removeCatchClause(iaeType); - code.addCatchClause(iaeType, previousLabel); - code.invokeStatic(thrower, null, localC); - code.loadConstant(localResult, "NONE"); - code.returnValue(localResult); - - code.mark(catchInner); - code.loadConstant(localResult, "INNER"); - code.returnValue(localResult); - - code.mark(catchOuter); - code.loadConstant(localResult, "OUTER"); - code.returnValue(localResult); - - Method method = getMethod(); - assertEquals("OUTER", method.invoke(null, 1, 0, 0)); - assertEquals("INNER", method.invoke(null, 0, 1, 0)); - assertEquals("OUTER", method.invoke(null, 0, 0, 1)); - assertEquals("NONE", method.invoke(null, 0, 0, 0)); - } - - public void testThrow() throws Exception { - /* - * public static void call() { - * throw new IllegalStateException(); - * } - */ - MethodId<?, Void> methodId = GENERATED.getMethod(Type.VOID, "call"); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Type<IllegalStateException> iseType = Type.get(IllegalStateException.class); - MethodId<IllegalStateException, Void> iseConstructor = iseType.getConstructor(); - Local<IllegalStateException> localIse = code.newLocal(iseType); - code.newInstance(localIse, iseConstructor); - code.throwValue(localIse); - - try { - getMethod().invoke(null); - fail(); - } catch (InvocationTargetException expected) { - assertEquals(IllegalStateException.class, expected.getCause().getClass()); - } - } - - public void testUnusedParameters() throws Exception { - /* - * public static void call(int unused1, long unused2, long unused3) {} - */ - MethodId<?, Void> methodId = GENERATED.getMethod( - Type.VOID, "call", Type.INT, Type.LONG, Type.LONG); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - code.returnVoid(); - getMethod().invoke(null, 1, 2, 3); - } - - public void testFloatingPointCompare() throws Exception { - Method floatG = floatingPointCompareMethod(Type.FLOAT, 1); - assertEquals(-1, floatG.invoke(null, 1.0f, Float.POSITIVE_INFINITY)); - assertEquals(-1, floatG.invoke(null, 1.0f, 2.0f)); - assertEquals(0, floatG.invoke(null, 1.0f, 1.0f)); - assertEquals(1, floatG.invoke(null, 2.0f, 1.0f)); - assertEquals(1, floatG.invoke(null, 1.0f, Float.NaN)); - assertEquals(1, floatG.invoke(null, Float.NaN, 1.0f)); - assertEquals(1, floatG.invoke(null, Float.NaN, Float.NaN)); - assertEquals(1, floatG.invoke(null, Float.NaN, Float.POSITIVE_INFINITY)); - - Method floatL = floatingPointCompareMethod(Type.FLOAT, -1); - assertEquals(-1, floatG.invoke(null, 1.0f, Float.POSITIVE_INFINITY)); - assertEquals(-1, floatL.invoke(null, 1.0f, 2.0f)); - assertEquals(0, floatL.invoke(null, 1.0f, 1.0f)); - assertEquals(1, floatL.invoke(null, 2.0f, 1.0f)); - assertEquals(-1, floatL.invoke(null, 1.0f, Float.NaN)); - assertEquals(-1, floatL.invoke(null, Float.NaN, 1.0f)); - assertEquals(-1, floatL.invoke(null, Float.NaN, Float.NaN)); - assertEquals(-1, floatL.invoke(null, Float.NaN, Float.POSITIVE_INFINITY)); - - Method doubleG = floatingPointCompareMethod(Type.DOUBLE, 1); - assertEquals(-1, doubleG.invoke(null, 1.0, Double.POSITIVE_INFINITY)); - assertEquals(-1, doubleG.invoke(null, 1.0, 2.0)); - assertEquals(0, doubleG.invoke(null, 1.0, 1.0)); - assertEquals(1, doubleG.invoke(null, 2.0, 1.0)); - assertEquals(1, doubleG.invoke(null, 1.0, Double.NaN)); - assertEquals(1, doubleG.invoke(null, Double.NaN, 1.0)); - assertEquals(1, doubleG.invoke(null, Double.NaN, Double.NaN)); - assertEquals(1, doubleG.invoke(null, Double.NaN, Double.POSITIVE_INFINITY)); - - Method doubleL = floatingPointCompareMethod(Type.DOUBLE, -1); - assertEquals(-1, doubleL.invoke(null, 1.0, Double.POSITIVE_INFINITY)); - assertEquals(-1, doubleL.invoke(null, 1.0, 2.0)); - assertEquals(0, doubleL.invoke(null, 1.0, 1.0)); - assertEquals(1, doubleL.invoke(null, 2.0, 1.0)); - assertEquals(-1, doubleL.invoke(null, 1.0, Double.NaN)); - assertEquals(-1, doubleL.invoke(null, Double.NaN, 1.0)); - assertEquals(-1, doubleL.invoke(null, Double.NaN, Double.NaN)); - assertEquals(-1, doubleL.invoke(null, Double.NaN, Double.POSITIVE_INFINITY)); - } - - private <T extends Number> Method floatingPointCompareMethod( - Type<T> valueType, int nanValue) throws Exception { - /* - * public static int call(float a, float b) { - * int result = a <=> b; - * return result; - * } - */ - reset(); - MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", valueType, valueType); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<T> localA = code.getParameter(0, valueType); - Local<T> localB = code.getParameter(1, valueType); - Local<Integer> localResult = code.newLocal(Type.INT); - code.compare(localA, localB, localResult, nanValue); - code.returnValue(localResult); - return getMethod(); - } - - public void testLongCompare() throws Exception { - /* - * public static int call(long a, long b) { - * int result = a <=> b; - * return result; - * } - */ - MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", Type.LONG, Type.LONG); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Long> localA = code.getParameter(0, Type.LONG); - Local<Long> localB = code.getParameter(1, Type.LONG); - Local<Integer> localResult = code.newLocal(Type.INT); - code.compare(localA, localB, localResult); - code.returnValue(localResult); - - Method method = getMethod(); - assertEquals(0, method.invoke(null, Long.MIN_VALUE, Long.MIN_VALUE)); - assertEquals(-1, method.invoke(null, Long.MIN_VALUE, 0)); - assertEquals(-1, method.invoke(null, Long.MIN_VALUE, Long.MAX_VALUE)); - assertEquals(1, method.invoke(null, 0, Long.MIN_VALUE)); - assertEquals(0, method.invoke(null, 0, 0)); - assertEquals(-1, method.invoke(null, 0, Long.MAX_VALUE)); - assertEquals(1, method.invoke(null, Long.MAX_VALUE, Long.MIN_VALUE)); - assertEquals(1, method.invoke(null, Long.MAX_VALUE, 0)); - assertEquals(0, method.invoke(null, Long.MAX_VALUE, Long.MAX_VALUE)); - } - - public void testArrayLength() throws Exception { - Method booleanArrayLength = arrayLengthMethod(BOOLEAN_ARRAY); - assertEquals(0, booleanArrayLength.invoke(null, new Object[] { new boolean[0] })); - assertEquals(5, booleanArrayLength.invoke(null, new Object[] { new boolean[5] })); - - Method intArrayLength = arrayLengthMethod(INT_ARRAY); - assertEquals(0, intArrayLength.invoke(null, new Object[] { new int[0] })); - assertEquals(5, intArrayLength.invoke(null, new Object[] { new int[5] })); - - Method longArrayLength = arrayLengthMethod(LONG_ARRAY); - assertEquals(0, longArrayLength.invoke(null, new Object[] { new long[0] })); - assertEquals(5, longArrayLength.invoke(null, new Object[] { new long[5] })); - - Method objectArrayLength = arrayLengthMethod(OBJECT_ARRAY); - assertEquals(0, objectArrayLength.invoke(null, new Object[] { new Object[0] })); - assertEquals(5, objectArrayLength.invoke(null, new Object[] { new Object[5] })); - - Method long2dArrayLength = arrayLengthMethod(LONG_2D_ARRAY); - assertEquals(0, long2dArrayLength.invoke(null, new Object[] { new long[0][0] })); - assertEquals(5, long2dArrayLength.invoke(null, new Object[] { new long[5][10] })); - } - - private <T> Method arrayLengthMethod(Type<T> valueType) throws Exception { - /* - * public static int call(long[] array) { - * int result = array.length; - * return result; - * } - */ - reset(); - MethodId<?, Integer> methodId = GENERATED.getMethod(Type.INT, "call", valueType); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<T> localArray = code.getParameter(0, valueType); - Local<Integer> localResult = code.newLocal(Type.INT); - code.arrayLength(localArray, localResult); - code.returnValue(localResult); - return getMethod(); - } - - public void testNewArray() throws Exception { - Method newBooleanArray = newArrayMethod(BOOLEAN_ARRAY); - assertEquals("[]", Arrays.toString((boolean[]) newBooleanArray.invoke(null, 0))); - assertEquals("[false, false, false]", - Arrays.toString((boolean[]) newBooleanArray.invoke(null, 3))); - - Method newIntArray = newArrayMethod(INT_ARRAY); - assertEquals("[]", Arrays.toString((int[]) newIntArray.invoke(null, 0))); - assertEquals("[0, 0, 0]", Arrays.toString((int[]) newIntArray.invoke(null, 3))); - - Method newLongArray = newArrayMethod(LONG_ARRAY); - assertEquals("[]", Arrays.toString((long[]) newLongArray.invoke(null, 0))); - assertEquals("[0, 0, 0]", Arrays.toString((long[]) newLongArray.invoke(null, 3))); - - Method newObjectArray = newArrayMethod(OBJECT_ARRAY); - assertEquals("[]", Arrays.toString((Object[]) newObjectArray.invoke(null, 0))); - assertEquals("[null, null, null]", - Arrays.toString((Object[]) newObjectArray.invoke(null, 3))); - - Method new2dLongArray = newArrayMethod(LONG_2D_ARRAY); - assertEquals("[]", Arrays.deepToString((long[][]) new2dLongArray.invoke(null, 0))); - assertEquals("[null, null, null]", - Arrays.deepToString((long[][]) new2dLongArray.invoke(null, 3))); - } - - private <T> Method newArrayMethod(Type<T> valueType) throws Exception { - /* - * public static long[] call(int length) { - * long[] result = new long[length]; - * return result; - * } - */ - reset(); - MethodId<?, T> methodId = GENERATED.getMethod(valueType, "call", Type.INT); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<Integer> localLength = code.getParameter(0, Type.INT); - Local<T> localResult = code.newLocal(valueType); - code.newArray(localLength, localResult); - code.returnValue(localResult); - return getMethod(); - } - - public void testReadAndWriteArray() throws Exception { - Method swapBooleanArray = arraySwapMethod(BOOLEAN_ARRAY, Type.BOOLEAN); - boolean[] booleans = new boolean[3]; - assertEquals(false, swapBooleanArray.invoke(null, booleans, 1, true)); - assertEquals("[false, true, false]", Arrays.toString(booleans)); - - Method swapIntArray = arraySwapMethod(INT_ARRAY, Type.INT); - int[] ints = new int[3]; - assertEquals(0, swapIntArray.invoke(null, ints, 1, 5)); - assertEquals("[0, 5, 0]", Arrays.toString(ints)); - - Method swapLongArray = arraySwapMethod(LONG_ARRAY, Type.LONG); - long[] longs = new long[3]; - assertEquals(0L, swapLongArray.invoke(null, longs, 1, 6L)); - assertEquals("[0, 6, 0]", Arrays.toString(longs)); - - Method swapObjectArray = arraySwapMethod(OBJECT_ARRAY, Type.OBJECT); - Object[] objects = new Object[3]; - assertEquals(null, swapObjectArray.invoke(null, objects, 1, "X")); - assertEquals("[null, X, null]", Arrays.toString(objects)); - - Method swapLong2dArray = arraySwapMethod(LONG_2D_ARRAY, LONG_ARRAY); - long[][] longs2d = new long[3][]; - assertEquals(null, swapLong2dArray.invoke(null, longs2d, 1, new long[] { 7 })); - assertEquals("[null, [7], null]", Arrays.deepToString(longs2d)); - } - - private <A, T> Method arraySwapMethod(Type<A> arrayType, Type<T> singleType) - throws Exception { - /* - * public static long swap(long[] array, int index, long newValue) { - * long result = array[index]; - * array[index] = newValue; - * return result; - * } - */ - reset(); - MethodId<?, T> methodId = GENERATED.getMethod( - singleType, "call", arrayType, Type.INT, singleType); - Code code = generator.declare(methodId, ACC_PUBLIC | ACC_STATIC); - Local<A> localArray = code.getParameter(0, arrayType); - Local<Integer> localIndex = code.getParameter(1, Type.INT); - Local<T> localNewValue = code.getParameter(2, singleType); - Local<T> localResult = code.newLocal(singleType); - code.aget(localArray, localIndex, localResult); - code.aput(localArray, localIndex, localNewValue); - code.returnValue(localResult); - return getMethod(); - } - - // TODO: fail if a label is unreachable (never navigated to) - - // TODO: more strict type parameters: Integer on methods - - // TODO: don't generate multiple times (?) - - private void addDefaultConstructor() { - Code code = generator.declare(GENERATED.getConstructor(), ACC_PUBLIC | ACC_CONSTRUCTOR); - Local<?> thisRef = code.getThis(GENERATED); - code.invokeDirect(Type.OBJECT.getConstructor(), null, thisRef); - code.returnVoid(); - } - - /** - * Returns the generated method. - */ - private Method getMethod() throws Exception { - Class<?> generated = loadAndGenerate(); - for (Method method : generated.getMethods()) { - if (method.getName().equals("call")) { - return method; - } - } - throw new IllegalStateException("no call() method"); - } - - private Class<?> loadAndGenerate() throws IOException, ClassNotFoundException { - return generator.load(DexGeneratorTest.class.getClassLoader()).loadClass("Generated"); - } -} diff --git a/dx/junit-tests/com/android/dx/gen/TypeTest.java b/dx/junit-tests/com/android/dx/gen/TypeTest.java deleted file mode 100644 index c2f4f0438..000000000 --- a/dx/junit-tests/com/android/dx/gen/TypeTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.gen; - -import junit.framework.TestCase; - -public final class TypeTest extends TestCase { - - private final DexGenerator generator = new DexGenerator(); - - public void testGetType() { - assertEquals("Ljava/lang/String;", Type.get(String.class).getName()); - assertEquals("[Ljava/lang/String;", Type.get(String[].class).getName()); - assertEquals("[[Ljava/lang/String;", Type.get(String[][].class).getName()); - assertEquals("I", Type.get(int.class).getName()); - assertEquals("[I", Type.get(int[].class).getName()); - assertEquals("[[I", Type.get(int[][].class).getName()); - } -} diff --git a/dx/src/com/android/dx/util/_tests/_BitIntSet.java b/dx/junit-tests/com/android/dx/util/BitIntSetTest.java index e26d7a4f5..d46d14fe3 100644 --- a/dx/src/com/android/dx/util/_tests/_BitIntSet.java +++ b/dx/junit-tests/com/android/dx/util/BitIntSetTest.java @@ -14,17 +14,12 @@ * limitations under the License. */ -package com.android.dx.util._tests; - -import com.android.dx.util.BitIntSet; -import com.android.dx.util.IntIterator; -import com.android.dx.util.ListIntSet; - -import junit.framework.TestCase; +package com.android.dx.util; import java.util.NoSuchElementException; +import junit.framework.TestCase; -public class _BitIntSet extends TestCase { +public final class BitIntSetTest extends TestCase { public void test_basic() { BitIntSet set = new BitIntSet(32); diff --git a/dx/src/com/android/dx/util/_tests/_Bits.java b/dx/junit-tests/com/android/dx/util/BitsTest.java index a95fc14d7..e4275132f 100644 --- a/dx/src/com/android/dx/util/_tests/_Bits.java +++ b/dx/junit-tests/com/android/dx/util/BitsTest.java @@ -14,17 +14,11 @@ * limitations under the License. */ -package com.android.dx.util._tests; - -import com.android.dx.util.Bits; +package com.android.dx.util; import junit.framework.TestCase; -/** - * Test the class {@code com.android.dx.util.Bits}. - */ -public class _Bits - extends TestCase { +public final class BitsTest extends TestCase { public void test_makeBitSet() { assertEquals(label(0), 0, Bits.makeBitSet(0).length); diff --git a/dx/src/com/android/dx/util/_tests/_IntList.java b/dx/junit-tests/com/android/dx/util/IntListTest.java index dadbd54fb..7a53a67ba 100644 --- a/dx/src/com/android/dx/util/_tests/_IntList.java +++ b/dx/junit-tests/com/android/dx/util/IntListTest.java @@ -14,19 +14,11 @@ * limitations under the License. */ -package com.android.dx.util._tests; - -import com.android.dx.util.IntList; +package com.android.dx.util; import junit.framework.TestCase; -/** - * Test the class {@code com.android.dx.util.IntList}. - */ -public class _IntList - extends TestCase { - // TODO: Add tests for the rest of the methods. - +public final class IntListTest extends TestCase { public void test_contains() { for (int sz = 0; sz < 100; sz++) { IntList list = new IntList(sz); diff --git a/dx/src/com/android/dx/util/_tests/_ListIntSet.java b/dx/junit-tests/com/android/dx/util/ListIntSetTest.java index ccd599178..868e630a1 100644 --- a/dx/src/com/android/dx/util/_tests/_ListIntSet.java +++ b/dx/junit-tests/com/android/dx/util/ListIntSetTest.java @@ -14,17 +14,12 @@ * limitations under the License. */ -package com.android.dx.util._tests; - -import com.android.dx.util.BitIntSet; -import com.android.dx.util.ListIntSet; -import com.android.dx.util.IntIterator; - -import junit.framework.TestCase; +package com.android.dx.util; import java.util.NoSuchElementException; +import junit.framework.TestCase; -public class _ListIntSet extends TestCase { +public final class ListIntSetTest extends TestCase { public void test_basic() { ListIntSet set = new ListIntSet(); diff --git a/dx/src/com/android/dx/command/Main.java b/dx/src/com/android/dx/command/Main.java index d0bbbe2c2..10a117929 100644 --- a/dx/src/com/android/dx/command/Main.java +++ b/dx/src/com/android/dx/command/Main.java @@ -18,8 +18,6 @@ package com.android.dx.command; import com.android.dx.Version; -import junit.textui.TestRunner; - /** * Main class for dx. It recognizes enough options to be able to dispatch * to the right "actual" main. @@ -50,8 +48,6 @@ public class Main { " [--width=<n>] [<file>.class | <file>.txt] ...\n" + " Dump classfiles, or transformations thereof, in a " + "human-oriented format.\n" + - " dx --junit [-wait] <TestClass>\n" + - " Run the indicated unit test.\n" + " dx --find-usages <file.dex> <declaring type> <member>\n" + " Find references and declarations to a field or method.\n" + " declaring type: a class name in internal form, like " + @@ -101,9 +97,6 @@ public class Main { com.android.dx.command.annotool.Main.main( without(args, i)); break; - } else if (arg.equals("--junit")) { - TestRunner.main(without(args, i)); - break; } else if (arg.equals("--find-usages")) { com.android.dx.command.findusages.Main.main(without(args, i)); break; diff --git a/dx/src/com/android/dx/dex/DexOptions.java b/dx/src/com/android/dx/dex/DexOptions.java index a72532565..03573844e 100644 --- a/dx/src/com/android/dx/dex/DexOptions.java +++ b/dx/src/com/android/dx/dex/DexOptions.java @@ -21,7 +21,7 @@ package com.android.dx.dex; */ public class DexOptions { /** target API level */ - public int targetApiLevel = DexFormat.API_CURRENT; + public int targetApiLevel = DexFormat.API_NO_EXTENDED_OPCODES; /** * Gets the dex file magic number corresponding to this instance. diff --git a/dx/src/com/android/dx/dex/TableOfContents.java b/dx/src/com/android/dx/dex/TableOfContents.java index 877dddbeb..fbe46264c 100644 --- a/dx/src/com/android/dx/dex/TableOfContents.java +++ b/dx/src/com/android/dx/dex/TableOfContents.java @@ -77,7 +77,7 @@ public final class TableOfContents { byte[] magic = headerIn.readByteArray(8); int apiTarget = DexFormat.magicToApi(magic); - if (apiTarget < 0) { + if (apiTarget != DexFormat.API_NO_EXTENDED_OPCODES) { throw new DexException("Unexpected magic: " + Arrays.toString(magic)); } @@ -166,7 +166,7 @@ public final class TableOfContents { } public void writeHeader(DexBuffer.Section out) throws IOException { - out.write(DexFormat.apiToMagic(DexFormat.API_CURRENT).getBytes("UTF-8")); + out.write(DexFormat.apiToMagic(DexFormat.API_NO_EXTENDED_OPCODES).getBytes("UTF-8")); out.writeInt(checksum); out.write(signature); out.writeInt(fileSize); diff --git a/dx/src/com/android/dx/dex/code/Dops.java b/dx/src/com/android/dx/dex/code/Dops.java index c0662527e..cc5c173ed 100644 --- a/dx/src/com/android/dx/dex/code/Dops.java +++ b/dx/src/com/android/dx/dex/code/Dops.java @@ -40,10 +40,7 @@ import com.android.dx.dex.code.form.Form31t; import com.android.dx.dex.code.form.Form32x; import com.android.dx.dex.code.form.Form35c; import com.android.dx.dex.code.form.Form3rc; -import com.android.dx.dex.code.form.Form41c; import com.android.dx.dex.code.form.Form51l; -import com.android.dx.dex.code.form.Form52c; -import com.android.dx.dex.code.form.Form5rc; import com.android.dx.dex.code.form.SpecialFormat; import com.android.dx.io.Opcodes; @@ -180,7 +177,7 @@ public final class Dops { public static final Dop CONST_CLASS = new Dop(Opcodes.CONST_CLASS, Opcodes.CONST_CLASS, - Opcodes.CONST_CLASS_JUMBO, Form21c.THE_ONE, true); + Opcodes.NO_NEXT, Form21c.THE_ONE, true); public static final Dop MONITOR_ENTER = new Dop(Opcodes.MONITOR_ENTER, Opcodes.MONITOR_ENTER, @@ -192,11 +189,11 @@ public final class Dops { public static final Dop CHECK_CAST = new Dop(Opcodes.CHECK_CAST, Opcodes.CHECK_CAST, - Opcodes.CHECK_CAST_JUMBO, Form21c.THE_ONE, true); + Opcodes.NO_NEXT, Form21c.THE_ONE, true); public static final Dop INSTANCE_OF = new Dop(Opcodes.INSTANCE_OF, Opcodes.INSTANCE_OF, - Opcodes.INSTANCE_OF_JUMBO, Form22c.THE_ONE, true); + Opcodes.NO_NEXT, Form22c.THE_ONE, true); public static final Dop ARRAY_LENGTH = new Dop(Opcodes.ARRAY_LENGTH, Opcodes.ARRAY_LENGTH, @@ -204,11 +201,11 @@ public final class Dops { public static final Dop NEW_INSTANCE = new Dop(Opcodes.NEW_INSTANCE, Opcodes.NEW_INSTANCE, - Opcodes.NEW_INSTANCE_JUMBO, Form21c.THE_ONE, true); + Opcodes.NO_NEXT, Form21c.THE_ONE, true); public static final Dop NEW_ARRAY = new Dop(Opcodes.NEW_ARRAY, Opcodes.NEW_ARRAY, - Opcodes.NEW_ARRAY_JUMBO, Form22c.THE_ONE, true); + Opcodes.NO_NEXT, Form22c.THE_ONE, true); public static final Dop FILLED_NEW_ARRAY = new Dop(Opcodes.FILLED_NEW_ARRAY, Opcodes.FILLED_NEW_ARRAY, @@ -216,7 +213,7 @@ public final class Dops { public static final Dop FILLED_NEW_ARRAY_RANGE = new Dop(Opcodes.FILLED_NEW_ARRAY_RANGE, Opcodes.FILLED_NEW_ARRAY, - Opcodes.FILLED_NEW_ARRAY_JUMBO, Form3rc.THE_ONE, false); + Opcodes.NO_NEXT, Form3rc.THE_ONE, false); public static final Dop FILL_ARRAY_DATA = new Dop(Opcodes.FILL_ARRAY_DATA, Opcodes.FILL_ARRAY_DATA, @@ -372,115 +369,115 @@ public final class Dops { public static final Dop IGET = new Dop(Opcodes.IGET, Opcodes.IGET, - Opcodes.IGET_JUMBO, Form22c.THE_ONE, true); + Opcodes.NO_NEXT, Form22c.THE_ONE, true); public static final Dop IGET_WIDE = new Dop(Opcodes.IGET_WIDE, Opcodes.IGET_WIDE, - Opcodes.IGET_WIDE_JUMBO, Form22c.THE_ONE, true); + Opcodes.NO_NEXT, Form22c.THE_ONE, true); public static final Dop IGET_OBJECT = new Dop(Opcodes.IGET_OBJECT, Opcodes.IGET_OBJECT, - Opcodes.IGET_OBJECT_JUMBO, Form22c.THE_ONE, true); + Opcodes.NO_NEXT, Form22c.THE_ONE, true); public static final Dop IGET_BOOLEAN = new Dop(Opcodes.IGET_BOOLEAN, Opcodes.IGET_BOOLEAN, - Opcodes.IGET_BOOLEAN_JUMBO, Form22c.THE_ONE, true); + Opcodes.NO_NEXT, Form22c.THE_ONE, true); public static final Dop IGET_BYTE = new Dop(Opcodes.IGET_BYTE, Opcodes.IGET_BYTE, - Opcodes.IGET_BYTE_JUMBO, Form22c.THE_ONE, true); + Opcodes.NO_NEXT, Form22c.THE_ONE, true); public static final Dop IGET_CHAR = new Dop(Opcodes.IGET_CHAR, Opcodes.IGET_CHAR, - Opcodes.IGET_CHAR_JUMBO, Form22c.THE_ONE, true); + Opcodes.NO_NEXT, Form22c.THE_ONE, true); public static final Dop IGET_SHORT = new Dop(Opcodes.IGET_SHORT, Opcodes.IGET_SHORT, - Opcodes.IGET_SHORT_JUMBO, Form22c.THE_ONE, true); + Opcodes.NO_NEXT, Form22c.THE_ONE, true); public static final Dop IPUT = new Dop(Opcodes.IPUT, Opcodes.IPUT, - Opcodes.IPUT_JUMBO, Form22c.THE_ONE, false); + Opcodes.NO_NEXT, Form22c.THE_ONE, false); public static final Dop IPUT_WIDE = new Dop(Opcodes.IPUT_WIDE, Opcodes.IPUT_WIDE, - Opcodes.IPUT_WIDE_JUMBO, Form22c.THE_ONE, false); + Opcodes.NO_NEXT, Form22c.THE_ONE, false); public static final Dop IPUT_OBJECT = new Dop(Opcodes.IPUT_OBJECT, Opcodes.IPUT_OBJECT, - Opcodes.IPUT_OBJECT_JUMBO, Form22c.THE_ONE, false); + Opcodes.NO_NEXT, Form22c.THE_ONE, false); public static final Dop IPUT_BOOLEAN = new Dop(Opcodes.IPUT_BOOLEAN, Opcodes.IPUT_BOOLEAN, - Opcodes.IPUT_BOOLEAN_JUMBO, Form22c.THE_ONE, false); + Opcodes.NO_NEXT, Form22c.THE_ONE, false); public static final Dop IPUT_BYTE = new Dop(Opcodes.IPUT_BYTE, Opcodes.IPUT_BYTE, - Opcodes.IPUT_BYTE_JUMBO, Form22c.THE_ONE, false); + Opcodes.NO_NEXT, Form22c.THE_ONE, false); public static final Dop IPUT_CHAR = new Dop(Opcodes.IPUT_CHAR, Opcodes.IPUT_CHAR, - Opcodes.IPUT_CHAR_JUMBO, Form22c.THE_ONE, false); + Opcodes.NO_NEXT, Form22c.THE_ONE, false); public static final Dop IPUT_SHORT = new Dop(Opcodes.IPUT_SHORT, Opcodes.IPUT_SHORT, - Opcodes.IPUT_SHORT_JUMBO, Form22c.THE_ONE, false); + Opcodes.NO_NEXT, Form22c.THE_ONE, false); public static final Dop SGET = new Dop(Opcodes.SGET, Opcodes.SGET, - Opcodes.SGET_JUMBO, Form21c.THE_ONE, true); + Opcodes.NO_NEXT, Form21c.THE_ONE, true); public static final Dop SGET_WIDE = new Dop(Opcodes.SGET_WIDE, Opcodes.SGET_WIDE, - Opcodes.SGET_WIDE_JUMBO, Form21c.THE_ONE, true); + Opcodes.NO_NEXT, Form21c.THE_ONE, true); public static final Dop SGET_OBJECT = new Dop(Opcodes.SGET_OBJECT, Opcodes.SGET_OBJECT, - Opcodes.SGET_OBJECT_JUMBO, Form21c.THE_ONE, true); + Opcodes.NO_NEXT, Form21c.THE_ONE, true); public static final Dop SGET_BOOLEAN = new Dop(Opcodes.SGET_BOOLEAN, Opcodes.SGET_BOOLEAN, - Opcodes.SGET_BOOLEAN_JUMBO, Form21c.THE_ONE, true); + Opcodes.NO_NEXT, Form21c.THE_ONE, true); public static final Dop SGET_BYTE = new Dop(Opcodes.SGET_BYTE, Opcodes.SGET_BYTE, - Opcodes.SGET_BYTE_JUMBO, Form21c.THE_ONE, true); + Opcodes.NO_NEXT, Form21c.THE_ONE, true); public static final Dop SGET_CHAR = new Dop(Opcodes.SGET_CHAR, Opcodes.SGET_CHAR, - Opcodes.SGET_CHAR_JUMBO, Form21c.THE_ONE, true); + Opcodes.NO_NEXT, Form21c.THE_ONE, true); public static final Dop SGET_SHORT = new Dop(Opcodes.SGET_SHORT, Opcodes.SGET_SHORT, - Opcodes.SGET_SHORT_JUMBO, Form21c.THE_ONE, true); + Opcodes.NO_NEXT, Form21c.THE_ONE, true); public static final Dop SPUT = new Dop(Opcodes.SPUT, Opcodes.SPUT, - Opcodes.SPUT_JUMBO, Form21c.THE_ONE, false); + Opcodes.NO_NEXT, Form21c.THE_ONE, false); public static final Dop SPUT_WIDE = new Dop(Opcodes.SPUT_WIDE, Opcodes.SPUT_WIDE, - Opcodes.SPUT_WIDE_JUMBO, Form21c.THE_ONE, false); + Opcodes.NO_NEXT, Form21c.THE_ONE, false); public static final Dop SPUT_OBJECT = new Dop(Opcodes.SPUT_OBJECT, Opcodes.SPUT_OBJECT, - Opcodes.SPUT_OBJECT_JUMBO, Form21c.THE_ONE, false); + Opcodes.NO_NEXT, Form21c.THE_ONE, false); public static final Dop SPUT_BOOLEAN = new Dop(Opcodes.SPUT_BOOLEAN, Opcodes.SPUT_BOOLEAN, - Opcodes.SPUT_BOOLEAN_JUMBO, Form21c.THE_ONE, false); + Opcodes.NO_NEXT, Form21c.THE_ONE, false); public static final Dop SPUT_BYTE = new Dop(Opcodes.SPUT_BYTE, Opcodes.SPUT_BYTE, - Opcodes.SPUT_BYTE_JUMBO, Form21c.THE_ONE, false); + Opcodes.NO_NEXT, Form21c.THE_ONE, false); public static final Dop SPUT_CHAR = new Dop(Opcodes.SPUT_CHAR, Opcodes.SPUT_CHAR, - Opcodes.SPUT_CHAR_JUMBO, Form21c.THE_ONE, false); + Opcodes.NO_NEXT, Form21c.THE_ONE, false); public static final Dop SPUT_SHORT = new Dop(Opcodes.SPUT_SHORT, Opcodes.SPUT_SHORT, - Opcodes.SPUT_SHORT_JUMBO, Form21c.THE_ONE, false); + Opcodes.NO_NEXT, Form21c.THE_ONE, false); public static final Dop INVOKE_VIRTUAL = new Dop(Opcodes.INVOKE_VIRTUAL, Opcodes.INVOKE_VIRTUAL, @@ -504,23 +501,23 @@ public final class Dops { public static final Dop INVOKE_VIRTUAL_RANGE = new Dop(Opcodes.INVOKE_VIRTUAL_RANGE, Opcodes.INVOKE_VIRTUAL, - Opcodes.INVOKE_VIRTUAL_JUMBO, Form3rc.THE_ONE, false); + Opcodes.NO_NEXT, Form3rc.THE_ONE, false); public static final Dop INVOKE_SUPER_RANGE = new Dop(Opcodes.INVOKE_SUPER_RANGE, Opcodes.INVOKE_SUPER, - Opcodes.INVOKE_SUPER_JUMBO, Form3rc.THE_ONE, false); + Opcodes.NO_NEXT, Form3rc.THE_ONE, false); public static final Dop INVOKE_DIRECT_RANGE = new Dop(Opcodes.INVOKE_DIRECT_RANGE, Opcodes.INVOKE_DIRECT, - Opcodes.INVOKE_DIRECT_JUMBO, Form3rc.THE_ONE, false); + Opcodes.NO_NEXT, Form3rc.THE_ONE, false); public static final Dop INVOKE_STATIC_RANGE = new Dop(Opcodes.INVOKE_STATIC_RANGE, Opcodes.INVOKE_STATIC, - Opcodes.INVOKE_STATIC_JUMBO, Form3rc.THE_ONE, false); + Opcodes.NO_NEXT, Form3rc.THE_ONE, false); public static final Dop INVOKE_INTERFACE_RANGE = new Dop(Opcodes.INVOKE_INTERFACE_RANGE, Opcodes.INVOKE_INTERFACE, - Opcodes.INVOKE_INTERFACE_JUMBO, Form3rc.THE_ONE, false); + Opcodes.NO_NEXT, Form3rc.THE_ONE, false); public static final Dop NEG_INT = new Dop(Opcodes.NEG_INT, Opcodes.NEG_INT, @@ -938,162 +935,6 @@ public final class Dops { new Dop(Opcodes.USHR_INT_LIT8, Opcodes.USHR_INT, Opcodes.NO_NEXT, Form22b.THE_ONE, true); - public static final Dop CONST_CLASS_JUMBO = - new Dop(Opcodes.CONST_CLASS_JUMBO, Opcodes.CONST_CLASS, - Opcodes.NO_NEXT, Form41c.THE_ONE, true); - - public static final Dop CHECK_CAST_JUMBO = - new Dop(Opcodes.CHECK_CAST_JUMBO, Opcodes.CHECK_CAST, - Opcodes.NO_NEXT, Form41c.THE_ONE, false); - - public static final Dop INSTANCE_OF_JUMBO = - new Dop(Opcodes.INSTANCE_OF_JUMBO, Opcodes.INSTANCE_OF, - Opcodes.NO_NEXT, Form52c.THE_ONE, true); - - public static final Dop NEW_INSTANCE_JUMBO = - new Dop(Opcodes.NEW_INSTANCE_JUMBO, Opcodes.NEW_INSTANCE, - Opcodes.NO_NEXT, Form41c.THE_ONE, true); - - public static final Dop NEW_ARRAY_JUMBO = - new Dop(Opcodes.NEW_ARRAY_JUMBO, Opcodes.NEW_ARRAY, - Opcodes.NO_NEXT, Form52c.THE_ONE, true); - - public static final Dop FILLED_NEW_ARRAY_JUMBO = - new Dop(Opcodes.FILLED_NEW_ARRAY_JUMBO, Opcodes.FILLED_NEW_ARRAY, - Opcodes.NO_NEXT, Form5rc.THE_ONE, false); - - public static final Dop IGET_JUMBO = - new Dop(Opcodes.IGET_JUMBO, Opcodes.IGET, - Opcodes.NO_NEXT, Form52c.THE_ONE, true); - - public static final Dop IGET_WIDE_JUMBO = - new Dop(Opcodes.IGET_WIDE_JUMBO, Opcodes.IGET_WIDE, - Opcodes.NO_NEXT, Form52c.THE_ONE, true); - - public static final Dop IGET_OBJECT_JUMBO = - new Dop(Opcodes.IGET_OBJECT_JUMBO, Opcodes.IGET_OBJECT, - Opcodes.NO_NEXT, Form52c.THE_ONE, true); - - public static final Dop IGET_BOOLEAN_JUMBO = - new Dop(Opcodes.IGET_BOOLEAN_JUMBO, Opcodes.IGET_BOOLEAN, - Opcodes.NO_NEXT, Form52c.THE_ONE, true); - - public static final Dop IGET_BYTE_JUMBO = - new Dop(Opcodes.IGET_BYTE_JUMBO, Opcodes.IGET_BYTE, - Opcodes.NO_NEXT, Form52c.THE_ONE, true); - - public static final Dop IGET_CHAR_JUMBO = - new Dop(Opcodes.IGET_CHAR_JUMBO, Opcodes.IGET_CHAR, - Opcodes.NO_NEXT, Form52c.THE_ONE, true); - - public static final Dop IGET_SHORT_JUMBO = - new Dop(Opcodes.IGET_SHORT_JUMBO, Opcodes.IGET_SHORT, - Opcodes.NO_NEXT, Form52c.THE_ONE, true); - - public static final Dop IPUT_JUMBO = - new Dop(Opcodes.IPUT_JUMBO, Opcodes.IPUT, - Opcodes.NO_NEXT, Form52c.THE_ONE, false); - - public static final Dop IPUT_WIDE_JUMBO = - new Dop(Opcodes.IPUT_WIDE_JUMBO, Opcodes.IPUT_WIDE, - Opcodes.NO_NEXT, Form52c.THE_ONE, false); - - public static final Dop IPUT_OBJECT_JUMBO = - new Dop(Opcodes.IPUT_OBJECT_JUMBO, Opcodes.IPUT_OBJECT, - Opcodes.NO_NEXT, Form52c.THE_ONE, false); - - public static final Dop IPUT_BOOLEAN_JUMBO = - new Dop(Opcodes.IPUT_BOOLEAN_JUMBO, Opcodes.IPUT_BOOLEAN, - Opcodes.NO_NEXT, Form52c.THE_ONE, false); - - public static final Dop IPUT_BYTE_JUMBO = - new Dop(Opcodes.IPUT_BYTE_JUMBO, Opcodes.IPUT_BYTE, - Opcodes.NO_NEXT, Form52c.THE_ONE, false); - - public static final Dop IPUT_CHAR_JUMBO = - new Dop(Opcodes.IPUT_CHAR_JUMBO, Opcodes.IPUT_CHAR, - Opcodes.NO_NEXT, Form52c.THE_ONE, false); - - public static final Dop IPUT_SHORT_JUMBO = - new Dop(Opcodes.IPUT_SHORT_JUMBO, Opcodes.IPUT_SHORT, - Opcodes.NO_NEXT, Form52c.THE_ONE, false); - - public static final Dop SGET_JUMBO = - new Dop(Opcodes.SGET_JUMBO, Opcodes.SGET, - Opcodes.NO_NEXT, Form41c.THE_ONE, true); - - public static final Dop SGET_WIDE_JUMBO = - new Dop(Opcodes.SGET_WIDE_JUMBO, Opcodes.SGET_WIDE, - Opcodes.NO_NEXT, Form41c.THE_ONE, true); - - public static final Dop SGET_OBJECT_JUMBO = - new Dop(Opcodes.SGET_OBJECT_JUMBO, Opcodes.SGET_OBJECT, - Opcodes.NO_NEXT, Form41c.THE_ONE, true); - - public static final Dop SGET_BOOLEAN_JUMBO = - new Dop(Opcodes.SGET_BOOLEAN_JUMBO, Opcodes.SGET_BOOLEAN, - Opcodes.NO_NEXT, Form41c.THE_ONE, true); - - public static final Dop SGET_BYTE_JUMBO = - new Dop(Opcodes.SGET_BYTE_JUMBO, Opcodes.SGET_BYTE, - Opcodes.NO_NEXT, Form41c.THE_ONE, true); - - public static final Dop SGET_CHAR_JUMBO = - new Dop(Opcodes.SGET_CHAR_JUMBO, Opcodes.SGET_CHAR, - Opcodes.NO_NEXT, Form41c.THE_ONE, true); - - public static final Dop SGET_SHORT_JUMBO = - new Dop(Opcodes.SGET_SHORT_JUMBO, Opcodes.SGET_SHORT, - Opcodes.NO_NEXT, Form41c.THE_ONE, true); - - public static final Dop SPUT_JUMBO = - new Dop(Opcodes.SPUT_JUMBO, Opcodes.SPUT, - Opcodes.NO_NEXT, Form41c.THE_ONE, false); - - public static final Dop SPUT_WIDE_JUMBO = - new Dop(Opcodes.SPUT_WIDE_JUMBO, Opcodes.SPUT_WIDE, - Opcodes.NO_NEXT, Form41c.THE_ONE, false); - - public static final Dop SPUT_OBJECT_JUMBO = - new Dop(Opcodes.SPUT_OBJECT_JUMBO, Opcodes.SPUT_OBJECT, - Opcodes.NO_NEXT, Form41c.THE_ONE, false); - - public static final Dop SPUT_BOOLEAN_JUMBO = - new Dop(Opcodes.SPUT_BOOLEAN_JUMBO, Opcodes.SPUT_BOOLEAN, - Opcodes.NO_NEXT, Form41c.THE_ONE, false); - - public static final Dop SPUT_BYTE_JUMBO = - new Dop(Opcodes.SPUT_BYTE_JUMBO, Opcodes.SPUT_BYTE, - Opcodes.NO_NEXT, Form41c.THE_ONE, false); - - public static final Dop SPUT_CHAR_JUMBO = - new Dop(Opcodes.SPUT_CHAR_JUMBO, Opcodes.SPUT_CHAR, - Opcodes.NO_NEXT, Form41c.THE_ONE, false); - - public static final Dop SPUT_SHORT_JUMBO = - new Dop(Opcodes.SPUT_SHORT_JUMBO, Opcodes.SPUT_SHORT, - Opcodes.NO_NEXT, Form41c.THE_ONE, false); - - public static final Dop INVOKE_VIRTUAL_JUMBO = - new Dop(Opcodes.INVOKE_VIRTUAL_JUMBO, Opcodes.INVOKE_VIRTUAL, - Opcodes.NO_NEXT, Form5rc.THE_ONE, false); - - public static final Dop INVOKE_SUPER_JUMBO = - new Dop(Opcodes.INVOKE_SUPER_JUMBO, Opcodes.INVOKE_SUPER, - Opcodes.NO_NEXT, Form5rc.THE_ONE, false); - - public static final Dop INVOKE_DIRECT_JUMBO = - new Dop(Opcodes.INVOKE_DIRECT_JUMBO, Opcodes.INVOKE_DIRECT, - Opcodes.NO_NEXT, Form5rc.THE_ONE, false); - - public static final Dop INVOKE_STATIC_JUMBO = - new Dop(Opcodes.INVOKE_STATIC_JUMBO, Opcodes.INVOKE_STATIC, - Opcodes.NO_NEXT, Form5rc.THE_ONE, false); - - public static final Dop INVOKE_INTERFACE_JUMBO = - new Dop(Opcodes.INVOKE_INTERFACE_JUMBO, Opcodes.INVOKE_INTERFACE, - Opcodes.NO_NEXT, Form5rc.THE_ONE, false); - // END(dops) // Static initialization. @@ -1321,45 +1162,6 @@ public final class Dops { set(SHL_INT_LIT8); set(SHR_INT_LIT8); set(USHR_INT_LIT8); - set(CONST_CLASS_JUMBO); - set(CHECK_CAST_JUMBO); - set(INSTANCE_OF_JUMBO); - set(NEW_INSTANCE_JUMBO); - set(NEW_ARRAY_JUMBO); - set(FILLED_NEW_ARRAY_JUMBO); - set(IGET_JUMBO); - set(IGET_WIDE_JUMBO); - set(IGET_OBJECT_JUMBO); - set(IGET_BOOLEAN_JUMBO); - set(IGET_BYTE_JUMBO); - set(IGET_CHAR_JUMBO); - set(IGET_SHORT_JUMBO); - set(IPUT_JUMBO); - set(IPUT_WIDE_JUMBO); - set(IPUT_OBJECT_JUMBO); - set(IPUT_BOOLEAN_JUMBO); - set(IPUT_BYTE_JUMBO); - set(IPUT_CHAR_JUMBO); - set(IPUT_SHORT_JUMBO); - set(SGET_JUMBO); - set(SGET_WIDE_JUMBO); - set(SGET_OBJECT_JUMBO); - set(SGET_BOOLEAN_JUMBO); - set(SGET_BYTE_JUMBO); - set(SGET_CHAR_JUMBO); - set(SGET_SHORT_JUMBO); - set(SPUT_JUMBO); - set(SPUT_WIDE_JUMBO); - set(SPUT_OBJECT_JUMBO); - set(SPUT_BOOLEAN_JUMBO); - set(SPUT_BYTE_JUMBO); - set(SPUT_CHAR_JUMBO); - set(SPUT_SHORT_JUMBO); - set(INVOKE_VIRTUAL_JUMBO); - set(INVOKE_SUPER_JUMBO); - set(INVOKE_DIRECT_JUMBO); - set(INVOKE_STATIC_JUMBO); - set(INVOKE_INTERFACE_JUMBO); // END(dops-init) } diff --git a/dx/src/com/android/dx/dex/code/InsnFormat.java b/dx/src/com/android/dx/dex/code/InsnFormat.java index bf9f08e52..c866fecdc 100644 --- a/dx/src/com/android/dx/dex/code/InsnFormat.java +++ b/dx/src/com/android/dx/dex/code/InsnFormat.java @@ -507,9 +507,8 @@ public abstract class InsnFormat { protected static short opcodeUnit(DalvInsn insn) { int opcode = insn.getOpcode().getOpcode(); - if ((opcode < 0xff) || (opcode > 0xffff)) { - throw new IllegalArgumentException( - "extended opcode out of range 255..65535"); + if ((opcode < 0x100) || (opcode > 0xffff)) { + throw new IllegalArgumentException("opcode out of range 0..65535"); } return (short) opcode; diff --git a/dx/src/com/android/dx/dex/code/form/Form32s.java b/dx/src/com/android/dx/dex/code/form/Form32s.java deleted file mode 100644 index e08147056..000000000 --- a/dx/src/com/android/dx/dex/code/form/Form32s.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.dex.code.form; - -import com.android.dx.dex.code.CstInsn; -import com.android.dx.dex.code.DalvInsn; -import com.android.dx.dex.code.InsnFormat; -import com.android.dx.rop.code.RegisterSpecList; -import com.android.dx.rop.cst.Constant; -import com.android.dx.rop.cst.CstLiteralBits; -import com.android.dx.util.AnnotatedOutput; - -import java.util.BitSet; - -/** - * Instruction format {@code 32s}. See the instruction format spec - * for details. - */ -public final class Form32s extends InsnFormat { - /** {@code non-null;} unique instance of this class */ - public static final InsnFormat THE_ONE = new Form32s(); - - /** - * Constructs an instance. This class is not publicly - * instantiable. Use {@link #THE_ONE}. - */ - private Form32s() { - // This space intentionally left blank. - } - - /** {@inheritDoc} */ - @Override - public String insnArgString(DalvInsn insn) { - RegisterSpecList regs = insn.getRegisters(); - CstLiteralBits value = (CstLiteralBits) ((CstInsn) insn).getConstant(); - - return regs.get(0).regString() + ", " + regs.get(1).regString() - + ", " + literalBitsString(value); - } - - /** {@inheritDoc} */ - @Override - public String insnCommentString(DalvInsn insn, boolean noteIndices) { - CstLiteralBits value = (CstLiteralBits) ((CstInsn) insn).getConstant(); - return literalBitsComment(value, 16); - } - - /** {@inheritDoc} */ - @Override - public int codeSize() { - return 3; - } - - /** {@inheritDoc} */ - @Override - public boolean isCompatible(DalvInsn insn) { - if (! ALLOW_EXTENDED_OPCODES) { - return false; - } - - RegisterSpecList regs = insn.getRegisters(); - if (!((insn instanceof CstInsn) && - (regs.size() == 2) && - unsignedFitsInByte(regs.get(0).getReg()) && - unsignedFitsInByte(regs.get(1).getReg()))) { - return false; - } - - CstInsn ci = (CstInsn) insn; - Constant cst = ci.getConstant(); - - if (!(cst instanceof CstLiteralBits)) { - return false; - } - - CstLiteralBits cb = (CstLiteralBits) cst; - - return cb.fitsInInt() && signedFitsInShort(cb.getIntBits()); - } - - /** {@inheritDoc} */ - @Override - public BitSet compatibleRegs(DalvInsn insn) { - RegisterSpecList regs = insn.getRegisters(); - BitSet bits = new BitSet(2); - - bits.set(0, unsignedFitsInByte(regs.get(0).getReg())); - bits.set(1, unsignedFitsInByte(regs.get(1).getReg())); - return bits; - } - - /** {@inheritDoc} */ - @Override - public void writeTo(AnnotatedOutput out, DalvInsn insn) { - RegisterSpecList regs = insn.getRegisters(); - int value = - ((CstLiteralBits) ((CstInsn) insn).getConstant()).getIntBits(); - - write(out, - opcodeUnit(insn), - codeUnit(regs.get(0).getReg(), regs.get(1).getReg()), - (short) value); - } -} diff --git a/dx/src/com/android/dx/dex/code/form/Form33x.java b/dx/src/com/android/dx/dex/code/form/Form33x.java deleted file mode 100644 index 9a569a000..000000000 --- a/dx/src/com/android/dx/dex/code/form/Form33x.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.dex.code.form; - -import com.android.dx.dex.code.DalvInsn; -import com.android.dx.dex.code.InsnFormat; -import com.android.dx.dex.code.SimpleInsn; -import com.android.dx.rop.code.RegisterSpecList; -import com.android.dx.util.AnnotatedOutput; - -import java.util.BitSet; - -/** - * Instruction format {@code 33x}. See the instruction format spec - * for details. - */ -public final class Form33x extends InsnFormat { - /** {@code non-null;} unique instance of this class */ - public static final InsnFormat THE_ONE = new Form33x(); - - /** - * Constructs an instance. This class is not publicly - * instantiable. Use {@link #THE_ONE}. - */ - private Form33x() { - // This space intentionally left blank. - } - - /** {@inheritDoc} */ - @Override - public String insnArgString(DalvInsn insn) { - RegisterSpecList regs = insn.getRegisters(); - return regs.get(0).regString() + ", " + regs.get(1).regString() + - ", " + regs.get(2).regString(); - } - - /** {@inheritDoc} */ - @Override - public String insnCommentString(DalvInsn insn, boolean noteIndices) { - // This format has no comment. - return ""; - } - - /** {@inheritDoc} */ - @Override - public int codeSize() { - return 3; - } - - /** {@inheritDoc} */ - @Override - public boolean isCompatible(DalvInsn insn) { - if (! ALLOW_EXTENDED_OPCODES) { - return false; - } - - RegisterSpecList regs = insn.getRegisters(); - - return (insn instanceof SimpleInsn) && - (regs.size() == 3) && - unsignedFitsInByte(regs.get(0).getReg()) && - unsignedFitsInByte(regs.get(1).getReg()) && - unsignedFitsInShort(regs.get(2).getReg()); - } - - /** {@inheritDoc} */ - @Override - public BitSet compatibleRegs(DalvInsn insn) { - RegisterSpecList regs = insn.getRegisters(); - BitSet bits = new BitSet(3); - - bits.set(0, unsignedFitsInByte(regs.get(0).getReg())); - bits.set(1, unsignedFitsInByte(regs.get(1).getReg())); - bits.set(2, unsignedFitsInShort(regs.get(2).getReg())); - return bits; - } - - /** {@inheritDoc} */ - @Override - public void writeTo(AnnotatedOutput out, DalvInsn insn) { - RegisterSpecList regs = insn.getRegisters(); - write(out, - opcodeUnit(insn), - codeUnit(regs.get(0).getReg(), regs.get(1).getReg()), - (short) regs.get(2).getReg()); - } -} diff --git a/dx/src/com/android/dx/dex/code/form/Form41c.java b/dx/src/com/android/dx/dex/code/form/Form41c.java deleted file mode 100644 index 24067bce4..000000000 --- a/dx/src/com/android/dx/dex/code/form/Form41c.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.dex.code.form; - -import com.android.dx.dex.code.CstInsn; -import com.android.dx.dex.code.DalvInsn; -import com.android.dx.dex.code.InsnFormat; -import com.android.dx.rop.code.RegisterSpec; -import com.android.dx.rop.code.RegisterSpecList; -import com.android.dx.rop.cst.Constant; -import com.android.dx.rop.cst.CstFieldRef; -import com.android.dx.rop.cst.CstType; -import com.android.dx.util.AnnotatedOutput; - -import java.util.BitSet; - -/** - * Instruction format {@code 41c}. See the instruction format spec - * for details. - */ -public final class Form41c extends InsnFormat { - /** {@code non-null;} unique instance of this class */ - public static final InsnFormat THE_ONE = new Form41c(); - - /** - * Constructs an instance. This class is not publicly - * instantiable. Use {@link #THE_ONE}. - */ - private Form41c() { - // This space intentionally left blank. - } - - /** {@inheritDoc} */ - @Override - public String insnArgString(DalvInsn insn) { - RegisterSpecList regs = insn.getRegisters(); - return regs.get(0).regString() + ", " + cstString(insn); - } - - /** {@inheritDoc} */ - @Override - public String insnCommentString(DalvInsn insn, boolean noteIndices) { - if (noteIndices) { - return cstComment(insn); - } else { - return ""; - } - } - - /** {@inheritDoc} */ - @Override - public int codeSize() { - return 4; - } - - /** {@inheritDoc} */ - @Override - public boolean isCompatible(DalvInsn insn) { - if (! ALLOW_EXTENDED_OPCODES) { - return false; - } - - if (!(insn instanceof CstInsn)) { - return false; - } - - RegisterSpecList regs = insn.getRegisters(); - RegisterSpec reg; - - switch (regs.size()) { - case 1: { - reg = regs.get(0); - break; - } - case 2: { - /* - * This format is allowed for ops that are effectively - * 2-arg but where the two args are identical. - */ - reg = regs.get(0); - if (reg.getReg() != regs.get(1).getReg()) { - return false; - } - break; - } - default: { - return false; - } - } - - if (!unsignedFitsInShort(reg.getReg())) { - return false; - } - - CstInsn ci = (CstInsn) insn; - Constant cst = ci.getConstant(); - - return (cst instanceof CstType) || - (cst instanceof CstFieldRef); - } - - /** {@inheritDoc} */ - @Override - public BitSet compatibleRegs(DalvInsn insn) { - RegisterSpecList regs = insn.getRegisters(); - int sz = regs.size(); - BitSet bits = new BitSet(sz); - boolean compat = unsignedFitsInByte(regs.get(0).getReg()); - - if (sz == 1) { - bits.set(0, compat); - } else { - if (regs.get(0).getReg() == regs.get(1).getReg()) { - bits.set(0, compat); - bits.set(1, compat); - } - } - - return bits; - } - - /** {@inheritDoc} */ - @Override - public void writeTo(AnnotatedOutput out, DalvInsn insn) { - RegisterSpecList regs = insn.getRegisters(); - int cpi = ((CstInsn) insn).getIndex(); - - write(out, opcodeUnit(insn), cpi, (short) regs.get(0).getReg()); - } -} diff --git a/dx/src/com/android/dx/dex/code/form/Form52c.java b/dx/src/com/android/dx/dex/code/form/Form52c.java deleted file mode 100644 index acd2124d6..000000000 --- a/dx/src/com/android/dx/dex/code/form/Form52c.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.dex.code.form; - -import com.android.dx.dex.code.CstInsn; -import com.android.dx.dex.code.DalvInsn; -import com.android.dx.dex.code.InsnFormat; -import com.android.dx.rop.code.RegisterSpecList; -import com.android.dx.rop.cst.Constant; -import com.android.dx.rop.cst.CstFieldRef; -import com.android.dx.rop.cst.CstType; -import com.android.dx.util.AnnotatedOutput; - -import java.util.BitSet; - -/** - * Instruction format {@code 52c}. See the instruction format spec - * for details. - */ -public final class Form52c extends InsnFormat { - /** {@code non-null;} unique instance of this class */ - public static final InsnFormat THE_ONE = new Form52c(); - - /** - * Constructs an instance. This class is not publicly - * instantiable. Use {@link #THE_ONE}. - */ - private Form52c() { - // This space intentionally left blank. - } - - /** {@inheritDoc} */ - @Override - public String insnArgString(DalvInsn insn) { - RegisterSpecList regs = insn.getRegisters(); - return regs.get(0).regString() + ", " + regs.get(1).regString() + - ", " + cstString(insn); - } - - /** {@inheritDoc} */ - @Override - public String insnCommentString(DalvInsn insn, boolean noteIndices) { - if (noteIndices) { - return cstComment(insn); - } else { - return ""; - } - } - - /** {@inheritDoc} */ - @Override - public int codeSize() { - return 5; - } - - /** {@inheritDoc} */ - @Override - public boolean isCompatible(DalvInsn insn) { - if (! ALLOW_EXTENDED_OPCODES) { - return false; - } - - RegisterSpecList regs = insn.getRegisters(); - if (!((insn instanceof CstInsn) && - (regs.size() == 2) && - unsignedFitsInShort(regs.get(0).getReg()) && - unsignedFitsInShort(regs.get(1).getReg()))) { - return false; - } - - CstInsn ci = (CstInsn) insn; - Constant cst = ci.getConstant(); - - return (cst instanceof CstType) || - (cst instanceof CstFieldRef); - } - - /** {@inheritDoc} */ - @Override - public BitSet compatibleRegs(DalvInsn insn) { - RegisterSpecList regs = insn.getRegisters(); - BitSet bits = new BitSet(2); - - bits.set(0, unsignedFitsInShort(regs.get(0).getReg())); - bits.set(1, unsignedFitsInShort(regs.get(1).getReg())); - return bits; - } - - /** {@inheritDoc} */ - @Override - public void writeTo(AnnotatedOutput out, DalvInsn insn) { - RegisterSpecList regs = insn.getRegisters(); - int cpi = ((CstInsn) insn).getIndex(); - - write(out, - opcodeUnit(insn), - cpi, - (short) regs.get(0).getReg(), - (short) regs.get(1).getReg()); - } -} diff --git a/dx/src/com/android/dx/dex/code/form/Form5rc.java b/dx/src/com/android/dx/dex/code/form/Form5rc.java deleted file mode 100644 index 0c5470252..000000000 --- a/dx/src/com/android/dx/dex/code/form/Form5rc.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.dex.code.form; - -import com.android.dx.dex.code.CstInsn; -import com.android.dx.dex.code.DalvInsn; -import com.android.dx.dex.code.InsnFormat; -import com.android.dx.rop.code.RegisterSpecList; -import com.android.dx.rop.cst.Constant; -import com.android.dx.rop.cst.CstMethodRef; -import com.android.dx.rop.cst.CstType; -import com.android.dx.util.AnnotatedOutput; - -/** - * Instruction format {@code 5rc}. See the instruction format spec - * for details. - */ -public final class Form5rc extends InsnFormat { - /** {@code non-null;} unique instance of this class */ - public static final InsnFormat THE_ONE = new Form5rc(); - - /** - * Constructs an instance. This class is not publicly - * instantiable. Use {@link #THE_ONE}. - */ - private Form5rc() { - // This space intentionally left blank. - } - - /** {@inheritDoc} */ - @Override - public String insnArgString(DalvInsn insn) { - return regRangeString(insn.getRegisters()) + ", " + - cstString(insn); - } - - /** {@inheritDoc} */ - @Override - public String insnCommentString(DalvInsn insn, boolean noteIndices) { - if (noteIndices) { - return cstComment(insn); - } else { - return ""; - } - } - - /** {@inheritDoc} */ - @Override - public int codeSize() { - return 5; - } - - /** {@inheritDoc} */ - @Override - public boolean isCompatible(DalvInsn insn) { - if (! ALLOW_EXTENDED_OPCODES) { - return false; - } - - if (!(insn instanceof CstInsn)) { - return false; - } - - CstInsn ci = (CstInsn) insn; - Constant cst = ci.getConstant(); - - if (!((cst instanceof CstMethodRef) || - (cst instanceof CstType))) { - return false; - } - - RegisterSpecList regs = ci.getRegisters(); - int sz = regs.size(); - - return (regs.size() == 0) || - (isRegListSequential(regs) && - unsignedFitsInShort(regs.get(0).getReg()) && - unsignedFitsInShort(regs.getWordCount())); - } - - /** {@inheritDoc} */ - @Override - public void writeTo(AnnotatedOutput out, DalvInsn insn) { - RegisterSpecList regs = insn.getRegisters(); - int cpi = ((CstInsn) insn).getIndex(); - int firstReg = (regs.size() == 0) ? 0 : regs.get(0).getReg(); - int count = regs.getWordCount(); - - write(out, opcodeUnit(insn), cpi, (short) count, (short) firstReg); - } -} diff --git a/dx/src/com/android/dx/dex/file/MemberIdsSection.java b/dx/src/com/android/dx/dex/file/MemberIdsSection.java index ef0d8cd92..ee844d9de 100644 --- a/dx/src/com/android/dx/dex/file/MemberIdsSection.java +++ b/dx/src/com/android/dx/dex/file/MemberIdsSection.java @@ -16,10 +16,19 @@ package com.android.dx.dex.file; +import com.android.dx.util.DexException; +import java.util.Formatter; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.atomic.AtomicInteger; + /** * Member (field or method) refs list section of a {@code .dex} file. */ public abstract class MemberIdsSection extends UniformItemSection { + /** The largest addressable member is 0xffff, in the dex spec as field@CCCC or meth@CCCC. */ + private static final int MAX_MEMBERS = 0x10000; + /** * Constructs an instance. The file offset is initially unknown. * @@ -36,9 +45,35 @@ public abstract class MemberIdsSection extends UniformItemSection { protected void orderItems() { int idx = 0; + if (items().size() > MAX_MEMBERS) { + throw new DexException(tooManyMembersMessage()); + } + for (Object i : items()) { ((MemberIdItem) i).setIndex(idx); idx++; } } + + private String tooManyMembersMessage() { + Map<String, AtomicInteger> membersByPackage = new TreeMap<String, AtomicInteger>(); + for (Object member : items()) { + String packageName = ((MemberIdItem) member).getDefiningClass().getPackageName(); + AtomicInteger count = membersByPackage.get(packageName); + if (count == null) { + count = new AtomicInteger(); + membersByPackage.put(packageName, count); + } + count.incrementAndGet(); + } + + Formatter formatter = new Formatter(); + String memberType = this instanceof MethodIdsSection ? "methods" : "fields"; + formatter.format("Too many %s: %d; max is %d. By package:", + memberType, items().size(), MAX_MEMBERS); + for (Map.Entry<String, AtomicInteger> entry : membersByPackage.entrySet()) { + formatter.format("%n%6d %s", entry.getValue().get(), entry.getKey()); + } + return formatter.toString(); + } } diff --git a/dx/src/com/android/dx/gen/BinaryOp.java b/dx/src/com/android/dx/gen/BinaryOp.java deleted file mode 100644 index 65a29983a..000000000 --- a/dx/src/com/android/dx/gen/BinaryOp.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.gen; - -import com.android.dx.rop.code.Rop; -import com.android.dx.rop.code.Rops; -import com.android.dx.rop.type.TypeList; - -/** - * An operation on two values of the same type. - * - * <p>Math operations ({@link #ADD}, {@link #SUBTRACT}, {@link #MULTIPLY}, - * {@link #DIVIDE}, and {@link #REMAINDER}) support ints, longs, floats and - * doubles. - * - * <p>Bit operations ({@link #AND}, {@link #OR}, {@link #XOR}, {@link - * #SHIFT_LEFT}, {@link #SHIFT_RIGHT}, {@link #UNSIGNED_SHIFT_RIGHT}) support - * ints and longs. - * - * <p>Division by zero behaves differently depending on the operand type. - * For int and long operands, {@link #DIVIDE} and {@link #REMAINDER} throw - * {@link ArithmeticException} if {@code b == 0}. For float and double operands, - * the operations return {@code NaN}. - */ -public enum BinaryOp { - /** {@code a + b} */ - ADD() { - @Override Rop rop(TypeList types) { - return Rops.opAdd(types); - } - }, - - /** {@code a - b} */ - SUBTRACT() { - @Override Rop rop(TypeList types) { - return Rops.opSub(types); - } - }, - - /** {@code a * b} */ - MULTIPLY() { - @Override Rop rop(TypeList types) { - return Rops.opMul(types); - } - }, - - /** {@code a / b} */ - DIVIDE() { - @Override Rop rop(TypeList types) { - return Rops.opDiv(types); - } - }, - - /** {@code a % b} */ - REMAINDER() { - @Override Rop rop(TypeList types) { - return Rops.opRem(types); - } - }, - - /** {@code a & b} */ - AND() { - @Override Rop rop(TypeList types) { - return Rops.opAnd(types); - } - }, - - /** {@code a | b} */ - OR() { - @Override Rop rop(TypeList types) { - return Rops.opOr(types); - } - }, - - /** {@code a ^ b} */ - XOR() { - @Override Rop rop(TypeList types) { - return Rops.opXor(types); - } - }, - - /** {@code a << b} */ - SHIFT_LEFT() { - @Override Rop rop(TypeList types) { - return Rops.opShl(types); - } - }, - - /** {@code a >> b} */ - SHIFT_RIGHT() { - @Override Rop rop(TypeList types) { - return Rops.opShr(types); - } - }, - - /** {@code a >>> b} */ - UNSIGNED_SHIFT_RIGHT() { - @Override Rop rop(TypeList types) { - return Rops.opUshr(types); - } - }; - - abstract Rop rop(com.android.dx.rop.type.TypeList types); -} diff --git a/dx/src/com/android/dx/gen/Code.java b/dx/src/com/android/dx/gen/Code.java deleted file mode 100644 index b44d01cdd..000000000 --- a/dx/src/com/android/dx/gen/Code.java +++ /dev/null @@ -1,568 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.gen; - -import com.android.dx.rop.code.BasicBlockList; -import com.android.dx.rop.code.Insn; -import com.android.dx.rop.code.PlainCstInsn; -import com.android.dx.rop.code.PlainInsn; -import com.android.dx.rop.code.RegisterSpecList; -import com.android.dx.rop.code.Rop; -import static com.android.dx.rop.code.Rop.BRANCH_GOTO; -import static com.android.dx.rop.code.Rop.BRANCH_NONE; -import static com.android.dx.rop.code.Rop.BRANCH_RETURN; -import com.android.dx.rop.code.Rops; -import com.android.dx.rop.code.SourcePosition; -import com.android.dx.rop.code.ThrowingCstInsn; -import com.android.dx.rop.code.ThrowingInsn; -import com.android.dx.rop.cst.CstInteger; -import com.android.dx.rop.type.StdTypeList; -import static com.android.dx.rop.type.Type.BT_BYTE; -import static com.android.dx.rop.type.Type.BT_CHAR; -import static com.android.dx.rop.type.Type.BT_INT; -import static com.android.dx.rop.type.Type.BT_SHORT; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -/** - * Builds a sequence of instructions. - */ -public final class Code { - private final MethodId<?, ?> method; - /** - * All allocated labels. Although the order of the labels in this list - * shouldn't impact behavior, it is used to determine basic block indices. - */ - private final List<Label> labels = new ArrayList<Label>(); - - /** - * The label currently receiving instructions. This is null if the most - * recent instruction was a return or goto. - */ - private Label currentLabel; - - /** true once we've fixed the positions of the parameter registers */ - private boolean localsInitialized; - - private final Local<?> thisLocal; - private final List<Local<?>> parameters = new ArrayList<Local<?>>(); - private final List<Local<?>> locals = new ArrayList<Local<?>>(); - private SourcePosition sourcePosition = SourcePosition.NO_INFO; - private final List<Type<?>> catchTypes = new ArrayList<Type<?>>(); - private final List<Label> catchLabels = new ArrayList<Label>(); - private StdTypeList catches = StdTypeList.EMPTY; - - Code(DexGenerator.MethodDeclaration methodDeclaration) { - this.method = methodDeclaration.method; - this.thisLocal = methodDeclaration.isStatic() - ? null - : Local.get(this, method.declaringType); - for (Type<?> parameter : method.parameters.types) { - parameters.add(Local.get(this, parameter)); - } - this.currentLabel = newLabel(); - this.currentLabel.marked = true; - } - - public <T> Local<T> newLocal(Type<T> type) { - if (localsInitialized) { - throw new IllegalStateException("Cannot allocate locals after adding instructions"); - } - Local<T> result = Local.get(this, type); - locals.add(result); - return result; - } - - public <T> Local<T> getParameter(int index, Type<T> type) { - return coerce(parameters.get(index), type); - } - - public <T> Local<T> getThis(Type<T> type) { - if (thisLocal == null) { - throw new IllegalStateException("static methods cannot access 'this'"); - } - return coerce(thisLocal, type); - } - - @SuppressWarnings("unchecked") // guarded by an equals check - private <T> Local<T> coerce(Local<?> local, Type<T> expectedType) { - if (!local.type.equals(expectedType)) { - throw new IllegalArgumentException( - "requested " + expectedType + " but was " + local.type); - } - return (Local<T>) local; - } - - /** - * Assigns registers to locals. From the spec: - * "the N arguments to a method land in the last N registers of the - * method's invocation frame, in order. Wide arguments consume two - * registers. Instance methods are passed a this reference as their - * first argument." - * - * In addition to assigning registers to each of the locals, this creates - * instructions to move parameters into their initial registers. These - * instructions are inserted before the code's first real instruction. - */ - void initializeLocals() { - if (localsInitialized) { - throw new AssertionError(); - } - localsInitialized = true; - - int reg = 0; - for (Local<?> local : locals) { - reg += local.initialize(reg); - } - if (thisLocal != null) { - reg += thisLocal.initialize(reg); - } - int firstParamReg = reg; - - List<Insn> moveParameterInstructions = new ArrayList<Insn>(); - for (Local<?> local : parameters) { - CstInteger paramConstant = CstInteger.make(reg - firstParamReg); - reg += local.initialize(reg); - moveParameterInstructions.add(new PlainCstInsn(Rops.opMoveParam(local.type.ropType), - sourcePosition, local.spec(), RegisterSpecList.EMPTY, paramConstant)); - } - labels.get(0).instructions.addAll(0, moveParameterInstructions); - } - - int paramSize() { - int result = 0; - for (Local<?> local : parameters) { - result += local.size(); - } - return result; - } - - // labels - - /** - * Creates a new label for use as a branch target. The new label must have - * code attached to it later by calling {@link #mark(Label)}. - */ - public Label newLabel() { - Label result = new Label(); - labels.add(result); - return result; - } - - /** - * Start defining instructions for the named label. - */ - public void mark(Label label) { - if (label.marked) { - throw new IllegalStateException("already marked"); - } - label.marked = true; - if (currentLabel != null) { - jump(label); // blocks must end with a branch, return or throw - } - currentLabel = label; - } - - public void jump(Label target) { - addInstruction(new PlainInsn(Rops.GOTO, sourcePosition, null, RegisterSpecList.EMPTY), - target); - } - - public void addCatchClause(Type<?> throwable, Label catchClause) { - if (catchTypes.contains(throwable)) { - throw new IllegalArgumentException("Already caught: " + throwable); - } - catchTypes.add(throwable); - catches = toTypeList(catchTypes); - catchLabels.add(catchClause); - } - - public Label removeCatchClause(Type<?> throwable) { - int index = catchTypes.indexOf(throwable); - if (index == -1) { - throw new IllegalArgumentException("No catch clause: " + throwable); - } - catchTypes.remove(index); - catches = toTypeList(catchTypes); - return catchLabels.remove(index); - } - - public void throwValue(Local<?> throwable) { - addInstruction(new ThrowingInsn(Rops.THROW, sourcePosition, - RegisterSpecList.make(throwable.spec()), catches)); - } - - private StdTypeList toTypeList(List<Type<?>> types) { - StdTypeList result = new StdTypeList(types.size()); - for (int i = 0; i < types.size(); i++) { - result.set(i, types.get(i).ropType); - } - return result; - } - - private void addInstruction(Insn insn) { - addInstruction(insn, null); - } - - /** - * @param branch the branches to follow; interpretation depends on the - * instruction's branchingness. - */ - private void addInstruction(Insn insn, Label branch) { - if (currentLabel == null || !currentLabel.marked) { - throw new IllegalStateException("no current label"); - } - currentLabel.instructions.add(insn); - - switch (insn.getOpcode().getBranchingness()) { - case BRANCH_NONE: - if (branch != null) { - throw new IllegalArgumentException("unexpected branch: " + branch); - } - return; - - case BRANCH_RETURN: - if (branch != null) { - throw new IllegalArgumentException("unexpected branch: " + branch); - } - currentLabel = null; - break; - - case BRANCH_GOTO: - if (branch == null) { - throw new IllegalArgumentException("branch == null"); - } - currentLabel.primarySuccessor = branch; - currentLabel = null; - break; - - case Rop.BRANCH_IF: - if (branch == null) { - throw new IllegalArgumentException("branch == null"); - } - splitCurrentLabel(branch, Collections.<Label>emptyList()); - break; - - case Rop.BRANCH_THROW: - if (branch != null) { - throw new IllegalArgumentException("unexpected branch: " + branch); - } - splitCurrentLabel(null, new ArrayList<Label>(catchLabels)); - break; - - default: - throw new IllegalArgumentException(); - } - } - - /** - * Closes the current label and starts a new one. - * - * @param catchLabels an immutable list of catch labels - */ - private void splitCurrentLabel(Label alternateSuccessor, List<Label> catchLabels) { - Label newLabel = newLabel(); - currentLabel.primarySuccessor = newLabel; - currentLabel.alternateSuccessor = alternateSuccessor; - currentLabel.catchLabels = catchLabels; - currentLabel = newLabel; - currentLabel.marked = true; - } - - // instructions: constants - - public <T> void loadConstant(Local<T> target, T value) { - Rop rop = Rops.opConst(target.type.ropType); - if (rop.getBranchingness() == BRANCH_NONE) { - addInstruction(new PlainCstInsn(rop, sourcePosition, target.spec(), - RegisterSpecList.EMPTY, Constants.getConstant(value))); - } else { - addInstruction(new ThrowingCstInsn(rop, sourcePosition, - RegisterSpecList.EMPTY, catches, Constants.getConstant(value))); - moveResult(target, true); - } - } - - // instructions: unary - - public <T> void negate(Local<T> source, Local<T> target) { - unary(Rops.opNeg(source.type.ropType), source, target); - } - - public <T> void not(Local<T> source, Local<T> target) { - unary(Rops.opNot(source.type.ropType), source, target); - } - - public void numericCast(Local<?> source, Local<?> target) { - unary(getCastRop(source.type.ropType, target.type.ropType), source, target); - } - - private Rop getCastRop(com.android.dx.rop.type.Type sourceType, - com.android.dx.rop.type.Type targetType) { - if (sourceType.getBasicType() == BT_INT) { - switch (targetType.getBasicType()) { - case BT_SHORT: - return Rops.TO_SHORT; - case BT_CHAR: - return Rops.TO_CHAR; - case BT_BYTE: - return Rops.TO_BYTE; - } - } - return Rops.opConv(targetType, sourceType); - } - - private void unary(Rop rop, Local<?> source, Local<?> target) { - addInstruction(new PlainInsn(rop, sourcePosition, target.spec(), source.spec())); - } - - // instructions: binary - - public <T> void op(BinaryOp op, Local<T> target, Local<T> a, Local<T> b) { - Rop rop = op.rop(StdTypeList.make(a.type.ropType, b.type.ropType)); - RegisterSpecList sources = RegisterSpecList.make(a.spec(), b.spec()); - - if (rop.getBranchingness() == BRANCH_NONE) { - addInstruction(new PlainInsn(rop, sourcePosition, target.spec(), sources)); - } else { - addInstruction(new ThrowingInsn(rop, sourcePosition, sources, catches)); - moveResult(target, true); - } - } - - // instructions: branches - - /** - * Compare ints. If the comparison is true, execution jumps to {@code - * trueLabel}. If it is false, execution continues to the next instruction. - */ - public <T> void compare(Comparison comparison, Local<T> a, Local<T> b, Label trueLabel) { - if (trueLabel == null) { - throw new IllegalArgumentException(); - } - Rop rop = comparison.rop(StdTypeList.make(a.type.ropType, b.type.ropType)); - addInstruction(new PlainInsn(rop, sourcePosition, null, - RegisterSpecList.make(a.spec(), b.spec())), trueLabel); - } - - /** - * Compare floats or doubles. - */ - public <T extends Number> void compare(Local<T> a, Local<T> b, Local<Integer> target, - int nanValue) { - Rop rop; - if (nanValue == 1) { - rop = Rops.opCmpg(a.type.ropType); - } else if (nanValue == -1) { - rop = Rops.opCmpl(a.type.ropType); - } else { - throw new IllegalArgumentException("expected 1 or -1 but was " + nanValue); - } - addInstruction(new PlainInsn(rop, sourcePosition, target.spec(), - RegisterSpecList.make(a.spec(), b.spec()))); - } - - /** - * Compare longs. - */ - public <T> void compare(Local<T> a, Local<T> b, Local<?> target) { - addInstruction(new PlainInsn(Rops.CMPL_LONG, sourcePosition, target.spec(), - RegisterSpecList.make(a.spec(), b.spec()))); - } - - // instructions: fields - - public <D, V> void iget(FieldId<D, V> fieldId, Local<D> instance, Local<V> target) { - addInstruction(new ThrowingCstInsn(Rops.opGetField(target.type.ropType), sourcePosition, - RegisterSpecList.make(instance.spec()), catches, fieldId.constant)); - moveResult(target, true); - } - - public <D, V> void iput(FieldId<D, V> fieldId, Local<D> instance, Local<V> source) { - addInstruction(new ThrowingCstInsn(Rops.opPutField(source.type.ropType), sourcePosition, - RegisterSpecList.make(source.spec(), instance.spec()), catches, fieldId.constant)); - } - - public <V> void sget(FieldId<?, V> fieldId, Local<V> target) { - addInstruction(new ThrowingCstInsn(Rops.opGetStatic(target.type.ropType), sourcePosition, - RegisterSpecList.EMPTY, catches, fieldId.constant)); - moveResult(target, true); - } - - public <V> void sput(FieldId<?, V> fieldId, Local<V> source) { - addInstruction(new ThrowingCstInsn(Rops.opPutStatic(source.type.ropType), sourcePosition, - RegisterSpecList.make(source.spec()), catches, fieldId.constant)); - } - - // instructions: invoke - - public <T> void newInstance(Local<T> target, MethodId<T, Void> constructor, Local<?>... args) { - if (target == null) { - throw new IllegalArgumentException(); - } - addInstruction(new ThrowingCstInsn(Rops.NEW_INSTANCE, sourcePosition, - RegisterSpecList.EMPTY, catches, constructor.declaringType.constant)); - moveResult(target, true); - invokeDirect(constructor, null, target, args); - } - - public <R> void invokeStatic(MethodId<?, R> method, Local<? super R> target, Local<?>... args) { - invoke(Rops.opInvokeStatic(method.prototype(true)), method, target, null, args); - } - - public <D, R> void invokeVirtual(MethodId<D, R> method, Local<? super R> target, - Local<? extends D> object, Local<?>... args) { - invoke(Rops.opInvokeVirtual(method.prototype(true)), method, target, object, args); - } - - public <D, R> void invokeDirect(MethodId<D, R> method, Local<? super R> target, - Local<? extends D> object, Local<?>... args) { - invoke(Rops.opInvokeDirect(method.prototype(true)), method, target, object, args); - } - - public <D, R> void invokeSuper(MethodId<D, R> method, Local<? super R> target, - Local<? extends D> object, Local<?>... args) { - invoke(Rops.opInvokeSuper(method.prototype(true)), method, target, object, args); - } - - public <D, R> void invokeInterface(MethodId<D, R> method, Local<? super R> target, - Local<? extends D> object, Local<?>... args) { - invoke(Rops.opInvokeInterface(method.prototype(true)), method, target, object, args); - } - - private <D, R> void invoke(Rop rop, MethodId<D, R> method, Local<? super R> target, - Local<? extends D> object, Local<?>... args) { - addInstruction(new ThrowingCstInsn(rop, sourcePosition, concatenate(object, args), - catches, method.constant)); - if (target != null) { - moveResult(target, false); - } - } - - // instructions: types - - public void instanceOfType(Local<?> target, Local<?> source, Type<?> type) { - addInstruction(new ThrowingCstInsn(Rops.INSTANCE_OF, sourcePosition, - RegisterSpecList.make(source.spec()), catches, type.constant)); - moveResult(target, true); - } - - public void typeCast(Local<?> source, Local<?> target) { - addInstruction(new ThrowingCstInsn(Rops.CHECK_CAST, sourcePosition, - RegisterSpecList.make(source.spec()), catches, target.type.constant)); - moveResult(target, true); - } - - // instructions: arrays - - public <T> void arrayLength(Local<T> array, Local<Integer> target) { - addInstruction(new ThrowingInsn(Rops.ARRAY_LENGTH, sourcePosition, - RegisterSpecList.make(array.spec()), catches)); - moveResult(target, true); - } - - public <T> void newArray(Local<Integer> length, Local<T> target) { - addInstruction(new ThrowingCstInsn(Rops.opNewArray(target.type.ropType), sourcePosition, - RegisterSpecList.make(length.spec()), catches, target.type.constant)); - moveResult(target, true); - } - - public void aget(Local<?> array, Local<Integer> index, Local<?> target) { - addInstruction(new ThrowingInsn(Rops.opAget(target.type.ropType), sourcePosition, - RegisterSpecList.make(array.spec(), index.spec()), catches)); - moveResult(target, true); - } - - public void aput(Local<?> array, Local<Integer> index, Local<?> source) { - addInstruction(new ThrowingInsn(Rops.opAput(source.type.ropType), sourcePosition, - RegisterSpecList.make(source.spec(), array.spec(), index.spec()), catches)); - } - - // instructions: return - - public void returnVoid() { - if (!method.returnType.equals(Type.VOID)) { - throw new IllegalArgumentException("declared " + method.returnType - + " but returned void"); - } - addInstruction(new PlainInsn(Rops.RETURN_VOID, sourcePosition, null, - RegisterSpecList.EMPTY)); - } - - public void returnValue(Local<?> result) { - if (!result.type.equals(method.returnType)) { - // TODO: this is probably too strict. - throw new IllegalArgumentException("declared " + method.returnType - + " but returned " + result.type); - } - addInstruction(new PlainInsn(Rops.opReturn(result.type.ropType), sourcePosition, - null, RegisterSpecList.make(result.spec()))); - } - - private void moveResult(Local<?> target, boolean afterNonInvokeThrowingInsn) { - Rop rop = afterNonInvokeThrowingInsn - ? Rops.opMoveResultPseudo(target.type.ropType) - : Rops.opMoveResult(target.type.ropType); - addInstruction(new PlainInsn(rop, sourcePosition, target.spec(), RegisterSpecList.EMPTY)); - } - - // produce BasicBlocks for dex - - BasicBlockList toBasicBlocks() { - if (!localsInitialized) { - initializeLocals(); - } - - cleanUpLabels(); - - BasicBlockList result = new BasicBlockList(labels.size()); - for (int i = 0; i < labels.size(); i++) { - result.set(i, labels.get(i).toBasicBlock()); - } - return result; - } - - /** - * Removes empty labels and assigns IDs to non-empty labels. - */ - private void cleanUpLabels() { - int id = 0; - for (Iterator<Label> i = labels.iterator(); i.hasNext();) { - Label label = i.next(); - if (label.isEmpty()) { - i.remove(); - } else { - label.compact(); - label.id = id++; - } - } - } - - private static RegisterSpecList concatenate(Local<?> first, Local<?>[] rest) { - int offset = (first != null) ? 1 : 0; - RegisterSpecList result = new RegisterSpecList(offset + rest.length); - if (first != null) { - result.set(0, first.spec()); - } - for (int i = 0; i < rest.length; i++) { - result.set(i + offset, rest[i].spec()); - } - return result; - } -} diff --git a/dx/src/com/android/dx/gen/Comparison.java b/dx/src/com/android/dx/gen/Comparison.java deleted file mode 100644 index 40a6e9724..000000000 --- a/dx/src/com/android/dx/gen/Comparison.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.gen; - -import com.android.dx.rop.code.Rop; -import com.android.dx.rop.code.Rops; -import com.android.dx.rop.type.TypeList; - -/** - * A comparison between two values of the same type. - */ -public enum Comparison { - - /** {@code a < b} */ - LT() { - @Override Rop rop(TypeList types) { - return Rops.opIfLt(types); - } - }, - - /** {@code a <= b} */ - LE() { - @Override Rop rop(TypeList types) { - return Rops.opIfLe(types); - } - }, - - /** {@code a == b} */ - EQ() { - @Override Rop rop(TypeList types) { - return Rops.opIfEq(types); - } - }, - - /** {@code a >= b} */ - GE() { - @Override Rop rop(TypeList types) { - return Rops.opIfGe(types); - } - }, - - /** {@code a > b} */ - GT() { - @Override Rop rop(TypeList types) { - return Rops.opIfGt(types); - } - }, - - /** {@code a != b} */ - NE() { - @Override Rop rop(TypeList types) { - return Rops.opIfNe(types); - } - }; - - abstract Rop rop(TypeList types); -} diff --git a/dx/src/com/android/dx/gen/Constants.java b/dx/src/com/android/dx/gen/Constants.java deleted file mode 100644 index 255c2e4ce..000000000 --- a/dx/src/com/android/dx/gen/Constants.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.gen; - -import com.android.dx.rop.cst.CstBoolean; -import com.android.dx.rop.cst.CstByte; -import com.android.dx.rop.cst.CstChar; -import com.android.dx.rop.cst.CstDouble; -import com.android.dx.rop.cst.CstFloat; -import com.android.dx.rop.cst.CstInteger; -import com.android.dx.rop.cst.CstKnownNull; -import com.android.dx.rop.cst.CstLong; -import com.android.dx.rop.cst.CstShort; -import com.android.dx.rop.cst.CstString; -import com.android.dx.rop.cst.CstType; -import com.android.dx.rop.cst.TypedConstant; - -/** - * Factory for rop constants. - */ -final class Constants { - private Constants() {} - - /** - * Returns a rop constant for the specified value. - * - * @param value null, a boxed primitive, String, Class, or Type. - */ - static TypedConstant getConstant(Object value) { - if (value == null) { - return CstKnownNull.THE_ONE; - } else if (value instanceof Boolean) { - return CstBoolean.make((Boolean) value); - } else if (value instanceof Byte) { - return CstByte.make((Byte) value); - } else if (value instanceof Character) { - return CstChar.make((Character) value); - } else if (value instanceof Double) { - return CstDouble.make(Double.doubleToLongBits((Double) value)); - } else if (value instanceof Float) { - return CstFloat.make(Float.floatToIntBits((Float) value)); - } else if (value instanceof Integer) { - return CstInteger.make((Integer) value); - } else if (value instanceof Long) { - return CstLong.make((Long) value); - } else if (value instanceof Short) { - return CstShort.make((Short) value); - } else if (value instanceof String) { - return new CstString((String) value); - } else if (value instanceof Class) { - return new CstType(Type.get((Class<?>) value).ropType); - } else if (value instanceof Type) { - return new CstType(((Type) value).ropType); - } else { - throw new UnsupportedOperationException("Not a constant: " + value); - } - } -} diff --git a/dx/src/com/android/dx/gen/DexGenerator.java b/dx/src/com/android/dx/gen/DexGenerator.java deleted file mode 100644 index 7cde9a93f..000000000 --- a/dx/src/com/android/dx/gen/DexGenerator.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.gen; - -import com.android.dx.dex.DexFormat; -import com.android.dx.dex.DexOptions; -import com.android.dx.dex.code.DalvCode; -import com.android.dx.dex.code.PositionList; -import com.android.dx.dex.code.RopTranslator; -import com.android.dx.dex.file.ClassDefItem; -import com.android.dx.dex.file.DexFile; -import com.android.dx.dex.file.EncodedField; -import com.android.dx.dex.file.EncodedMethod; -import com.android.dx.rop.code.AccessFlags; -import static com.android.dx.rop.code.AccessFlags.*; -import com.android.dx.rop.code.LocalVariableInfo; -import com.android.dx.rop.code.RopMethod; -import com.android.dx.rop.cst.CstString; -import com.android.dx.rop.cst.CstType; -import com.android.dx.rop.type.StdTypeList; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.jar.JarEntry; -import java.util.jar.JarOutputStream; - -/** - * Define types, fields and methods. - */ -public final class DexGenerator { - private final Map<Type<?>, TypeDeclaration> types - = new LinkedHashMap<Type<?>, TypeDeclaration>(); - - private TypeDeclaration getTypeDeclaration(Type<?> type) { - TypeDeclaration result = types.get(type); - if (result == null) { - result = new TypeDeclaration(type); - types.put(type, result); - } - return result; - } - - /** - * @param flags any flags masked by {@link com.android.dx.rop.code.AccessFlags#CLASS_FLAGS}. - */ - public void declare(Type<?> type, String sourceFile, int flags, - Type<?> supertype, Type<?>... interfaces) { - TypeDeclaration declaration = getTypeDeclaration(type); - if (declaration.declared) { - throw new IllegalStateException("already declared: " + type); - } - declaration.declared = true; - declaration.flags = flags; - declaration.supertype = supertype; - declaration.sourceFile = sourceFile; - declaration.interfaces = new TypeList(interfaces); - } - - /** - * @param flags any flags masked by {@link com.android.dx.rop.code.AccessFlags#METHOD_FLAGS}. - */ - public Code declare(MethodId<?, ?> method, int flags) { - TypeDeclaration typeDeclaration = getTypeDeclaration(method.declaringType); - if (typeDeclaration.methods.containsKey(method)) { - throw new IllegalStateException("already declared: " + method); - } - MethodDeclaration methodDeclaration = new MethodDeclaration(method, flags); - typeDeclaration.methods.put(method, methodDeclaration); - return methodDeclaration.code; - } - - /** - * @param flags any flags masked by {@link AccessFlags#FIELD_FLAGS}. - */ - public void declare(FieldId<?, ?> fieldId, int flags, Object staticValue) { - TypeDeclaration typeDeclaration = getTypeDeclaration(fieldId.declaringType); - if (typeDeclaration.fields.containsKey(fieldId)) { - throw new IllegalStateException("already declared: " + fieldId); - } - FieldDeclaration fieldDeclaration = new FieldDeclaration(fieldId, flags, staticValue); - typeDeclaration.fields.put(fieldId, fieldDeclaration); - } - - /** - * Returns a .dex formatted file. - */ - public byte[] generate() { - DexFile outputDex = new DexFile(new DexOptions()); - - for (TypeDeclaration typeDeclaration : types.values()) { - outputDex.add(typeDeclaration.toClassDefItem()); - } - - try { - return outputDex.toDex(null, false); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - * Loads the generated types into the current dalvikvm process. - */ - public ClassLoader load(ClassLoader parent) throws IOException { - byte[] dex = generate(); - - /* - * This implementation currently dumps the dex to the filesystem. It - * jars the emitted .dex for the benefit of Gingerbread and earlier - * devices, which can't load .dex files directly. - * - * TODO: load the dex from memory where supported. - */ - File result = File.createTempFile("Generated", ".jar"); - result.deleteOnExit(); - JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(result)); - jarOut.putNextEntry(new JarEntry(DexFormat.DEX_IN_JAR_NAME)); - jarOut.write(dex); - jarOut.closeEntry(); - jarOut.close(); - try { - Class<?> pathClassLoader = Class.forName("dalvik.system.PathClassLoader"); - return (ClassLoader) pathClassLoader.getConstructor(String.class, ClassLoader.class) - .newInstance(result.getPath(), parent); - } catch (ClassNotFoundException e) { - throw new UnsupportedOperationException("load() requires a Dalvik VM", e); - } catch (InvocationTargetException e) { - throw new RuntimeException(e.getCause()); - } catch (InstantiationException e) { - throw new AssertionError(); - } catch (NoSuchMethodException e) { - throw new AssertionError(); - } catch (IllegalAccessException e) { - throw new AssertionError(); - } - } - - private static class TypeDeclaration { - private final Type<?> type; - - /** declared state */ - private boolean declared; - private int flags; - private Type<?> supertype; - private String sourceFile; - private TypeList interfaces; - - private final Map<FieldId, FieldDeclaration> fields - = new LinkedHashMap<FieldId, FieldDeclaration>(); - private final Map<MethodId, MethodDeclaration> methods - = new LinkedHashMap<MethodId, MethodDeclaration>(); - - TypeDeclaration(Type<?> type) { - this.type = type; - } - - ClassDefItem toClassDefItem() { - if (!declared) { - throw new IllegalStateException("Undeclared type " + type + " declares members: " - + fields.keySet() + " " + methods.keySet()); - } - - DexOptions dexOptions = new DexOptions(); - dexOptions.targetApiLevel = DexFormat.API_NO_EXTENDED_OPCODES; - - CstType thisType = type.constant; - - ClassDefItem out = new ClassDefItem(thisType, flags, supertype.constant, - interfaces.ropTypes, new CstString(sourceFile)); - - for (MethodDeclaration method : methods.values()) { - EncodedMethod encoded = method.toEncodedMethod(dexOptions); - if (method.isDirect()) { - out.addDirectMethod(encoded); - } else { - out.addVirtualMethod(encoded); - } - } - for (FieldDeclaration field : fields.values()) { - EncodedField encoded = field.toEncodedField(); - if (field.isStatic()) { - out.addStaticField(encoded, Constants.getConstant(field.staticValue)); - } else { - out.addInstanceField(encoded); - } - } - - return out; - } - } - - static class FieldDeclaration { - final FieldId<?, ?> fieldId; - private final int accessFlags; - private final Object staticValue; - - FieldDeclaration(FieldId<?, ?> fieldId, int accessFlags, Object staticValue) { - if ((accessFlags & (AccessFlags.ACC_STATIC)) == 0 && staticValue != null) { - throw new IllegalArgumentException("instance fields may not have a value"); - } - this.fieldId = fieldId; - this.accessFlags = accessFlags; - this.staticValue = staticValue; - } - - EncodedField toEncodedField() { - return new EncodedField(fieldId.constant, accessFlags); - } - - public boolean isStatic() { - return (accessFlags & (AccessFlags.ACC_STATIC)) != 0; - } - } - - static class MethodDeclaration { - final MethodId<?, ?> method; - private final int flags; - private final Code code; - - public MethodDeclaration(MethodId<?, ?> method, int flags) { - this.method = method; - this.flags = flags; - this.code = new Code(this); - } - - boolean isStatic() { - return (flags & ACC_STATIC) != 0; - } - - boolean isDirect() { - return (flags & (ACC_STATIC | ACC_PRIVATE | ACC_CONSTRUCTOR)) != 0; - } - - EncodedMethod toEncodedMethod(DexOptions dexOptions) { - RopMethod ropMethod = new RopMethod(code.toBasicBlocks(), 0); - LocalVariableInfo locals = null; - DalvCode dalvCode = RopTranslator.translate( - ropMethod, PositionList.NONE, locals, code.paramSize(), dexOptions); - return new EncodedMethod(method.constant, flags, dalvCode, StdTypeList.EMPTY); - } - } -} diff --git a/dx/src/com/android/dx/gen/FieldId.java b/dx/src/com/android/dx/gen/FieldId.java deleted file mode 100644 index 62ef73bdd..000000000 --- a/dx/src/com/android/dx/gen/FieldId.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.gen; - -import com.android.dx.rop.cst.CstFieldRef; -import com.android.dx.rop.cst.CstNat; -import com.android.dx.rop.cst.CstString; - -/** - * A field. - */ -public final class FieldId<D, V> { - final Type<D> declaringType; - final Type<V> type; - final String name; - - /** cached converted state */ - final CstNat nat; - final CstFieldRef constant; - - FieldId(Type<D> declaringType, Type<V> type, String name) { - if (declaringType == null || type == null || name == null) { - throw new NullPointerException(); - } - this.declaringType = declaringType; - this.type = type; - this.name = name; - this.nat = new CstNat(new CstString(name), new CstString(type.name)); - this.constant = new CstFieldRef(declaringType.constant, nat); - } - - public Type<D> getDeclaringType() { - return declaringType; - } - - public Type<V> getType() { - return type; - } - - public String getName() { - return name; - } - - @Override public boolean equals(Object o) { - return o instanceof FieldId - && ((FieldId<?, ?>) o).declaringType.equals(declaringType) - && ((FieldId<?, ?>) o).name.equals(name); - } - - @Override public int hashCode() { - return declaringType.hashCode() + 37 * name.hashCode(); - } - - @Override public String toString() { - return declaringType + "." + name; - } -} diff --git a/dx/src/com/android/dx/gen/Label.java b/dx/src/com/android/dx/gen/Label.java deleted file mode 100644 index 633b5f161..000000000 --- a/dx/src/com/android/dx/gen/Label.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.gen; - -import com.android.dx.rop.code.BasicBlock; -import com.android.dx.rop.code.Insn; -import com.android.dx.rop.code.InsnList; -import com.android.dx.util.IntList; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * A branch target in a list of instructions. - */ -public final class Label { - - final List<Insn> instructions = new ArrayList<Insn>(); - - boolean marked = false; - - /** an immutable list of labels corresponding to the types in the catch list */ - List<Label> catchLabels = Collections.emptyList(); - - /** contains the next instruction if no branch occurs */ - Label primarySuccessor; - - /** contains the instruction to jump to if the if is true */ - Label alternateSuccessor; - - int id = -1; - - Label() {} - - boolean isEmpty() { - return instructions.isEmpty(); - } - - void compact() { - for (int i = 0; i < catchLabels.size(); i++) { - while (catchLabels.get(i).isEmpty()) { - catchLabels.set(i, catchLabels.get(i).primarySuccessor); - } - } - while (primarySuccessor != null && primarySuccessor.isEmpty()) { - primarySuccessor = primarySuccessor.primarySuccessor; - } - while (alternateSuccessor != null && alternateSuccessor.isEmpty()) { - alternateSuccessor = alternateSuccessor.primarySuccessor; - } - } - - BasicBlock toBasicBlock() { - InsnList result = new InsnList(instructions.size()); - for (int i = 0; i < instructions.size(); i++) { - result.set(i, instructions.get(i)); - } - result.setImmutable(); - - int primarySuccessorIndex = -1; - IntList successors = new IntList(); - for (Label catchLabel : catchLabels) { - successors.add(catchLabel.id); - } - if (primarySuccessor != null) { - primarySuccessorIndex = primarySuccessor.id; - successors.add(primarySuccessorIndex); - } - if (alternateSuccessor != null) { - successors.add(alternateSuccessor.id); - } - successors.setImmutable(); - - return new BasicBlock(id, result, successors, primarySuccessorIndex); - } -} diff --git a/dx/src/com/android/dx/gen/Local.java b/dx/src/com/android/dx/gen/Local.java deleted file mode 100644 index b98759c3f..000000000 --- a/dx/src/com/android/dx/gen/Local.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.gen; - -import com.android.dx.rop.code.RegisterSpec; - -/** - * A temporary variable that holds a single value. - */ -public final class Local<T> { - private final Code code; - final Type<T> type; - private int reg = -1; - private RegisterSpec spec; - - private Local(Code code, Type<T> type) { - this.code = code; - this.type = type; - } - - static <T> Local<T> get(Code code, Type<T> type) { - return new Local<T>(code, type); - } - - /** - * Assigns registers to this local. - * - * @return the number of registers required. - */ - int initialize(int reg) { - this.reg = reg; - this.spec = RegisterSpec.make(reg, type.ropType); - return size(); - } - - int size() { - return type.ropType.getCategory(); - } - - RegisterSpec spec() { - if (spec == null) { - code.initializeLocals(); - if (spec == null) { - throw new AssertionError(); - } - } - return spec; - } - - public Type getType() { - return type; - } - - @Override public String toString() { - return "v" + reg + "(" + type + ")"; - } -} diff --git a/dx/src/com/android/dx/gen/MethodId.java b/dx/src/com/android/dx/gen/MethodId.java deleted file mode 100644 index 29d088ab4..000000000 --- a/dx/src/com/android/dx/gen/MethodId.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.gen; - -import com.android.dx.rop.cst.CstMethodRef; -import com.android.dx.rop.cst.CstNat; -import com.android.dx.rop.cst.CstString; -import com.android.dx.rop.type.Prototype; -import java.util.List; - -/** - * A method or constructor. - */ -public final class MethodId<D, R> { - final Type<D> declaringType; - final Type<R> returnType; - final String name; - final TypeList parameters; - - /** cached converted state */ - final CstNat nat; - final CstMethodRef constant; - - MethodId(Type<D> declaringType, Type<R> returnType, String name, TypeList parameters) { - if (declaringType == null || returnType == null || name == null || parameters == null) { - throw new NullPointerException(); - } - this.declaringType = declaringType; - this.returnType = returnType; - this.name = name; - this.parameters = parameters; - this.nat = new CstNat(new CstString(name), new CstString(descriptor(false))); - this.constant = new CstMethodRef(declaringType.constant, nat); - } - - public Type<D> getDeclaringType() { - return declaringType; - } - - public Type<R> getReturnType() { - return returnType; - } - - public String getName() { - return name; - } - - public List<Type<?>> getParameters() { - return parameters.asList(); - } - - /** - * Returns a descriptor like "(Ljava/lang/Class;[I)Ljava/lang/Object;". - */ - String descriptor(boolean includeThis) { - StringBuilder result = new StringBuilder(); - result.append("("); - if (includeThis) { - result.append(declaringType.name); - } - for (Type t : parameters.types) { - result.append(t.name); - } - result.append(")"); - result.append(returnType.name); - return result.toString(); - } - - Prototype prototype(boolean includeThis) { - return Prototype.intern(descriptor(includeThis)); - } - - @Override public boolean equals(Object o) { - return o instanceof MethodId - && ((MethodId<?, ?>) o).declaringType.equals(declaringType) - && ((MethodId<?, ?>) o).name.equals(name) - && ((MethodId<?, ?>) o).parameters.equals(parameters) - && ((MethodId<?, ?>) o).returnType.equals(returnType); - } - - @Override public int hashCode() { - int result = 17; - result = 31 * result + declaringType.hashCode(); - result = 31 * result + name.hashCode(); - result = 31 * result + parameters.hashCode(); - result = 31 * result + returnType.hashCode(); - return result; - } - - @Override public String toString() { - return declaringType + "." + name + "(" + parameters + ")"; - } -} diff --git a/dx/src/com/android/dx/gen/Type.java b/dx/src/com/android/dx/gen/Type.java deleted file mode 100644 index 3b81f6d1d..000000000 --- a/dx/src/com/android/dx/gen/Type.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.gen; - -import com.android.dx.rop.cst.CstType; -import java.util.HashMap; -import java.util.Map; - -/** - * A primitive type, interface or class. - */ -public final class Type<T> { - /** The {@code boolean} primitive type. */ - public static final Type<Boolean> BOOLEAN - = new Type<Boolean>(com.android.dx.rop.type.Type.BOOLEAN); - - /** The {@code byte} primitive type. */ - public static final Type<Byte> BYTE = new Type<Byte>(com.android.dx.rop.type.Type.BYTE); - - /** The {@code char} primitive type. */ - public static final Type<Character> CHAR - = new Type<Character>(com.android.dx.rop.type.Type.CHAR); - - /** The {@code double} primitive type. */ - public static final Type<Double> DOUBLE = new Type<Double>(com.android.dx.rop.type.Type.DOUBLE); - - /** The {@code float} primitive type. */ - public static final Type<Float> FLOAT = new Type<Float>(com.android.dx.rop.type.Type.FLOAT); - - /** The {@code int} primitive type. */ - public static final Type<Integer> INT = new Type<Integer>(com.android.dx.rop.type.Type.INT); - - /** The {@code long} primitive type. */ - public static final Type<Long> LONG = new Type<Long>(com.android.dx.rop.type.Type.LONG); - - /** The {@code short} primitive type. */ - public static final Type<Short> SHORT = new Type<Short>(com.android.dx.rop.type.Type.SHORT); - - /** The {@code void} primitive type. Only used as a return type. */ - public static final Type<Void> VOID = new Type<Void>(com.android.dx.rop.type.Type.VOID); - - /** The {@code Object} type. */ - public static final Type<Object> OBJECT = new Type<Object>(com.android.dx.rop.type.Type.OBJECT); - - /** The {@code String} type. */ - public static final Type<String> STRING = new Type<String>(com.android.dx.rop.type.Type.STRING); - - private static final Map<Class<?>, Type<?>> PRIMITIVE_TO_TYPE - = new HashMap<Class<?>, Type<?>>(); - static { - PRIMITIVE_TO_TYPE.put(boolean.class, BOOLEAN); - PRIMITIVE_TO_TYPE.put(byte.class, BYTE); - PRIMITIVE_TO_TYPE.put(char.class, CHAR); - PRIMITIVE_TO_TYPE.put(double.class, DOUBLE); - PRIMITIVE_TO_TYPE.put(float.class, FLOAT); - PRIMITIVE_TO_TYPE.put(int.class, INT); - PRIMITIVE_TO_TYPE.put(long.class, LONG); - PRIMITIVE_TO_TYPE.put(short.class, SHORT); - PRIMITIVE_TO_TYPE.put(void.class, VOID); - } - - final String name; - - /** cached converted values */ - final com.android.dx.rop.type.Type ropType; - final CstType constant; - - Type(com.android.dx.rop.type.Type ropType) { - this(ropType.getDescriptor(), ropType); - } - - Type(String name, com.android.dx.rop.type.Type ropType) { - if (name == null || ropType == null) { - throw new NullPointerException(); - } - this.name = name; - this.ropType = ropType; - this.constant = CstType.intern(ropType); - } - - /** - * @param name a descriptor like "Ljava/lang/Class;". - */ - public static <T> Type<T> get(String name) { - return new Type<T>(name, com.android.dx.rop.type.Type.internReturnType(name)); - } - - public static <T> Type<T> get(Class<T> type) { - if (type.isPrimitive()) { - @SuppressWarnings("unchecked") // guarded by equals - Type<T> result = (Type<T>) PRIMITIVE_TO_TYPE.get(type); - return result; - } - String name = type.getName().replace('.', '/'); - return get(type.isArray() ? name : 'L' + name + ';'); - } - - public <V> FieldId<T, V> getField(Type<V> type, String name) { - return new FieldId<T, V>(this, type, name); - } - - public MethodId<T, Void> getConstructor(Type<?>... parameters) { - return new MethodId<T, Void>(this, VOID, "<init>", new TypeList(parameters)); - } - - public <R> MethodId<T, R> getMethod(Type<R> returnType, String name, Type<?>... parameters) { - return new MethodId<T, R>(this, returnType, name, new TypeList(parameters)); - } - - public String getName() { - return name; - } - - @Override public boolean equals(Object o) { - return o instanceof Type - && ((Type) o).name.equals(name); - } - - @Override public int hashCode() { - return name.hashCode(); - } - - @Override public String toString() { - return name; - } -} diff --git a/dx/src/com/android/dx/gen/TypeList.java b/dx/src/com/android/dx/gen/TypeList.java deleted file mode 100644 index e18ed4a28..000000000 --- a/dx/src/com/android/dx/gen/TypeList.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.gen; - -import com.android.dx.rop.type.StdTypeList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * An immutable of types. - */ -final class TypeList { - final Type<?>[] types; - final StdTypeList ropTypes; - - TypeList(Type<?>[] types) { - this.types = types.clone(); - this.ropTypes = new StdTypeList(types.length); - for (int i = 0; i < types.length; i++) { - ropTypes.set(i, types[i].ropType); - } - } - - /** - * Returns an immutable list. - */ - public List<Type<?>> asList() { - return Collections.unmodifiableList(Arrays.asList(types)); - } - - @Override public boolean equals(Object o) { - return o instanceof TypeList && Arrays.equals(((TypeList) o).types, types); - } - - @Override public int hashCode() { - return Arrays.hashCode(types); - } - - @Override public String toString() { - StringBuilder result = new StringBuilder(); - for (int i = 0; i < types.length; i++) { - if (i > 0) { - result.append(", "); - } - result.append(types[i]); - } - return result.toString(); - } -} diff --git a/dx/src/com/android/dx/io/DexBuffer.java b/dx/src/com/android/dx/io/DexBuffer.java index e6f908bfa..39e5858e6 100644 --- a/dx/src/com/android/dx/io/DexBuffer.java +++ b/dx/src/com/android/dx/io/DexBuffer.java @@ -217,7 +217,7 @@ public final class DexBuffer { return length; } - private static int fourByteAlign(int position) { + public static int fourByteAlign(int position) { return (position + 3) & ~3; } diff --git a/dx/src/com/android/dx/io/OpcodeInfo.java b/dx/src/com/android/dx/io/OpcodeInfo.java index c8fcf25d5..2040d352c 100644 --- a/dx/src/com/android/dx/io/OpcodeInfo.java +++ b/dx/src/com/android/dx/io/OpcodeInfo.java @@ -931,162 +931,6 @@ public final class OpcodeInfo { new Info(Opcodes.USHR_INT_LIT8, "ushr-int/lit8", InstructionCodec.FORMAT_22B, IndexType.NONE); - public static final Info CONST_CLASS_JUMBO = - new Info(Opcodes.CONST_CLASS_JUMBO, "const-class/jumbo", - InstructionCodec.FORMAT_41C, IndexType.TYPE_REF); - - public static final Info CHECK_CAST_JUMBO = - new Info(Opcodes.CHECK_CAST_JUMBO, "check-cast/jumbo", - InstructionCodec.FORMAT_41C, IndexType.TYPE_REF); - - public static final Info INSTANCE_OF_JUMBO = - new Info(Opcodes.INSTANCE_OF_JUMBO, "instance-of/jumbo", - InstructionCodec.FORMAT_52C, IndexType.TYPE_REF); - - public static final Info NEW_INSTANCE_JUMBO = - new Info(Opcodes.NEW_INSTANCE_JUMBO, "new-instance/jumbo", - InstructionCodec.FORMAT_41C, IndexType.TYPE_REF); - - public static final Info NEW_ARRAY_JUMBO = - new Info(Opcodes.NEW_ARRAY_JUMBO, "new-array/jumbo", - InstructionCodec.FORMAT_52C, IndexType.TYPE_REF); - - public static final Info FILLED_NEW_ARRAY_JUMBO = - new Info(Opcodes.FILLED_NEW_ARRAY_JUMBO, "filled-new-array/jumbo", - InstructionCodec.FORMAT_5RC, IndexType.TYPE_REF); - - public static final Info IGET_JUMBO = - new Info(Opcodes.IGET_JUMBO, "iget/jumbo", - InstructionCodec.FORMAT_52C, IndexType.FIELD_REF); - - public static final Info IGET_WIDE_JUMBO = - new Info(Opcodes.IGET_WIDE_JUMBO, "iget-wide/jumbo", - InstructionCodec.FORMAT_52C, IndexType.FIELD_REF); - - public static final Info IGET_OBJECT_JUMBO = - new Info(Opcodes.IGET_OBJECT_JUMBO, "iget-object/jumbo", - InstructionCodec.FORMAT_52C, IndexType.FIELD_REF); - - public static final Info IGET_BOOLEAN_JUMBO = - new Info(Opcodes.IGET_BOOLEAN_JUMBO, "iget-boolean/jumbo", - InstructionCodec.FORMAT_52C, IndexType.FIELD_REF); - - public static final Info IGET_BYTE_JUMBO = - new Info(Opcodes.IGET_BYTE_JUMBO, "iget-byte/jumbo", - InstructionCodec.FORMAT_52C, IndexType.FIELD_REF); - - public static final Info IGET_CHAR_JUMBO = - new Info(Opcodes.IGET_CHAR_JUMBO, "iget-char/jumbo", - InstructionCodec.FORMAT_52C, IndexType.FIELD_REF); - - public static final Info IGET_SHORT_JUMBO = - new Info(Opcodes.IGET_SHORT_JUMBO, "iget-short/jumbo", - InstructionCodec.FORMAT_52C, IndexType.FIELD_REF); - - public static final Info IPUT_JUMBO = - new Info(Opcodes.IPUT_JUMBO, "iput/jumbo", - InstructionCodec.FORMAT_52C, IndexType.FIELD_REF); - - public static final Info IPUT_WIDE_JUMBO = - new Info(Opcodes.IPUT_WIDE_JUMBO, "iput-wide/jumbo", - InstructionCodec.FORMAT_52C, IndexType.FIELD_REF); - - public static final Info IPUT_OBJECT_JUMBO = - new Info(Opcodes.IPUT_OBJECT_JUMBO, "iput-object/jumbo", - InstructionCodec.FORMAT_52C, IndexType.FIELD_REF); - - public static final Info IPUT_BOOLEAN_JUMBO = - new Info(Opcodes.IPUT_BOOLEAN_JUMBO, "iput-boolean/jumbo", - InstructionCodec.FORMAT_52C, IndexType.FIELD_REF); - - public static final Info IPUT_BYTE_JUMBO = - new Info(Opcodes.IPUT_BYTE_JUMBO, "iput-byte/jumbo", - InstructionCodec.FORMAT_52C, IndexType.FIELD_REF); - - public static final Info IPUT_CHAR_JUMBO = - new Info(Opcodes.IPUT_CHAR_JUMBO, "iput-char/jumbo", - InstructionCodec.FORMAT_52C, IndexType.FIELD_REF); - - public static final Info IPUT_SHORT_JUMBO = - new Info(Opcodes.IPUT_SHORT_JUMBO, "iput-short/jumbo", - InstructionCodec.FORMAT_52C, IndexType.FIELD_REF); - - public static final Info SGET_JUMBO = - new Info(Opcodes.SGET_JUMBO, "sget/jumbo", - InstructionCodec.FORMAT_41C, IndexType.FIELD_REF); - - public static final Info SGET_WIDE_JUMBO = - new Info(Opcodes.SGET_WIDE_JUMBO, "sget-wide/jumbo", - InstructionCodec.FORMAT_41C, IndexType.FIELD_REF); - - public static final Info SGET_OBJECT_JUMBO = - new Info(Opcodes.SGET_OBJECT_JUMBO, "sget-object/jumbo", - InstructionCodec.FORMAT_41C, IndexType.FIELD_REF); - - public static final Info SGET_BOOLEAN_JUMBO = - new Info(Opcodes.SGET_BOOLEAN_JUMBO, "sget-boolean/jumbo", - InstructionCodec.FORMAT_41C, IndexType.FIELD_REF); - - public static final Info SGET_BYTE_JUMBO = - new Info(Opcodes.SGET_BYTE_JUMBO, "sget-byte/jumbo", - InstructionCodec.FORMAT_41C, IndexType.FIELD_REF); - - public static final Info SGET_CHAR_JUMBO = - new Info(Opcodes.SGET_CHAR_JUMBO, "sget-char/jumbo", - InstructionCodec.FORMAT_41C, IndexType.FIELD_REF); - - public static final Info SGET_SHORT_JUMBO = - new Info(Opcodes.SGET_SHORT_JUMBO, "sget-short/jumbo", - InstructionCodec.FORMAT_41C, IndexType.FIELD_REF); - - public static final Info SPUT_JUMBO = - new Info(Opcodes.SPUT_JUMBO, "sput/jumbo", - InstructionCodec.FORMAT_41C, IndexType.FIELD_REF); - - public static final Info SPUT_WIDE_JUMBO = - new Info(Opcodes.SPUT_WIDE_JUMBO, "sput-wide/jumbo", - InstructionCodec.FORMAT_41C, IndexType.FIELD_REF); - - public static final Info SPUT_OBJECT_JUMBO = - new Info(Opcodes.SPUT_OBJECT_JUMBO, "sput-object/jumbo", - InstructionCodec.FORMAT_41C, IndexType.FIELD_REF); - - public static final Info SPUT_BOOLEAN_JUMBO = - new Info(Opcodes.SPUT_BOOLEAN_JUMBO, "sput-boolean/jumbo", - InstructionCodec.FORMAT_41C, IndexType.FIELD_REF); - - public static final Info SPUT_BYTE_JUMBO = - new Info(Opcodes.SPUT_BYTE_JUMBO, "sput-byte/jumbo", - InstructionCodec.FORMAT_41C, IndexType.FIELD_REF); - - public static final Info SPUT_CHAR_JUMBO = - new Info(Opcodes.SPUT_CHAR_JUMBO, "sput-char/jumbo", - InstructionCodec.FORMAT_41C, IndexType.FIELD_REF); - - public static final Info SPUT_SHORT_JUMBO = - new Info(Opcodes.SPUT_SHORT_JUMBO, "sput-short/jumbo", - InstructionCodec.FORMAT_41C, IndexType.FIELD_REF); - - public static final Info INVOKE_VIRTUAL_JUMBO = - new Info(Opcodes.INVOKE_VIRTUAL_JUMBO, "invoke-virtual/jumbo", - InstructionCodec.FORMAT_5RC, IndexType.METHOD_REF); - - public static final Info INVOKE_SUPER_JUMBO = - new Info(Opcodes.INVOKE_SUPER_JUMBO, "invoke-super/jumbo", - InstructionCodec.FORMAT_5RC, IndexType.METHOD_REF); - - public static final Info INVOKE_DIRECT_JUMBO = - new Info(Opcodes.INVOKE_DIRECT_JUMBO, "invoke-direct/jumbo", - InstructionCodec.FORMAT_5RC, IndexType.METHOD_REF); - - public static final Info INVOKE_STATIC_JUMBO = - new Info(Opcodes.INVOKE_STATIC_JUMBO, "invoke-static/jumbo", - InstructionCodec.FORMAT_5RC, IndexType.METHOD_REF); - - public static final Info INVOKE_INTERFACE_JUMBO = - new Info(Opcodes.INVOKE_INTERFACE_JUMBO, "invoke-interface/jumbo", - InstructionCodec.FORMAT_5RC, IndexType.METHOD_REF); - // END(opcode-info-defs) // Static initialization. @@ -1320,45 +1164,6 @@ public final class OpcodeInfo { set(SHL_INT_LIT8); set(SHR_INT_LIT8); set(USHR_INT_LIT8); - set(CONST_CLASS_JUMBO); - set(CHECK_CAST_JUMBO); - set(INSTANCE_OF_JUMBO); - set(NEW_INSTANCE_JUMBO); - set(NEW_ARRAY_JUMBO); - set(FILLED_NEW_ARRAY_JUMBO); - set(IGET_JUMBO); - set(IGET_WIDE_JUMBO); - set(IGET_OBJECT_JUMBO); - set(IGET_BOOLEAN_JUMBO); - set(IGET_BYTE_JUMBO); - set(IGET_CHAR_JUMBO); - set(IGET_SHORT_JUMBO); - set(IPUT_JUMBO); - set(IPUT_WIDE_JUMBO); - set(IPUT_OBJECT_JUMBO); - set(IPUT_BOOLEAN_JUMBO); - set(IPUT_BYTE_JUMBO); - set(IPUT_CHAR_JUMBO); - set(IPUT_SHORT_JUMBO); - set(SGET_JUMBO); - set(SGET_WIDE_JUMBO); - set(SGET_OBJECT_JUMBO); - set(SGET_BOOLEAN_JUMBO); - set(SGET_BYTE_JUMBO); - set(SGET_CHAR_JUMBO); - set(SGET_SHORT_JUMBO); - set(SPUT_JUMBO); - set(SPUT_WIDE_JUMBO); - set(SPUT_OBJECT_JUMBO); - set(SPUT_BOOLEAN_JUMBO); - set(SPUT_BYTE_JUMBO); - set(SPUT_CHAR_JUMBO); - set(SPUT_SHORT_JUMBO); - set(INVOKE_VIRTUAL_JUMBO); - set(INVOKE_SUPER_JUMBO); - set(INVOKE_DIRECT_JUMBO); - set(INVOKE_STATIC_JUMBO); - set(INVOKE_INTERFACE_JUMBO); // END(opcode-info-init) } diff --git a/dx/src/com/android/dx/io/Opcodes.java b/dx/src/com/android/dx/io/Opcodes.java index 4a255f7d4..6dba49d9e 100644 --- a/dx/src/com/android/dx/io/Opcodes.java +++ b/dx/src/com/android/dx/io/Opcodes.java @@ -259,45 +259,6 @@ public final class Opcodes { public static final int SHL_INT_LIT8 = 0xe0; public static final int SHR_INT_LIT8 = 0xe1; public static final int USHR_INT_LIT8 = 0xe2; - public static final int CONST_CLASS_JUMBO = 0x00ff; - public static final int CHECK_CAST_JUMBO = 0x01ff; - public static final int INSTANCE_OF_JUMBO = 0x02ff; - public static final int NEW_INSTANCE_JUMBO = 0x03ff; - public static final int NEW_ARRAY_JUMBO = 0x04ff; - public static final int FILLED_NEW_ARRAY_JUMBO = 0x05ff; - public static final int IGET_JUMBO = 0x06ff; - public static final int IGET_WIDE_JUMBO = 0x07ff; - public static final int IGET_OBJECT_JUMBO = 0x08ff; - public static final int IGET_BOOLEAN_JUMBO = 0x09ff; - public static final int IGET_BYTE_JUMBO = 0x0aff; - public static final int IGET_CHAR_JUMBO = 0x0bff; - public static final int IGET_SHORT_JUMBO = 0x0cff; - public static final int IPUT_JUMBO = 0x0dff; - public static final int IPUT_WIDE_JUMBO = 0x0eff; - public static final int IPUT_OBJECT_JUMBO = 0x0fff; - public static final int IPUT_BOOLEAN_JUMBO = 0x10ff; - public static final int IPUT_BYTE_JUMBO = 0x11ff; - public static final int IPUT_CHAR_JUMBO = 0x12ff; - public static final int IPUT_SHORT_JUMBO = 0x13ff; - public static final int SGET_JUMBO = 0x14ff; - public static final int SGET_WIDE_JUMBO = 0x15ff; - public static final int SGET_OBJECT_JUMBO = 0x16ff; - public static final int SGET_BOOLEAN_JUMBO = 0x17ff; - public static final int SGET_BYTE_JUMBO = 0x18ff; - public static final int SGET_CHAR_JUMBO = 0x19ff; - public static final int SGET_SHORT_JUMBO = 0x1aff; - public static final int SPUT_JUMBO = 0x1bff; - public static final int SPUT_WIDE_JUMBO = 0x1cff; - public static final int SPUT_OBJECT_JUMBO = 0x1dff; - public static final int SPUT_BOOLEAN_JUMBO = 0x1eff; - public static final int SPUT_BYTE_JUMBO = 0x1fff; - public static final int SPUT_CHAR_JUMBO = 0x20ff; - public static final int SPUT_SHORT_JUMBO = 0x21ff; - public static final int INVOKE_VIRTUAL_JUMBO = 0x22ff; - public static final int INVOKE_SUPER_JUMBO = 0x23ff; - public static final int INVOKE_DIRECT_JUMBO = 0x24ff; - public static final int INVOKE_STATIC_JUMBO = 0x25ff; - public static final int INVOKE_INTERFACE_JUMBO = 0x26ff; // END(opcodes) // TODO: Generate these payload opcodes with opcode-gen. diff --git a/dx/src/com/android/dx/io/instructions/DecodedInstruction.java b/dx/src/com/android/dx/io/instructions/DecodedInstruction.java index e418a1c0b..a8bc8592e 100644 --- a/dx/src/com/android/dx/io/instructions/DecodedInstruction.java +++ b/dx/src/com/android/dx/io/instructions/DecodedInstruction.java @@ -21,7 +21,6 @@ import com.android.dx.io.OpcodeInfo; import com.android.dx.io.Opcodes; import com.android.dx.util.DexException; import com.android.dx.util.Hex; - import java.io.EOFException; /** @@ -59,7 +58,7 @@ public abstract class DecodedInstruction { /** * literal value argument; also used for special verification error - * constants (formats 20bc and 40sc) as well as should-be-zero values + * constants (format 20bc) as well as should-be-zero values * (formats 10x, 20t, 30t, and 32x) */ private final long literal; @@ -90,7 +89,7 @@ public abstract class DecodedInstruction { decoded[in.cursor()] = DecodedInstruction.decode(in); } } catch (EOFException ex) { - throw new AssertionError("shouldn't happen"); + throw new DexException(ex); } return decoded; diff --git a/dx/src/com/android/dx/io/instructions/InstructionCodec.java b/dx/src/com/android/dx/io/instructions/InstructionCodec.java index b864b8365..2e803ed6b 100644 --- a/dx/src/com/android/dx/io/instructions/InstructionCodec.java +++ b/dx/src/com/android/dx/io/instructions/InstructionCodec.java @@ -605,139 +605,6 @@ public enum InstructionCodec { } }, - FORMAT_33X() { - @Override public DecodedInstruction decode(int opcodeUnit, - CodeInput in) throws EOFException { - int ab = in.read(); - int a = byte0(ab); - int b = byte1(ab); - int c = in.read(); - return new ThreeRegisterDecodedInstruction( - this, opcodeUnit, 0, null, - 0, 0L, - a, b, c); - } - - @Override public void encode(DecodedInstruction insn, CodeOutput out) { - out.write( - insn.getOpcodeUnit(), - codeUnit(insn.getA(), insn.getB()), - insn.getCUnit()); - } - }, - - FORMAT_32S() { - @Override public DecodedInstruction decode(int opcodeUnit, - CodeInput in) throws EOFException { - int ab = in.read(); - int a = byte0(ab); - int b = byte1(ab); - int literal = (short) in.read(); // sign-extend - return new TwoRegisterDecodedInstruction( - this, opcodeUnit, 0, null, - 0, literal, - a, b); - } - - @Override public void encode(DecodedInstruction insn, CodeOutput out) { - out.write( - insn.getOpcodeUnit(), - codeUnit(insn.getA(), insn.getB()), - insn.getLiteralUnit()); - } - }, - - FORMAT_40SC() { - @Override public DecodedInstruction decode(int opcodeUnit, - CodeInput in) throws EOFException { - // Note: We use the literal field to hold the decoded AA value. - int index = in.readInt(); - int literal = in.read(); - return new ZeroRegisterDecodedInstruction( - this, opcodeUnit, index, IndexType.VARIES, - 0, literal); - } - - @Override public void encode(DecodedInstruction insn, CodeOutput out) { - int index = insn.getIndex(); - out.write( - insn.getOpcodeUnit(), - unit0(index), - unit1(index), - insn.getLiteralUnit()); - } - }, - - FORMAT_41C() { - @Override public DecodedInstruction decode(int opcodeUnit, - CodeInput in) throws EOFException { - int index = in.readInt(); - int a = in.read(); - IndexType indexType = OpcodeInfo.getIndexType(opcodeUnit); - return new OneRegisterDecodedInstruction( - this, opcodeUnit, index, indexType, - 0, 0L, - a); - } - - @Override public void encode(DecodedInstruction insn, CodeOutput out) { - int index = insn.getIndex(); - out.write( - insn.getOpcodeUnit(), - unit0(index), - unit1(index), - insn.getAUnit()); - } - }, - - FORMAT_52C() { - @Override public DecodedInstruction decode(int opcodeUnit, - CodeInput in) throws EOFException { - int index = in.readInt(); - int a = in.read(); - int b = in.read(); - IndexType indexType = OpcodeInfo.getIndexType(opcodeUnit); - return new TwoRegisterDecodedInstruction( - this, opcodeUnit, index, indexType, - 0, 0L, - a, b); - } - - @Override public void encode(DecodedInstruction insn, CodeOutput out) { - int index = insn.getIndex(); - out.write( - insn.getOpcodeUnit(), - unit0(index), - unit1(index), - insn.getAUnit(), - insn.getBUnit()); - } - }, - - FORMAT_5RC() { - @Override public DecodedInstruction decode(int opcodeUnit, - CodeInput in) throws EOFException { - int index = in.readInt(); - int registerCount = in.read(); - int a = in.read(); - IndexType indexType = OpcodeInfo.getIndexType(opcodeUnit); - return new RegisterRangeDecodedInstruction( - this, opcodeUnit, index, indexType, - 0, 0L, - a, registerCount); - } - - @Override public void encode(DecodedInstruction insn, CodeOutput out) { - int index = insn.getIndex(); - out.write( - insn.getOpcodeUnit(), - unit0(index), - unit1(index), - insn.getRegisterCountUnit(), - insn.getAUnit()); - } - }, - FORMAT_PACKED_SWITCH_PAYLOAD() { @Override public DecodedInstruction decode(int opcodeUnit, CodeInput in) throws EOFException { diff --git a/dx/src/com/android/dx/merge/DexMerger.java b/dx/src/com/android/dx/merge/DexMerger.java index 8078f640e..a6f413a5d 100644 --- a/dx/src/com/android/dx/merge/DexMerger.java +++ b/dx/src/com/android/dx/merge/DexMerger.java @@ -33,7 +33,9 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Combine two dex files into one. @@ -594,6 +596,8 @@ public final class DexMerger { transformAnnotationSets(dexB, bIndexMap); transformAnnotationDirectories(dexA, aIndexMap); transformAnnotationDirectories(dexB, bIndexMap); + transformStaticValues(dexA, aIndexMap); + transformStaticValues(dexB, bIndexMap); } private void transformAnnotationSets(DexBuffer in, IndexMap indexMap) { @@ -616,6 +620,16 @@ public final class DexMerger { } } + private void transformStaticValues(DexBuffer in, IndexMap indexMap) { + TableOfContents.Section section = in.getTableOfContents().encodedArrays; + if (section.exists()) { + DexBuffer.Section staticValuesIn = in.open(section.off); + for (int i = 0; i < section.size; i++) { + transformStaticValues(staticValuesIn, indexMap); + } + } + } + /** * Reads a class_def_item beginning at {@code in} and writes the index and * data. @@ -643,13 +657,7 @@ public final class DexMerger { } int staticValuesOff = classDef.getStaticValuesOffset(); - if (staticValuesOff == 0) { - idsDefsOut.writeInt(0); - } else { - DexBuffer.Section staticValuesIn = in.open(staticValuesOff); - idsDefsOut.writeInt(encodedArrayOut.getPosition()); - transformStaticValues(staticValuesIn, indexMap); - } + idsDefsOut.writeInt(indexMap.adjustStaticValues(staticValuesOff)); } /** @@ -923,6 +931,7 @@ public final class DexMerger { private void transformStaticValues(DexBuffer.Section in, IndexMap indexMap) { contentsOut.encodedArrays.size++; + indexMap.putStaticValuesOffset(in.getPosition(), encodedArrayOut.getPosition()); indexMap.adjustEncodedArray(in.readEncodedArray()).writeTo(encodedArrayOut); } @@ -1008,6 +1017,9 @@ public final class DexMerger { // all of the bytes in a debug info section may be uleb/sleb debugInfo += contents.debugInfos.byteCount * 2; } + + typeList = DexBuffer.fourByteAlign(typeList); + code = DexBuffer.fourByteAlign(code); } public int size() { diff --git a/dx/src/com/android/dx/merge/IndexMap.java b/dx/src/com/android/dx/merge/IndexMap.java index a7b20bede..a5c9584dc 100644 --- a/dx/src/com/android/dx/merge/IndexMap.java +++ b/dx/src/com/android/dx/merge/IndexMap.java @@ -48,6 +48,7 @@ public final class IndexMap { private final HashMap<Integer, Integer> annotationOffsets; private final HashMap<Integer, Integer> annotationSetOffsets; private final HashMap<Integer, Integer> annotationDirectoryOffsets; + private final HashMap<Integer, Integer> staticValuesOffsets; public IndexMap(DexBuffer target, TableOfContents tableOfContents) { this.target = target; @@ -60,14 +61,16 @@ public final class IndexMap { this.annotationOffsets = new HashMap<Integer, Integer>(); this.annotationSetOffsets = new HashMap<Integer, Integer>(); this.annotationDirectoryOffsets = new HashMap<Integer, Integer>(); + this.staticValuesOffsets = new HashMap<Integer, Integer>(); /* - * A type list, annotation set, or annotation directory at offset 0 is - * always empty. Always map offset 0 to 0. + * A type list, annotation set, annotation directory, or static value at + * offset 0 is always empty. Always map offset 0 to 0. */ this.typeListOffsets.put(0, 0); this.annotationSetOffsets.put(0, 0); this.annotationDirectoryOffsets.put(0, 0); + this.staticValuesOffsets.put(0, 0); } public void putTypeListOffset(int oldOffset, int newOffset) { @@ -98,6 +101,13 @@ public final class IndexMap { annotationDirectoryOffsets.put(oldOffset, newOffset); } + public void putStaticValuesOffset(int oldOffset, int newOffset) { + if (oldOffset <= 0 || newOffset <= 0) { + throw new IllegalArgumentException(); + } + staticValuesOffsets.put(oldOffset, newOffset); + } + public int adjustString(int stringIndex) { return stringIndex == ClassDef.NO_INDEX ? ClassDef.NO_INDEX : stringIds[stringIndex]; } @@ -145,6 +155,10 @@ public final class IndexMap { return annotationDirectoryOffsets.get(annotationDirectoryOffset); } + public int adjustStaticValues(int staticValuesOffset) { + return staticValuesOffsets.get(staticValuesOffset); + } + public MethodId adjust(MethodId methodId) { return new MethodId(target, adjustType(methodId.getDeclaringClassIndex()), diff --git a/dx/src/com/android/dx/rop/cst/CstType.java b/dx/src/com/android/dx/rop/cst/CstType.java index 8624028aa..870fcb480 100644 --- a/dx/src/com/android/dx/rop/cst/CstType.java +++ b/dx/src/com/android/dx/rop/cst/CstType.java @@ -17,7 +17,6 @@ package com.android.dx.rop.cst; import com.android.dx.rop.type.Type; - import java.util.HashMap; /** @@ -229,4 +228,22 @@ public final class CstType extends TypedConstant { return descriptor; } + + /** + * Returns a human readable package name for this type, like "java.util". + * If this is an array type, this returns the package name of the array's + * component type. If this is a primitive type, this returns "default". + */ + public String getPackageName() { + // descriptor is a string like "[[Ljava/util/String;" + String descriptor = getDescriptor().getString(); + int lastSlash = descriptor.lastIndexOf('/'); + int lastLeftSquare = descriptor.lastIndexOf('['); // -1 unless this is an array + if (lastSlash == -1) { + return "default"; + } else { + // +2 to skip the '[' and the 'L' prefix + return descriptor.substring(lastLeftSquare + 2, lastSlash).replace('/', '.'); + } + } } diff --git a/dx/src/com/android/dx/ssa/_tests/_DomFront.java b/dx/src/com/android/dx/ssa/_tests/_DomFront.java deleted file mode 100644 index 3d891c9bb..000000000 --- a/dx/src/com/android/dx/ssa/_tests/_DomFront.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dx.ssa._tests; - -import junit.framework.TestCase; - -/** - * Test the class {@code com.android.dx.ssa.DomFront}. - */ -public class _DomFront - extends TestCase { - - public void test_one() { - - } - - -} diff --git a/dx/src/junit/extensions/ActiveTestSuite.java b/dx/src/junit/extensions/ActiveTestSuite.java deleted file mode 100644 index 1a3f163ec..000000000 --- a/dx/src/junit/extensions/ActiveTestSuite.java +++ /dev/null @@ -1,64 +0,0 @@ -package junit.extensions; - -import junit.framework.*; - -/** - * A TestSuite for active Tests. It runs each - * test in a separate thread and waits until all - * threads have terminated. - * -- Aarhus Radisson Scandinavian Center 11th floor - */ -public class ActiveTestSuite extends TestSuite { - private volatile int fActiveTestDeathCount; - - public ActiveTestSuite() { - } - - public ActiveTestSuite(Class theClass) { - super(theClass); - } - - public ActiveTestSuite(String name) { - super (name); - } - - public ActiveTestSuite(Class theClass, String name) { - super(theClass, name); - } - - public void run(TestResult result) { - fActiveTestDeathCount= 0; - super.run(result); - waitUntilFinished(); - } - - public void runTest(final Test test, final TestResult result) { - Thread t= new Thread() { - public void run() { - try { - // inlined due to limitation in VA/Java - //ActiveTestSuite.super.runTest(test, result); - test.run(result); - } finally { - ActiveTestSuite.this.runFinished(test); - } - } - }; - t.start(); - } - - synchronized void waitUntilFinished() { - while (fActiveTestDeathCount < testCount()) { - try { - wait(); - } catch (InterruptedException e) { - return; // ignore - } - } - } - - synchronized public void runFinished(Test test) { - fActiveTestDeathCount++; - notifyAll(); - } -} diff --git a/dx/src/junit/extensions/ExceptionTestCase.java b/dx/src/junit/extensions/ExceptionTestCase.java deleted file mode 100644 index fae574625..000000000 --- a/dx/src/junit/extensions/ExceptionTestCase.java +++ /dev/null @@ -1,46 +0,0 @@ -package junit.extensions; - -import junit.framework.*; - -/** - * A TestCase that expects an Exception of class fExpected to be thrown. - * The other way to check that an expected exception is thrown is: - * <pre> - * try { - * shouldThrow(); - * } - * catch (SpecialException e) { - * return; - * } - * fail("Expected SpecialException"); - * </pre> - * - * To use ExceptionTestCase, create a TestCase like: - * <pre> - * new ExceptionTestCase("testShouldThrow", SpecialException.class); - * </pre> - */ -public class ExceptionTestCase extends TestCase { - Class<?> fExpected; - - public ExceptionTestCase(String name, Class exception) { - super(name); - fExpected= exception; - } - /** - * Execute the test method expecting that an Exception of - * class fExpected or one of its subclasses will be thrown - */ - protected void runTest() throws Throwable { - try { - super.runTest(); - } - catch (Exception e) { - if (fExpected.isAssignableFrom(e.getClass())) - return; - else - throw e; - } - fail("Expected exception " + fExpected); - } -} diff --git a/dx/src/junit/extensions/RepeatedTest.java b/dx/src/junit/extensions/RepeatedTest.java deleted file mode 100644 index ebce77547..000000000 --- a/dx/src/junit/extensions/RepeatedTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package junit.extensions; - -import junit.framework.*; - -/** - * A Decorator that runs a test repeatedly. - * - */ -public class RepeatedTest extends TestDecorator { - private int fTimesRepeat; - - public RepeatedTest(Test test, int repeat) { - super(test); - if (repeat < 0) - throw new IllegalArgumentException("Repetition count must be > 0"); - fTimesRepeat= repeat; - } - public int countTestCases() { - return super.countTestCases()*fTimesRepeat; - } - public void run(TestResult result) { - for (int i= 0; i < fTimesRepeat; i++) { - if (result.shouldStop()) - break; - super.run(result); - } - } - public String toString() { - return super.toString()+"(repeated)"; - } -} diff --git a/dx/src/junit/extensions/TestDecorator.java b/dx/src/junit/extensions/TestDecorator.java deleted file mode 100644 index a8e9e7d46..000000000 --- a/dx/src/junit/extensions/TestDecorator.java +++ /dev/null @@ -1,38 +0,0 @@ -package junit.extensions; - -import junit.framework.*; - -/** - * A Decorator for Tests. Use TestDecorator as the base class - * for defining new test decorators. Test decorator subclasses - * can be introduced to add behaviour before or after a test - * is run. - * - */ -public class TestDecorator extends Assert implements Test { - protected Test fTest; - - public TestDecorator(Test test) { - fTest= test; - } - /** - * The basic run behaviour. - */ - public void basicRun(TestResult result) { - fTest.run(result); - } - public int countTestCases() { - return fTest.countTestCases(); - } - public void run(TestResult result) { - basicRun(result); - } - - public String toString() { - return fTest.toString(); - } - - public Test getTest() { - return fTest; - } -} diff --git a/dx/src/junit/extensions/TestSetup.java b/dx/src/junit/extensions/TestSetup.java deleted file mode 100644 index f1c25face..000000000 --- a/dx/src/junit/extensions/TestSetup.java +++ /dev/null @@ -1,37 +0,0 @@ -package junit.extensions; - -import junit.framework.*; - -/** - * A Decorator to set up and tear down additional fixture state. - * Subclass TestSetup and insert it into your tests when you want - * to set up additional state once before the tests are run. - */ -public class TestSetup extends TestDecorator { - - public TestSetup(Test test) { - super(test); - } - public void run(final TestResult result) { - Protectable p= new Protectable() { - public void protect() throws Exception { - setUp(); - basicRun(result); - tearDown(); - } - }; - result.runProtected(this, p); - } - /** - * Sets up the fixture. Override to set up additional fixture - * state. - */ - protected void setUp() throws Exception { - } - /** - * Tears down the fixture. Override to tear down the additional - * fixture state. - */ - protected void tearDown() throws Exception { - } -} diff --git a/dx/src/junit/framework/Assert.java b/dx/src/junit/framework/Assert.java deleted file mode 100644 index eb5d96042..000000000 --- a/dx/src/junit/framework/Assert.java +++ /dev/null @@ -1,291 +0,0 @@ -package junit.framework; - -/** - * A set of assert methods. Messages are only displayed when an assert fails. - */ - -public class Assert { - /** - * Protect constructor since it is a static only class - */ - protected Assert() { - } - - /** - * Asserts that a condition is true. If it isn't it throws - * an AssertionFailedError with the given message. - */ - static public void assertTrue(String message, boolean condition) { - if (!condition) - fail(message); - } - /** - * Asserts that a condition is true. If it isn't it throws - * an AssertionFailedError. - */ - static public void assertTrue(boolean condition) { - assertTrue(null, condition); - } - /** - * Asserts that a condition is false. If it isn't it throws - * an AssertionFailedError with the given message. - */ - static public void assertFalse(String message, boolean condition) { - assertTrue(message, !condition); - } - /** - * Asserts that a condition is false. If it isn't it throws - * an AssertionFailedError. - */ - static public void assertFalse(boolean condition) { - assertFalse(null, condition); - } - /** - * Fails a test with the given message. - */ - static public void fail(String message) { - throw new AssertionFailedError(message); - } - /** - * Fails a test with no message. - */ - static public void fail() { - fail(null); - } - /** - * Asserts that two objects are equal. If they are not - * an AssertionFailedError is thrown with the given message. - */ - static public void assertEquals(String message, Object expected, Object actual) { - if (expected == null && actual == null) - return; - if (expected != null && expected.equals(actual)) - return; - failNotEquals(message, expected, actual); - } - /** - * Asserts that two objects are equal. If they are not - * an AssertionFailedError is thrown. - */ - static public void assertEquals(Object expected, Object actual) { - assertEquals(null, expected, actual); - } - /** - * Asserts that two Strings are equal. - */ - static public void assertEquals(String message, String expected, String actual) { - if (expected == null && actual == null) - return; - if (expected != null && expected.equals(actual)) - return; - throw new ComparisonFailure(message, expected, actual); - } - /** - * Asserts that two Strings are equal. - */ - static public void assertEquals(String expected, String actual) { - assertEquals(null, expected, actual); - } - /** - * Asserts that two doubles are equal concerning a delta. If they are not - * an AssertionFailedError is thrown with the given message. If the expected - * value is infinity then the delta value is ignored. - */ - static public void assertEquals(String message, double expected, double actual, double delta) { - // handle infinity specially since subtracting to infinite values gives NaN and the - // the following test fails - if (Double.isInfinite(expected)) { - if (!(expected == actual)) - failNotEquals(message, new Double(expected), new Double(actual)); - } else if (!(Math.abs(expected-actual) <= delta)) // Because comparison with NaN always returns false - failNotEquals(message, new Double(expected), new Double(actual)); - } - /** - * Asserts that two doubles are equal concerning a delta. If the expected - * value is infinity then the delta value is ignored. - */ - static public void assertEquals(double expected, double actual, double delta) { - assertEquals(null, expected, actual, delta); - } - /** - * Asserts that two floats are equal concerning a delta. If they are not - * an AssertionFailedError is thrown with the given message. If the expected - * value is infinity then the delta value is ignored. - */ - static public void assertEquals(String message, float expected, float actual, float delta) { - // handle infinity specially since subtracting to infinite values gives NaN and the - // the following test fails - if (Float.isInfinite(expected)) { - if (!(expected == actual)) - failNotEquals(message, new Float(expected), new Float(actual)); - } else if (!(Math.abs(expected-actual) <= delta)) - failNotEquals(message, new Float(expected), new Float(actual)); - } - /** - * Asserts that two floats are equal concerning a delta. If the expected - * value is infinity then the delta value is ignored. - */ - static public void assertEquals(float expected, float actual, float delta) { - assertEquals(null, expected, actual, delta); - } - /** - * Asserts that two longs are equal. If they are not - * an AssertionFailedError is thrown with the given message. - */ - static public void assertEquals(String message, long expected, long actual) { - assertEquals(message, new Long(expected), new Long(actual)); - } - /** - * Asserts that two longs are equal. - */ - static public void assertEquals(long expected, long actual) { - assertEquals(null, expected, actual); - } - /** - * Asserts that two booleans are equal. If they are not - * an AssertionFailedError is thrown with the given message. - */ - static public void assertEquals(String message, boolean expected, boolean actual) { - assertEquals(message, new Boolean(expected), new Boolean(actual)); - } - /** - * Asserts that two booleans are equal. - */ - static public void assertEquals(boolean expected, boolean actual) { - assertEquals(null, expected, actual); - } - /** - * Asserts that two bytes are equal. If they are not - * an AssertionFailedError is thrown with the given message. - */ - static public void assertEquals(String message, byte expected, byte actual) { - assertEquals(message, new Byte(expected), new Byte(actual)); - } - /** - * Asserts that two bytes are equal. - */ - static public void assertEquals(byte expected, byte actual) { - assertEquals(null, expected, actual); - } - /** - * Asserts that two chars are equal. If they are not - * an AssertionFailedError is thrown with the given message. - */ - static public void assertEquals(String message, char expected, char actual) { - assertEquals(message, new Character(expected), new Character(actual)); - } - /** - * Asserts that two chars are equal. - */ - static public void assertEquals(char expected, char actual) { - assertEquals(null, expected, actual); - } - /** - * Asserts that two shorts are equal. If they are not - * an AssertionFailedError is thrown with the given message. - */ - static public void assertEquals(String message, short expected, short actual) { - assertEquals(message, new Short(expected), new Short(actual)); - } - /** - * Asserts that two shorts are equal. - */ - static public void assertEquals(short expected, short actual) { - assertEquals(null, expected, actual); - } - /** - * Asserts that two ints are equal. If they are not - * an AssertionFailedError is thrown with the given message. - */ - static public void assertEquals(String message, int expected, int actual) { - assertEquals(message, new Integer(expected), new Integer(actual)); - } - /** - * Asserts that two ints are equal. - */ - static public void assertEquals(int expected, int actual) { - assertEquals(null, expected, actual); - } - /** - * Asserts that an object isn't null. - */ - static public void assertNotNull(Object object) { - assertNotNull(null, object); - } - /** - * Asserts that an object isn't null. If it is - * an AssertionFailedError is thrown with the given message. - */ - static public void assertNotNull(String message, Object object) { - assertTrue(message, object != null); - } - /** - * Asserts that an object is null. - */ - static public void assertNull(Object object) { - assertNull(null, object); - } - /** - * Asserts that an object is null. If it is not - * an AssertionFailedError is thrown with the given message. - */ - static public void assertNull(String message, Object object) { - assertTrue(message, object == null); - } - /** - * Asserts that two objects refer to the same object. If they are not - * an AssertionFailedError is thrown with the given message. - */ - static public void assertSame(String message, Object expected, Object actual) { - if (expected == actual) - return; - failNotSame(message, expected, actual); - } - /** - * Asserts that two objects refer to the same object. If they are not - * the same an AssertionFailedError is thrown. - */ - static public void assertSame(Object expected, Object actual) { - assertSame(null, expected, actual); - } - /** - * Asserts that two objects refer to the same object. If they are not - * an AssertionFailedError is thrown with the given message. - */ - static public void assertNotSame(String message, Object expected, Object actual) { - if (expected == actual) - failSame(message); - } - /** - * Asserts that two objects refer to the same object. If they are not - * the same an AssertionFailedError is thrown. - */ - static public void assertNotSame(Object expected, Object actual) { - assertNotSame(null, expected, actual); - } - - static private void failSame(String message) { - String formatted= ""; - if (message != null) - formatted= message+" "; - fail(formatted+"expected not same"); - } - - static private void failNotSame(String message, Object expected, Object actual) { - String formatted= ""; - if (message != null) - formatted= message+" "; - fail(formatted+"expected same:<"+expected+"> was not:<"+actual+">"); - } - - static private void failNotEquals(String message, Object expected, Object actual) { - fail(format(message, expected, actual)); - } - - static String format(String message, Object expected, Object actual) { - String formatted= ""; - if (message != null) - formatted= message+" "; - return formatted+"expected:<"+expected+"> but was:<"+actual+">"; - } -} diff --git a/dx/src/junit/framework/AssertionFailedError.java b/dx/src/junit/framework/AssertionFailedError.java deleted file mode 100644 index 9aee0018f..000000000 --- a/dx/src/junit/framework/AssertionFailedError.java +++ /dev/null @@ -1,13 +0,0 @@ -package junit.framework; - -/** - * Thrown when an assertion failed. - */ -public class AssertionFailedError extends Error { - - public AssertionFailedError () { - } - public AssertionFailedError (String message) { - super (message); - } -} diff --git a/dx/src/junit/framework/ComparisonFailure.java b/dx/src/junit/framework/ComparisonFailure.java deleted file mode 100644 index 1bfe591c5..000000000 --- a/dx/src/junit/framework/ComparisonFailure.java +++ /dev/null @@ -1,68 +0,0 @@ -package junit.framework; - -/** - * Thrown when an assert equals for Strings failed. - * - * Inspired by a patch from Alex Chaffee mailto:alex@purpletech.com - */ -public class ComparisonFailure extends AssertionFailedError { - private String fExpected; - private String fActual; - - /** - * Constructs a comparison failure. - * @param message the identifying message or null - * @param expected the expected string value - * @param actual the actual string value - */ - public ComparisonFailure (String message, String expected, String actual) { - super (message); - fExpected= expected; - fActual= actual; - } - - /** - * Returns "..." in place of common prefix and "..." in - * place of common suffix between expected and actual. - * - * @see java.lang.Throwable#getMessage() - */ - public String getMessage() { - if (fExpected == null || fActual == null) - return Assert.format(super.getMessage(), fExpected, fActual); - - int end= Math.min(fExpected.length(), fActual.length()); - - int i= 0; - for(; i < end; i++) { - if (fExpected.charAt(i) != fActual.charAt(i)) - break; - } - int j= fExpected.length()-1; - int k= fActual.length()-1; - for (; k >= i && j >= i; k--,j--) { - if (fExpected.charAt(j) != fActual.charAt(k)) - break; - } - String actual, expected; - - // equal strings - if (j < i && k < i) { - expected= fExpected; - actual= fActual; - } else { - expected= fExpected.substring(i, j+1); - actual= fActual.substring(i, k+1); - if (i <= end && i > 0) { - expected= "..."+expected; - actual= "..."+actual; - } - - if (j < fExpected.length()-1) - expected= expected+"..."; - if (k < fActual.length()-1) - actual= actual+"..."; - } - return Assert.format(super.getMessage(), expected, actual); - } -} diff --git a/dx/src/junit/framework/Protectable.java b/dx/src/junit/framework/Protectable.java deleted file mode 100644 index 8243555a1..000000000 --- a/dx/src/junit/framework/Protectable.java +++ /dev/null @@ -1,14 +0,0 @@ -package junit.framework; - -/** - * A <em>Protectable</em> can be run and can throw a Throwable. - * - * @see TestResult - */ -public interface Protectable { - - /** - * Run the the following method protected. - */ - public abstract void protect() throws Throwable; -} diff --git a/dx/src/junit/framework/Test.java b/dx/src/junit/framework/Test.java deleted file mode 100644 index 1c6d57b36..000000000 --- a/dx/src/junit/framework/Test.java +++ /dev/null @@ -1,17 +0,0 @@ -package junit.framework; - -/** - * A <em>Test</em> can be run and collect its results. - * - * @see TestResult - */ -public interface Test { - /** - * Counts the number of test cases that will be run by this test. - */ - public abstract int countTestCases(); - /** - * Runs a test and collects its result in a TestResult instance. - */ - public abstract void run(TestResult result); -} diff --git a/dx/src/junit/framework/TestCase.java b/dx/src/junit/framework/TestCase.java deleted file mode 100644 index 8988c45ef..000000000 --- a/dx/src/junit/framework/TestCase.java +++ /dev/null @@ -1,197 +0,0 @@ -package junit.framework; - -import java.lang.reflect.*; - -/** - * A test case defines the fixture to run multiple tests. To define a test case<br> - * 1) implement a subclass of TestCase<br> - * 2) define instance variables that store the state of the fixture<br> - * 3) initialize the fixture state by overriding <code>setUp</code><br> - * 4) clean-up after a test by overriding <code>tearDown</code>.<br> - * Each test runs in its own fixture so there - * can be no side effects among test runs. - * Here is an example: - * <pre> - * public class MathTest extends TestCase { - * protected double fValue1; - * protected double fValue2; - * - * protected void setUp() { - * fValue1= 2.0; - * fValue2= 3.0; - * } - * } - * </pre> - * - * For each test implement a method which interacts - * with the fixture. Verify the expected results with assertions specified - * by calling <code>assertTrue</code> with a boolean. - * <pre> - * public void testAdd() { - * double result= fValue1 + fValue2; - * assertTrue(result == 5.0); - * } - * </pre> - * Once the methods are defined you can run them. The framework supports - * both a static type safe and more dynamic way to run a test. - * In the static way you override the runTest method and define the method to - * be invoked. A convenient way to do so is with an anonymous inner class. - * <pre> - * TestCase test= new MathTest("add") { - * public void runTest() { - * testAdd(); - * } - * }; - * test.run(); - * </pre> - * The dynamic way uses reflection to implement <code>runTest</code>. It dynamically finds - * and invokes a method. - * In this case the name of the test case has to correspond to the test method - * to be run. - * <pre> - * TestCase= new MathTest("testAdd"); - * test.run(); - * </pre> - * The tests to be run can be collected into a TestSuite. JUnit provides - * different <i>test runners</i> which can run a test suite and collect the results. - * A test runner either expects a static method <code>suite</code> as the entry - * point to get a test to run or it will extract the suite automatically. - * <pre> - * public static Test suite() { - * suite.addTest(new MathTest("testAdd")); - * suite.addTest(new MathTest("testDivideByZero")); - * return suite; - * } - * </pre> - * @see TestResult - * @see TestSuite - */ - -public abstract class TestCase extends Assert implements Test { - /** - * the name of the test case - */ - private String fName; - - /** - * No-arg constructor to enable serialization. This method - * is not intended to be used by mere mortals without calling setName(). - */ - public TestCase() { - fName= null; - } - /** - * Constructs a test case with the given name. - */ - public TestCase(String name) { - fName= name; - } - /** - * Counts the number of test cases executed by run(TestResult result). - */ - public int countTestCases() { - return 1; - } - /** - * Creates a default TestResult object - * - * @see TestResult - */ - protected TestResult createResult() { - return new TestResult(); - } - /** - * A convenience method to run this test, collecting the results with a - * default TestResult object. - * - * @see TestResult - */ - public TestResult run() { - TestResult result= createResult(); - run(result); - return result; - } - /** - * Runs the test case and collects the results in TestResult. - */ - public void run(TestResult result) { - result.run(this); - } - /** - * Runs the bare test sequence. - * @exception Throwable if any exception is thrown - */ - public void runBare() throws Throwable { - setUp(); - try { - runTest(); - } - finally { - tearDown(); - } - } - /** - * Override to run the test and assert its state. - * @exception Throwable if any exception is thrown - */ - protected void runTest() throws Throwable { - assertNotNull(fName); - Method runMethod= null; - try { - // use getMethod to get all public inherited - // methods. getDeclaredMethods returns all - // methods of this class but excludes the - // inherited ones. - runMethod= getClass().getMethod(fName, (Class[]) null); - } catch (NoSuchMethodException e) { - fail("Method \""+fName+"\" not found"); - } - if (!Modifier.isPublic(runMethod.getModifiers())) { - fail("Method \""+fName+"\" should be public"); - } - - try { - runMethod.invoke(this, (Object[]) new Class[0]); - } - catch (InvocationTargetException e) { - e.fillInStackTrace(); - throw e.getTargetException(); - } - catch (IllegalAccessException e) { - e.fillInStackTrace(); - throw e; - } - } - /** - * Sets up the fixture, for example, open a network connection. - * This method is called before a test is executed. - */ - protected void setUp() throws Exception { - } - /** - * Tears down the fixture, for example, close a network connection. - * This method is called after a test is executed. - */ - protected void tearDown() throws Exception { - } - /** - * Returns a string representation of the test case - */ - public String toString() { - return getName() + "(" + getClass().getName() + ")"; - } - /** - * Gets the name of a TestCase - * @return returns a String - */ - public String getName() { - return fName; - } - /** - * Sets the name of a TestCase - * @param name The name to set - */ - public void setName(String name) { - fName= name; - } -} diff --git a/dx/src/junit/framework/TestFailure.java b/dx/src/junit/framework/TestFailure.java deleted file mode 100644 index 664747d81..000000000 --- a/dx/src/junit/framework/TestFailure.java +++ /dev/null @@ -1,57 +0,0 @@ -package junit.framework; - -import java.io.PrintWriter; -import java.io.StringWriter; - - -/** - * A <code>TestFailure</code> collects a failed test together with - * the caught exception. - * @see TestResult - */ -public class TestFailure extends Object { - protected Test fFailedTest; - protected Throwable fThrownException; - - - /** - * Constructs a TestFailure with the given test and exception. - */ - public TestFailure(Test failedTest, Throwable thrownException) { - fFailedTest= failedTest; - fThrownException= thrownException; - } - /** - * Gets the failed test. - */ - public Test failedTest() { - return fFailedTest; - } - /** - * Gets the thrown exception. - */ - public Throwable thrownException() { - return fThrownException; - } - /** - * Returns a short description of the failure. - */ - public String toString() { - StringBuffer buffer= new StringBuffer(); - buffer.append(fFailedTest+": "+fThrownException.getMessage()); - return buffer.toString(); - } - public String trace() { - StringWriter stringWriter= new StringWriter(); - PrintWriter writer= new PrintWriter(stringWriter); - thrownException().printStackTrace(writer); - StringBuffer buffer= stringWriter.getBuffer(); - return buffer.toString(); - } - public String exceptionMessage() { - return thrownException().getMessage(); - } - public boolean isFailure() { - return thrownException() instanceof AssertionFailedError; - } -} diff --git a/dx/src/junit/framework/TestListener.java b/dx/src/junit/framework/TestListener.java deleted file mode 100644 index 755818752..000000000 --- a/dx/src/junit/framework/TestListener.java +++ /dev/null @@ -1,23 +0,0 @@ -package junit.framework; - -/** - * A Listener for test progress - */ -public interface TestListener { - /** - * An error occurred. - */ - public void addError(Test test, Throwable t); - /** - * A failure occurred. - */ - public void addFailure(Test test, AssertionFailedError t); - /** - * A test ended. - */ - public void endTest(Test test); - /** - * A test started. - */ - public void startTest(Test test); -} diff --git a/dx/src/junit/framework/TestResult.java b/dx/src/junit/framework/TestResult.java deleted file mode 100644 index 4b1a7e2ed..000000000 --- a/dx/src/junit/framework/TestResult.java +++ /dev/null @@ -1,166 +0,0 @@ -package junit.framework; - -import java.util.Vector; -import java.util.Enumeration; - -/** - * A <code>TestResult</code> collects the results of executing - * a test case. It is an instance of the Collecting Parameter pattern. - * The test framework distinguishes between <i>failures</i> and <i>errors</i>. - * A failure is anticipated and checked for with assertions. Errors are - * unanticipated problems like an <code>ArrayIndexOutOfBoundsException</code>. - * - * @see Test - */ -public class TestResult extends Object { - protected Vector<TestFailure> fFailures; - protected Vector<TestFailure> fErrors; - protected Vector<TestListener> fListeners; - protected int fRunTests; - private boolean fStop; - - public TestResult() { - fFailures= new Vector<TestFailure>(); - fErrors= new Vector<TestFailure>(); - fListeners= new Vector<TestListener>(); - fRunTests= 0; - fStop= false; - } - /** - * Adds an error to the list of errors. The passed in exception - * caused the error. - */ - public synchronized void addError(Test test, Throwable t) { - fErrors.addElement(new TestFailure(test, t)); - for (Enumeration e= cloneListeners().elements(); e.hasMoreElements(); ) { - ((TestListener)e.nextElement()).addError(test, t); - } - } - /** - * Adds a failure to the list of failures. The passed in exception - * caused the failure. - */ - public synchronized void addFailure(Test test, AssertionFailedError t) { - fFailures.addElement(new TestFailure(test, t)); - for (Enumeration e= cloneListeners().elements(); e.hasMoreElements(); ) { - ((TestListener)e.nextElement()).addFailure(test, t); - } - } - /** - * Registers a TestListener - */ - public synchronized void addListener(TestListener listener) { - fListeners.addElement(listener); - } - /** - * Unregisters a TestListener - */ - public synchronized void removeListener(TestListener listener) { - fListeners.removeElement(listener); - } - /** - * Returns a copy of the listeners. - */ - private synchronized Vector cloneListeners() { - return (Vector)fListeners.clone(); - } - /** - * Informs the result that a test was completed. - */ - public void endTest(Test test) { - for (Enumeration e= cloneListeners().elements(); e.hasMoreElements(); ) { - ((TestListener)e.nextElement()).endTest(test); - } - } - /** - * Gets the number of detected errors. - */ - public synchronized int errorCount() { - return fErrors.size(); - } - /** - * Returns an Enumeration for the errors - */ - public synchronized Enumeration errors() { - return fErrors.elements(); - } - /** - * Gets the number of detected failures. - */ - public synchronized int failureCount() { - return fFailures.size(); - } - /** - * Returns an Enumeration for the failures - */ - public synchronized Enumeration failures() { - return fFailures.elements(); - } - /** - * Runs a TestCase. - */ - protected void run(final TestCase test) { - startTest(test); - Protectable p= new Protectable() { - public void protect() throws Throwable { - test.runBare(); - } - }; - runProtected(test, p); - - endTest(test); - } - /** - * Gets the number of run tests. - */ - public synchronized int runCount() { - return fRunTests; - } - /** - * Runs a TestCase. - */ - public void runProtected(final Test test, Protectable p) { - try { - p.protect(); - } - catch (AssertionFailedError e) { - addFailure(test, e); - } - catch (ThreadDeath e) { // don't catch ThreadDeath by accident - throw e; - } - catch (Throwable e) { - addError(test, e); - } - } - /** - * Checks whether the test run should stop - */ - public synchronized boolean shouldStop() { - return fStop; - } - /** - * Informs the result that a test will be started. - */ - public void startTest(Test test) { - final int count= test.countTestCases(); - synchronized(this) { - fRunTests+= count; - } - for (Enumeration e= cloneListeners().elements(); e.hasMoreElements(); ) { - ((TestListener)e.nextElement()).startTest(test); - } - } - /** - * Marks that the test run should stop. - */ - public synchronized void stop() { - fStop= true; - } - /** - * Returns whether the entire test was successful or not. - */ - public synchronized boolean wasSuccessful() { - return failureCount() == 0 && errorCount() == 0; - } -} diff --git a/dx/src/junit/framework/TestSuite.java b/dx/src/junit/framework/TestSuite.java deleted file mode 100644 index 2987ad12c..000000000 --- a/dx/src/junit/framework/TestSuite.java +++ /dev/null @@ -1,265 +0,0 @@ -package junit.framework; - -import java.util.Vector; -import java.util.Enumeration; -import java.io.PrintWriter;import java.io.StringWriter;import java.lang.reflect.*; -import java.lang.reflect.Constructor; - -/** - * A <code>TestSuite</code> is a <code>Composite</code> of Tests. - * It runs a collection of test cases. Here is an example using - * the dynamic test definition. - * <pre> - * TestSuite suite= new TestSuite(); - * suite.addTest(new MathTest("testAdd")); - * suite.addTest(new MathTest("testDivideByZero")); - * </pre> - * Alternatively, a TestSuite can extract the tests to be run automatically. - * To do so you pass the class of your TestCase class to the - * TestSuite constructor. - * <pre> - * TestSuite suite= new TestSuite(MathTest.class); - * </pre> - * This constructor creates a suite with all the methods - * starting with "test" that take no arguments. - * - * @see Test - */ -public class TestSuite implements Test { - - private Vector<Test> fTests= new Vector<Test>(10); - private String fName; - - /** - * Constructs an empty TestSuite. - */ - public TestSuite() { - } - - /** - * Constructs a TestSuite from the given class with the given name. - * @see TestSuite#TestSuite(Class) - */ - public TestSuite(Class theClass, String name) { - this(theClass); - setName(name); - } - - /** - * Constructs a TestSuite from the given class. Adds all the methods - * starting with "test" as test cases to the suite. - * Parts of this method was written at 2337 meters in the Huffihutte, - * Kanton Uri - */ - public TestSuite(final Class theClass) { - fName= theClass.getName(); - try { - getTestConstructor(theClass); // Avoid generating multiple error messages - } catch (NoSuchMethodException e) { - addTest(warning("Class "+theClass.getName()+" has no public constructor TestCase(String name) or TestCase()")); - return; - } - - if (!Modifier.isPublic(theClass.getModifiers())) { - addTest(warning("Class "+theClass.getName()+" is not public")); - return; - } - - Class superClass= theClass; - Vector<String> names= new Vector<String>(); - while (Test.class.isAssignableFrom(superClass)) { - Method[] methods= superClass.getDeclaredMethods(); - for (int i= 0; i < methods.length; i++) { - addTestMethod(methods[i], names, theClass); - } - superClass= superClass.getSuperclass(); - } - if (fTests.size() == 0) - addTest(warning("No tests found in "+theClass.getName())); - } - - /** - * Constructs an empty TestSuite. - */ - public TestSuite(String name) { - setName(name); - } - - /** - * Adds a test to the suite. - */ - public void addTest(Test test) { - fTests.addElement(test); - } - - /** - * Adds the tests from the given class to the suite - */ - public void addTestSuite(Class testClass) { - addTest(new TestSuite(testClass)); - } - - private void addTestMethod(Method m, Vector<String> names, Class theClass) { - String name= m.getName(); - if (names.contains(name)) - return; - if (! isPublicTestMethod(m)) { - if (isTestMethod(m)) - addTest(warning("Test method isn't public: "+m.getName())); - return; - } - names.addElement(name); - addTest(createTest(theClass, name)); - } - - /** - * ...as the moon sets over the early morning Merlin, Oregon - * mountains, our intrepid adventurers type... - */ - static public Test createTest(Class theClass, String name) { - Constructor constructor; - try { - constructor= getTestConstructor(theClass); - } catch (NoSuchMethodException e) { - return warning("Class "+theClass.getName()+" has no public constructor TestCase(String name) or TestCase()"); - } - Object test; - try { - if (constructor.getParameterTypes().length == 0) { - test= constructor.newInstance(new Object[0]); - if (test instanceof TestCase) - ((TestCase) test).setName(name); - } else { - test= constructor.newInstance(new Object[]{name}); - } - } catch (InstantiationException e) { - return(warning("Cannot instantiate test case: "+name+" ("+exceptionToString(e)+")")); - } catch (InvocationTargetException e) { - return(warning("Exception in constructor: "+name+" ("+exceptionToString(e.getTargetException())+")")); - } catch (IllegalAccessException e) { - return(warning("Cannot access test case: "+name+" ("+exceptionToString(e)+")")); - } - return (Test) test; - } - - /** - * Converts the stack trace into a string - */ - private static String exceptionToString(Throwable t) { - StringWriter stringWriter= new StringWriter(); - PrintWriter writer= new PrintWriter(stringWriter); - t.printStackTrace(writer); - return stringWriter.toString(); - - } - - /** - * Counts the number of test cases that will be run by this test. - */ - public int countTestCases() { - int count= 0; - for (Enumeration e= tests(); e.hasMoreElements(); ) { - Test test= (Test)e.nextElement(); - count= count + test.countTestCases(); - } - return count; - } - - /** - * Gets a constructor which takes a single String as - * its argument or a no arg constructor. - */ - public static Constructor getTestConstructor(Class theClass) throws NoSuchMethodException { - Class[] args= { String.class }; - try { - return theClass.getConstructor(args); - } catch (NoSuchMethodException e) { - // fall through - } - return theClass.getConstructor(new Class[0]); - } - - private boolean isPublicTestMethod(Method m) { - return isTestMethod(m) && Modifier.isPublic(m.getModifiers()); - } - - private boolean isTestMethod(Method m) { - String name= m.getName(); - Class[] parameters= m.getParameterTypes(); - Class returnType= m.getReturnType(); - return parameters.length == 0 && name.startsWith("test") && returnType.equals(Void.TYPE); - } - - /** - * Runs the tests and collects their result in a TestResult. - */ - public void run(TestResult result) { - for (Enumeration e= tests(); e.hasMoreElements(); ) { - if (result.shouldStop() ) - break; - Test test= (Test)e.nextElement(); - runTest(test, result); - } - } - - public void runTest(Test test, TestResult result) { - test.run(result); - } - - /** - * Returns the test at the given index - */ - public Test testAt(int index) { - return (Test)fTests.elementAt(index); - } - - /** - * Returns the number of tests in this suite - */ - public int testCount() { - return fTests.size(); - } - - /** - * Returns the tests as an enumeration - */ - public Enumeration tests() { - return fTests.elements(); - } - - /** - */ - public String toString() { - if (getName() != null) - return getName(); - return super.toString(); - } - - /** - * Sets the name of the suite. - * @param name The name to set - */ - public void setName(String name) { - fName= name; - } - - /** - * Returns the name of the suite. Not all - * test suites have a name and this method - * can return null. - */ - public String getName() { - return fName; - } - - /** - * Returns a test which will fail and log a warning message. - */ - private static Test warning(final String message) { - return new TestCase("warning") { - protected void runTest() { - fail(message); - } - }; - } -} diff --git a/dx/src/junit/runner/BaseTestRunner.java b/dx/src/junit/runner/BaseTestRunner.java deleted file mode 100644 index 39c8c2f98..000000000 --- a/dx/src/junit/runner/BaseTestRunner.java +++ /dev/null @@ -1,323 +0,0 @@ -package junit.runner; - -import junit.framework.*; -import java.lang.reflect.*; -import java.text.NumberFormat; -import java.io.*; -import java.util.*; - -/** - * Base class for all test runners. - * This class was born live on stage in Sardinia during XP2000. - */ -public abstract class BaseTestRunner implements TestListener { - public static final String SUITE_METHODNAME= "suite"; - - private static Properties fPreferences; - static int fgMaxMessageLength= 500; - static boolean fgFilterStack= true; - boolean fLoading= true; - - /* - * Implementation of TestListener - */ - public synchronized void startTest(Test test) { - testStarted(test.toString()); - } - - protected static void setPreferences(Properties preferences) { - fPreferences= preferences; - } - - protected static Properties getPreferences() { - if (fPreferences == null) { - fPreferences= new Properties(); - fPreferences.put("loading", "true"); - fPreferences.put("filterstack", "true"); - readPreferences(); - } - return fPreferences; - } - - public static void savePreferences() throws IOException { - FileOutputStream fos= new FileOutputStream(getPreferencesFile()); - try { - getPreferences().store(fos, ""); - } finally { - fos.close(); - } - } - - public void setPreference(String key, String value) { - getPreferences().setProperty(key, value); - } - - public synchronized void endTest(Test test) { - testEnded(test.toString()); - } - - public synchronized void addError(final Test test, final Throwable t) { - testFailed(TestRunListener.STATUS_ERROR, test, t); - } - - public synchronized void addFailure(final Test test, final AssertionFailedError t) { - testFailed(TestRunListener.STATUS_FAILURE, test, t); - } - - // TestRunListener implementation - - public abstract void testStarted(String testName); - - public abstract void testEnded(String testName); - - public abstract void testFailed(int status, Test test, Throwable t); - - /** - * Returns the Test corresponding to the given suite. This is - * a template method, subclasses override runFailed(), clearStatus(). - */ - public Test getTest(String suiteClassName) { - if (suiteClassName.length() <= 0) { - clearStatus(); - return null; - } - Class testClass= null; - try { - testClass= loadSuiteClass(suiteClassName); - } catch (ClassNotFoundException e) { - String clazz= e.getMessage(); - if (clazz == null) - clazz= suiteClassName; - runFailed("Class not found \""+clazz+"\""); - return null; - } catch(Exception e) { - runFailed("Error: "+e.toString()); - return null; - } - Method suiteMethod= null; - try { - suiteMethod= testClass.getMethod(SUITE_METHODNAME, new Class[0]); - } catch(Exception e) { - // try to extract a test suite automatically - clearStatus(); - return new TestSuite(testClass); - } - if (! Modifier.isStatic(suiteMethod.getModifiers())) { - runFailed("Suite() method must be static"); - return null; - } - Test test= null; - try { - test= (Test)suiteMethod.invoke(null, (Object[]) new Class[0]); // static method - if (test == null) - return test; - } - catch (InvocationTargetException e) { - runFailed("Failed to invoke suite():" + e.getTargetException().toString()); - return null; - } - catch (IllegalAccessException e) { - runFailed("Failed to invoke suite():" + e.toString()); - return null; - } - - clearStatus(); - return test; - } - - /** - * Returns the formatted string of the elapsed time. - */ - public String elapsedTimeAsString(long runTime) { - return NumberFormat.getInstance().format((double)runTime/1000); - } - - /** - * Processes the command line arguments and - * returns the name of the suite class to run or null - */ - protected String processArguments(String[] args) { - String suiteName= null; - for (int i= 0; i < args.length; i++) { - if (args[i].equals("-noloading")) { - setLoading(false); - } else if (args[i].equals("-nofilterstack")) { - fgFilterStack= false; - } else if (args[i].equals("-c")) { - if (args.length > i+1) - suiteName= extractClassName(args[i+1]); - else - System.out.println("Missing Test class name"); - i++; - } else { - suiteName= args[i]; - } - } - return suiteName; - } - - /** - * Sets the loading behaviour of the test runner - */ - public void setLoading(boolean enable) { - fLoading= enable; - } - /** - * Extract the class name from a String in VA/Java style - */ - public String extractClassName(String className) { - if(className.startsWith("Default package for")) - return className.substring(className.lastIndexOf(".")+1); - return className; - } - - /** - * Truncates a String to the maximum length. - */ - public static String truncate(String s) { - if (fgMaxMessageLength != -1 && s.length() > fgMaxMessageLength) - s= s.substring(0, fgMaxMessageLength)+"..."; - return s; - } - - /** - * Override to define how to handle a failed loading of - * a test suite. - */ - protected abstract void runFailed(String message); - - /** - * Returns the loaded Class for a suite name. - */ - protected Class loadSuiteClass(String suiteClassName) throws ClassNotFoundException { - return getLoader().load(suiteClassName); - } - - /** - * Clears the status message. - */ - protected void clearStatus() { // Belongs in the GUI TestRunner class - } - - /** - * Returns the loader to be used. - */ - public TestSuiteLoader getLoader() { - if (useReloadingTestSuiteLoader()) - return new ReloadingTestSuiteLoader(); - return new StandardTestSuiteLoader(); - } - - protected boolean useReloadingTestSuiteLoader() { - return getPreference("loading").equals("true") && !inVAJava() && fLoading; - } - - private static File getPreferencesFile() { - String home= System.getProperty("user.home"); - return new File(home, "junit.properties"); - } - - private static void readPreferences() { - InputStream is= null; - try { - is= new FileInputStream(getPreferencesFile()); - setPreferences(new Properties(getPreferences())); - getPreferences().load(is); - } catch (IOException e) { - try { - if (is != null) - is.close(); - } catch (IOException e1) { - } - } - } - - public static String getPreference(String key) { - return getPreferences().getProperty(key); - } - - public static int getPreference(String key, int dflt) { - String value= getPreference(key); - int intValue= dflt; - if (value == null) - return intValue; - try { - intValue= Integer.parseInt(value); - } catch (NumberFormatException ne) { - } - return intValue; - } - - public static boolean inVAJava() { - try { - Class.forName("com.ibm.uvm.tools.DebugSupport"); - } - catch (Exception e) { - return false; - } - return true; - } - - /** - * Returns a filtered stack trace - */ - public static String getFilteredTrace(Throwable t) { - StringWriter stringWriter= new StringWriter(); - PrintWriter writer= new PrintWriter(stringWriter); - t.printStackTrace(writer); - StringBuffer buffer= stringWriter.getBuffer(); - String trace= buffer.toString(); - return BaseTestRunner.getFilteredTrace(trace); - } - - /** - * Filters stack frames from internal JUnit classes - */ - public static String getFilteredTrace(String stack) { - if (showStackRaw()) - return stack; - - StringWriter sw= new StringWriter(); - PrintWriter pw= new PrintWriter(sw); - StringReader sr= new StringReader(stack); - BufferedReader br= new BufferedReader(sr); - - String line; - try { - while ((line= br.readLine()) != null) { - if (!filterLine(line)) - pw.println(line); - } - } catch (Exception IOException) { - return stack; // return the stack unfiltered - } - return sw.toString(); - } - - protected static boolean showStackRaw() { - return !getPreference("filterstack").equals("true") || fgFilterStack == false; - } - - static boolean filterLine(String line) { - String[] patterns= new String[] { - "junit.framework.TestCase", - "junit.framework.TestResult", - "junit.framework.TestSuite", - "junit.framework.Assert.", // don't filter AssertionFailure - "junit.swingui.TestRunner", - "junit.awtui.TestRunner", - "junit.textui.TestRunner", - "java.lang.reflect.Method.invoke(" - }; - for (int i= 0; i < patterns.length; i++) { - if (line.indexOf(patterns[i]) > 0) - return true; - } - return false; - } - - static { - fgMaxMessageLength= getPreference("maxmessage", fgMaxMessageLength); - } - -} diff --git a/dx/src/junit/runner/ClassPathTestCollector.java b/dx/src/junit/runner/ClassPathTestCollector.java deleted file mode 100644 index 24bf1e998..000000000 --- a/dx/src/junit/runner/ClassPathTestCollector.java +++ /dev/null @@ -1,80 +0,0 @@ -package junit.runner; - -import java.util.*; -import java.io.*; - -/** - * An implementation of a TestCollector that consults the - * class path. It considers all classes on the class path - * excluding classes in JARs. It leaves it up to subclasses - * to decide whether a class is a runnable Test. - * - * @see TestCollector - */ -public abstract class ClassPathTestCollector implements TestCollector { - - static final int SUFFIX_LENGTH= ".class".length(); - - public ClassPathTestCollector() { - } - - public Enumeration collectTests() { - String classPath= System.getProperty("java.class.path"); - Hashtable result = collectFilesInPath(classPath); - return result.elements(); - } - - public Hashtable collectFilesInPath(String classPath) { - Hashtable result= collectFilesInRoots(splitClassPath(classPath)); - return result; - } - - Hashtable collectFilesInRoots(Vector roots) { - Hashtable<String,String> result= new Hashtable<String,String>(100); - Enumeration e= roots.elements(); - while (e.hasMoreElements()) - gatherFiles(new File((String)e.nextElement()), "", result); - return result; - } - - void gatherFiles(File classRoot, String classFileName, Hashtable<String,String> result) { - File thisRoot= new File(classRoot, classFileName); - if (thisRoot.isFile()) { - if (isTestClass(classFileName)) { - String className= classNameFromFile(classFileName); - result.put(className, className); - } - return; - } - String[] contents= thisRoot.list(); - if (contents != null) { - for (int i= 0; i < contents.length; i++) - gatherFiles(classRoot, classFileName+File.separatorChar+contents[i], result); - } - } - - Vector splitClassPath(String classPath) { - Vector<String> result= new Vector<String>(); - String separator= System.getProperty("path.separator"); - StringTokenizer tokenizer= new StringTokenizer(classPath, separator); - while (tokenizer.hasMoreTokens()) - result.addElement(tokenizer.nextToken()); - return result; - } - - protected boolean isTestClass(String classFileName) { - return - classFileName.endsWith(".class") && - classFileName.indexOf('$') < 0 && - classFileName.indexOf("Test") > 0; - } - - protected String classNameFromFile(String classFileName) { - // convert /a/b.class to a.b - String s= classFileName.substring(0, classFileName.length()-SUFFIX_LENGTH); - String s2= s.replace(File.separatorChar, '.'); - if (s2.startsWith(".")) - return s2.substring(1); - return s2; - } -} diff --git a/dx/src/junit/runner/FailureDetailView.java b/dx/src/junit/runner/FailureDetailView.java deleted file mode 100644 index 762326b3f..000000000 --- a/dx/src/junit/runner/FailureDetailView.java +++ /dev/null @@ -1,23 +0,0 @@ -package junit.runner; - -import java.awt.Component; - -import junit.framework.*; - -/** - * A view to show a details about a failure - */ -public interface FailureDetailView { - /** - * Returns the component used to present the TraceView - */ - public Component getComponent(); - /** - * Shows details of a TestFailure - */ - public void showFailure(TestFailure failure); - /** - * Clears the view - */ - public void clear(); -} diff --git a/dx/src/junit/runner/LoadingTestCollector.java b/dx/src/junit/runner/LoadingTestCollector.java deleted file mode 100644 index b13835930..000000000 --- a/dx/src/junit/runner/LoadingTestCollector.java +++ /dev/null @@ -1,69 +0,0 @@ -package junit.runner; - -import java.lang.reflect.*; -import junit.runner.*; -import junit.framework.*; - -/** - * An implementation of a TestCollector that loads - * all classes on the class path and tests whether - * it is assignable from Test or provides a static suite method. - * @see TestCollector - */ -public class LoadingTestCollector extends ClassPathTestCollector { - - TestCaseClassLoader fLoader; - - public LoadingTestCollector() { - fLoader= new TestCaseClassLoader(); - } - - protected boolean isTestClass(String classFileName) { - try { - if (classFileName.endsWith(".class")) { - Class testClass= classFromFile(classFileName); - return (testClass != null) && isTestClass(testClass); - } - } - catch (ClassNotFoundException expected) { - } - catch (NoClassDefFoundError notFatal) { - } - return false; - } - - Class classFromFile(String classFileName) throws ClassNotFoundException { - String className= classNameFromFile(classFileName); - if (!fLoader.isExcluded(className)) - return fLoader.loadClass(className, false); - return null; - } - - boolean isTestClass(Class testClass) { - if (hasSuiteMethod(testClass)) - return true; - if (Test.class.isAssignableFrom(testClass) && - Modifier.isPublic(testClass.getModifiers()) && - hasPublicConstructor(testClass)) - return true; - return false; - } - - boolean hasSuiteMethod(Class testClass) { - try { - testClass.getMethod(BaseTestRunner.SUITE_METHODNAME, new Class[0]); - } catch(Exception e) { - return false; - } - return true; - } - - boolean hasPublicConstructor(Class testClass) { - try { - TestSuite.getTestConstructor(testClass); - } catch(NoSuchMethodException e) { - return false; - } - return true; - } -} diff --git a/dx/src/junit/runner/ReloadingTestSuiteLoader.java b/dx/src/junit/runner/ReloadingTestSuiteLoader.java deleted file mode 100644 index f7ef919cc..000000000 --- a/dx/src/junit/runner/ReloadingTestSuiteLoader.java +++ /dev/null @@ -1,19 +0,0 @@ -package junit.runner; - -/** - * A TestSuite loader that can reload classes. - */ -public class ReloadingTestSuiteLoader implements TestSuiteLoader { - - public Class load(String suiteClassName) throws ClassNotFoundException { - return createLoader().loadClass(suiteClassName, true); - } - - public Class reload(Class aClass) throws ClassNotFoundException { - return createLoader().loadClass(aClass.getName(), true); - } - - protected TestCaseClassLoader createLoader() { - return new TestCaseClassLoader(); - } -} diff --git a/dx/src/junit/runner/SimpleTestCollector.java b/dx/src/junit/runner/SimpleTestCollector.java deleted file mode 100644 index 9d1956ad2..000000000 --- a/dx/src/junit/runner/SimpleTestCollector.java +++ /dev/null @@ -1,20 +0,0 @@ -package junit.runner; - -/** - * An implementation of a TestCollector that considers - * a class to be a test class when it contains the - * pattern "Test" in its name - * @see TestCollector - */ -public class SimpleTestCollector extends ClassPathTestCollector { - - public SimpleTestCollector() { - } - - protected boolean isTestClass(String classFileName) { - return - classFileName.endsWith(".class") && - classFileName.indexOf('$') < 0 && - classFileName.indexOf("Test") > 0; - } -} diff --git a/dx/src/junit/runner/Sorter.java b/dx/src/junit/runner/Sorter.java deleted file mode 100644 index e614ab47e..000000000 --- a/dx/src/junit/runner/Sorter.java +++ /dev/null @@ -1,38 +0,0 @@ -package junit.runner; - -import java.util.*; - -import junit.runner.*; - -/** - * A custom quick sort with support to customize the swap behaviour. - * NOTICE: We can't use the the sorting support from the JDK 1.2 collection - * classes because of the JDK 1.1.7 compatibility. - */ -public class Sorter { - public static interface Swapper { - public void swap(Vector values, int left, int right); - } - - public static void sortStrings(Vector values , int left, int right, Swapper swapper) { - int oleft= left; - int oright= right; - String mid= (String)values.elementAt((left + right) / 2); - do { - while (((String)(values.elementAt(left))).compareTo(mid) < 0) - left++; - while (mid.compareTo((String)(values.elementAt(right))) < 0) - right--; - if (left <= right) { - swapper.swap(values, left, right); - left++; - right--; - } - } while (left <= right); - - if (oleft < right) - sortStrings(values, oleft, right, swapper); - if (left < oright) - sortStrings(values, left, oright, swapper); - } -} diff --git a/dx/src/junit/runner/StandardTestSuiteLoader.java b/dx/src/junit/runner/StandardTestSuiteLoader.java deleted file mode 100644 index e2bd765ee..000000000 --- a/dx/src/junit/runner/StandardTestSuiteLoader.java +++ /dev/null @@ -1,19 +0,0 @@ -package junit.runner; - -/** - * The standard test suite loader. It can only load the same class once. - */ -public class StandardTestSuiteLoader implements TestSuiteLoader { - /** - * Uses the system class loader to load the test class - */ - public Class load(String suiteClassName) throws ClassNotFoundException { - return Class.forName(suiteClassName); - } - /** - * Uses the system class loader to load the test class - */ - public Class reload(Class aClass) throws ClassNotFoundException { - return aClass; - } -} diff --git a/dx/src/junit/runner/TestCaseClassLoader.java b/dx/src/junit/runner/TestCaseClassLoader.java deleted file mode 100644 index 543641a85..000000000 --- a/dx/src/junit/runner/TestCaseClassLoader.java +++ /dev/null @@ -1,226 +0,0 @@ -package junit.runner; - -import java.util.*; -import java.io.*; -import java.net.URL; -import java.util.zip.*; - -/** - * A custom class loader which enables the reloading - * of classes for each test run. The class loader - * can be configured with a list of package paths that - * should be excluded from loading. The loading - * of these packages is delegated to the system class - * loader. They will be shared across test runs. - * <p> - * The list of excluded package paths is specified in - * a properties file "excluded.properties" that is located in - * the same place as the TestCaseClassLoader class. - * <p> - * <b>Known limitation:</b> the TestCaseClassLoader cannot load classes - * from jar files. - */ - - -public class TestCaseClassLoader extends ClassLoader { - /** scanned class path */ - private Vector<String> fPathItems; - /** default excluded paths */ - private String[] defaultExclusions= { - "junit.framework.", - "junit.extensions.", - "junit.runner." - }; - /** name of excluded properties file */ - static final String EXCLUDED_FILE= "excluded.properties"; - /** excluded paths */ - private Vector<String> fExcluded; - - /** - * Constructs a TestCaseLoader. It scans the class path - * and the excluded package paths - */ - public TestCaseClassLoader() { - this(System.getProperty("java.class.path")); - } - - /** - * Constructs a TestCaseLoader. It scans the class path - * and the excluded package paths - */ - public TestCaseClassLoader(String classPath) { - scanPath(classPath); - readExcludedPackages(); - } - - private void scanPath(String classPath) { - String separator= System.getProperty("path.separator"); - fPathItems= new Vector<String>(10); - StringTokenizer st= new StringTokenizer(classPath, separator); - while (st.hasMoreTokens()) { - fPathItems.addElement(st.nextToken()); - } - } - - public URL getResource(String name) { - return ClassLoader.getSystemResource(name); - } - - public InputStream getResourceAsStream(String name) { - return ClassLoader.getSystemResourceAsStream(name); - } - - public boolean isExcluded(String name) { - for (int i= 0; i < fExcluded.size(); i++) { - if (name.startsWith((String) fExcluded.elementAt(i))) { - return true; - } - } - return false; - } - - public synchronized Class loadClass(String name, boolean resolve) - throws ClassNotFoundException { - - Class c= findLoadedClass(name); - if (c != null) - return c; - // - // Delegate the loading of excluded classes to the - // standard class loader. - // - if (isExcluded(name)) { - try { - c= findSystemClass(name); - return c; - } catch (ClassNotFoundException e) { - // keep searching - } - } - if (c == null) { - byte[] data= lookupClassData(name); - if (data == null) - throw new ClassNotFoundException(); - c= defineClass(name, data, 0, data.length); - } - if (resolve) - resolveClass(c); - return c; - } - - private byte[] lookupClassData(String className) throws ClassNotFoundException { - byte[] data= null; - for (int i= 0; i < fPathItems.size(); i++) { - String path= (String) fPathItems.elementAt(i); - String fileName= className.replace('.', '/')+".class"; - if (isJar(path)) { - data= loadJarData(path, fileName); - } else { - data= loadFileData(path, fileName); - } - if (data != null) - return data; - } - throw new ClassNotFoundException(className); - } - - boolean isJar(String pathEntry) { - return pathEntry.endsWith(".jar") || - pathEntry.endsWith(".zip") || - pathEntry.endsWith(".apk"); - } - - private byte[] loadFileData(String path, String fileName) { - File file= new File(path, fileName); - if (file.exists()) { - return getClassData(file); - } - return null; - } - - private byte[] getClassData(File f) { - try { - FileInputStream stream= new FileInputStream(f); - ByteArrayOutputStream out= new ByteArrayOutputStream(1000); - byte[] b= new byte[1000]; - int n; - while ((n= stream.read(b)) != -1) - out.write(b, 0, n); - stream.close(); - out.close(); - return out.toByteArray(); - - } catch (IOException e) { - } - return null; - } - - private byte[] loadJarData(String path, String fileName) { - ZipFile zipFile= null; - InputStream stream= null; - File archive= new File(path); - if (!archive.exists()) - return null; - try { - zipFile= new ZipFile(archive); - } catch(IOException io) { - return null; - } - ZipEntry entry= zipFile.getEntry(fileName); - if (entry == null) - return null; - int size= (int) entry.getSize(); - try { - stream= zipFile.getInputStream(entry); - byte[] data= new byte[size]; - int pos= 0; - while (pos < size) { - int n= stream.read(data, pos, data.length - pos); - pos += n; - } - zipFile.close(); - return data; - } catch (IOException e) { - } finally { - try { - if (stream != null) - stream.close(); - } catch (IOException e) { - } - } - return null; - } - - private void readExcludedPackages() { - fExcluded= new Vector<String>(10); - for (int i= 0; i < defaultExclusions.length; i++) - fExcluded.addElement(defaultExclusions[i]); - - InputStream is= getClass().getResourceAsStream(EXCLUDED_FILE); - if (is == null) - return; - Properties p= new Properties(); - try { - p.load(is); - } - catch (IOException e) { - return; - } finally { - try { - is.close(); - } catch (IOException e) { - } - } - for (Enumeration e= p.propertyNames(); e.hasMoreElements(); ) { - String key= (String)e.nextElement(); - if (key.startsWith("excluded.")) { - String path= p.getProperty(key); - path= path.trim(); - if (path.endsWith("*")) - path= path.substring(0, path.length()-1); - if (path.length() > 0) - fExcluded.addElement(path); - } - } - } -} diff --git a/dx/src/junit/runner/TestCollector.java b/dx/src/junit/runner/TestCollector.java deleted file mode 100644 index 73efb4e39..000000000 --- a/dx/src/junit/runner/TestCollector.java +++ /dev/null @@ -1,16 +0,0 @@ -package junit.runner; - -import java.util.*; - - -/** - * Collects Test class names to be presented - * by the TestSelector. - * @see TestSelector - */ -public interface TestCollector { - /** - * Returns an enumeration of Strings with qualified class names - */ - public Enumeration collectTests(); -} diff --git a/dx/src/junit/runner/TestRunListener.java b/dx/src/junit/runner/TestRunListener.java deleted file mode 100644 index b11ef0744..000000000 --- a/dx/src/junit/runner/TestRunListener.java +++ /dev/null @@ -1,19 +0,0 @@ -package junit.runner; -/** - * A listener interface for observing the - * execution of a test run. Unlike TestListener, - * this interface using only primitive objects, - * making it suitable for remote test execution. - */ - public interface TestRunListener { - /* test status constants*/ - public static final int STATUS_ERROR= 1; - public static final int STATUS_FAILURE= 2; - - public void testRunStarted(String testSuiteName, int testCount); - public void testRunEnded(long elapsedTime); - public void testRunStopped(long elapsedTime); - public void testStarted(String testName); - public void testEnded(String testName); - public void testFailed(int status, String testName, String trace); -} diff --git a/dx/src/junit/runner/TestSuiteLoader.java b/dx/src/junit/runner/TestSuiteLoader.java deleted file mode 100644 index 39a4cf79a..000000000 --- a/dx/src/junit/runner/TestSuiteLoader.java +++ /dev/null @@ -1,9 +0,0 @@ -package junit.runner; - -/** - * An interface to define how a test suite should be loaded. - */ -public interface TestSuiteLoader { - abstract public Class load(String suiteClassName) throws ClassNotFoundException; - abstract public Class reload(Class aClass) throws ClassNotFoundException; -} diff --git a/dx/src/junit/runner/Version.java b/dx/src/junit/runner/Version.java deleted file mode 100644 index b4541abde..000000000 --- a/dx/src/junit/runner/Version.java +++ /dev/null @@ -1,14 +0,0 @@ -package junit.runner; - -/** - * This class defines the current version of JUnit - */ -public class Version { - private Version() { - // don't instantiate - } - - public static String id() { - return "3.8.1"; - } -} diff --git a/dx/src/junit/runner/excluded.properties b/dx/src/junit/runner/excluded.properties deleted file mode 100644 index 32846283e..000000000 --- a/dx/src/junit/runner/excluded.properties +++ /dev/null @@ -1,12 +0,0 @@ -# -# The list of excluded package paths for the TestCaseClassLoader -# -excluded.0=sun.* -excluded.1=com.sun.* -excluded.2=org.omg.* -excluded.3=javax.* -excluded.4=sunw.* -excluded.5=java.* -excluded.6=org.w3c.dom.* -excluded.7=org.xml.sax.* -excluded.8=net.jini.* diff --git a/dx/src/junit/runner/logo.gif b/dx/src/junit/runner/logo.gif Binary files differdeleted file mode 100644 index d0e154738..000000000 --- a/dx/src/junit/runner/logo.gif +++ /dev/null diff --git a/dx/src/junit/runner/smalllogo.gif b/dx/src/junit/runner/smalllogo.gif Binary files differdeleted file mode 100644 index 7b25eaf6a..000000000 --- a/dx/src/junit/runner/smalllogo.gif +++ /dev/null diff --git a/dx/src/junit/textui/ResultPrinter.java b/dx/src/junit/textui/ResultPrinter.java deleted file mode 100644 index 1ebb7a178..000000000 --- a/dx/src/junit/textui/ResultPrinter.java +++ /dev/null @@ -1,139 +0,0 @@ - -package junit.textui; - -import java.io.PrintStream; -import java.text.NumberFormat; -import java.util.Enumeration; - -import junit.framework.AssertionFailedError; -import junit.framework.Test; -import junit.framework.TestFailure; -import junit.framework.TestListener; -import junit.framework.TestResult; -import junit.runner.BaseTestRunner; - -public class ResultPrinter implements TestListener { - PrintStream fWriter; - int fColumn= 0; - - public ResultPrinter(PrintStream writer) { - fWriter= writer; - } - - /* API for use by textui.TestRunner - */ - - synchronized void print(TestResult result, long runTime) { - printHeader(runTime); - printErrors(result); - printFailures(result); - printFooter(result); - } - - void printWaitPrompt() { - getWriter().println(); - getWriter().println("<RETURN> to continue"); - } - - /* Internal methods - */ - - protected void printHeader(long runTime) { - getWriter().println(); - getWriter().println("Time: "+elapsedTimeAsString(runTime)); - } - - protected void printErrors(TestResult result) { - printDefects(result.errors(), result.errorCount(), "error"); - } - - protected void printFailures(TestResult result) { - printDefects(result.failures(), result.failureCount(), "failure"); - } - - protected void printDefects(Enumeration booBoos, int count, String type) { - if (count == 0) return; - if (count == 1) - getWriter().println("There was " + count + " " + type + ":"); - else - getWriter().println("There were " + count + " " + type + "s:"); - for (int i= 1; booBoos.hasMoreElements(); i++) { - printDefect((TestFailure) booBoos.nextElement(), i); - } - } - - public void printDefect(TestFailure booBoo, int count) { // only public for testing purposes - printDefectHeader(booBoo, count); - printDefectTrace(booBoo); - } - - protected void printDefectHeader(TestFailure booBoo, int count) { - // I feel like making this a println, then adding a line giving the throwable a chance to print something - // before we get to the stack trace. - getWriter().print(count + ") " + booBoo.failedTest()); - } - - protected void printDefectTrace(TestFailure booBoo) { - getWriter().print(BaseTestRunner.getFilteredTrace(booBoo.trace())); - } - - protected void printFooter(TestResult result) { - if (result.wasSuccessful()) { - getWriter().println(); - getWriter().print("OK"); - getWriter().println (" (" + result.runCount() + " test" + (result.runCount() == 1 ? "": "s") + ")"); - - } else { - getWriter().println(); - getWriter().println("FAILURES!!!"); - getWriter().println("Tests run: "+result.runCount()+ - ", Failures: "+result.failureCount()+ - ", Errors: "+result.errorCount()); - } - getWriter().println(); - } - - - /** - * Returns the formatted string of the elapsed time. - * Duplicated from BaseTestRunner. Fix it. - */ - protected String elapsedTimeAsString(long runTime) { - return NumberFormat.getInstance().format((double)runTime/1000); - } - - public PrintStream getWriter() { - return fWriter; - } - /** - * @see junit.framework.TestListener#addError(Test, Throwable) - */ - public void addError(Test test, Throwable t) { - getWriter().print("E"); - } - - /** - * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError) - */ - public void addFailure(Test test, AssertionFailedError t) { - getWriter().print("F"); - } - - /** - * @see junit.framework.TestListener#endTest(Test) - */ - public void endTest(Test test) { - } - - /** - * @see junit.framework.TestListener#startTest(Test) - */ - public void startTest(Test test) { - getWriter().print("."); - if (fColumn++ >= 40) { - getWriter().println(); - fColumn= 0; - } - } - -} diff --git a/dx/src/junit/textui/TestRunner.java b/dx/src/junit/textui/TestRunner.java deleted file mode 100644 index 8bdc3258a..000000000 --- a/dx/src/junit/textui/TestRunner.java +++ /dev/null @@ -1,189 +0,0 @@ -package junit.textui; - - -import java.io.PrintStream; - -import junit.framework.*; -import junit.runner.*; - -/** - * A command line based tool to run tests. - * <pre> - * java junit.textui.TestRunner [-wait] TestCaseClass - * </pre> - * TestRunner expects the name of a TestCase class as argument. - * If this class defines a static <code>suite</code> method it - * will be invoked and the returned test is run. Otherwise all - * the methods starting with "test" having no arguments are run. - * <p> - * When the wait command line argument is given TestRunner - * waits until the users types RETURN. - * <p> - * TestRunner prints a trace as the tests are executed followed by a - * summary at the end. - */ -public class TestRunner extends BaseTestRunner { - private ResultPrinter fPrinter; - - public static final int SUCCESS_EXIT= 0; - public static final int FAILURE_EXIT= 1; - public static final int EXCEPTION_EXIT= 2; - - /** - * Constructs a TestRunner. - */ - public TestRunner() { - this(System.out); - } - - /** - * Constructs a TestRunner using the given stream for all the output - */ - public TestRunner(PrintStream writer) { - this(new ResultPrinter(writer)); - } - - /** - * Constructs a TestRunner using the given ResultPrinter all the output - */ - public TestRunner(ResultPrinter printer) { - fPrinter= printer; - } - - /** - * Runs a suite extracted from a TestCase subclass. - */ - static public void run(Class testClass) { - run(new TestSuite(testClass)); - } - - /** - * Runs a single test and collects its results. - * This method can be used to start a test run - * from your program. - * <pre> - * public static void main (String[] args) { - * test.textui.TestRunner.run(suite()); - * } - * </pre> - */ - static public TestResult run(Test test) { - TestRunner runner= new TestRunner(); - return runner.doRun(test); - } - - /** - * Runs a single test and waits until the user - * types RETURN. - */ - static public void runAndWait(Test suite) { - TestRunner aTestRunner= new TestRunner(); - aTestRunner.doRun(suite, true); - } - - /** - * Always use the StandardTestSuiteLoader. Overridden from - * BaseTestRunner. - */ - public TestSuiteLoader getLoader() { - return new StandardTestSuiteLoader(); - } - - public void testFailed(int status, Test test, Throwable t) { - } - - public void testStarted(String testName) { - } - - public void testEnded(String testName) { - } - - /** - * Creates the TestResult to be used for the test run. - */ - protected TestResult createTestResult() { - return new TestResult(); - } - - public TestResult doRun(Test test) { - return doRun(test, false); - } - - public TestResult doRun(Test suite, boolean wait) { - TestResult result= createTestResult(); - result.addListener(fPrinter); - long startTime= System.currentTimeMillis(); - suite.run(result); - long endTime= System.currentTimeMillis(); - long runTime= endTime-startTime; - fPrinter.print(result, runTime); - - pause(wait); - return result; - } - - protected void pause(boolean wait) { - if (!wait) return; - fPrinter.printWaitPrompt(); - try { - System.in.read(); - } - catch(Exception e) { - } - } - - public static void main(String args[]) { - TestRunner aTestRunner= new TestRunner(); - try { - TestResult r= aTestRunner.start(args); - if (!r.wasSuccessful()) - System.exit(FAILURE_EXIT); - System.exit(SUCCESS_EXIT); - } catch(Exception e) { - System.err.println(e.getMessage()); - System.exit(EXCEPTION_EXIT); - } - } - - /** - * Starts a test run. Analyzes the command line arguments - * and runs the given test suite. - */ - protected TestResult start(String args[]) throws Exception { - String testCase= ""; - boolean wait= false; - - for (int i= 0; i < args.length; i++) { - if (args[i].equals("-wait")) - wait= true; - else if (args[i].equals("-c")) - testCase= extractClassName(args[++i]); - else if (args[i].equals("-v")) - System.err.println("JUnit "+Version.id()+" by Kent Beck and Erich Gamma"); - else - testCase= args[i]; - } - - if (testCase.equals("")) - throw new Exception("Usage: TestRunner [-wait] testCaseName, where name is the name of the TestCase class"); - - try { - Test suite= getTest(testCase); - return doRun(suite, wait); - } - catch(Exception e) { - throw new Exception("Could not create and run test suite: "+e); - } - } - - protected void runFailed(String message) { - System.err.println(message); - System.exit(FAILURE_EXIT); - } - - public void setPrinter(ResultPrinter printer) { - fPrinter= printer; - } - - -} |