001 package sysModel.classFile.code; 002 003 import sysModel.classFile.code.instructions.*; 004 import junit.framework.TestCase; 005 006 import java.io.IOException; 007 import java.util.Arrays; 008 009 /** 010 * Unit tests for InstructionList class. 011 * 012 * @author Mathias Ricken 013 */ 014 public class InstructionListTest extends TestCase { 015 protected final byte[] TEST_CODE = new byte[]{ 016 Opcode.ALOAD_0, // 0 017 Opcode.IFEQ, 0, 0, // 1 018 Opcode.GOTO, 0, 0, // 4 019 Opcode.GOTO_W, 0, 0, 0, 0, // 7 020 Opcode.ALOAD, 0, // 12 021 Opcode.WIDE, Opcode.ALOAD, 0, 0, // 14 022 Opcode.IINC, 0, 0, // 18 023 Opcode.WIDE, Opcode.IINC, 0, 0, 0, 0, // 21 024 Opcode.TABLESWITCH, /*default*/(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xf1, /*low*/0, 0, 0, 5, /*high*/0, 0, 0, 7, 025 /*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 026 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, 027 /*offset*/0, 0, 0, 0, /*key*/ 0, 0, 0, 1, /*offset*/ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x1c, // 52 028 Opcode.RETURN // 80 029 }; 030 031 protected final byte[] TEST_CODE2 = new byte[]{ 032 Opcode.ALOAD_0, 033 Opcode.ALOAD_1, 034 Opcode.INVOKESTATIC, 0, 0, 035 Opcode.RETURN 036 }; 037 038 protected final byte[] TEST_CODE_INVALID = new byte[]{ 039 Opcode.ALOAD 040 }; 041 042 protected final byte[] TEST_CODE_EMPTY = new byte[]{}; 043 044 protected final byte[] TEST_CODE_INSERTDELETE = new byte[]{ 045 Opcode.GOTO, (byte)0x00, (byte)0x0A, // 0 046 Opcode.GOTO, (byte)0x00, (byte)0x03, // 3 047 Opcode.NOP, // 6 048 Opcode.GOTO, (byte)0xFF, (byte)0xFC, // 7 049 Opcode.GOTO, (byte)0xFF, (byte)0xFD // 10 050 }; 051 052 protected final byte[] TEST_CODE_DELETE_RESULT = new byte[]{ 053 Opcode.GOTO, (byte)0x00, (byte)0x09, // 0 054 Opcode.GOTO, (byte)0x00, (byte)0x03, // 3 055 Opcode.GOTO, (byte)0xFF, (byte)0xFD, // 6 056 Opcode.GOTO, (byte)0xFF, (byte)0xFD // 9 057 }; 058 059 protected final byte[] TEST_CODE_DELETE_RESULT2 = new byte[]{ 060 Opcode.GOTO, (byte)0x00, (byte)0x06, // 0 061 Opcode.GOTO, (byte)0x00, (byte)0x03, // 3 062 Opcode.GOTO, (byte)0xFF, (byte)0xFD // 6 063 }; 064 065 protected final byte[] TEST_CODE_INSERT_RESULT = new byte[]{ 066 Opcode.GOTO, (byte)0x00, (byte)0x0B, // 0 067 Opcode.GOTO, (byte)0x00, (byte)0x03, // 3 068 Opcode.NOP, // 6 069 Opcode.NOP, // 7 070 Opcode.GOTO, (byte)0xFF, (byte)0xFB, // 8 071 Opcode.GOTO, (byte)0xFF, (byte)0xFD // 11 072 }; 073 074 protected final byte[] TEST_CODE_INSERT_RESULT2 = new byte[]{ 075 Opcode.GOTO, (byte)0x00, (byte)0x25, // 0 076 Opcode.GOTO, (byte)0x00, (byte)0x03, // 3 077 Opcode.TABLESWITCH, 0, /*default*/(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x1A, /*low*/ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x05, 078 /*high*/(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x07, /*5*/(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfd, 079 /*6*/(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x1B, /*7*/(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x1F, // 6 080 Opcode.NOP, // 32 081 Opcode.NOP, // 33 082 Opcode.GOTO, (byte)0xFF, (byte)0xE1, // 34 083 Opcode.GOTO, (byte)0xFF, (byte)0xFD // 37 084 }; 085 086 protected final byte[] TEST_CODE_INSERT_RESULT3 = new byte[]{ 087 Opcode.GOTO, (byte)0x00, (byte)0x25, // 0 088 Opcode.GOTO, (byte)0x00, (byte)0x03, // 3 089 Opcode.NOP, // 6 090 Opcode.TABLESWITCH, /*default*/(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x19, /*low*/ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x05, 091 /*high*/(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x07, /*5*/(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xfc, 092 /*6*/(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x1A, /*7*/(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x1E, // 7 093 Opcode.NOP, // 32 094 Opcode.NOP, // 33 095 Opcode.GOTO, (byte)0xFF, (byte)0xE1, // 34 096 Opcode.GOTO, (byte)0xFF, (byte)0xFD // 37 097 }; 098 099 public void testCtorAndGetCode() throws IOException { 100 InstructionList ilist = new InstructionList(TEST_CODE); 101 102 byte[] generatedCode = ilist.getCode(); 103 assertTrue("Generated bytecode not the same", Arrays.equals(TEST_CODE, generatedCode)); 104 105 ilist.setCode(TEST_CODE2); 106 107 generatedCode = ilist.getCode(); 108 assertTrue("Generated bytecode not the same", Arrays.equals(TEST_CODE2, generatedCode)); 109 } 110 111 public void testExceptions() { 112 try { 113 InstructionList ilist = new InstructionList(TEST_CODE_INVALID); 114 fail("Should have thrown IllegalArgumentException, invalid block length"); 115 } 116 catch(IllegalArgumentException e) { 117 // passed 118 } 119 catch(Throwable t) { 120 fail("Should have thrown IllegalArgumentException, invalid block length"); 121 } 122 123 InstructionList ilist = new InstructionList(TEST_CODE_EMPTY); 124 try { 125 ilist.setCode(TEST_CODE_INVALID); 126 fail("Should have thrown IllegalArgumentException, invalid block length"); 127 } 128 catch(IllegalArgumentException e) { 129 // passed 130 } 131 catch(Throwable t) { 132 fail("Should have thrown IllegalArgumentException, invalid block length"); 133 } 134 135 ilist = new InstructionList(TEST_CODE); 136 try { 137 ilist.setIndex(-1); 138 fail("Should have thrown IndexOutOfBoundsException, invalid index"); 139 } 140 catch(IndexOutOfBoundsException e) { 141 // passed 142 } 143 catch(Throwable t) { 144 fail("Should have thrown IndexOutOfBoundsException, invalid block length"); 145 } 146 try { 147 ilist.setIndex(11); 148 fail("Should have thrown IndexOutOfBoundsException, invalid index"); 149 } 150 catch(IndexOutOfBoundsException e) { 151 // passed 152 } 153 catch(Throwable t) { 154 fail("Should have thrown IndexOutOfBoundsException, invalid block length"); 155 } 156 } 157 158 public void testIndex() { 159 InstructionList ilist = new InstructionList(TEST_CODE); 160 161 assertEquals("Wrong index", 0, ilist.getIndex()); 162 assertEquals("Wrong opcode", Opcode.ALOAD_0, ilist.getOpcode()); 163 assertEquals("Wrong instruction", GenericInstruction.class, ilist.getInstr().getClass()); 164 assertEquals("Problem in advanceIndex", true, ilist.advanceIndex()); 165 166 assertEquals("Wrong index", 1, ilist.getIndex()); 167 assertEquals("Wrong opcode", Opcode.IFEQ, ilist.getOpcode()); 168 assertEquals("Wrong instruction", BranchInstruction.class, ilist.getInstr().getClass()); 169 assertEquals("Problem in advanceIndex", true, ilist.advanceIndex()); 170 171 assertEquals("Wrong index", 2, ilist.getIndex()); 172 assertEquals("Wrong opcode", Opcode.GOTO, ilist.getOpcode()); 173 assertEquals("Wrong instruction", BranchInstruction.class, ilist.getInstr().getClass()); 174 assertEquals("Problem in advanceIndex", true, ilist.advanceIndex()); 175 176 assertEquals("Wrong index", 3, ilist.getIndex()); 177 assertEquals("Wrong opcode", Opcode.GOTO_W, ilist.getOpcode()); 178 assertEquals("Wrong instruction", WideBranchInstruction.class, ilist.getInstr().getClass()); 179 assertEquals("Problem in advanceIndex", true, ilist.advanceIndex()); 180 181 assertEquals("Wrong index", 4, ilist.getIndex()); 182 assertEquals("Wrong opcode", Opcode.ALOAD, ilist.getOpcode()); 183 assertEquals("Wrong instruction", GenericInstruction.class, ilist.getInstr().getClass()); 184 assertEquals("Problem in advanceIndex", true, ilist.advanceIndex()); 185 186 assertEquals("Wrong index", 5, ilist.getIndex()); 187 assertEquals("Wrong opcode", Opcode.WIDE, ilist.getOpcode()); 188 assertEquals("Wrong instruction", WideInstruction.class, ilist.getInstr().getClass()); 189 assertEquals("Problem in advanceIndex", true, ilist.advanceIndex()); 190 191 assertEquals("Wrong index", 6, ilist.getIndex()); 192 assertEquals("Wrong opcode", Opcode.IINC, ilist.getOpcode()); 193 assertEquals("Wrong instruction", GenericInstruction.class, ilist.getInstr().getClass()); 194 assertEquals("Problem in advanceIndex", true, ilist.advanceIndex()); 195 196 assertEquals("Wrong index", 7, ilist.getIndex()); 197 assertEquals("Wrong opcode", Opcode.WIDE, ilist.getOpcode()); 198 assertEquals("Wrong instruction", WideInstruction.class, ilist.getInstr().getClass()); 199 assertEquals("Problem in advanceIndex", true, ilist.advanceIndex()); 200 201 assertEquals("Wrong index", 8, ilist.getIndex()); 202 assertEquals("Wrong opcode", Opcode.TABLESWITCH, ilist.getOpcode()); 203 assertEquals("Wrong instruction", TableSwitchInstruction.class, ilist.getInstr().getClass()); 204 assertEquals("Problem in advanceIndex", true, ilist.advanceIndex()); 205 206 assertEquals("Wrong index", 9, ilist.getIndex()); 207 assertEquals("Wrong opcode", Opcode.LOOKUPSWITCH, ilist.getOpcode()); 208 assertEquals("Wrong instruction", LookupSwitchInstruction.class, ilist.getInstr().getClass()); 209 assertEquals("Problem in advanceIndex", true, ilist.advanceIndex()); 210 211 assertEquals("Wrong index", 10, ilist.getIndex()); 212 assertEquals("Wrong opcode", Opcode.RETURN, ilist.getOpcode()); 213 assertEquals("Wrong instruction", GenericInstruction.class, ilist.getInstr().getClass()); 214 assertEquals("Problem in advanceIndex", false, ilist.advanceIndex()); 215 } 216 217 public void testFindOpcode() { 218 InstructionList ilist = new InstructionList(TEST_CODE); 219 220 assertEquals("Should have found ALOAD_0", true, ilist.findOpcode(Opcode.ALOAD_0)); 221 assertEquals("Wrong index", 0, ilist.getIndex()); 222 223 assertEquals("Should have found ALOAD", true, ilist.findOpcode(Opcode.ALOAD)); 224 assertEquals("Wrong index", 4, ilist.getIndex()); 225 ilist.advanceIndex(); 226 227 assertEquals("Should have not have found ALOAD", false, ilist.findOpcode(Opcode.ALOAD)); 228 assertEquals("Wrong index", 11, ilist.getIndex()); 229 } 230 231 public void testFindInstr() { 232 InstructionList ilist = new InstructionList(TEST_CODE); 233 LineNumberTable lnt = new LineNumberTable(TEST_CODE); 234 235 assertEquals("Should have found ALOAD_0", true, ilist.findInstruction( 236 new GenericInstruction(TEST_CODE, (short)0, (short)0, lnt))); 237 assertEquals("Wrong index", 0, ilist.getIndex()); 238 239 assertEquals("Should have found ALOAD", true, ilist.findInstruction( 240 new GenericInstruction(TEST_CODE, (short)12, (short)12, lnt))); 241 assertEquals("Wrong index", 4, ilist.getIndex()); 242 ilist.advanceIndex(); 243 244 assertEquals("Should have not found ALOAD", false, ilist.findInstruction( 245 new GenericInstruction(TEST_CODE, (short)12, (short)12, lnt))); 246 assertEquals("Wrong index", 11, ilist.getIndex()); 247 248 ilist.setIndex(0); 249 250 assertEquals("Should have not found ALOAD", false, ilist.findInstruction( 251 new GenericInstruction(new byte[]{Opcode.ALOAD, 1}, (short)0, (short)12, lnt))); 252 assertEquals("Wrong index", 11, ilist.getIndex()); 253 } 254 255 public void testDelete() { 256 InstructionList ilist = new InstructionList(TEST_CODE_INSERTDELETE); 257 258 ilist.setIndex(2); 259 assertEquals("Should not be at end yet", true, ilist.deleteInstr(null)); 260 assertEquals("At wrong index", 2, ilist.getIndex()); 261 assertEquals("Wrong result", new InstructionList(TEST_CODE_DELETE_RESULT), ilist); 262 263 ilist.setIndex(3); 264 assertEquals("Should be at end", false, ilist.deleteInstr(null)); 265 assertEquals("At wrong index", 3, ilist.getIndex()); 266 assertEquals("Wrong result", new InstructionList(TEST_CODE_DELETE_RESULT2), ilist); 267 } 268 269 public void testInsert() { 270 InstructionList ilist = new InstructionList(TEST_CODE_INSERTDELETE); 271 272 ilist.setIndex(2); 273 ilist.insertInstr(new GenericInstruction(new byte[]{Opcode.NOP}), null); 274 assertEquals("At wrong index", 2, ilist.getIndex()); 275 assertEquals("Wrong result", new InstructionList(TEST_CODE_INSERT_RESULT), ilist); 276 277 ilist.insertInstr(new TableSwitchInstruction(2, 5, 7, new int[]{1, 3, 5}), null); 278 assertEquals("At wrong index", 2, ilist.getIndex()); 279 assertEquals("Wrong result", new InstructionList(TEST_CODE_INSERT_RESULT2), ilist); 280 281 // this causes the TABLESWITCH instruction to repad 282 ilist.insertInstr(new GenericInstruction(new byte[]{Opcode.NOP}), null); 283 assertEquals("At wrong index", 2, ilist.getIndex()); 284 assertEquals("Wrong result", new InstructionList(TEST_CODE_INSERT_RESULT3), ilist); 285 } 286 }