blob: edb2b0e340a0529a530bb3db3dc78fc4350493cf [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.bcel;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.util.stream.Stream;
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.LineNumber;
import org.apache.bcel.classfile.LineNumberTable;
import org.apache.bcel.classfile.LocalVariable;
import org.apache.bcel.classfile.LocalVariableTable;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.classfile.Utility;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.InvokeInstruction;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.Type;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
public class PLSETestCase extends AbstractTestCase {
/**
* BCEL-208: A couple of methods in MethodGen.java need to test for an empty instruction list.
*/
@Test
public void testBCEL208() throws ClassNotFoundException {
final JavaClass clazz = getTestJavaClass(PACKAGE_BASE_NAME + ".data.PLSETestClass");
final ClassGen gen = new ClassGen(clazz);
final ConstantPoolGen pool = gen.getConstantPool();
final Method m = gen.getMethodAt(1);
final MethodGen mg = new MethodGen(m, gen.getClassName(), pool);
mg.setInstructionList(null);
mg.addLocalVariable("local2", Type.INT, null, null);
// currently, this will cause null pointer exception
mg.getLocalVariableTable(pool);
}
/**
* BCEL-262:
*/
@Test
public void testBCEL262() throws ClassNotFoundException {
final JavaClass clazz = getTestJavaClass(PACKAGE_BASE_NAME + ".data.PLSETestEnum");
final ClassGen gen = new ClassGen(clazz);
final ConstantPoolGen pool = gen.getConstantPool();
// get the values() method
final Method m = gen.getMethodAt(0);
final MethodGen mg = new MethodGen(m, gen.getClassName(), pool);
final InstructionList il = mg.getInstructionList();
// get the invokevirtual instruction
final InstructionHandle ih = il.findHandle(3);
final InvokeInstruction ii = (InvokeInstruction) ih.getInstruction();
// without fix, the getClassName() will throw:
// java.lang.IllegalArgumentException: Cannot be used on an array type
final String cn = ii.getClassName(pool);
assertEquals("[Lorg.apache.bcel.data.PLSETestEnum;", cn);
}
/**
* BCEL-295:
*/
@Test
public void testBCEL295() throws Exception {
final JavaClass clazz = getTestJavaClass(PACKAGE_BASE_NAME + ".data.PLSETestClass2");
final ClassGen cg = new ClassGen(clazz);
final ConstantPoolGen pool = cg.getConstantPool();
final Method m = cg.getMethodAt(1); // 'main'
final LocalVariableTable lvt = m.getLocalVariableTable();
final LocalVariable lv = lvt.getLocalVariable(2, 4); // 'i'
// System.out.println(lv);
final MethodGen mg = new MethodGen(m, cg.getClassName(), pool);
final LocalVariableTable newLvt = mg.getLocalVariableTable(mg.getConstantPool());
final LocalVariable newLv = newLvt.getLocalVariable(2, 4); // 'i'
// System.out.println(new_lv);
assertEquals(lv.getLength(), newLv.getLength(), "live range length");
}
/**
* BCEL-361: LineNumber.toString() treats code offset as signed
*/
@Test
public void testBCEL361() throws Exception {
final JavaClass clazz = getTestJavaClass(PACKAGE_BASE_NAME + ".data.LargeMethod");
final Method[] methods = clazz.getMethods();
final Method m = methods[0];
// System.out.println(m.getName());
final Code code = m.getCode();
final LineNumberTable lnt = code.getLineNumberTable();
final LineNumber[] lineNumbers = lnt.getLineNumberTable();
final String data = lineNumbers[lineNumbers.length - 1].toString();
// System.out.println(data);
// System.out.println(data.contains("-"));
assertFalse(data.contains("-"), "code offsets must be positive");
Stream.of(lineNumbers).forEach(ln -> assertFalse(ln.getLineNumber() < 0));
Stream.of(lineNumbers).forEach(ln -> assertFalse(ln.getStartPC() < 0));
}
/**
* BCEL-79:
*/
@Test
public void testBCEL79() throws ClassNotFoundException {
final JavaClass clazz = getTestJavaClass(PACKAGE_BASE_NAME + ".data.PLSETestClass");
final ClassGen gen = new ClassGen(clazz);
final ConstantPoolGen pool = gen.getConstantPool();
final Method m = gen.getMethodAt(2);
final LocalVariableTable lvt = m.getLocalVariableTable();
// System.out.println(lvt);
// System.out.println(lvt.getTableLength());
final MethodGen mg = new MethodGen(m, gen.getClassName(), pool);
final LocalVariableTable newLvt = mg.getLocalVariableTable(mg.getConstantPool());
// System.out.println(new_lvt);
assertEquals(lvt.getTableLength(), newLvt.getTableLength(), "number of locals");
}
/**
* Test to improve BCEL tests code coverage for classfile/Utility.java.
*/
@ParameterizedTest
@ValueSource(booleans = { true, false })
public void testCoverage(final boolean compress) throws ClassNotFoundException, java.io.IOException {
// load a class with a wide variety of byte codes - including tableswitch and lookupswitch
final JavaClass clazz = getTestJavaClass(PACKAGE_BASE_NAME + ".data.ConstantPoolX");
for (final Method m : clazz.getMethods()) {
final String signature = m.getSignature();
Utility.methodTypeToSignature(Utility.methodSignatureReturnType(signature), Utility.methodSignatureArgumentTypes(signature)); // discard result
final Code code = m.getCode();
if (code != null) {
// TODO: need for real assertions here
final String encoded = Utility.encode(code.getCode(), compress);
assertNotNull(encoded);
// following statement will throw exeception without classfile/Utility.encode fix
assertNotNull(Utility.decode(encoded, compress));
assertNotNull(code.toString());
}
}
}
}