Home | History | Annotate | Download | only in builder
      1 package org.jf.dexlib2.builder;
      2 
      3 import com.google.common.collect.Lists;
      4 import junit.framework.Assert;
      5 import org.jf.dexlib2.Opcode;
      6 import org.jf.dexlib2.builder.instruction.BuilderInstruction10t;
      7 import org.jf.dexlib2.builder.instruction.BuilderInstruction10x;
      8 import org.jf.dexlib2.builder.instruction.BuilderInstruction20t;
      9 import org.jf.dexlib2.iface.MethodImplementation;
     10 import org.jf.dexlib2.iface.instruction.Instruction;
     11 import org.jf.dexlib2.iface.instruction.OffsetInstruction;
     12 import org.junit.Test;
     13 
     14 import java.util.List;
     15 
     16 public 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