Skip to content

Commit

Permalink
Add filter for assert statement
Browse files Browse the repository at this point in the history
  • Loading branch information
bjkail committed Oct 18, 2017
1 parent ec6287a commit 2c80983
Show file tree
Hide file tree
Showing 7 changed files with 384 additions and 4 deletions.
@@ -0,0 +1,124 @@
/*******************************************************************************
* Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*
*******************************************************************************/
package org.jacoco.core.internal.analysis.filter;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;

import org.jacoco.core.internal.instr.InstrSupport;
import org.junit.Test;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.MethodNode;

public class AssertFilterTest implements IFilterOutput {

private final IFilter filter = new AssertFilter();

private AbstractInsnNode fromInclusive;
private AbstractInsnNode toInclusive;

@Test
public void should_filter_initialize() {
final Label disable = new Label();
final Label init = new Label();

final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
"<clinit>", "()V", null, null);
m.visitLdcInsn(Type.getObjectType("p/C"));
final AbstractInsnNode fromInclusive = m.instructions.getLast();

m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class",
"desiredAssertionStatus", "()Z", false);
m.visitJumpInsn(Opcodes.IFNE, disable);
m.visitInsn(Opcodes.ICONST_1);
m.visitJumpInsn(Opcodes.GOTO, init);

m.visitLabel(disable);
m.visitInsn(Opcodes.ICONST_0);

m.visitLabel(init);
m.visitFieldInsn(Opcodes.PUTSTATIC, "p/C", "$assertionsDisabled", "Z");
final AbstractInsnNode toInclusive = m.instructions.getLast();

filter.filter("p/C", "java/lang/Object", m, this);
assertEquals(fromInclusive, this.fromInclusive);
assertEquals(toInclusive, this.toInclusive);
}

@Test
public void should_filter_assert() {
final Label disabled = new Label();

final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
"m", "(Z)V", null, null);
m.visitFieldInsn(Opcodes.GETSTATIC, "p/C", "$assertionsDisabled", "Z");
final AbstractInsnNode fromInclusive = m.instructions.getLast();

m.visitJumpInsn(Opcodes.IFNE, disabled);
final AbstractInsnNode toInclusive = m.instructions.getLast();

m.visitVarInsn(Opcodes.ILOAD, 1);
m.visitJumpInsn(Opcodes.IFNE, disabled);
m.visitTypeInsn(Opcodes.NEW, "java/lang/AssertionError");
m.visitInsn(Opcodes.DUP);
m.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/AssertionError",
"<init>", "()V", false);
m.visitInsn(Opcodes.ATHROW);
m.visitLabel(disabled);

filter.filter("p/C", "java/lang/Object", m, this);
assertEquals(fromInclusive, this.fromInclusive);
assertEquals(toInclusive, this.toInclusive);
}

@Test
public void should_filter_assert_message() {
final Label disabled = new Label();

final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0,
"m", "(Z)V", null, null);
m.visitFieldInsn(Opcodes.GETSTATIC, "p/C", "$assertionsDisabled", "Z");
final AbstractInsnNode fromInclusive = m.instructions.getLast();

m.visitJumpInsn(Opcodes.IFNE, disabled);
final AbstractInsnNode toInclusive = m.instructions.getLast();

m.visitVarInsn(Opcodes.ILOAD, 1);
m.visitJumpInsn(Opcodes.IFNE, disabled);
m.visitTypeInsn(Opcodes.NEW, "java/lang/AssertionError");
m.visitInsn(Opcodes.DUP);
m.visitLdcInsn("m");
m.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/AssertionError",
"<init>", "(Ljava/lang/Object;)V", false);
m.visitInsn(Opcodes.ATHROW);
m.visitLabel(disabled);

filter.filter("p/C", "java/lang/Object", m, this);
assertEquals(fromInclusive, this.fromInclusive);
assertEquals(toInclusive, this.toInclusive);
}

public void ignore(final AbstractInsnNode fromInclusive,
final AbstractInsnNode toInclusive) {
assertNull(this.fromInclusive);
this.fromInclusive = fromInclusive;
this.toInclusive = toInclusive;
}

public void merge(final AbstractInsnNode i1, final AbstractInsnNode i2) {
fail();
}

}
@@ -0,0 +1,58 @@
/*******************************************************************************
* Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*
*******************************************************************************/
package org.jacoco.core.test.filter;

import org.jacoco.core.analysis.ICounter;
import org.jacoco.core.test.filter.targets.Assert;
import org.jacoco.core.test.validation.ValidationTestBase;
import org.junit.Test;

/**
* Test of filtering of a bytecode that is generated for an assert statement.
*/
public class AssertTest extends ValidationTestBase {

public AssertTest() {
super(Assert.class);
}

/**
* {@link Assert}
*/
@Test
public void clinit() {
assertMethod("<clinit>", ICounter.FULLY_COVERED);
}

/**
* {@link Assert#simple()}
*/
@Test
public void simple() {
assertLine("simple", ICounter.PARTLY_COVERED, 1, 1, 4, 2);
}

/**
* {@link Assert#message()}
*/
@Test
public void message() {
assertLine("message", ICounter.PARTLY_COVERED, 1, 1, 5, 2);
}

/**
* {@link Assert.SimpleClinit}
*/
@Test
public void clinit_simple() {
assertLine("clinit", ICounter.PARTLY_COVERED, 1, 1, 4, 2);
}
}
@@ -0,0 +1,40 @@
/*******************************************************************************
* Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*
*******************************************************************************/
package org.jacoco.core.test.filter.targets;

public class Assert {

public static boolean b = true;

public static void simple() {
assert b; // $line-simple$
}

public static void message() {
assert b : "m"; // $line-message$
}

public static class SimpleClinit {
static {
assert b; // $line-clinit$
}

public static void init() {
}
}

public static void main(String[] args) {
simple();
message();
SimpleClinit.init();
}

}
Expand Up @@ -12,6 +12,7 @@
package org.jacoco.core.test.validation;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;

import java.io.IOException;
Expand All @@ -20,8 +21,10 @@

import org.jacoco.core.analysis.Analyzer;
import org.jacoco.core.analysis.CoverageBuilder;
import org.jacoco.core.analysis.IClassCoverage;
import org.jacoco.core.analysis.ICounter;
import org.jacoco.core.analysis.ILine;
import org.jacoco.core.analysis.IMethodCoverage;
import org.jacoco.core.analysis.ISourceFileCoverage;
import org.jacoco.core.data.ExecutionData;
import org.jacoco.core.data.ExecutionDataStore;
Expand Down Expand Up @@ -54,6 +57,8 @@ public abstract class ValidationTestBase {

private ISourceFileCoverage sourceCoverage;

private IClassCoverage classCoverage;

private Source source;

private InstrumentingLoader loader;
Expand All @@ -76,6 +81,7 @@ public void setup() throws Exception {

private ExecutionDataStore execute() throws Exception {
loader = new InstrumentingLoader(target);
loader.setDefaultAssertionStatus(true);
run(loader.loadClass(target.getName()));
return loader.collect();
}
Expand All @@ -92,14 +98,23 @@ private void analyze(final ExecutionDataStore store) throws IOException {
analyze(analyzer, data);
}

String srcName = target.getName().replace('.', '/') + ".java";
String name = target.getName().replace('.', '/');
String srcName = name + ".java";
for (ISourceFileCoverage file : builder.getSourceFiles()) {
if (srcName.equals(file.getPackageName() + "/" + file.getName())) {
sourceCoverage = file;
return;
break;
}
}
assertNotNull("No source node for " + name, sourceCoverage);

for (IClassCoverage c : builder.getClasses()) {
if (c.getName().equals(name)) {
classCoverage = c;
break;
}
}
fail("No source node found for " + srcName);
assertNotNull("No class node for " + name, classCoverage);
}

private void analyze(final Analyzer analyzer, final ExecutionData data)
Expand All @@ -114,6 +129,18 @@ protected void assertMethodCount(final int expectedTotal) {
sourceCoverage.getMethodCounter().getTotalCount());
}

protected void assertMethod(final String name, final int status) {
for (IMethodCoverage method : classCoverage.getMethods()) {
if (method.getName().equals(name)) {
int methodStatus = method.getInstructionCounter().getStatus();
assertEquals("Instruction status in method " + name,
STATUS_NAME[status], STATUS_NAME[methodStatus]);
return;
}
}
fail("No method node for " + name);
}

protected void assertLine(final String tag, final int status) {
final int nr = source.getLineNumber(tag);
final ILine line = sourceCoverage.getLine(nr);
Expand All @@ -135,6 +162,19 @@ protected void assertLine(final String tag, final int status,
line.getBranchCounter());
}

protected void assertLine(final String tag, final int status,
final int missedBranches, final int coveredBranches,
final int missedInstructions, final int coveredInstructions) {
assertLine(tag, status, missedBranches, coveredBranches);
final int nr = source.getLineNumber(tag);
final ILine line = sourceCoverage.getLine(nr);
final String msg = String.format("Instructions in line %s: %s",
Integer.valueOf(nr), source.getLine(nr));
assertEquals(msg + " branches", CounterImpl
.getInstance(missedInstructions, coveredInstructions),
line.getInstructionCounter());
}

protected void assertLogEvents(String... events) throws Exception {
final Method getter = Class.forName(Stubs.class.getName(), false,
loader).getMethod("getLogEvents");
Expand Down

0 comments on commit 2c80983

Please sign in to comment.