xref: /aosp_15_r20/external/javassist/src/test/javassist/JvstTest4.java (revision f1fbf3c2ab775ce834e0af96b7a85bdc7a0eac65)
1 package javassist;
2 
3 import java.io.DataOutputStream;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.FileOutputStream;
7 import java.util.HashSet;
8 
9 import org.junit.FixMethodOrder;
10 import org.junit.runners.MethodSorters;
11 
12 import javassist.bytecode.*;
13 import javassist.bytecode.annotation.Annotation;
14 import javassist.expr.*;
15 
16 @SuppressWarnings({"rawtypes","unchecked","unused"})
17 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
18 public class JvstTest4 extends JvstTestRoot {
JvstTest4(String name)19     public JvstTest4(String name) {
20         super(name);
21     }
22 
testInsertLocalVars()23     public void testInsertLocalVars() throws Exception {
24         CtClass cc = sloader.get("test4.LocalVars");
25 
26         CtMethod m1 = cc.getDeclaredMethod("run");
27         m1.getMethodInfo().getCodeAttribute().insertLocalVar(2, 20);
28         m1.getMethodInfo().rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile());
29         CtMethod m2 = cc.getDeclaredMethod("run2");
30         m2.getMethodInfo().getCodeAttribute().insertLocalVar(2, 0x101);
31         m2.getMethodInfo().rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile());
32 
33         cc.writeFile();
34         Object obj = make(cc.getName());
35         assertEquals(10, invoke(obj, "run"));
36         assertEquals(10, invoke(obj, "run2"));
37     }
38 
testCodeConv()39     public void testCodeConv() throws Exception {
40         CtClass cc = sloader.get("test4.CodeConv");
41         CtMethod m1 = cc.getDeclaredMethod("m1");
42         CtMethod m2 = cc.getDeclaredMethod("m2");
43         CtMethod m3 = cc.getDeclaredMethod("m3");
44         CodeConverter conv = new CodeConverter();
45         conv.insertAfterMethod(m1, m3);
46         conv.insertBeforeMethod(m2, m3);
47         cc.instrument(conv);
48         cc.writeFile();
49         Object obj = make(cc.getName());
50         assertEquals(111033, invoke(obj, "run"));
51     }
52 
testCodeConv2()53     public void testCodeConv2() throws Exception {
54         CtClass cc = sloader.get("test4.CodeConv2");
55         CtField f = cc.getDeclaredField("field");
56         CtField f2 = cc.getDeclaredField("sf");
57         CtMethod run = cc.getDeclaredMethod("run");
58         CodeConverter conv = new CodeConverter();
59         conv.replaceFieldRead(f, cc, "read");
60         conv.replaceFieldWrite(f, cc, "write");
61         conv.replaceFieldRead(f2, cc, "read");
62         conv.replaceFieldWrite(f2, cc, "write");
63         run.instrument(conv);
64         cc.writeFile();
65         Object obj = make(cc.getName());
66         assertEquals(14001600, invoke(obj, "run"));
67     }
68 
testInsGap()69     public void testInsGap() throws Exception {
70         CtClass cc = sloader.get("test4.GapSwitch");
71         ExprEditor ed = new ExprEditor() {
72             public void edit(MethodCall c) throws CannotCompileException {
73                 c.replace("{ value++; $_ = $proceed($$); }");
74             }
75         };
76 
77         CtMethod m1 = cc.getDeclaredMethod("run");
78         m1.instrument(ed);
79         CtMethod m2 = cc.getDeclaredMethod("run2");
80         m2.instrument(ed);
81 
82         final CtMethod m3 = cc.getDeclaredMethod("run3");
83         m3.instrument(new ExprEditor() {
84             public void edit(MethodCall c) throws CannotCompileException {
85                 CodeIterator it = m3.getMethodInfo().getCodeAttribute().iterator();
86                 try {
87                     it.insertGap(c.indexOfBytecode(), 5000);
88                 } catch (BadBytecode e) {
89                     throw new CannotCompileException(e);
90                 }
91             }
92         });
93         m3.getMethodInfo().rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile());
94 
95         cc.writeFile();
96         Object obj = make(cc.getName());
97         assertEquals(1010, invoke(obj, "run"));
98         assertEquals(1100, invoke(obj, "run2"));
99         assertEquals(12222, invoke(obj, "run3"));
100     }
101 
testAnnotationCheck()102     public void testAnnotationCheck() throws Exception {
103         CtClass cc = sloader.get("test4.Anno");
104         CtMethod m1 = cc.getDeclaredMethod("foo");
105         CtField f = cc.getDeclaredField("value");
106 
107         assertTrue(cc.hasAnnotation(test4.Anno1.class));
108         assertFalse(cc.hasAnnotation(java.lang.annotation.Documented.class));
109 
110         assertTrue(cc.hasAnnotation(test4.Anno1.class.getName()));
111         assertFalse(cc.hasAnnotation(java.lang.annotation.Documented.class.getName()));
112 
113         assertEquals("empty", ((test4.Anno1)cc.getAnnotation(test4.Anno1.class)).value());
114         assertNull(cc.getAnnotation(Deprecated.class));
115 
116         assertTrue(m1.hasAnnotation(test4.Anno1.class));
117         assertFalse(m1.hasAnnotation(java.lang.annotation.Documented.class));
118         assertTrue(m1.getAnnotation(test4.Anno1.class) != null);
119         assertNull(m1.getAnnotation(Deprecated.class));
120 
121         assertTrue(f.hasAnnotation(test4.Anno1.class));
122         assertFalse(f.hasAnnotation(java.lang.annotation.Documented.class));
123         assertTrue(f.getAnnotation(test4.Anno1.class) != null);
124         assertNull(f.getAnnotation(Deprecated.class));
125     }
126 
testRename()127     public void testRename() throws Exception {
128         CtClass cc = sloader.get("test4.Rename");
129         cc.setName("test4.Rename2");
130         cc.rebuildClassFile();
131         cc.writeFile();
132         CtClass cc2 = sloader.get("test4.IRename");
133         cc2.replaceClassName("test4.Rename", "test4.Rename2");
134         cc2.rebuildClassFile();
135         cc2.writeFile();
136         Object obj = make(cc.getName());
137         assertEquals("test4.Rename2", obj.getClass().getName());
138         assertEquals(14, invoke(obj, "run"));
139     }
140 
testRename2()141     public void testRename2() throws Exception {
142         CtClass cc = sloader.get("test4.Signature");
143         cc.setName("test4.Sig");
144         cc.rebuildClassFile();
145         cc.writeFile();
146         Object obj = make(cc.getName());
147         assertEquals(3, invoke(obj, "run"));
148     }
149 
testJIRA93()150     public void testJIRA93() throws Exception {
151         ClassPool cp = ClassPool.getDefault();
152         CtClass cc = sloader.getCtClass("test4.JIRA93");
153         CtMethod m = cc.getDeclaredMethod("foo");
154 
155         m.addLocalVariable("bar", CtClass.longType);
156         // The original bug report includes the next line.
157         // But this is not a bug.
158         //m.insertAfter("bar;", true);
159         // Instead, the following code is OK.
160         m.insertBefore("bar = 0;");
161         m.insertAfter("bar;", false);
162 
163         cc.writeFile();
164         Object obj = make(cc.getName());
165     }
166 
testNewRemover()167     public void testNewRemover() throws Exception {
168         CtClass cc = sloader.get("test4.NewRemover");
169         CtMethod mth = cc.getDeclaredMethod("make");
170         mth.getMethodInfo().rebuildStackMap(cc.getClassPool());
171         mth.getMethodInfo().rebuildStackMapForME(cc.getClassPool());
172         //cc.debugWriteFile("debug");
173         CodeConverter conv = new CodeConverter();
174         conv.replaceNew(cc, cc, "make2");
175         mth.instrument(conv);
176         cc.writeFile();
177         Object obj = make(cc.getName());
178         assertEquals(10, invoke(obj, "run"));
179     }
180 
testClassFileWriter()181     public void testClassFileWriter() throws Exception {
182         ClassFileWriter cfw = new ClassFileWriter(ClassFile.JAVA_4, 0);
183         ClassFileWriter.ConstPoolWriter cpw = cfw.getConstPool();
184 
185         ClassFileWriter.FieldWriter fw = cfw.getFieldWriter();
186         fw.add(AccessFlag.PUBLIC, "value", "J", null);
187         fw.add(AccessFlag.PROTECTED | AccessFlag.STATIC, "value2", "Ljava/lang/String;", null);
188 
189         ClassFileWriter.MethodWriter mw = cfw.getMethodWriter();
190 
191         mw.begin(AccessFlag.PUBLIC, MethodInfo.nameInit, "()V", null, null);
192         assertEquals(0, mw.size());
193         mw.add(Opcode.ALOAD_0);
194         assertEquals(1, mw.size());
195         mw.addInvoke(Opcode.INVOKESPECIAL, "java/lang/Object", MethodInfo.nameInit, "()V");
196         mw.add(Opcode.RETURN);
197         mw.codeEnd(1, 1);
198         mw.end(null, null);
199 
200         mw.begin(AccessFlag.PUBLIC, "move", "(II)V", null, null);
201         assertEquals(0, mw.size());
202         mw.add(Opcode.ALOAD_0);
203         mw.addInvoke(Opcode.INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;");
204         assertEquals(4, mw.size());
205         mw.add(Opcode.POP);
206         mw.add(Opcode.RETURN);
207         mw.add(Opcode.POP);
208         mw.add(Opcode.RETURN);
209         mw.codeEnd(1, 3);
210         mw.addCatch(0, 4, 6, cpw.addClassInfo("java/lang/Exception"));
211         mw.addCatch(0, 4, 6, cpw.addClassInfo("java/lang/Throwable"));
212         mw.end(null, null);
213 
214         String[] exceptions = { "java/lang/Exception", "java/lang/NullPointerException" };
215         mw.begin(AccessFlag.PUBLIC, "move2", "()V", exceptions, null);
216         mw.add(Opcode.RETURN);
217         mw.codeEnd(0, 1);
218         StackMapTable.Writer stack = new StackMapTable.Writer(32);
219         stack.sameFrame(1);
220         mw.end(stack, null);
221 
222         mw.begin(AccessFlag.PUBLIC, "foo", "()I", null, null);
223         mw.add(Opcode.ICONST_2);
224         mw.add(Opcode.IRETURN);
225         mw.codeEnd(1, 1);
226         mw.end(null, null);
227 
228         byte[] out = cfw.end(AccessFlag.PUBLIC, cpw.addClassInfo("test4/WrittenFile"),
229                              cpw.addClassInfo("java/lang/Object"),
230                              null, null);
231         FileOutputStream fos = new FileOutputStream("test4/WrittenFile.class");
232         fos.write(out);
233         fos.close();
234         Object obj = make("test4.WrittenFile");
235         assertNotNull(obj);
236         assertEquals(2, invoke(obj, "foo"));
237     }
238 
testClassFileWriter2()239     public void testClassFileWriter2() throws Exception {
240         ClassFileWriter cfw = new ClassFileWriter(ClassFile.JAVA_4, 0);
241         ClassFileWriter.ConstPoolWriter cpw = cfw.getConstPool();
242 
243         ClassFileWriter.FieldWriter fw = cfw.getFieldWriter();
244         fw.add(AccessFlag.PUBLIC | AccessFlag.STATIC, "value", "I", null);
245 
246         ClassFileWriter.MethodWriter mw = cfw.getMethodWriter();
247 
248         mw.begin(AccessFlag.PUBLIC, MethodInfo.nameInit, "()V", null, null);
249         mw.add(Opcode.ALOAD_0);
250         mw.addInvoke(Opcode.INVOKESPECIAL, "java/lang/Object", MethodInfo.nameInit, "()V");
251         mw.add(Opcode.RETURN);
252         mw.codeEnd(1, 1);
253         mw.end(null, null);
254 
255         String[] exceptions = { "java/lang/Exception" };
256         mw.begin(AccessFlag.PUBLIC | AccessFlag.ABSTRACT, "move", "(II)V", exceptions, null);
257         mw.end(null, null);
258 
259         int thisClass = cpw.addClassInfo("test4/WrittenFile2");
260         int superClass = cpw.addClassInfo("java/lang/Object");
261 
262         cfw.end(new DataOutputStream(new FileOutputStream("test4/WrittenFile2.class")),
263                 AccessFlag.PUBLIC | AccessFlag.ABSTRACT, thisClass, superClass,
264                 null, null);
265 
266         File f = new File("test4/WrittenFile2.class");
267         byte[] file = new byte[(int)f.length()];
268         FileInputStream fis = new FileInputStream(f);
269         fis.read(file);
270         fis.close();
271 
272         byte[] out = cfw.end(AccessFlag.PUBLIC | AccessFlag.ABSTRACT, thisClass,
273                              superClass, null, null);
274 
275         assertEquals(out.length, file.length);
276         for (int i = 0; i < out.length; i++)
277             assertEquals(out[i], file[i]);
278 
279         CtClass sub = dloader.makeClass("test4.WrittenFile2sub", dloader.get("test4.WrittenFile2"));
280         sub.addMethod(CtMethod.make("public void move(int i, int j) {}", sub));
281         sub.addMethod(CtMethod.make("public int foo() { move(0, 1); return 1; }", sub));
282         sub.writeFile();
283         Object obj = make("test4.WrittenFile2sub");
284         assertEquals(1, invoke(obj, "foo"));
285     }
286 
testClassFileWriter3()287     public void testClassFileWriter3() throws Exception {
288         ClassFileWriter cfw = new ClassFileWriter(ClassFile.JAVA_4, 0);
289         ClassFileWriter.ConstPoolWriter cpw = cfw.getConstPool();
290         int superClass = cpw.addClassInfo("java/lang/Object");
291 
292         final int syntheticTag = cpw.addUtf8Info("Synthetic");
293         ClassFileWriter.AttributeWriter attribute = new ClassFileWriter.AttributeWriter() {
294             public void write(DataOutputStream out) throws java.io.IOException {
295                 out.writeShort(syntheticTag);
296                 out.writeInt(0);
297             }
298 
299             public int size() {
300                 return 1;
301             }
302         };
303 
304         ClassFileWriter.FieldWriter fw = cfw.getFieldWriter();
305         fw.add(AccessFlag.PUBLIC, "value", "J", null);
306         fw.add(AccessFlag.PROTECTED | AccessFlag.STATIC, "value2", "Ljava/lang/String;", attribute);
307 
308         ClassFileWriter.MethodWriter mw = cfw.getMethodWriter();
309 
310         mw.begin(AccessFlag.PUBLIC, MethodInfo.nameInit, "()V", null, attribute);
311         mw.add(Opcode.ALOAD_0);
312         mw.add(Opcode.INVOKESPECIAL);
313         mw.add16(cpw.addMethodrefInfo(superClass, cpw.addNameAndTypeInfo(MethodInfo.nameInit, "()V")));
314         // mw.addInvoke(Opcode.INVOKESPECIAL, "java/lang/Object", MethodInfo.nameInit, "()V");
315         mw.add(Opcode.RETURN);
316         mw.codeEnd(1, 1);
317         mw.end(null, null);
318 
319         mw.begin(AccessFlag.PUBLIC, "foo", "()I", null, attribute);
320         mw.add(Opcode.ICONST_2);
321         mw.add(Opcode.IRETURN);
322         mw.codeEnd(1, 1);
323         mw.end(null, null);
324 
325         int thisClass = cpw.addClassInfo("test4/WrittenFile3");
326         cfw.end(new DataOutputStream(new FileOutputStream("test4/WrittenFile3.class")),
327                 AccessFlag.PUBLIC, thisClass, superClass,
328                 null, attribute);
329 
330         File f = new File("test4/WrittenFile3.class");
331         byte[] file = new byte[(int)f.length()];
332         FileInputStream fis = new FileInputStream(f);
333         fis.read(file);
334         fis.close();
335 
336         byte[] out = cfw.end(AccessFlag.PUBLIC, thisClass, superClass,
337                              null, attribute);
338 
339         assertEquals(out.length, file.length);
340         for (int i = 0; i < out.length; i++)
341             assertEquals(out[i], file[i]);
342 
343         Object obj = make("test4.WrittenFile3");
344         assertNotNull(obj);
345         assertEquals(2, invoke(obj, "foo"));
346     }
347 
testCtArray()348     public void testCtArray() throws Exception {
349         CtClass cc = sloader.get("int");
350         assertEquals(Modifier.FINAL | Modifier.PUBLIC, cc.getModifiers());
351         cc = sloader.get("int[]");
352         assertEquals(Modifier.FINAL | Modifier.PUBLIC, cc.getModifiers());
353         cc = sloader.get("java.lang.String[]");
354         assertEquals(Modifier.FINAL | Modifier.PUBLIC, cc.getModifiers());
355         CtClass[] intfs = cc.getInterfaces();
356         assertEquals(Cloneable.class.getName(), intfs[0].getName());
357         assertEquals(java.io.Serializable.class.getName(), intfs[1].getName());
358         cc = sloader.get("test4.CtArrayTest[]");
359         assertEquals(Modifier.FINAL | Modifier.PUBLIC, cc.getModifiers());
360     }
361 
testAnalysisType()362     public void testAnalysisType() throws Exception {
363         testAnalysisType2(sloader.get("int[]"), 1);
364         testAnalysisType2(sloader.get("java.lang.String[][]"), 2);
365         sloader.makeClass("A");
366         testAnalysisType2(sloader.getCtClass("A"), 0);
367         testAnalysisType2(sloader.getCtClass("A[]"), 1);
368         testAnalysisType2(sloader.getCtClass("A[][]"), 2);
369     }
370 
testAnalysisType2(CtClass cc, int size)371     private void testAnalysisType2(CtClass cc, int size) throws Exception {
372         javassist.bytecode.analysis.Type t = javassist.bytecode.analysis.Type.get(cc);
373         assertEquals(cc.getName(), size, t.getDimensions());
374     }
375 
testArrayType()376     public void testArrayType() throws Exception {
377         CtClass at = sloader.get("java.lang.Object[]");
378         CtClass[] intfs = at.getInterfaces();
379         assertEquals(intfs.length, 2);
380         assertEquals(intfs[0].getName(), java.lang.Cloneable.class.getName());
381         assertEquals(intfs[1].getName(), java.io.Serializable.class.getName());
382 
383         assertTrue(at.subtypeOf(sloader.get(java.lang.Object.class.getName())));
384         assertTrue(at.subtypeOf(intfs[0]));
385         assertTrue(at.subtypeOf(intfs[1]));
386         assertTrue(at.subtypeOf(intfs[1]));
387         CtClass subt = sloader.get(java.text.CharacterIterator.class.getName());
388         assertFalse(at.subtypeOf(subt));
389     }
390 
testGetFieldDesc()391     public void testGetFieldDesc() throws Exception {
392         CtClass cc = sloader.get("test4.GetFieldDesc");
393         cc.getDeclaredField("f", "I");
394         cc.getField("s", "Ljava/lang/String;");
395         CtClass cc2 = sloader.get("test4.GetFieldDescSub");
396         assertEquals(cc2.getField("s", "Ljava/lang/String;").getDeclaringClass().getName(),
397                 "test4.GetFieldDesc");
398         assertEquals(cc2.getField("s", "I").getDeclaringClass().getName(),
399                 "test4.GetFieldDescSub");
400     }
401 
testMakeMethod()402     public void testMakeMethod() throws CannotCompileException {
403         CtClass ctClass = sloader.makeClass("test4.MakeMethod2");
404         CtNewMethod.make("public String foox(){return test4.MakeMethod.foo();}", ctClass);
405         CtNewMethod.make("public String foo(){return test4.MakeMethod.foo();}", ctClass);
406     }
407 
testVarArgs()408     public void testVarArgs() throws Exception {
409         CtClass cc = sloader.get("test4.VarArgs");
410         CtMethod m = CtMethod.make("public int foo(int i, String[] args) { return args.length; }", cc);
411         m.setModifiers(m.getModifiers() | Modifier.VARARGS);
412         cc.addMethod(m);
413         m = CtMethod.make("public int run() { return goo(7, new int[] { 1, 2, 3 }); }", cc);
414         cc.addMethod(m);
415         cc.writeFile();
416         Object obj = make(cc.getName());
417         assertEquals(3, invoke(obj, "run"));
418     }
419 
testGetAllRef()420     public void testGetAllRef() throws Exception {
421         CtClass cc = sloader.get("test4.GetAllRef");
422         ClassFile cf = cc.getClassFile();
423         AttributeInfo ainfo
424             = cf.getAttribute(AnnotationsAttribute.visibleTag);
425         ClassMap map = new ClassMap();
426         map.put("test4.GetAllRefAnno", "test4.GetAllRefAnno2");
427         map.put("test4.GetAllRefEnum", "test4.GetAllRefEnum2");
428         map.put("java.lang.String", "java.lang.StringBuilder");
429         cf.addAttribute(ainfo.copy(cf.getConstPool(), map));
430         cc.writeFile();
431         cc.detach();
432 
433         cc = dloader.get(cc.getName());
434         test4.GetAllRefAnno2 anno
435             = (test4.GetAllRefAnno2)cc.getAnnotation(test4.GetAllRefAnno2.class);
436         assertEquals(test4.GetAllRefEnum2.A, anno.getA());
437         assertEquals(StringBuilder.class, anno.getC());
438     }
439 
testGetAllRefB()440     public void testGetAllRefB() throws Exception {
441         CtClass cc = sloader.get("test4.GetAllRefB");
442         ClassMap map = new ClassMap();
443         map.put("test4.GetAllRefAnno", "test4.GetAllRefAnno2");
444         map.put("test4.GetAllRefEnum", "test4.GetAllRefEnum2");
445         map.put("java.lang.String", "java.lang.StringBuilder");
446         cc.replaceClassName(map);
447         //cc.replaceClassName("test4.GetAllRefAnno", "test4.GetAllRefAnno2");
448         cc.writeFile();
449 
450         cc = dloader.get(cc.getName());
451         test4.GetAllRefAnno2 anno
452             = (test4.GetAllRefAnno2)cc.getAnnotation(test4.GetAllRefAnno2.class);
453         assertEquals(test4.GetAllRefEnum2.A, anno.getA());
454         assertEquals(StringBuilder.class, anno.getC());
455         /*
456         AnnotationsAttribute aainfo = (AnnotationsAttribute)
457             cc.getClassFile().getAttribute(AnnotationsAttribute.visibleTag);
458         Annotation[] a = aainfo.getAnnotations();
459         System.err.println(a[0].getTypeName());
460         System.err.println(a[0]);
461         */
462     }
463 
testGetAllRefC()464     public void testGetAllRefC() throws Exception {
465         CtClass cc = sloader.get("test4.GetAllRefC");
466         HashSet set = new HashSet();
467         set.add("java.lang.Object");
468         set.add("java.lang.String");
469         set.add("test4.GetAllRefC");
470         set.add("test4.GetAllRefAnno");
471         set.add("test4.GetAllRefEnum");
472         set.add("test4.GetAllRefAnnoC");
473         set.add("test4.GetAllRefAnnoC2");
474         set.add("test4.GetAllRefAnnoC3");
475         set.add("test4.GetAllRefAnnoC4");
476         java.util.Collection<String> refs
477             = (java.util.Collection<String>)cc.getRefClasses();
478         assertEquals(set.size(), refs.size());
479         for (String s: refs) {
480             assertTrue(set.contains(s));
481         }
482     }
483 
testGetAllRefInner()484     public void testGetAllRefInner() throws Exception {
485         HashSet set = new HashSet();
486         set.add("java.lang.Object");
487         set.add("test4.GetAllRefInnerTest");
488         set.add("test4.GetAllRefInnerTest$1");
489         set.add("test4.GetAllRefInnerTest$2");
490         CtClass cc = sloader.get("test4.GetAllRefInnerTest");
491         int size = 0;
492         for (Object s: cc.getRefClasses()) {
493             assertTrue((String)s, set.contains(s));
494             ++size;
495         }
496 
497         assertEquals(set.size(), size);
498     }
499 
testNestedClass()500     public void testNestedClass() throws Exception {
501         CtClass cc = sloader.get("test4.NestedClass$1");
502         CtClass[] tab = cc.getNestedClasses();
503         assertEquals(1, tab.length);
504         assertEquals("test4.NestedClass$1$1", tab[0].getName());
505 
506         cc = sloader.get("test4.NestedClass$1$1");
507         tab = cc.getNestedClasses();
508         assertEquals(0, tab.length);
509 
510         cc = sloader.get("test4.NestedClass");
511         tab = cc.getNestedClasses();
512         for (CtClass c: tab) {
513             System.err.println(c.getName());
514         }
515 
516         // Eclipse compiler sets tab.length to 4 but javac sets to 3.
517         assertTrue(tab.length == 4 || tab.length == 3);
518         for (CtClass c: tab) {
519             String name = c.getName();
520             assertTrue(name.equals("test4.NestedClass$N")
521                        || name.equals("test4.NestedClass$S")
522                        || name.equals("test4.NestedClass$1")
523                        || name.equals("test4.NestedClass$1In"));
524         }
525 
526         cc = sloader.get("test4.NestedClass$1In");
527         tab = cc.getNestedClasses();
528         assertEquals(0, tab.length);
529     }
530 
testGetClasses()531     public void testGetClasses() throws Exception {
532         CtClass cc = sloader.get("test4.NestedClass");
533         CtClass[] tab = cc.getDeclaredClasses();
534 
535         // Eclipse compiler sets tab.length to 4 but javac sets to 3.
536         assertTrue(tab.length == 4 || tab.length == 3);
537         for (CtClass c: tab) {
538             String name = c.getName();
539             assertTrue(name.equals("test4.NestedClass$N")
540                        || name.equals("test4.NestedClass$S")
541                        || name.equals("test4.NestedClass$1")
542                        || name.equals("test4.NestedClass$1In"));
543         }
544 
545         cc = sloader.get("test4.NestedClass$1In");
546         tab = cc.getDeclaredClasses();
547         assertEquals(0, tab.length);
548     }
549 
testImportPac()550     public void testImportPac() throws Exception {
551         CtClass cc = sloader.makeClass("test4.TestImpP");
552         sloader.importPackage("test4.NewImportPac");
553         try {
554             cc.addMethod(CtNewMethod.make(
555                 "public int foo(){ " +
556                 "  ImportPac obj = new ImportPac();" +
557                 "  return obj.getClass().getName().length(); }", cc));
558             fail("ImportPac was found");
559         }
560         catch (CannotCompileException e) {}
561 
562         cc.addMethod(CtNewMethod.make(
563                 "public int bar(){ " +
564                         "  NewImportPac obj = new NewImportPac();" +
565                         "  return obj.getClass().getName().length(); }", cc));
566         sloader.clearImportedPackages();
567     }
568 
testLength()569     public void testLength() throws Exception {
570         CtClass cc = sloader.makeClass("test4.LengthTest");
571         cc.addMethod(CtNewMethod.make(
572                 "public int len(String s){ " +
573                         "  return s.length(); }", cc));
574         cc.addField(CtField.make("int length = 100;", cc));
575         cc.addConstructor(CtNewConstructor.defaultConstructor(cc));
576         cc.addMethod(CtNewMethod.make(
577                 "public int run(){ " +
578                         "  test4.LengthTest t = new test4.LengthTest();" +
579                         "  return len(\"foo\") + t.length + test4.length.m(); }", cc));
580         try {
581             cc.addMethod(CtNewMethod.make(
582                     "public int run(){ " +
583                             "  return test4no.length.m(); }", cc));
584             fail("test4no was found!");
585         }
586         catch (CannotCompileException e) {
587             System.out.println(e);
588         }
589         cc.writeFile();
590         Object obj = make(cc.getName());
591         assertEquals(110, invoke(obj, "run"));
592     }
593 
testAaload()594     public void testAaload() throws Exception {
595         CtClass clazz = sloader.get("test4.Aaload");
596         CtMethod method = clazz.getMethod("narf", "()V");
597         method.instrument(new ExprEditor() {
598             @Override
599             public void edit(MethodCall call) throws CannotCompileException {
600                 String name = call.getMethodName();
601                 if (name.equals("addActionListener"))
602                     call.replace("$0." + name + "($$);");
603             }
604         });
605     }
606 
607     @SuppressWarnings("deprecation")
testMakePackage()608     public void testMakePackage() throws Exception {
609         if (ClassFile.MAJOR_VERSION >= ClassFile.JAVA_9) {
610             ClassPool pool = ClassPool.getDefault();
611             try {
612                 pool.makePackage(pool.getClassLoader(), "test4.pack2");
613                 fail("makePackage() ran");
614             }
615             catch (CannotCompileException e) {}
616         }
617     }
618 
619     @SuppressWarnings("deprecation")
testPackage()620     public void testPackage() throws Throwable {    // JASSIST-147
621         String packageName = "test4.pack";
622         ClassPool pool = ClassPool.getDefault();
623         try {
624             pool.makePackage(pool.getClassLoader(), packageName);
625             pool.makePackage(pool.getClassLoader(), packageName);
626         }
627         catch (CannotCompileException e) {
628             if (ClassFile.MAJOR_VERSION >= ClassFile.JAVA_9)
629                 return;         // makePackage() does not work in Java 9.
630         }
631 
632         CtClass ctcl = pool.makeClass("test4.pack.Clazz");
633         Class cl = ctcl.toClass();
634         Object obj = cl.getConstructor().newInstance();
635         assertEquals(packageName, obj.getClass().getPackage().getName());
636     }
637 
638     public static final String BASE_PATH = "../../";
639     public static final String JAVASSIST_JAR = BASE_PATH + "javassist.jar";
640     public static final String CLASSES_FOLDER = BASE_PATH + "build/classes";
641     public static final String TEST_CLASSES_FOLDER = BASE_PATH + "build/test-classes";
642 
643     public static class Inner1 {
get()644         public static int get() {
645             return 0;
646         }
647     }
648 
testJIRA150()649     public void testJIRA150() throws Exception {
650         ClassPool pool = new ClassPool(true);
651         for(int paths=0; paths<50; paths++) {
652             pool.appendClassPath(JAVASSIST_JAR);
653             pool.appendClassPath(CLASSES_FOLDER);
654             pool.appendClassPath(TEST_CLASSES_FOLDER);
655         }
656         CtClass cc = pool.get("Jassist150$Inner1");
657         CtMethod ccGet = cc.getDeclaredMethod("get");
658         long startTime = System.currentTimeMillis();
659         for(int replace=0; replace<1000; replace++) {
660             ccGet.setBody(
661                     "{ int n1 = java.lang.Integer#valueOf(1); " +
662                     "  int n2 = java.lang.Integer#valueOf(2); " +
663                     "  int n3 = java.lang.Integer#valueOf(3); " +
664                     "  int n4 = java.lang.Integer#valueOf(4); " +
665                     "  int n5 = java.lang.Integer#valueOf(5); " +
666                     "  return n1+n2+n3+n4+n5; }");
667         }
668         long endTime = System.currentTimeMillis();
669         for(int replace=0; replace<1000; replace++) {
670             ccGet.setBody(
671                     "{ int n1 = java.lang.Integer.valueOf(1); " +
672                     "  int n2 = java.lang.Integer.valueOf(2); " +
673                     "  int n3 = java.lang.Integer.valueOf(3); " +
674                     "  int n4 = java.lang.Integer.valueOf(4); " +
675                     "  int n5 = java.lang.Integer.valueOf(5); " +
676                     "  return n1+n2+n3+n4+n5; }");
677         }
678         long endTime2 = System.currentTimeMillis();
679         for(int replace=0; replace<1000; replace++) {
680             ccGet.setBody(
681                 "{ int n1 = Integer.valueOf(1); " +
682                 "  int n2 = Integer.valueOf(2); " +
683                 "  int n3 = Integer.valueOf(3); " +
684                 "  int n4 = Integer.valueOf(4); " +
685                 "  int n5 = Integer.valueOf(5); " +
686                 "  return n1+n2+n3+n4+n5; }");
687         }
688         long endTime3 = System.currentTimeMillis();
689         long t1 = endTime - startTime;
690         long t2 = endTime2 - endTime;
691         long t3 = endTime3 - endTime2;
692         System.out.println("JIRA150: " + t1 + ", " + t2 + ", " + t3);
693         assertTrue("performance test (the next try may succeed): " + t2 + " < 6 * " + t1,
694                    t2 < t1 * 6);
695         assertTrue(t3 + " < 3 * " + t1, t3 < t1 * 3);
696     }
697 
testJIRA150b()698     public void testJIRA150b() throws Exception {
699         int origSize = javassist.compiler.MemberResolver.getInvalidMapSize();
700         int N = 100;
701         for (int k = 0; k < N; k++) {
702             ClassPool pool = new ClassPool(true);
703             for(int paths=0; paths<50; paths++) {
704                 pool.appendClassPath(JAVASSIST_JAR);
705                 pool.appendClassPath(CLASSES_FOLDER);
706                 pool.appendClassPath(TEST_CLASSES_FOLDER);
707             }
708             CtClass cc = pool.get("Jassist150$Inner1");
709             CtMethod ccGet = cc.getDeclaredMethod("get");
710             for(int replace=0; replace < 5; replace++) {
711                 ccGet.setBody(
712                     "{ int n1 = java.lang.Integer#valueOf(1); " +
713                     "  int n2 = java.lang.Integer#valueOf(2); " +
714                     "  int n3 = java.lang.Integer#valueOf(3); " +
715                     "  int n4 = java.lang.Integer#valueOf(4); " +
716                     "  int n5 = java.lang.Integer#valueOf(5); " +
717                     "  return n1+n2+n3+n4+n5; }");
718             }
719             pool = null;
720         }
721 
722         // try to run garbage collection.
723         int[][] mem = new int[100][];
724         int[] large;
725         for (int i = 0; i < 100; i++) {
726             large = new int[1000000];
727             large[large.length - 2] = 9 + i;
728             mem[i] = large;
729         }
730         System.gc();
731         System.gc();
732         int size = javassist.compiler.MemberResolver.getInvalidMapSize();
733         System.out.println("JIRA150b " + size + " " + mem[mem.length - 1][mem[0].length - 2]);
734         // Now this seems obsolete.
735         // assertTrue("JIRA150b size: " + origSize + " " + size, size < origSize + N);
736     }
737 
testJIRA152()738     public void testJIRA152() throws Exception {
739         CtClass cc = sloader.get("test4.JIRA152");
740         CtMethod mth = cc.getDeclaredMethod("buildColumnOverride");
741         //CtMethod mth = cc.getDeclaredMethod("tested");
742         mth.instrument(new ExprEditor() {
743             public void edit(MethodCall c) throws CannotCompileException {
744                 c.replace("try{ $_ = $proceed($$); } catch (Throwable t) { throw t; }");
745             }
746         });
747         cc.writeFile();
748         Object obj = make(cc.getName());
749         assertEquals(1, invoke(obj, "test"));
750     }
751 
testJIRA151()752     public void testJIRA151() {
753         // try it using classloader of TestDescForName Desc.useContextClassLoader = false;
754         assertTrue(javassist.runtime.Desc.getClazz("[Ljava.lang.String;") != null);
755         //Thread.currentThread().setContextClassLoader(TestDescForName.class.getClassLoader());
756         boolean old = javassist.runtime.Desc.useContextClassLoader;
757         javassist.runtime.Desc.useContextClassLoader = true;
758         assertTrue(javassist.runtime.Desc.getClazz("[Ljava.lang.String;") != null);
759         javassist.runtime.Desc.useContextClassLoader = old;
760     }
761 
testJIRA166()762     public void testJIRA166() throws Exception {
763         CtClass cc = sloader.get("test4.JIRA166");
764         cc.instrument(new ExprEditor() {
765             public void edit(FieldAccess fa) throws CannotCompileException {
766                 if (fa.isReader() && fa.getFieldName().equals("length"))
767                     fa.replace("length = self().length + \"!\"; $_ = ($r) this.length.substring(1);");
768             }
769         });
770         cc.writeFile();
771         Object obj = make(cc.getName());
772         assertEquals(1, invoke(obj, "run"));
773     }
774 
testGenericSignature()775     public void testGenericSignature() throws Exception {
776         CtClass cc = sloader.makeClass("test4.GenSig");
777         CtClass objClass = sloader.get(CtClass.javaLangObject);
778         SignatureAttribute.ClassSignature cs
779             = new SignatureAttribute.ClassSignature(
780                     new SignatureAttribute.TypeParameter[] {
781                             new SignatureAttribute.TypeParameter("T") });
782         cc.setGenericSignature(cs.encode());    // <T:Ljava/lang/Object;>Ljava/lang/Object;
783 
784         CtField f = new CtField(objClass, "value", cc);
785         SignatureAttribute.TypeVariable tvar = new SignatureAttribute.TypeVariable("T");
786         f.setGenericSignature(tvar.encode());   // TT;
787         cc.addField(f);
788 
789         CtMethod m = CtNewMethod.make("public Object get(){return value;}", cc);
790         SignatureAttribute.MethodSignature ms
791             = new SignatureAttribute.MethodSignature(null, null, tvar, null);
792         m.setGenericSignature(ms.encode());     // ()TT;
793         cc.addMethod(m);
794 
795         CtMethod m2 = CtNewMethod.make("public void set(Object v){value = v;}", cc);
796         SignatureAttribute.MethodSignature ms2
797             = new SignatureAttribute.MethodSignature(null, new SignatureAttribute.Type[] { tvar },
798                                                      new SignatureAttribute.BaseType("void"), null);
799         m2.setGenericSignature(ms2.encode());   // (TT;)V;
800         cc.addMethod(m2);
801 
802         cc.writeFile();
803         Object obj = make(cc.getName());
804         Class clazz = obj.getClass();
805         assertEquals("T", clazz.getTypeParameters()[0].getName());
806         assertEquals("T", ((java.lang.reflect.TypeVariable)clazz.getDeclaredField("value").getGenericType()).getName());
807         java.lang.reflect.Method rm = clazz.getDeclaredMethod("get", new Class[0]);
808         assertEquals("T", ((java.lang.reflect.TypeVariable)rm.getGenericReturnType()).getName());
809         java.lang.reflect.Method rm2 = clazz.getDeclaredMethod("set", new Class[] { Object.class });
810         assertEquals("T", ((java.lang.reflect.TypeVariable)rm2.getGenericParameterTypes()[0]).getName());
811     }
812 
testJIRA171()813     public void testJIRA171() throws Exception {
814         SignatureAttribute.MethodSignature ms
815             = SignatureAttribute.toMethodSignature("(Ljava/lang/Object;Lorg/apache/hadoop/io/Text;"
816               + "Lorg/apache/hadoop/mapreduce/Mapper<Ljava/lang/Object;Lorg/apache/hadoop/io/Text;"
817               + "Lorg/apache/hadoop/io/Text;Lorg/apache/hadoop/io/IntWritable;>.Context;)V");
818         String s = ms.toString();
819         System.out.println(s);
820         assertEquals("<> (java.lang.Object, org.apache.hadoop.io.Text, "
821                      + "org.apache.hadoop.mapreduce.Mapper<java.lang.Object, org.apache.hadoop.io.Text, "
822                      + "org.apache.hadoop.io.Text, org.apache.hadoop.io.IntWritable>.Context) void", s);
823     }
824 
testAfter()825     public void testAfter() throws Exception {
826         CtClass cc = sloader.get("test4.AfterTest");
827         CtMethod m1 = cc.getDeclaredMethod("m1");
828         m1.insertAfter("print();");
829         CtMethod m2 = cc.getDeclaredMethod("m2");
830         m2.insertAfter("print();");
831         CtMethod m3 = cc.getDeclaredMethod("m3");
832         m3.insertAfter("print();");
833         CtMethod m4 = cc.getDeclaredMethod("m4");
834         m4.insertAfter("print();");
835 
836         CtMethod mm1 = cc.getDeclaredMethod("mm1");
837         mm1.insertAfter("print();", true);
838         CtMethod mm2 = cc.getDeclaredMethod("mm2");
839         mm2.insertAfter("print();", true);
840         CtMethod mm3 = cc.getDeclaredMethod("mm3");
841         mm3.insertAfter("print();", true);
842         CtMethod mm4 = cc.getDeclaredMethod("mm4");
843         mm4.insertAfter("print();", true);
844 
845         cc.writeFile();
846         Object obj = make(cc.getName());
847         assertEquals(131, invoke(obj, "test1"));
848         assertEquals(112, invoke(obj, "test2"));
849         assertEquals(10, invoke(obj, "test3"));
850         assertEquals(100, invoke(obj, "test4"));
851 
852         assertEquals(131, invoke(obj, "test11"));
853         assertEquals(112, invoke(obj, "test22"));
854         assertEquals(10, invoke(obj, "test33"));
855         assertEquals(100, invoke(obj, "test44"));
856     }
857 
testJIRA186()858     public void testJIRA186() throws Exception {
859     	CtClass cc = sloader.get("test4.JIRA186");
860     	cc.getDeclaredMethod("test").insertBefore("{" +
861     			  "  java.util.List l = new java.util.ArrayList();" +
862     			  "  l.add(this.toString());" +
863     			  "}");
864         cc.writeFile();
865         Object obj = make(cc.getName());
866         assertEquals(1, invoke(obj, "test"));
867     }
868 
869     // JASSIST-190
testMultipleCatch()870     public void testMultipleCatch() throws Exception {
871         CtClass cc = sloader.get("test4.MultiCatch");
872         CtMethod m1 = cc.getDeclaredMethod("m1");
873         m1.insertAfter("print();");
874         cc.writeFile();
875         Object obj = make(cc.getName());
876         assertEquals(12, invoke(obj, "test1"));
877     }
878 
879     // JASSIST-185
testLocalVariableTypeTable()880     public void testLocalVariableTypeTable() throws Exception {
881         CtClass cc = sloader.get("test4.Lvtt");
882         CtMethod m = cc.getDeclaredMethod("run");
883         m.addParameter(CtClass.intType);
884         cc.writeFile();
885         Object obj = make(cc.getName());
886     }
887 
888     // JASSISt-181
testAnnotationWithGenerics()889     public void testAnnotationWithGenerics() throws Exception {
890     	CtClass cc0 = sloader.get("test4.JIRA181b");
891         CtField field0 = cc0.getField("aField");
892         String s0 = field0.getAnnotation(test4.JIRA181b.Condition.class).toString();
893         assertEquals("@test4.JIRA181b$Condition(condition=java.lang.String.class)", s0);
894         CtField field01 = cc0.getField("aField2");
895         String s01 = field01.getAnnotation(test4.JIRA181b.Condition.class).toString();
896         assertEquals("@test4.JIRA181b$Condition(condition=void.class)", s01);
897 
898         CtClass cc = sloader.get("test4.JIRA181");
899         CtField field = cc.getField("aField");
900         String s = field.getAnnotation(test4.JIRA181.Condition.class).toString();
901         if (ClassFile.MAJOR_VERSION < ClassFile.JAVA_9)
902             assertEquals("@test4.JIRA181$Condition(condition=test4.JIRA181<T>.B.class)", s);
903         else
904             assertEquals("@test4.JIRA181$Condition(condition=test4.JIRA181.B.class)", s);
905 
906         CtField field2 = cc.getField("aField2");
907         String s2 = field2.getAnnotation(test4.JIRA181.Condition2.class).toString();
908         if (ClassFile.MAJOR_VERSION < ClassFile.JAVA_9)
909             assertEquals("@test4.JIRA181$Condition2(condition=test4.JIRA181<T>.B[].class)", s2);
910         else
911             assertEquals("@test4.JIRA181$Condition2(condition=test4.JIRA181.B[].class)", s2);
912     }
913 
testJIRA195()914     public void testJIRA195() throws Exception {
915         CtClass cc = sloader.get("test4.JIRA195");
916         CtMethod mth = cc.getDeclaredMethod("test");
917         mth.getMethodInfo().rebuildStackMap(cc.getClassPool());
918         cc.writeFile();
919         Object obj = make(cc.getName());
920         assertEquals(4, invoke(obj, "run"));
921     }
922 
testJIRA188()923     public void testJIRA188() throws Exception {
924         CtClass cc = sloader.makeClass("test4.JIRA188");
925         CtField f = new CtField(CtClass.intType, "f", cc);
926         f.setModifiers(Modifier.PRIVATE);
927         cc.addField(f);
928         cc.addMethod(CtNewMethod.make(
929                 "public int getf(test4.JIRA188 p){ return p.f; }", cc));
930         cc.detach();
931         // System.gc();
932         try {
933             cc = sloader.get("test4.JIRA188");
934             fail("test4.JIRA188 found");
935         }
936         catch (NotFoundException e) {}
937         cc = sloader.makeClass("test4.JIRA188");
938         cc.addField(new CtField(CtClass.intType, "g", cc));
939         cc.addMethod(CtNewMethod.make(
940                 "public int getf(test4.JIRA188 p){ return p.g; }", cc));
941     }
942 
testJIRA158()943     public void testJIRA158() throws Exception {
944         CtClass cc = sloader.get("test4.JIRA158");
945         cc.addMethod(CtMethod.make("public int run() { return obj.foo(jj, dd) + obj.bar(j, d); }", cc));
946         cc.writeFile();
947         Object obj = make(cc.getName());
948         assertEquals(15, invoke(obj, "run"));
949     }
950 
testJIRA207()951     public void testJIRA207() throws Exception {
952         CtClass cc = sloader.get("test4.JIRA207");
953         CtMethod cm = cc.getDeclaredMethod("foo");
954         cm.insertBefore("throw new Exception();");
955 
956         CtMethod cm2 = cc.getDeclaredMethod("run2");
957         cm2.insertBefore("throw new Exception();");
958         cc.writeFile();
959         Object obj = make(cc.getName());
960         try {
961             invoke(obj, "run2");
962             fail("run2");
963         }
964         catch (Exception e) {}
965     }
966 
testJIRA212()967     public void testJIRA212() throws Exception {
968         CtClass cc = sloader.get("test4.JIRA212");
969         for (final CtBehavior behavior : cc.getDeclaredBehaviors()) {
970             behavior.instrument(new ExprEditor() {
971                     public void edit(FieldAccess fieldAccess) throws CannotCompileException {
972                         String fieldName = fieldAccess.getFieldName().substring(0,1).toUpperCase() + fieldAccess.getFieldName().substring(1);
973                         if (fieldAccess.isReader()) {
974                             // Rewrite read access
975                             fieldAccess.replace("$_ = $0.get" + fieldName + "();");
976                         } else if (fieldAccess.isWriter()) {
977                             // Rewrite write access
978                             fieldAccess.replace("$0.set" + fieldName + "($1);");
979                         }
980                     }});
981         }
982         cc.writeFile();
983         Object obj = make(cc.getName());
984     }
985 
testWhileTrueKO()986     public void testWhileTrueKO() throws Exception {
987         final ClassPool pool = ClassPool.getDefault();
988         final CtClass cc = pool.makeClass("test4.TestWhileTrueKO");
989         String source = "public void testWhile() { while(true) { break; } }";
990         cc.addMethod(CtMethod.make(source, cc));
991         cc.writeFile();
992         make(cc.getName());
993     }
994 
testWhileTrueOK()995     public void testWhileTrueOK() throws Exception {
996         final ClassPool pool = ClassPool.getDefault();
997         final CtClass cc = pool.makeClass("test4.TestWhileTrueOK");
998         String source = "public void testWhile() { while(0==0) { break; }}";
999         cc.addMethod(CtMethod.make(source, cc));
1000         cc.writeFile();
1001         make(cc.getName());
1002     }
1003 
1004     // JIRA JASSIST-224
testMethodParameters()1005     public void testMethodParameters() throws Exception {
1006         Class rc = test4.MethodParamTest.class;
1007         java.lang.reflect.Method m = rc.getDeclaredMethods()[0];
1008         java.lang.reflect.Parameter[] params = m.getParameters();
1009         assertEquals("i", params[0].getName());
1010         assertEquals("s", params[1].getName());
1011 
1012         CtClass cc = sloader.get("test4.MethodParamTest");
1013         ClassFile cf = cc.getClassFile2();
1014         ConstPool cp = cf.getConstPool();
1015         MethodInfo minfo = cf.getMethod("test");
1016         MethodParametersAttribute attr
1017             = (MethodParametersAttribute)minfo.getAttribute(MethodParametersAttribute.tag);
1018         assertEquals(2, attr.size());
1019         assertEquals("i", cp.getUtf8Info(attr.name(0)));
1020         assertEquals("s", cp.getUtf8Info(attr.name(1)));
1021 
1022         attr = (MethodParametersAttribute)attr.copy(cp, null);
1023         assertEquals(2, attr.size());
1024         assertEquals("i", cp.getUtf8Info(attr.name(0)));
1025         assertEquals("s", cp.getUtf8Info(attr.name(1)));
1026     }
1027 
1028     // JIRA JASSIST-220
testStaticInterfaceMethods()1029     public void testStaticInterfaceMethods() throws Exception {
1030         CtClass cc = sloader.get("test4.JIRA220");
1031 
1032         cc.getMethod("foo", "()V").instrument(new ExprEditor() {
1033             @Override
1034             public void edit(MethodCall m) throws CannotCompileException {
1035                 try {
1036                     m.getClassName();
1037                 } catch (Exception e) {
1038                     fail(e.getMessage());
1039                 }
1040             }
1041         });
1042     }
1043 
1044     // JIRA-230
testDeadcode()1045     public void testDeadcode() throws Exception {
1046         CtClass newClass = sloader.makeClass("test4.TestDeadcode");
1047         addDeadCode(newClass, "public void evaluate(){if (false) {int i = 0;}}");
1048         addDeadCode(newClass, "public void evaluate2(){if (false == true) {int i = 0;}}");
1049         addDeadCode(newClass, "public void evaluate3(){if (true) {} else {} int i = 0; if (false) {} else {} i++; }");
1050         addDeadCode(newClass, "public void evaluate4(){ for (;false;); int i = false ? 1 : 0; while (true) { return; }}");
1051         addDeadCode(newClass, "public void evaluate5(){ boolean b = !false; b = false && b; b = true && true;"
1052                             + "  b = true || b; b = b || false; }");
1053         addDeadCode(newClass, "public boolean evaluate6(){ return !false; }");
1054         addDeadCode(newClass, "public boolean evaluate7(){ return !true; }");
1055 
1056         newClass.debugWriteFile();
1057         Class<?> cClass = newClass.toClass(test4.DefineClassCapability.class);
1058         Object o = cClass.getConstructor().newInstance();
1059         java.lang.reflect.Method m = cClass.getMethod("evaluate");
1060         m.invoke(o);
1061         m = cClass.getMethod("evaluate2");
1062         m.invoke(o);
1063         m = cClass.getMethod("evaluate3");
1064         m.invoke(o);
1065         m = cClass.getMethod("evaluate4");
1066         m.invoke(o);
1067         m = cClass.getMethod("evaluate6");
1068         assertTrue((boolean)m.invoke(o));
1069         m = cClass.getMethod("evaluate7");
1070         assertFalse((boolean)m.invoke(o));
1071         m = cClass.getMethod("evaluate5");
1072         m.invoke(o);
1073     }
1074 
addDeadCode(CtClass cc, String meth)1075     private void addDeadCode(CtClass cc, String meth) throws Exception {
1076         CtMethod m = CtNewMethod.make(meth, cc);
1077         cc.addMethod(m);
1078     }
1079 
testAnnArg()1080     public void testAnnArg() throws Exception {
1081         CtClass cc = sloader.get("test4.AnnoArg");
1082         CtMethod m = cc.getDeclaredMethod("foo");
1083         test4.AnnoArg.AnnoArgAt a = (test4.AnnoArg.AnnoArgAt)m.getAnnotations()[0];
1084         assertEquals("test4.AnnoArg$B", a.value().getName());
1085         System.out.println(a.value().getName());
1086     }
1087 
testDeclaredMethods()1088     public void testDeclaredMethods() throws Exception {
1089         CtClass cc = sloader.get("test4.DeclMethodsList");
1090         CtMethod[] meth = cc.getDeclaredMethods("foo");
1091         assertEquals(2, meth.length);
1092         assertEquals("()V", meth[0].getSignature());
1093         assertEquals("(I)I", meth[1].getSignature());
1094         meth = cc.getDeclaredMethods("bar");
1095         assertEquals(1, meth.length);
1096         assertEquals("()V", meth[0].getSignature());
1097         meth = cc.getDeclaredMethods("baz");
1098         assertEquals(0, meth.length);
1099     }
1100 
testAnnotationLoader()1101     public void testAnnotationLoader() throws Exception {
1102         CtClass anno = sloader.makeAnnotation("test4.AnnoLoadAnno");
1103         anno.debugWriteFile();
1104         CtClass cc = sloader.get("test4.AnnoLoad");
1105         CtMethod m = cc.getDeclaredMethod("foo");
1106         ClassFile cf = cc.getClassFile();
1107         ConstPool cp = cf.getConstPool();
1108         AnnotationsAttribute attr
1109             = new AnnotationsAttribute(cp, AnnotationsAttribute.visibleTag);
1110         Annotation a = new Annotation(anno.getName(), cp);
1111         a.addMemberValue("value", new javassist.bytecode.annotation.StringMemberValue("file/path", cp));
1112         attr.setAnnotation(a);
1113         m.getMethodInfo().addAttribute(attr);
1114         cc.writeFile();
1115         anno.toClass(test4.DefineClassCapability.class);
1116         Class<?> rc = ((java.lang.annotation.Annotation)m.getAnnotations()[0]).annotationType();
1117         assertEquals(anno.getName(), rc.getName());
1118     }
1119 }
1120