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