FixGotoTest.java revision 6762350ca0e11ca69ecb2c7bcf78cbafa2103ad6
1package org.jf.dexlib2.builder; 2 3import com.google.common.collect.Lists; 4import junit.framework.Assert; 5import org.jf.dexlib2.Opcode; 6import org.jf.dexlib2.builder.instruction.BuilderInstruction10t; 7import org.jf.dexlib2.builder.instruction.BuilderInstruction10x; 8import org.jf.dexlib2.builder.instruction.BuilderInstruction20t; 9import org.jf.dexlib2.iface.MethodImplementation; 10import org.jf.dexlib2.iface.instruction.Instruction; 11import org.jf.dexlib2.iface.instruction.OffsetInstruction; 12import org.junit.Test; 13 14import java.util.List; 15 16public class FixGotoTest { 17 @Test 18 public void testFixGotoToGoto16() { 19 MethodImplementationBuilder builder = new MethodImplementationBuilder(1); 20 21 Label gotoTarget = builder.getLabel("gotoTarget"); 22 builder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, gotoTarget)); 23 24 for (int i=0; i<500; i++) { 25 builder.addInstruction(new BuilderInstruction10x(Opcode.NOP)); 26 } 27 28 builder.addLabel("gotoTarget"); 29 builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); 30 31 MethodImplementation impl = builder.getMethodImplementation(); 32 33 List<? extends Instruction> instructions = Lists.newArrayList(impl.getInstructions()); 34 Assert.assertEquals(502, instructions.size()); 35 36 Assert.assertEquals(Opcode.GOTO_16, instructions.get(0).getOpcode()); 37 Assert.assertEquals(502, ((OffsetInstruction)instructions.get(0)).getCodeOffset()); 38 } 39 40 @Test 41 public void testFixGotoToGoto32() { 42 MethodImplementationBuilder builder = new MethodImplementationBuilder(1); 43 44 Label gotoTarget = builder.getLabel("gotoTarget"); 45 builder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, gotoTarget)); 46 47 for (int i=0; i<70000; i++) { 48 builder.addInstruction(new BuilderInstruction10x(Opcode.NOP)); 49 } 50 51 builder.addLabel("gotoTarget"); 52 builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); 53 54 MethodImplementation impl = builder.getMethodImplementation(); 55 56 List<? extends Instruction> instructions = Lists.newArrayList(impl.getInstructions()); 57 Assert.assertEquals(70002, instructions.size()); 58 59 Assert.assertEquals(Opcode.GOTO_32, instructions.get(0).getOpcode()); 60 Assert.assertEquals(70003, ((OffsetInstruction)instructions.get(0)).getCodeOffset()); 61 } 62 63 @Test 64 public void testFixGoto16ToGoto32() { 65 MethodImplementationBuilder builder = new MethodImplementationBuilder(1); 66 67 Label gotoTarget = builder.getLabel("gotoTarget"); 68 builder.addInstruction(new BuilderInstruction20t(Opcode.GOTO_16, gotoTarget)); 69 70 for (int i=0; i<70000; i++) { 71 builder.addInstruction(new BuilderInstruction10x(Opcode.NOP)); 72 } 73 74 builder.addLabel("gotoTarget"); 75 builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); 76 77 MethodImplementation impl = builder.getMethodImplementation(); 78 79 List<? extends Instruction> instructions = Lists.newArrayList(impl.getInstructions()); 80 Assert.assertEquals(70002, instructions.size()); 81 82 Assert.assertEquals(Opcode.GOTO_32, instructions.get(0).getOpcode()); 83 Assert.assertEquals(70003, ((OffsetInstruction)instructions.get(0)).getCodeOffset()); 84 } 85 86 @Test 87 public void testFixGotoCascading() { 88 MethodImplementationBuilder builder = new MethodImplementationBuilder(1); 89 90 Label goto16Target = builder.getLabel("goto16Target"); 91 builder.addInstruction(new BuilderInstruction20t(Opcode.GOTO_16, goto16Target)); 92 93 for (int i=0; i<1000; i++) { 94 builder.addInstruction(new BuilderInstruction10x(Opcode.NOP)); 95 } 96 97 Label gotoTarget = builder.getLabel("gotoTarget"); 98 builder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, gotoTarget)); 99 100 for (int i=0; i<499; i++) { 101 builder.addInstruction(new BuilderInstruction10x(Opcode.NOP)); 102 } 103 104 builder.addLabel("gotoTarget"); 105 106 for (int i=0; i<31265; i++) { 107 builder.addInstruction(new BuilderInstruction10x(Opcode.NOP)); 108 } 109 110 builder.addLabel("goto16Target"); 111 builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); 112 113 MethodImplementation impl = builder.getMethodImplementation(); 114 115 List<? extends Instruction> instructions = Lists.newArrayList(impl.getInstructions()); 116 Assert.assertEquals(32767, instructions.size()); 117 118 Assert.assertEquals(Opcode.GOTO_32, instructions.get(0).getOpcode()); 119 Assert.assertEquals(32769, ((OffsetInstruction)instructions.get(0)).getCodeOffset()); 120 121 } 122} 123