001    package sysModel.classFile.code.instructions;
002    
003    import sysModel.classFile.code.Opcode;
004    import junit.framework.TestCase;
005    
006    import java.io.ByteArrayOutputStream;
007    import java.io.IOException;
008    import java.util.Arrays;
009    import java.util.LinkedList;
010    
011    /**
012     * Unit tests for AInstruction classes.
013     *
014     * @author Mathias Ricken
015     */
016    public class AInstructionTest extends TestCase {
017        public void testFactory() throws IOException {
018            AInstruction i;
019            short pc = 0;
020            LinkedList<AInstruction> list = new LinkedList<AInstruction>();
021            ByteArrayOutputStream baos = new ByteArrayOutputStream();
022    
023            byte[] code = new byte[]{
024                Opcode.ALOAD_0, // 0
025                Opcode.IFEQ, 0, 0, // 1
026                Opcode.GOTO, 0, 0, // 4
027                Opcode.GOTO_W, 0, 0, 0, 0, // 7
028                Opcode.ALOAD, 0, // 12
029                Opcode.WIDE, Opcode.ALOAD, 0, 0, // 14
030                Opcode.IINC, 0, 0, // 18
031                Opcode.WIDE, Opcode.IINC, 0, 0, 0, 0, // 21
032                Opcode.TABLESWITCH, /*default*/(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xf1, /*low*/0, 0, 0, 5, /*high*/0, 0, 0, 7,
033                /*5*/(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xf3, /*6*/(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xf7, /*7*/(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfa, // 27
034                Opcode.LOOKUPSWITCH, /*pad*/ 0, 0, 0, /*default*/(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xe7, /*n*/0, 0, 0, 2, /*key*/0, 0, 0, 0,
035                /*offset*/0, 0, 0, 0, /*key*/ 0, 0, 0, 1, /*offset*/ (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xcc, // 52
036                Opcode.RETURN // 80
037            };
038            LineNumberTable lnt = new LineNumberTable(code);
039    
040            i = AInstruction.makeInstruction(code, pc, pc, lnt);
041            assertEquals("Wrong instruction", GenericInstruction.class, i.getClass());
042            assertEquals("Wrong size", 1, i.getBytecodeLength(pc));
043            list.add(i);
044            pc += i.getBytecodeLength(pc);
045    
046            i = AInstruction.makeInstruction(code, pc, pc, lnt);
047            assertEquals("Wrong instruction", BranchInstruction.class, i.getClass());
048            assertEquals("Wrong size", 3, i.getBytecodeLength(pc));
049            list.add(i);
050            pc += i.getBytecodeLength(pc);
051    
052            i = AInstruction.makeInstruction(code, pc, pc, lnt);
053            assertEquals("Wrong instruction", BranchInstruction.class, i.getClass());
054            assertEquals("Wrong size", 3, i.getBytecodeLength(pc));
055            list.add(i);
056            pc += i.getBytecodeLength(pc);
057    
058            i = AInstruction.makeInstruction(code, pc, pc, lnt);
059            assertEquals("Wrong instruction", WideBranchInstruction.class, i.getClass());
060            assertEquals("Wrong size", 5, i.getBytecodeLength(pc));
061            list.add(i);
062            pc += i.getBytecodeLength(pc);
063    
064            i = AInstruction.makeInstruction(code, pc, pc, lnt);
065            assertEquals("Wrong instruction", GenericInstruction.class, i.getClass());
066            assertEquals("Wrong size", 2, i.getBytecodeLength(pc));
067            list.add(i);
068            pc += i.getBytecodeLength(pc);
069    
070            i = AInstruction.makeInstruction(code, pc, pc, lnt);
071            assertEquals("Wrong instruction", WideInstruction.class, i.getClass());
072            assertEquals("Wrong size", 4, i.getBytecodeLength(pc));
073            list.add(i);
074            pc += i.getBytecodeLength(pc);
075    
076            i = AInstruction.makeInstruction(code, pc, pc, lnt);
077            assertEquals("Wrong instruction", GenericInstruction.class, i.getClass());
078            assertEquals("Wrong size", 3, i.getBytecodeLength(pc));
079            list.add(i);
080            pc += i.getBytecodeLength(pc);
081    
082            i = AInstruction.makeInstruction(code, pc, pc, lnt);
083            assertEquals("Wrong instruction", WideInstruction.class, i.getClass());
084            assertEquals("Wrong size", 6, i.getBytecodeLength(pc));
085            list.add(i);
086            pc += i.getBytecodeLength(pc);
087    
088            i = AInstruction.makeInstruction(code, pc, pc, lnt);
089            assertEquals("Wrong instruction", TableSwitchInstruction.class, i.getClass());
090            assertEquals("Wrong size", 25, i.getBytecodeLength(pc));
091            list.add(i);
092            pc += i.getBytecodeLength(pc);
093    
094            i = AInstruction.makeInstruction(code, pc, pc, lnt);
095            assertEquals("Wrong instruction", LookupSwitchInstruction.class, i.getClass());
096            assertEquals("Wrong size", 28, i.getBytecodeLength(pc));
097            list.add(i);
098            pc += i.getBytecodeLength(pc);
099    
100            i = AInstruction.makeInstruction(code, pc, pc, lnt);
101            assertEquals("Wrong instruction", GenericInstruction.class, i.getClass());
102            assertEquals("Wrong size", 1, i.getBytecodeLength(pc));
103            list.add(i);
104    
105            LineNumberTable reverseLnt = new LineNumberTable(list);
106            pc = 0;
107            for(AInstruction instr : list) {
108                baos.write(instr.getBytecode(pc, reverseLnt));
109                pc += instr.getBytecodeLength(pc);
110            }
111    
112            byte[] generatedCode = baos.toByteArray();
113            assertTrue("Generated bytecode not the same", Arrays.equals(code, generatedCode));
114        }
115    
116        public void testCorrespondingLoad() {
117            AInstruction i;
118    
119            i = new GenericInstruction(new byte[] {Opcode.ISTORE_0});
120            assertEquals("Wrong load for ISTORE_0", "iload_0 ", AInstruction.getCorrespondingLoad(i).toString());
121    
122            i = new GenericInstruction(new byte[] {Opcode.ASTORE_3});
123            assertEquals("Wrong load for ASTORE_3", "aload_3 ", AInstruction.getCorrespondingLoad(i).toString());
124    
125            i = new GenericInstruction(new byte[] {Opcode.IASTORE});
126            assertEquals("Wrong load for IASTORE", "iaload ", AInstruction.getCorrespondingLoad(i).toString());
127    
128            i = new GenericInstruction(new byte[] {Opcode.SASTORE});
129            assertEquals("Wrong load for SASTORE", "saload ", AInstruction.getCorrespondingLoad(i).toString());
130    
131            i = new GenericInstruction(new byte[] {Opcode.ISTORE, 5});
132            assertEquals("Wrong load for ISTORE", "iload 05 ", AInstruction.getCorrespondingLoad(i).toString());
133    
134            i = new GenericInstruction(new byte[] {Opcode.ASTORE, 5});
135            assertEquals("Wrong load for ASTORE", "aload 05 ", AInstruction.getCorrespondingLoad(i).toString());
136    
137            i = new WideInstruction(new byte[] {Opcode.ISTORE, 0, 5});
138            assertEquals("Wrong load for WIDE ISTORE", "wide iload 00 05 ", AInstruction.getCorrespondingLoad(i).toString());
139    
140            i = new WideInstruction(new byte[] {Opcode.ASTORE, 0, 5});
141            assertEquals("Wrong load for WIDE ASTORE", "wide aload 00 05 ", AInstruction.getCorrespondingLoad(i).toString());
142        }
143    
144        public void testCorrespondingStore() {
145            AInstruction i;
146    
147            i = new GenericInstruction(new byte[] {Opcode.ILOAD_0});
148            assertEquals("Wrong store for ILOAD_0", "istore_0 ", AInstruction.getCorrespondingStore(i).toString());
149    
150            i = new GenericInstruction(new byte[] {Opcode.ALOAD_3});
151            assertEquals("Wrong store for ALOAD_3", "astore_3 ", AInstruction.getCorrespondingStore(i).toString());
152    
153            i = new GenericInstruction(new byte[] {Opcode.IALOAD});
154            assertEquals("Wrong store for IALOAD", "iastore ", AInstruction.getCorrespondingStore(i).toString());
155    
156            i = new GenericInstruction(new byte[] {Opcode.SALOAD});
157            assertEquals("Wrong store for SALOAD", "sastore ", AInstruction.getCorrespondingStore(i).toString());
158    
159            i = new GenericInstruction(new byte[] {Opcode.ILOAD, 5});
160            assertEquals("Wrong store for ILOAD", "istore 05 ", AInstruction.getCorrespondingStore(i).toString());
161    
162            i = new GenericInstruction(new byte[] {Opcode.ALOAD, 5});
163            assertEquals("Wrong store for ALOAD", "astore 05 ", AInstruction.getCorrespondingStore(i).toString());
164    
165            i = new WideInstruction(new byte[] {Opcode.ILOAD, 0, 5});
166            assertEquals("Wrong store for WIDE ILOAD", "wide istore 00 05 ", AInstruction.getCorrespondingStore(i).toString());
167    
168            i = new WideInstruction(new byte[] {Opcode.ALOAD, 0, 5});
169            assertEquals("Wrong store for WIDE ALOAD", "wide astore 00 05 ", AInstruction.getCorrespondingStore(i).toString());
170        }
171    }