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