blob: 592416df6d9359f4fcf74352e4a19f0f1f7489c5 [file]
/*
* 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
*
* https://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.generic;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assumptions.assumeFalse;
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.util.SyntheticRepository;
import org.apache.commons.lang3.JavaVersion;
import org.apache.commons.lang3.SystemUtils;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
final class EmptyVisitorTest {
/*
* https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-6.html#jvms-6.2
*/
private static final String RESERVED_OPCODE = "Reserved opcode";
@ParameterizedTest
@ValueSource(strings = {
// @formatter:off
"java.math.BigInteger", // contains instructions [AALOAD, AASTORE, ACONST_NULL, ALOAD, ANEWARRAY, ARETURN, ARRAYLENGTH,
// ASTORE, ATHROW, BALOAD, BASTORE, BIPUSH, CALOAD, CHECKCAST, D2I, DADD, DALOAD, DASTORE, DCONST
// DDIV, DMUL, DRETURN, DSUB, DUP, DUP2, DUP_X2, FCONST, FRETURN, GETFIELD, GETSTATIC, GOTO, I2B,
// I2D, I2L, IADD, IALOAD, IAND, IASTORE, ICONST, IDIV, IFEQ, IFGE, IFGT, IFLE, IFLT, IFNE,
// IFNONNULL, IFNULL, IF_ACMPNE, IF_ICMPEQ, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ICMPLT, IF_ICMPNE,
// IINC, ILOAD, IMUL, INEG, INSTANCEOF, INVOKESPECIAL, INVOKESTATIC, INVOKEVIRTUAL, IOR, IREM,
// IRETURN, ISHL, ISHR, ISTORE, ISUB, IUSHR, IXOR, L2D, L2F, L2I, LADD, LALOAD, LAND, LASTORE, LCMP,
// LCONST, LDC, LDC2_W, LDC_W, LDIV, LLOAD, LMUL, LNEG, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR,
// LSTORE, LSUB, LUSHR, NEW, NEWARRAY, POP, PUTFIELD, PUTSTATIC, RETURN, SIPUSH]
"java.math.BigDecimal", // contains instructions [CASTORE, D2L, DLOAD, FALOAD, FASTORE, FDIV, FMUL, I2S, IF_ACMPEQ, LXOR,
// MONITORENTER, MONITOREXIT, TABLESWITCH]
"java.awt.Color", // contains instructions [D2F, DCMPG, DCMPL, F2D, F2I, FADD, FCMPG, FCMPL, FLOAD, FSTORE, FSUB, I2F,
// INVOKEDYNAMIC]
"java.util.Map", // contains instruction INVOKEINTERFACE
"java.io.Bits", // contains instruction I2C
"java.io.BufferedInputStream", // contains instruction DUP_X1
"java.io.StreamTokenizer", // contains instruction DNEG, DSTORE
"java.lang.Float", // contains instruction F2L
"java.lang.invoke.LambdaForm", // contains instruction MULTIANEWARRAY,
"java.nio.Bits", // contains instruction POP2,
"java.nio.HeapShortBuffer", // contains instruction SALOAD, SASTORE
"Java8Example2", // contains instruction FREM
"java.awt.GradientPaintContext", // contains instruction DREM
"java.util.concurrent.atomic.DoubleAccumulator", // contains instruction DUP2_X1
"java.util.Hashtable", // contains instruction FNEG
"javax.swing.text.html.CSS", // contains instruction DUP2_X2
"org.apache.bcel.generic.LargeJump", // contains instruction GOTO_W
"org.apache.commons.lang.SerializationUtils" // contains instruction JSR
// @formatter:on
})
void test(final String className) throws ClassNotFoundException {
// "java.io.Bits" is not in Java 21.
assumeFalse(SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_21) && className.equals("java.io.Bits"));
final JavaClass javaClass = SyntheticRepository.getInstance().loadClass(className);
for (final Method method : javaClass.getMethods()) {
final Code code = method.getCode();
if (code != null) {
final InstructionList instructionList = new InstructionList(code.getCode());
for (final InstructionHandle instructionHandle : instructionList) {
instructionHandle.accept(new EmptyVisitor() {
@Override
public void visitBREAKPOINT(final BREAKPOINT obj) {
fail(RESERVED_OPCODE);
}
@Override
public void visitIMPDEP1(final IMPDEP1 obj) {
fail(RESERVED_OPCODE);
}
@Override
public void visitIMPDEP2(final IMPDEP2 obj) {
fail(RESERVED_OPCODE);
}
});
}
}
}
}
}