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;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertTrue;
22  
23  import java.io.ByteArrayInputStream;
24  import java.io.ByteArrayOutputStream;
25  import java.io.DataInputStream;
26  import java.io.DataOutputStream;
27  import java.io.IOException;
28  
29  import org.apache.bcel.generic.ClassElementValueGen;
30  import org.apache.bcel.generic.ClassGen;
31  import org.apache.bcel.generic.ConstantPoolGen;
32  import org.apache.bcel.generic.ElementValueGen;
33  import org.apache.bcel.generic.EnumElementValueGen;
34  import org.apache.bcel.generic.ObjectType;
35  import org.apache.bcel.generic.SimpleElementValueGen;
36  import org.junit.jupiter.api.Test;
37  
38  public class ElementValueGenTestCase extends AbstractTestCase {
39      private void checkSerialize(final ElementValueGen evgBefore, final ConstantPoolGen cpg) throws IOException {
40          final String beforeValue = evgBefore.stringifyValue();
41          final ByteArrayOutputStream baos = new ByteArrayOutputStream();
42          try (DataOutputStream dos = new DataOutputStream(baos)) {
43              evgBefore.dump(dos);
44              dos.flush();
45          }
46          ElementValueGen evgAfter;
47          try (DataInputStream dis = new DataInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
48              evgAfter = ElementValueGen.readElementValue(dis, cpg);
49          }
50          final String afterValue = evgAfter.stringifyValue();
51          assertEquals(beforeValue, afterValue, "Deserialization failed");
52      }
53  
54      private ClassGen createClassGen(final String className) {
55          return new ClassGen(className, "java.lang.Object", "<generated>", Const.ACC_PUBLIC | Const.ACC_SUPER, null);
56      }
57  
58      @Test
59      public void testCreateBooleanElementValue() throws Exception {
60          final ClassGen cg = createClassGen("HelloWorld");
61          final ConstantPoolGen cp = cg.getConstantPool();
62          final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_BOOLEAN, cp, true);
63          // Creation of an element like that should leave a new entry in the
64          // cpool
65          final int idx = cp.lookupInteger(1); // 1 == true
66          assertEquals(idx, evg.getIndex(), "Should have the same index in the constantpool");
67          checkSerialize(evg, cp);
68      }
69  
70      @Test
71      public void testCreateByteElementValue() throws Exception {
72          final ClassGen cg = createClassGen("HelloWorld");
73          final ConstantPoolGen cp = cg.getConstantPool();
74          final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_BYTE, cp, (byte) 'z');
75          // Creation of an element like that should leave a new entry in the
76          // cpool
77          final int idx = cp.lookupInteger((byte) 'z');
78          assertEquals(idx, evg.getIndex(), "Should have the same index in the constantpool");
79          checkSerialize(evg, cp);
80      }
81  
82      @Test
83      public void testCreateCharElementValue() throws Exception {
84          final ClassGen cg = createClassGen("HelloWorld");
85          final ConstantPoolGen cp = cg.getConstantPool();
86          final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_CHAR, cp, 't');
87          // Creation of an element like that should leave a new entry in the
88          // cpool
89          final int idx = cp.lookupInteger('t');
90          assertEquals(idx, evg.getIndex(), "Should have the same index in the constantpool");
91          checkSerialize(evg, cp);
92      }
93  
94      // //
95      // Create class element value
96      @Test
97      public void testCreateClassElementValue() throws Exception {
98          final ClassGen cg = createClassGen("HelloWorld");
99          final ConstantPoolGen cp = cg.getConstantPool();
100         final ObjectType classType = new ObjectType("java.lang.Integer");
101         final ClassElementValueGen evg = new ClassElementValueGen(classType, cp);
102         assertTrue(evg.getClassString().contains("Integer"), "Unexpected value for contained class: '" + evg.getClassString() + "'");
103         checkSerialize(evg, cp);
104     }
105 
106     @Test
107     public void testCreateDoubleElementValue() throws Exception {
108         final ClassGen cg = createClassGen("HelloWorld");
109         final ConstantPoolGen cp = cg.getConstantPool();
110         final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_DOUBLE, cp, 333.44);
111         // Creation of an element like that should leave a new entry in the
112         // cpool
113         final int idx = cp.lookupDouble(333.44);
114         assertEquals(idx, evg.getIndex(), "Should have the same index in the constantpool");
115         checkSerialize(evg, cp);
116     }
117 
118     // //
119     // Create enum element value
120     @Test
121     public void testCreateEnumElementValue() throws Exception {
122         final ClassGen cg = createClassGen("HelloWorld");
123         final ConstantPoolGen cp = cg.getConstantPool();
124         final ObjectType enumType = new ObjectType("SimpleEnum"); // Supports rainbow
125         // :)
126         final EnumElementValueGen evg = new EnumElementValueGen(enumType, "Red", cp);
127         // Creation of an element like that should leave a new entry in the
128         // cpool
129         assertEquals(cp.lookupUtf8("Red"), evg.getValueIndex(), "The new ElementValue value index should match the contents of the constantpool");
130         // BCELBUG: Should the class signature or class name be in the constant
131         // pool? (see note in ConstantPool)
132         // assertTrue("The new ElementValue type index should match the contents
133         // of the constantpool but "+
134         // evg.getTypeIndex()+"!="+cp.lookupClass(enumType.getSignature()),
135         // evg.getTypeIndex()==cp.lookupClass(enumType.getSignature()));
136         checkSerialize(evg, cp);
137     }
138 
139     @Test
140     public void testCreateFloatElementValue() throws Exception {
141         final ClassGen cg = createClassGen("HelloWorld");
142         final ConstantPoolGen cp = cg.getConstantPool();
143         final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_FLOAT, cp, 111.222f);
144         // Creation of an element like that should leave a new entry in the
145         // cpool
146         assertEquals(cp.lookupFloat(111.222f), evg.getIndex(), "Should have the same index in the constantpool");
147         checkSerialize(evg, cp);
148     }
149 
150     /**
151      * Create primitive element values
152      */
153     @Test
154     public void testCreateIntegerElementValue() throws Exception {
155         final ClassGen cg = createClassGen("HelloWorld");
156         final ConstantPoolGen cp = cg.getConstantPool();
157         final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_INT, cp, 555);
158         // Creation of an element like that should leave a new entry in the
159         // cpool
160         assertEquals(cp.lookupInteger(555), evg.getIndex(), "Should have the same index in the constantpool");
161         checkSerialize(evg, cp);
162     }
163 
164     @Test
165     public void testCreateLongElementValue() throws Exception {
166         final ClassGen cg = createClassGen("HelloWorld");
167         final ConstantPoolGen cp = cg.getConstantPool();
168         final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_LONG, cp, 3334455L);
169         // Creation of an element like that should leave a new entry in the
170         // cpool
171         final int idx = cp.lookupLong(3334455L);
172         assertEquals(idx, evg.getIndex(), "Should have the same index in the constantpool");
173         checkSerialize(evg, cp);
174     }
175 
176     @Test
177     public void testCreateShortElementValue() throws Exception {
178         final ClassGen cg = createClassGen("HelloWorld");
179         final ConstantPoolGen cp = cg.getConstantPool();
180         final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.PRIMITIVE_SHORT, cp, (short) 42);
181         // Creation of an element like that should leave a new entry in the
182         // cpool
183         final int idx = cp.lookupInteger(42);
184         assertEquals(idx, evg.getIndex(), "Should have the same index in the constantpool");
185         checkSerialize(evg, cp);
186     }
187 
188     // //
189     // Create string element values
190     @Test
191     public void testCreateStringElementValue() throws Exception {
192         // Create HelloWorld
193         final ClassGen cg = createClassGen("HelloWorld");
194         final ConstantPoolGen cp = cg.getConstantPool();
195         final SimpleElementValueGen evg = new SimpleElementValueGen(ElementValueGen.STRING, cp, "hello");
196         // Creation of an element like that should leave a new entry in the
197         // cpool
198         assertEquals(cp.lookupUtf8("hello"), evg.getIndex(), "Should have the same index in the constantpool");
199         checkSerialize(evg, cp);
200     }
201 }