View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.apache.bcel.generic;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertFalse;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertNull;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  import static org.junit.jupiter.api.Assertions.fail;
27  
28  import java.util.Arrays;
29  import java.util.List;
30  
31  import org.apache.bcel.Repository;
32  import org.apache.bcel.classfile.JavaClass;
33  import org.apache.bcel.classfile.Method;
34  import org.junit.jupiter.api.Test;
35  
36  public class MethodGenTestCase {
37  
38      @interface A {
39      }
40  
41      @interface B {
42      }
43  
44      public static class Bar {
45          public class Inner {
46              public Inner(@A final Object a, @B final Object b) {
47  
48              }
49          }
50      }
51  
52      public static class Foo {
53          public void bar() {
54              @SuppressWarnings("unused")
55              final int a = 1;
56          }
57      }
58  
59      private MethodGen getMethod(final Class<?> cls, final String name) throws ClassNotFoundException {
60          final JavaClass jc = Repository.lookupClass(cls);
61          final ConstantPoolGen cp = new ConstantPoolGen(jc.getConstantPool());
62          for (final Method method : jc.getMethods()) {
63              if (method.getName().equals(name)) {
64                  return new MethodGen(method, jc.getClassName(), cp);
65              }
66          }
67  
68          fail(() -> "Method " + name + " not found in class " + cls);
69          return null;
70      }
71  
72      @Test
73      public void testAnnotationsAreUnpacked() throws Exception {
74          final JavaClass jc = Repository.lookupClass(Bar.Inner.class);
75          final ClassGen cg = new ClassGen(jc);
76          final MethodGen mg = new MethodGen(cg.getMethodAt(0), cg.getClassName(), cg.getConstantPool());
77          final List<AnnotationEntryGen> firstParamAnnotations = mg.getAnnotationsOnParameter(0);
78          assertEquals(1, firstParamAnnotations.size(), "Wrong number of annotations in the first parameter");
79          final List<AnnotationEntryGen> secondParamAnnotations = mg.getAnnotationsOnParameter(1);
80          assertEquals(1, secondParamAnnotations.size(), "Wrong number of annotations in the second parameter");
81      }
82  
83      private void testInvalidNullMethodBody(final String className) throws ClassNotFoundException {
84          final JavaClass jc = Repository.lookupClass(className);
85          final ClassGen classGen = new ClassGen(jc);
86          for (final Method method : jc.getMethods()) {
87              new MethodGen(method, jc.getClassName(), classGen.getConstantPool());
88          }
89      }
90  
91      @Test
92      public void testInvalidNullMethodBody_EmptyStaticInit() throws Exception {
93          testInvalidNullMethodBody("org.apache.bcel.generic.EmptyStaticInit");
94      }
95  
96      @Test
97      public void testInvalidNullMethodBody_MailDateFormat() {
98          assertThrows(IllegalStateException.class, () -> testInvalidNullMethodBody("javax.mail.internet.MailDateFormat"));
99      }
100 
101     @Test
102     public void testRemoveLocalVariable() throws Exception {
103         final MethodGen mg = getMethod(Foo.class, "bar");
104 
105         final LocalVariableGen lv = mg.getLocalVariables()[1];
106         assertEquals("a", lv.getName(), "variable name");
107         final InstructionHandle start = lv.getStart();
108         final InstructionHandle end = lv.getEnd();
109         assertNotNull(start, "scope start");
110         assertNotNull(end, "scope end");
111         assertTrue(Arrays.asList(start.getTargeters()).contains(lv), "scope start not targeted by the local variable");
112         assertTrue(Arrays.asList(end.getTargeters()).contains(lv), "scope end not targeted by the local variable");
113 
114         // now let's remove the local variable
115         mg.removeLocalVariable(lv);
116 
117         assertFalse(Arrays.asList(start.getTargeters()).contains(lv), "scope start still targeted by the removed variable");
118         assertFalse(Arrays.asList(end.getTargeters()).contains(lv), "scope end still targeted by the removed variable");
119         assertNull(lv.getStart(), "scope start");
120         assertNull(lv.getEnd(), "scope end");
121     }
122 
123     @Test
124     public void testRemoveLocalVariables() throws Exception {
125         final MethodGen mg = getMethod(Foo.class, "bar");
126 
127         final LocalVariableGen lv = mg.getLocalVariables()[1];
128         assertEquals("a", lv.getName(), "variable name");
129         final InstructionHandle start = lv.getStart();
130         final InstructionHandle end = lv.getEnd();
131         assertNotNull(start, "scope start");
132         assertNotNull(end, "scope end");
133         assertTrue(Arrays.asList(start.getTargeters()).contains(lv), "scope start not targeted by the local variable");
134         assertTrue(Arrays.asList(end.getTargeters()).contains(lv), "scope end not targeted by the local variable");
135 
136         // now let's remove the local variables
137         mg.removeLocalVariables();
138 
139         assertFalse(Arrays.asList(start.getTargeters()).contains(lv), "scope start still targeted by the removed variable");
140         assertFalse(Arrays.asList(end.getTargeters()).contains(lv), "scope end still targeted by the removed variable");
141         assertNull(lv.getStart(), "scope start");
142         assertNull(lv.getEnd(), "scope end");
143     }
144 }