diff options
Diffstat (limited to 'org.jacoco.core.test/src/org/jacoco')
4 files changed, 191 insertions, 1 deletions
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java index 114ebb59..de3ec4d9 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodAnalyzerTest.java @@ -14,6 +14,9 @@ package org.jacoco.core.internal.analysis; import static org.junit.Assert.assertEquals; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; import org.jacoco.core.analysis.ILine; import org.jacoco.core.analysis.IMethodCoverage; @@ -449,7 +452,7 @@ public class MethodAnalyzerTest implements IProbeIdGenerator { assertLine(1002, 0, 1, 0, 0); } - // === Scenario: table switch === + // === Scenario: table switch with and without replace filtering === private void createTableSwitch() { final Label l0 = new Label(); @@ -494,6 +497,41 @@ public class MethodAnalyzerTest implements IProbeIdGenerator { assertEquals(4, nextProbeId); } + private static final IFilter SWITCH_FILTER = new IFilter() { + public void filter(final MethodNode methodNode, + final IFilterContext context, final IFilterOutput output) { + final AbstractInsnNode i = methodNode.instructions.get(3); + assertEquals(Opcodes.TABLESWITCH, i.getOpcode()); + final AbstractInsnNode t1 = methodNode.instructions.get(6); + assertEquals(Opcodes.BIPUSH, t1.getOpcode()); + final AbstractInsnNode t2 = methodNode.instructions.get(13); + assertEquals(Opcodes.BIPUSH, t2.getOpcode()); + + final Set<AbstractInsnNode> newTargets = new HashSet<AbstractInsnNode>(); + newTargets.add(t1); + newTargets.add(t2); + output.replaceBranches(i, newTargets); + } + }; + + @Test + public void table_switch_with_filter_should_show_2_branches_when_original_replaced() { + createTableSwitch(); + runMethodAnalzer(SWITCH_FILTER); + + assertLine(1001, 2, 0, 2, 0); + } + + @Test + public void table_switch_with_filter_should_show_full_branch_coverage_when_new_targets_covered() { + createTableSwitch(); + probes[0] = true; + probes[1] = true; + runMethodAnalzer(SWITCH_FILTER); + + assertLine(1001, 0, 2, 0, 2); + } + @Test public void table_switch_should_show_missed_when_no_probes_are_executed() { createTableSwitch(); diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBase.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBase.java index 50bb59f3..12064123 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBase.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FilterTestBase.java @@ -16,6 +16,7 @@ import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.List; +import java.util.Set; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.MethodNode; @@ -42,6 +43,11 @@ public abstract class FilterTestBase { final AbstractInsnNode i2) { fail(); } + + public void replaceBranches(final AbstractInsnNode source, + final Set<AbstractInsnNode> newTargets) { + fail(); + } }; final void assertIgnored(Range... ranges) { diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FinallyFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FinallyFilterTest.java index 987f3398..843790ec 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FinallyFilterTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/FinallyFilterTest.java @@ -421,4 +421,9 @@ public class FinallyFilterTest implements IFilterOutput { } } + public void replaceBranches(final AbstractInsnNode source, + final Set<AbstractInsnNode> newTargets) { + fail(); + } + } diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchEcjFilterTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchEcjFilterTest.java new file mode 100644 index 00000000..e1bfcb82 --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/StringSwitchEcjFilterTest.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * Copyright (c) 2009, 2018 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: + * Evgeny Mandrikov - initial API and implementation + * + *******************************************************************************/ +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 java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +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.tree.AbstractInsnNode; +import org.objectweb.asm.tree.MethodNode; + +/** + * Unit tests for {@link StringSwitchEcjFilter}. + */ +public class StringSwitchEcjFilterTest { + + private final IFilter filter = new StringSwitchEcjFilter(); + + private final FilterContextMock context = new FilterContextMock(); + + private AbstractInsnNode fromInclusive; + private AbstractInsnNode toInclusive; + + private AbstractInsnNode source; + private Set<AbstractInsnNode> newTargets; + + private final IFilterOutput output = new IFilterOutput() { + public void ignore(final AbstractInsnNode fromInclusive, + final AbstractInsnNode toInclusive) { + assertNull(StringSwitchEcjFilterTest.this.fromInclusive); + StringSwitchEcjFilterTest.this.fromInclusive = fromInclusive; + StringSwitchEcjFilterTest.this.toInclusive = toInclusive; + } + + public void merge(final AbstractInsnNode i1, + final AbstractInsnNode i2) { + fail(); + } + + public void replaceBranches(final AbstractInsnNode source, + final Set<AbstractInsnNode> newTargets) { + assertNull(StringSwitchEcjFilterTest.this.source); + StringSwitchEcjFilterTest.this.source = source; + StringSwitchEcjFilterTest.this.newTargets = newTargets; + } + }; + + @Test + public void should_filter() { + final Set<AbstractInsnNode> expectedNewTargets = new HashSet<AbstractInsnNode>(); + + final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, + "name", "()V", null, null); + + final Label case1 = new Label(); + final Label case2 = new Label(); + final Label case3 = new Label(); + final Label caseDefault = new Label(); + final Label h1 = new Label(); + final Label h2 = new Label(); + + m.visitVarInsn(Opcodes.ALOAD, 1); + + m.visitVarInsn(Opcodes.ASTORE, 2); + m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode", + "()I", false); + m.visitTableSwitchInsn(97, 98, caseDefault, h1, h2); + + m.visitLabel(h1); + final AbstractInsnNode expectedFromInclusive = m.instructions.getLast(); + + m.visitVarInsn(Opcodes.ALOAD, 2); + m.visitLdcInsn("a"); + m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", + "(Ljava/lang/Object;)Z", false); + // if equal "a", then goto its case + m.visitJumpInsn(Opcodes.IFNE, case1); + + m.visitVarInsn(Opcodes.ALOAD, 2); + m.visitLdcInsn("\0a"); + m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", + "(Ljava/lang/Object;)Z", false); + // if equal "\0a", then goto its case + m.visitJumpInsn(Opcodes.IFNE, case2); + + // goto default case + m.visitJumpInsn(Opcodes.GOTO, caseDefault); + + m.visitLabel(h2); + + m.visitVarInsn(Opcodes.ALOAD, 2); + m.visitLdcInsn("b"); + m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", + "(Ljava/lang/Object;)Z", false); + // if equal "b", then goto its case + m.visitJumpInsn(Opcodes.IFNE, case3); + + // goto default case + m.visitJumpInsn(Opcodes.GOTO, caseDefault); + final AbstractInsnNode expectedToInclusive = m.instructions.getLast(); + + m.visitLabel(caseDefault); + m.visitInsn(Opcodes.RETURN); + expectedNewTargets.add(m.instructions.getLast()); + m.visitLabel(case1); + m.visitInsn(Opcodes.RETURN); + expectedNewTargets.add(m.instructions.getLast()); + m.visitLabel(case2); + m.visitInsn(Opcodes.RETURN); + expectedNewTargets.add(m.instructions.getLast()); + m.visitLabel(case3); + m.visitInsn(Opcodes.RETURN); + expectedNewTargets.add(m.instructions.getLast()); + + filter.filter(m, context, output); + + assertEquals(expectedFromInclusive.getPrevious(), source); + assertEquals(expectedNewTargets, newTargets); + assertEquals(expectedFromInclusive, fromInclusive); + assertEquals(expectedToInclusive, toInclusive); + } + +} |