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