1 package test.javassist.convert; 2 3 import java.net.URL; 4 import java.net.URLClassLoader; 5 import java.util.HashMap; 6 import java.util.Map; 7 8 import javassist.ClassPool; 9 import javassist.CodeConverter; 10 import javassist.CtClass; 11 import junit.framework.TestCase; 12 13 public class ArrayAccessReplaceTest extends TestCase { 14 private static SimpleInterface simple; 15 setUp()16 public void setUp() throws Exception { 17 ClassPool pool = new ClassPool(true); 18 CtClass echoClass = pool.get(ArrayAccessReplaceTest.class.getName() + "$Echo"); 19 CtClass simpleClass = pool.get(ArrayAccessReplaceTest.class.getName() + "$Simple"); 20 CodeConverter converter = new CodeConverter(); 21 converter.replaceArrayAccess(echoClass, new CodeConverter.DefaultArrayAccessReplacementMethodNames()); 22 simpleClass.instrument(converter); 23 //simpleClass.writeFile("/tmp"); 24 simple = (SimpleInterface) simpleClass.toClass(new URLClassLoader(new URL[0], getClass().getClassLoader()), Class.class.getProtectionDomain()).newInstance(); 25 } 26 testComplex()27 public void testComplex() throws Exception { 28 ClassPool pool = new ClassPool(true); 29 CtClass clazz = pool.get(ArrayAccessReplaceTest.class.getName() + "$Complex"); 30 31 CodeConverter converter = new CodeConverter(); 32 converter.replaceArrayAccess(clazz, new CodeConverter.DefaultArrayAccessReplacementMethodNames()); 33 clazz.instrument(converter); 34 ComplexInterface instance = (ComplexInterface) clazz.toClass(new URLClassLoader(new URL[0], getClass().getClassLoader()), Class.class.getProtectionDomain()).newInstance(); 35 assertEquals(new Integer(5), instance.complexRead(4)); 36 } 37 testBoolean()38 public void testBoolean() throws Exception { 39 for (int i = 0; i < 100; i++) { 40 boolean value = i % 5 == 0; 41 simple.setBoolean(i, value); 42 } 43 44 for (int i = 0; i < 100; i++) { 45 boolean value = i % 5 == 0; 46 assertEquals(value, simple.getBoolean(i)); 47 } 48 } 49 testByte()50 public void testByte() throws Exception { 51 for (byte i = 0; i < 100; i++) { 52 simple.setByte(i, i); 53 } 54 55 for (byte i = 0; i < 100; i++) { 56 assertEquals(i, simple.getByte(i)); 57 } 58 } 59 testShort()60 public void testShort() throws Exception { 61 for (short i = 0; i < 100; i++) { 62 simple.setShort(i, i); 63 } 64 65 for (short i = 0; i < 100; i++) { 66 assertEquals(i, simple.getShort(i)); 67 } 68 } 69 testChar()70 public void testChar() throws Exception { 71 for (char i = 0; i < 100; i++) { 72 simple.setChar(i, i); 73 } 74 75 for (char i = 0; i < 100; i++) { 76 assertEquals(i, simple.getChar(i)); 77 } 78 } 79 testInt()80 public void testInt() throws Exception { 81 for (int i = 0; i < 100; i++) { 82 simple.setInt(i, i); 83 } 84 85 for (int i = 0; i < 100; i++) { 86 assertEquals(i, simple.getInt(i)); 87 } 88 } 89 testLong()90 public void testLong() throws Exception { 91 for (int i = 0; i < 100; i++) { 92 simple.setLong(i, i); 93 } 94 95 for (int i = 0; i < 100; i++) { 96 assertEquals(i, simple.getLong(i)); 97 } 98 } 99 testFloat()100 public void testFloat() throws Exception { 101 for (int i = 0; i < 100; i++) { 102 simple.setFloat(i, i); 103 } 104 105 for (int i = 0; i < 100; i++) { 106 assertEquals((float)i, simple.getFloat(i), 0); 107 } 108 } 109 testDouble()110 public void testDouble() throws Exception { 111 for (int i = 0; i < 100; i++) { 112 simple.setDouble(i, i); 113 } 114 115 for (int i = 0; i < 100; i++) { 116 assertEquals((double)i, simple.getDouble(i), 0); 117 } 118 } 119 testObject()120 public void testObject() throws Exception { 121 for (int i = 0; i < 100; i++) { 122 simple.setObject(i, new Integer(i)); 123 } 124 125 for (int i = 0; i < 100; i++) { 126 assertEquals(new Integer(i), simple.getObject(i)); 127 } 128 } 129 testFoo()130 public void testFoo() throws Exception { 131 for (int i = 0; i < 100; i++) { 132 simple.setFoo(i, new Foo(i)); 133 } 134 135 for (int i = 0; i < 100; i++) { 136 assertEquals(new Foo(i), simple.getFoo(i)); 137 } 138 } 139 testMulti()140 public void testMulti() throws Exception { 141 for (int i = 2; i < 100; i++) { 142 simple.setMultiFoo(0, 1, i, new Foo(i)); 143 } 144 145 for (int i = 2; i < 100; i++) { 146 assertEquals(new Foo(i), simple.getMultiFoo(0, 1, i)); 147 } 148 } 149 150 public static class Echo { 151 public static Map byteMap = new HashMap(); 152 public static Map charMap = new HashMap(); 153 public static Map doubleMap = new HashMap(); 154 public static Map floatMap = new HashMap(); 155 public static Map intMap = new HashMap(); 156 public static Map longMap = new HashMap(); 157 public static Map objectMap = new HashMap(); 158 public static Map shortMap = new HashMap(); 159 arrayReadObject(Object array, int index)160 public static Object arrayReadObject(Object array, int index) { 161 return objectMap.get(new Integer(index)); 162 } 163 arrayWriteObject(Object array, int index, Object element)164 public static void arrayWriteObject(Object array, int index, Object element) { 165 objectMap.put(new Integer(index), element); 166 } 167 arrayReadByteOrBoolean(Object array, int index)168 public static byte arrayReadByteOrBoolean(Object array, int index) { 169 return ((Byte)byteMap.get(new Integer(index))).byteValue(); 170 } 171 arrayWriteByteOrBoolean(Object array, int index, byte element)172 public static void arrayWriteByteOrBoolean(Object array, int index, byte element) { 173 byteMap.put(new Integer(index), new Byte(element)); 174 } 175 arrayReadChar(Object array, int index)176 public static char arrayReadChar(Object array, int index) { 177 return ((Character)charMap.get(new Integer(index))).charValue(); 178 } 179 arrayWriteChar(Object array, int index, char element)180 public static void arrayWriteChar(Object array, int index, char element) { 181 charMap.put(new Integer(index), new Character(element)); 182 } 183 arrayReadDouble(Object array, int index)184 public static double arrayReadDouble(Object array, int index) { 185 return ((Double)doubleMap.get(new Integer(index))).doubleValue(); 186 } 187 arrayWriteDouble(Object array, int index, double element)188 public static void arrayWriteDouble(Object array, int index, double element) { 189 doubleMap.put(new Integer(index), new Double(element)); 190 } 191 arrayReadFloat(Object array, int index)192 public static float arrayReadFloat(Object array, int index) { 193 return ((Float)floatMap.get(new Integer(index))).floatValue(); 194 } 195 arrayWriteFloat(Object array, int index, float element)196 public static void arrayWriteFloat(Object array, int index, float element) { 197 floatMap.put(new Integer(index), new Float(element)); 198 } 199 arrayReadInt(Object array, int index)200 public static int arrayReadInt(Object array, int index) { 201 return ((Integer)intMap.get(new Integer(index))).intValue(); 202 } 203 arrayWriteInt(Object array, int index, int element)204 public static void arrayWriteInt(Object array, int index, int element) { 205 intMap.put(new Integer(index), new Integer(element)); 206 } 207 arrayReadLong(Object array, int index)208 public static long arrayReadLong(Object array, int index) { 209 return ((Long)longMap.get(new Integer(index))).longValue(); 210 } 211 arrayWriteLong(Object array, int index, long element)212 public static void arrayWriteLong(Object array, int index, long element) { 213 longMap.put(new Integer(index), new Long(element)); 214 } 215 arrayReadShort(Object array, int index)216 public static short arrayReadShort(Object array, int index) { 217 return ((Short)shortMap.get(new Integer(index))).shortValue(); 218 } 219 arrayWriteShort(Object array, int index, short element)220 public static void arrayWriteShort(Object array, int index, short element) { 221 shortMap.put(new Integer(index), new Short(element)); 222 } 223 } 224 225 public static class Foo { 226 public int bar; 227 Foo(int bar)228 public Foo(int bar) { 229 this.bar = bar; 230 } 231 hashCode()232 public int hashCode() { 233 return bar; 234 } 235 equals(Object o)236 public boolean equals(Object o) { 237 if (! (o instanceof Foo)) 238 return false; 239 240 return ((Foo)o).bar == bar; 241 } 242 } 243 244 public static interface SimpleInterface { setBoolean(int pos, boolean value)245 public void setBoolean(int pos, boolean value); getBoolean(int pos)246 public boolean getBoolean(int pos); 247 setByte(int pos, byte value)248 public void setByte(int pos, byte value); getByte(int pos)249 public byte getByte(int pos); 250 setShort(int pos, short value)251 public void setShort(int pos, short value); getShort(int pos)252 public short getShort(int pos); 253 setChar(int pos, char value)254 public void setChar(int pos, char value); getChar(int pos)255 public char getChar(int pos); 256 setInt(int pos, int value)257 public void setInt(int pos, int value); getInt(int pos)258 public int getInt(int pos); 259 setLong(int pos, long value)260 public void setLong(int pos, long value); getLong(int pos)261 public long getLong(int pos); 262 setFloat(int pos, float value)263 public void setFloat(int pos, float value); getFloat(int pos)264 public float getFloat(int pos); 265 setDouble(int pos, double value)266 public void setDouble(int pos, double value); getDouble(int pos)267 public double getDouble(int pos); 268 setObject(int pos, Object value)269 public void setObject(int pos, Object value); getObject(int pos)270 public Object getObject(int pos); 271 setFoo(int pos, Foo value)272 public void setFoo(int pos, Foo value); getFoo(int pos)273 public Foo getFoo(int pos); 274 setMultiFoo(int one, int two, int three, Foo foo)275 public void setMultiFoo(int one, int two, int three, Foo foo); getMultiFoo(int one, int two, int three)276 public Foo getMultiFoo(int one, int two, int three); 277 } 278 279 public static class Simple implements SimpleInterface { 280 private boolean[] booleans; 281 private byte[] bytes; 282 private short[] shorts; 283 private char[] chars; 284 private int[] ints; 285 private long[] longs; 286 private float[] floats; 287 private double[] doubles; 288 private Object[] objects; 289 private Foo[] foos; 290 private Foo[][][] multi; 291 Simple()292 public Simple() { 293 multi[0] = new Foo[0][0]; 294 multi[0][1] = new Foo[0]; 295 } 296 getBoolean(int pos)297 public boolean getBoolean(int pos) { 298 return booleans[pos]; 299 } 300 getByte(int pos)301 public byte getByte(int pos) { 302 return bytes[pos]; 303 } 304 getChar(int pos)305 public char getChar(int pos) { 306 return chars[pos]; 307 } 308 getDouble(int pos)309 public double getDouble(int pos) { 310 return doubles[pos]; 311 } 312 getFloat(int pos)313 public float getFloat(int pos) { 314 return floats[pos]; 315 } 316 getFoo(int pos)317 public Foo getFoo(int pos) { 318 return foos[pos]; 319 } 320 getInt(int pos)321 public int getInt(int pos) { 322 return ints[pos]; 323 } 324 getLong(int pos)325 public long getLong(int pos) { 326 return longs[pos]; 327 } 328 getObject(int pos)329 public Object getObject(int pos) { 330 return objects[pos]; 331 } 332 getShort(int pos)333 public short getShort(int pos) { 334 return shorts[pos]; 335 } 336 getMultiFoo(int one, int two, int three)337 public Foo getMultiFoo(int one, int two, int three) { 338 return multi[one][two][three]; 339 } 340 setBoolean(int pos, boolean value)341 public void setBoolean(int pos, boolean value) { 342 booleans[pos] = value; 343 } 344 setByte(int pos, byte value)345 public void setByte(int pos, byte value) { 346 bytes[pos] = value; 347 } 348 setChar(int pos, char value)349 public void setChar(int pos, char value) { 350 chars[pos] = value; 351 } 352 setDouble(int pos, double value)353 public void setDouble(int pos, double value) { 354 doubles[pos] = value; 355 } 356 setFloat(int pos, float value)357 public void setFloat(int pos, float value) { 358 floats[pos] = value; 359 } 360 setFoo(int pos, Foo value)361 public void setFoo(int pos, Foo value) { 362 foos[pos] = value; 363 } 364 setInt(int pos, int value)365 public void setInt(int pos, int value) { 366 ints[pos] = value; 367 } 368 setLong(int pos, long value)369 public void setLong(int pos, long value) { 370 longs[pos] = value; 371 } 372 setObject(int pos, Object value)373 public void setObject(int pos, Object value) { 374 objects[pos] = value; 375 } 376 setShort(int pos, short value)377 public void setShort(int pos, short value) { 378 shorts[pos] = value; 379 } 380 setMultiFoo(int one, int two, int three, Foo foo)381 public void setMultiFoo(int one, int two, int three, Foo foo) { 382 multi[one][two][three] = foo; 383 } 384 } 385 386 public static interface ComplexInterface { complexRead(int x)387 public Number complexRead(int x); 388 } 389 390 public static class Complex implements ComplexInterface { 391 private Integer[] nums; 392 private Long[] longNums; 393 private static Integer justRead; 394 arrayReadObject(Object array, int offset)395 public static Object arrayReadObject(Object array, int offset) { 396 return new Integer(justRead.intValue() + offset); 397 } 398 arrayWriteObject(Object array, int offset, Object element)399 public static void arrayWriteObject(Object array, int offset, Object element) { 400 justRead = (Integer) element; 401 } 402 getInteger(int i)403 public Object getInteger(int i) { 404 return (Object) new Integer(i); 405 } 406 complexRead(int x)407 public Number complexRead(int x) { 408 Number[] ns = null; 409 Number n1, n2, n3, n4; 410 try { 411 ((Object[])ns)[1] = getInteger(x); 412 // We have to throw an error since we can't intercept 413 // a guaranteed null array read yet (likely never will be able to) 414 throw new Error("hi"); 415 } catch (Error error) { 416 ns = nums; 417 } catch (Exception exception) { 418 ns = longNums; 419 } finally { 420 n1 = ns[1]; 421 n2 = ns[2]; 422 n3 = ns[3]; 423 n4 = ns[4]; 424 425 n2.intValue(); 426 n3.intValue(); 427 n4.intValue(); 428 } 429 430 return n1; 431 } 432 } 433 }