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