package com.googlecode.dex2jar.test;
import com.googlecode.d2j.DexConstants;
import com.googlecode.d2j.Field;
import com.googlecode.d2j.Method;
import com.googlecode.d2j.visitors.DexClassVisitor;
import com.googlecode.d2j.visitors.DexCodeVisitor;
import com.googlecode.d2j.visitors.DexFieldVisitor;
import com.googlecode.d2j.visitors.DexMethodVisitor;
import org.junit.Assert;
import org.junit.Test;
import static com.googlecode.d2j.reader.Op.*;
public class AutoCastTest implements DexConstants {
/**
* generate code, it works fine on JVM, but fails on Dalvik VM
*
* <pre>
* class a {
* private static short theField;
*
* public a() {
* theField = 0xffFFffFF + theField;// the 0xffFFffFF is not casted
* }
* }
* </pre>
*
* @param cv
*/
public static void strict(DexClassVisitor cv) {
Field f = new Field("La;", "theField", "S");
DexMethodVisitor mv = cv.visitMethod(ACC_PUBLIC, new Method("La;", "<init>", new String[] {}, "V"));
if (mv != null) {
DexCodeVisitor code = mv.visitCode();
if (code != null) {
code.visitRegister(3);
code.visitMethodStmt(INVOKE_SUPER, new int[] { 2 }, new Method("Ljava/lang/Object;", "<init>",
new String[] {}, "V"));
code.visitFieldStmt(SGET_BOOLEAN, 0, -1, f);
code.visitConstStmt(CONST, 1, 0xffFFffFF);
code.visitStmt3R(ADD_INT, 0, 0, 1);
code.visitFieldStmt(SPUT_SHORT, 0, -1, f);
code.visitStmt0R(RETURN_VOID);
code.visitEnd();
}
mv.visitEnd();
}
DexFieldVisitor fv = cv.visitField(ACC_PRIVATE | ACC_STATIC, f, 0);
if (fv != null) {
fv.visitEnd();
}
}
@Test
public void test() throws Exception {
byte[] data = TestUtils.testDexASMifier(getClass(), "strict", "a");
Class<?> clz = TestUtils.defineClass("a", data);
Object c = clz.newInstance();
Assert.assertNotNull(c);
java.lang.reflect.Field f = clz.getDeclaredField("theField");
f.setAccessible(true);
Short r = (Short) f.get(null);
Assert.assertEquals(-1, r.intValue());
// it's already ok to run on JVM and able to convert to dex,
// // check for I2S instruction
// ClassReader cr = new ClassReader(data);
// ClassNode cn = new ClassNode();
// cr.accept(cn, 0);
// boolean find = false;
// for (Object m : cn.methods) {
// MethodNode method = (MethodNode) m;
// for (AbstractInsnNode p = method.instructions.getFirst(); p != null; p = p.getNext()) {
// if (p.getOpcode() == Opcodes.I2S) {
// find = true;
// break;
// }
// }
// }
// Assert.assertTrue("we need an I2S instruction", find);
}
}