1package test.javassist.convert;
2
3import java.net.URL;
4import java.net.URLClassLoader;
5import java.util.HashMap;
6import java.util.Map;
7
8import javassist.ClassPool;
9import javassist.CodeConverter;
10import javassist.CtClass;
11import junit.framework.TestCase;
12
13public class ArrayAccessReplaceTest extends TestCase {
14    private static SimpleInterface simple;
15
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
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
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
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
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
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
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
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
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
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
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
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
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
160        public static Object arrayReadObject(Object array, int index) {
161            return objectMap.get(new Integer(index));
162        }
163
164        public static void arrayWriteObject(Object array, int index, Object element) {
165            objectMap.put(new Integer(index), element);
166        }
167
168        public static byte arrayReadByteOrBoolean(Object array, int index) {
169            return ((Byte)byteMap.get(new Integer(index))).byteValue();
170        }
171
172        public static void arrayWriteByteOrBoolean(Object array, int index, byte element) {
173            byteMap.put(new Integer(index), new Byte(element));
174        }
175
176        public static char arrayReadChar(Object array, int index) {
177            return ((Character)charMap.get(new Integer(index))).charValue();
178        }
179
180        public static void arrayWriteChar(Object array, int index, char element) {
181            charMap.put(new Integer(index), new Character(element));
182        }
183
184        public static double arrayReadDouble(Object array, int index) {
185            return ((Double)doubleMap.get(new Integer(index))).doubleValue();
186        }
187
188        public static void arrayWriteDouble(Object array, int index, double element) {
189            doubleMap.put(new Integer(index), new Double(element));
190        }
191
192        public static float arrayReadFloat(Object array, int index) {
193            return ((Float)floatMap.get(new Integer(index))).floatValue();
194        }
195
196        public static void arrayWriteFloat(Object array, int index, float element) {
197            floatMap.put(new Integer(index), new Float(element));
198        }
199
200        public static int arrayReadInt(Object array, int index) {
201            return ((Integer)intMap.get(new Integer(index))).intValue();
202        }
203
204        public static void arrayWriteInt(Object array, int index, int element) {
205            intMap.put(new Integer(index), new Integer(element));
206        }
207
208        public static long arrayReadLong(Object array, int index) {
209            return ((Long)longMap.get(new Integer(index))).longValue();
210        }
211
212        public static void arrayWriteLong(Object array, int index, long element) {
213            longMap.put(new Integer(index), new Long(element));
214        }
215
216        public static short arrayReadShort(Object array, int index) {
217            return ((Short)shortMap.get(new Integer(index))).shortValue();
218        }
219
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
228        public Foo(int bar) {
229            this.bar = bar;
230        }
231
232        public int hashCode() {
233            return bar;
234        }
235
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 {
245        public void setBoolean(int pos, boolean value);
246        public boolean getBoolean(int pos);
247
248        public void setByte(int pos, byte value);
249        public byte getByte(int pos);
250
251        public void setShort(int pos, short value);
252        public short getShort(int pos);
253
254        public void setChar(int pos, char value);
255        public char getChar(int pos);
256
257        public void setInt(int pos, int value);
258        public int getInt(int pos);
259
260        public void setLong(int pos, long value);
261        public long getLong(int pos);
262
263        public void setFloat(int pos, float value);
264        public float getFloat(int pos);
265
266        public void setDouble(int pos, double value);
267        public double getDouble(int pos);
268
269        public void setObject(int pos, Object value);
270        public Object getObject(int pos);
271
272        public void setFoo(int pos, Foo value);
273        public Foo getFoo(int pos);
274
275        public void setMultiFoo(int one, int two, int three, Foo foo);
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
292        public Simple() {
293           multi[0] = new Foo[0][0];
294           multi[0][1] = new Foo[0];
295        }
296
297        public boolean getBoolean(int pos) {
298            return booleans[pos];
299        }
300
301        public byte getByte(int pos) {
302            return bytes[pos];
303        }
304
305        public char getChar(int pos) {
306            return chars[pos];
307        }
308
309        public double getDouble(int pos) {
310            return doubles[pos];
311        }
312
313        public float getFloat(int pos) {
314            return floats[pos];
315        }
316
317        public Foo getFoo(int pos) {
318            return foos[pos];
319        }
320
321        public int getInt(int pos) {
322            return ints[pos];
323        }
324
325        public long getLong(int pos) {
326            return longs[pos];
327        }
328
329        public Object getObject(int pos) {
330            return objects[pos];
331        }
332
333        public short getShort(int pos) {
334            return shorts[pos];
335        }
336
337        public Foo getMultiFoo(int one, int two, int three) {
338            return multi[one][two][three];
339        }
340
341        public void setBoolean(int pos, boolean value) {
342            booleans[pos] = value;
343        }
344
345        public void setByte(int pos, byte value) {
346            bytes[pos] = value;
347        }
348
349        public void setChar(int pos, char value) {
350            chars[pos] = value;
351        }
352
353        public void setDouble(int pos, double value) {
354            doubles[pos] = value;
355        }
356
357        public void setFloat(int pos, float value) {
358            floats[pos] = value;
359        }
360
361        public void setFoo(int pos, Foo value) {
362            foos[pos] = value;
363        }
364
365        public void setInt(int pos, int value) {
366            ints[pos] = value;
367        }
368
369        public void setLong(int pos, long value) {
370            longs[pos] = value;
371        }
372
373        public void setObject(int pos, Object value) {
374            objects[pos] = value;
375        }
376
377        public void setShort(int pos, short value) {
378            shorts[pos] = value;
379        }
380
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 {
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
395        public static Object arrayReadObject(Object array, int offset) {
396            return new Integer(justRead.intValue() + offset);
397        }
398
399        public static void arrayWriteObject(Object array, int offset, Object element) {
400            justRead = (Integer) element;
401        }
402
403        public Object getInteger(int i) {
404            return (Object) new Integer(i);
405        }
406
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}