This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-bcel.git
The following commit(s) were added to refs/heads/master by this push: new 158b7c17 Verifier: test and coverage for SWAP instruction (#188) 158b7c17 is described below commit 158b7c1702484196cc00aa07cdf58462a7fb51d3 Author: nbauma109 <nbauma...@users.noreply.github.com> AuthorDate: Thu Dec 29 20:48:04 2022 +0100 Verifier: test and coverage for SWAP instruction (#188) * added test for SWAP instruction * SWAP: added new line at EOF * use class extension org/apache/bcel/data/SWAP.class * added comments to pom * added comments to test input and check for SWAP in compiled class Co-authored-by: nbauma109 <nbauma...@github.com> --- pom.xml | 7 ++ src/test/java/org/apache/bcel/data/SWAP.java | 37 +++++++++ .../apache/bcel/verifier/VerifierMainTestCase.java | 93 ++++++++++++++++++++++ 3 files changed, 137 insertions(+) diff --git a/pom.xml b/pom.xml index 2f1da017..82ebf15e 100644 --- a/pom.xml +++ b/pom.xml @@ -514,6 +514,13 @@ <scope>test</scope> </dependency> <!-- END very old jars for Justice verifier --> + <dependency> + <!-- Eclipse compiler: useful to generate specific .class file patterns --> + <groupId>org.eclipse.jdt</groupId> + <artifactId>ecj</artifactId> + <version>3.26.0</version> <!-- last JDK8-compatible version --> + <scope>test</scope> + </dependency> </dependencies> <profiles> diff --git a/src/test/java/org/apache/bcel/data/SWAP.java b/src/test/java/org/apache/bcel/data/SWAP.java new file mode 100644 index 00000000..81a291e2 --- /dev/null +++ b/src/test/java/org/apache/bcel/data/SWAP.java @@ -0,0 +1,37 @@ +/* + * 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.data; + +import java.lang.reflect.Constructor; + +/* + * A test for SWAP instruction. + * To be compiled with Eclipse Compiler (ecj) with source/target 1.4. + * This is a requirement for SWAP instruction to be generated. + * If compiled with javac source/target 1.1+ or ecj source/target 1.5+, no SWAP instruction is generated. + */ +public class SWAP { + public static Constructor getTestConstructor(final Class theClass) throws NoSuchMethodException { + final Class[] args = { String.class }; + try { + return theClass.getConstructor(args); + } catch (final NoSuchMethodException e) { + } + return theClass.getConstructor(new Class[0]); + } +} diff --git a/src/test/java/org/apache/bcel/verifier/VerifierMainTestCase.java b/src/test/java/org/apache/bcel/verifier/VerifierMainTestCase.java new file mode 100644 index 00000000..a1ea219e --- /dev/null +++ b/src/test/java/org/apache/bcel/verifier/VerifierMainTestCase.java @@ -0,0 +1,93 @@ +/* + * 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.verifier; + +import org.apache.bcel.AbstractTestCase; +import org.apache.bcel.classfile.ClassParser; +import org.apache.bcel.classfile.JavaClass; +import org.apache.bcel.classfile.Method; +import org.apache.bcel.generic.EmptyVisitor; +import org.apache.bcel.generic.InstructionHandle; +import org.apache.bcel.generic.InstructionList; +import org.apache.bcel.generic.SWAP; +import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.internal.compiler.batch.Main; +import org.junit.jupiter.api.Test; + +import java.io.BufferedInputStream; +import java.io.InputStream; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class VerifierMainTestCase extends AbstractTestCase { + + @Test + public void testSWAP() throws Exception { + final String[] argv = new String[] { "src/test/java/org/apache/bcel/data/SWAP.java", "-g", "-source", "1.4", "-target", "1.4", "-d", "target/test-classes" }; + new Main(new PrintWriter(System.out), new PrintWriter(System.err), false/*systemExit*/, null/*options*/, null/*progress*/).compile(argv); + final String javaAgent = getJavaAgent(); + final List<String> args = new ArrayList<>(); + args.add("java"); + if (javaAgent != null) { + args.add(javaAgent.replace("jacoco.exec", "jacoco_org.apache.bcel.data.SWAP.exec")); + } + args.add("-cp"); + args.add(System.getProperty("java.class.path")); + args.add("org.apache.bcel.verifier.Verifier"); + args.add("org/apache/bcel/data/SWAP.class"); + final ProcessBuilder pb = new ProcessBuilder(args); + pb.redirectErrorStream(true); + final Process p = pb.start(); + try (BufferedInputStream is = new BufferedInputStream(p.getInputStream())) { + final byte[] buff = new byte[2048]; + final StringBuilder sb = new StringBuilder(); + for (int len; (len = is.read(buff)) != -1;) { + sb.append(new String(buff, 0, len)); + } + final String output = sb.toString(); + assertEquals(0, p.waitFor(), output); + assertEquals(0, StringUtils.countMatches(output, "VERIFIED_REJECTED"), output); + assertEquals(6, StringUtils.countMatches(output, "VERIFIED_OK"), output); + } + // Class has passed the JustIce verifier, but now we need to ensure that the SWAP instruction is in the compiled class. + final List<SWAP> swapInstructionsList = new ArrayList<>(); + final EmptyVisitor swapCollector = new EmptyVisitor() { + @Override + public void visitSWAP(final SWAP obj) { + swapInstructionsList.add(obj); + super.visitSWAP(obj); + } + }; + try (InputStream in = Files.newInputStream(Paths.get("target/test-classes/org/apache/bcel/data/SWAP.class"))) { + final ClassParser classParser = new ClassParser(in, "SWAP.class"); + final JavaClass javaClass = classParser.parse(); + final Method method = javaClass.getMethod(org.apache.bcel.data.SWAP.class.getMethod("getTestConstructor", Class.class)); + final byte[] code = method.getCode().getCode(); + final InstructionList instructionList = new InstructionList(code); + for (final InstructionHandle instructionHandle : instructionList) { + instructionHandle.accept(swapCollector); + } + } + assertEquals(1, swapInstructionsList.size()); + } +}