From 4d4d02e6dbfb17f454bf4579ee13209e9f035154 Mon Sep 17 00:00:00 2001 From: "Marc R. Hoffmann" Date: Thu, 15 Nov 2018 00:39:53 +0100 Subject: Refactor coverage analysis package (#744) * Encapsulate insn/branch status tracking in Instruction * Move Instruction to the analysis package * Encapsulate Instruction building in new class InstructionsBuilder * Separate coverage calculation from filtering --- .../core/internal/analysis/InstructionTest.java | 173 ++++++++++++++++ .../internal/analysis/InstructionsBuilderTest.java | 189 +++++++++++++++++ .../core/internal/analysis/MethodAnalyzerTest.java | 13 +- .../analysis/MethodCoverageCalculatorTest.java | 224 +++++++++++++++++++++ .../jacoco/core/internal/flow/InstructionTest.java | 124 ------------ .../jacoco/core/internal/flow/LabelInfoTest.java | 6 +- 6 files changed, 598 insertions(+), 131 deletions(-) create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionTest.java create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionsBuilderTest.java create mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageCalculatorTest.java delete mode 100644 org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java (limited to 'org.jacoco.core.test/src/org') diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionTest.java new file mode 100644 index 00000000..ec740e80 --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionTest.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * 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: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.core.internal.analysis; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; + +import org.junit.Before; +import org.junit.Test; + +/** + * Unit tests for {@link Instruction}. + */ +public class InstructionTest { + + private Instruction instruction; + + @Before + public void setup() { + instruction = new Instruction(123); + } + + @Test + public void getLine_should_return_line_number() { + assertEquals(123, instruction.getLine()); + } + + @Test + public void new_instance_should_have_no_coverage_and_no_branches() { + assertEquals(CounterImpl.COUNTER_1_0, + instruction.getInstructionCounter()); + assertEquals(CounterImpl.COUNTER_0_0, instruction.getBranchCounter()); + } + + @Test + public void addBranchWithInstruction_should_not_increment_branches_when_only_one_branch_is_added() { + instruction.addBranch(new Instruction(122), 0); + + assertEquals(CounterImpl.COUNTER_0_0, instruction.getBranchCounter()); + } + + @Test + public void addBranchWithInstruction_should_increment_branches_when_two_branches_are_added() { + instruction.addBranch(new Instruction(122), 0); + instruction.addBranch(new Instruction(123), 1); + + assertEquals(CounterImpl.getInstance(2, 0), + instruction.getBranchCounter()); + } + + @Test + public void addBranchWithInstruction_should_propagate_existing_coverage_status() { + final Instruction target = new Instruction(122); + target.addBranch(true, 0); + + instruction.addBranch(target, 0); + + assertEquals(CounterImpl.COUNTER_0_1, + instruction.getInstructionCounter()); + } + + @Test + public void addBranchWithProbe_should_increment_branches_when_covered() { + instruction.addBranch(true, 0); + instruction.addBranch(true, 1); + + assertEquals(CounterImpl.getInstance(0, 1), + instruction.getInstructionCounter()); + assertEquals(CounterImpl.getInstance(0, 2), + instruction.getBranchCounter()); + } + + @Test + public void addBranchWithProbe_should_increment_branches_when_not_covered() { + instruction.addBranch(false, 0); + instruction.addBranch(false, 1); + + assertEquals(CounterImpl.getInstance(1, 0), + instruction.getInstructionCounter()); + assertEquals(CounterImpl.getInstance(2, 0), + instruction.getBranchCounter()); + } + + @Test + public void addBranchWithProbe_should_increment_branches_when_partly_covered() { + instruction.addBranch(false, 0); + instruction.addBranch(true, 1); + + assertEquals(CounterImpl.getInstance(0, 1), + instruction.getInstructionCounter()); + assertEquals(CounterImpl.getInstance(1, 1), + instruction.getBranchCounter()); + } + + @Test + public void addBranchWithProbe_should_propagate_coverage_status_to_existing_predecessors() { + final Instruction i1 = new Instruction(124); + final Instruction i2 = new Instruction(125); + instruction.addBranch(i1, 3); + i1.addBranch(i2, 5); + + i2.addBranch(true, 8); + + assertEquals(CounterImpl.COUNTER_0_1, + instruction.getInstructionCounter()); + } + + @Test + public void addBranch_should_count_large_number_of_branches() { + for (int branch = 0; branch < 0x1000; branch++) { + instruction.addBranch(true, branch); + } + + assertEquals(CounterImpl.getInstance(0, 0x1000), + instruction.getBranchCounter()); + } + + @Test + public void addBranch_should_propagate_coverage_status_over_very_long_sequence() { + Instruction next = instruction; + for (int i = 0; i < 0x10000; i++) { + final Instruction insn = new Instruction(i); + next.addBranch(insn, 0); + next = insn; + } + next.addBranch(true, 0); + + assertEquals(CounterImpl.COUNTER_0_1, + instruction.getInstructionCounter()); + } + + @Test + public void merge_should_calculate_superset_of_covered_branches() { + final Instruction i1 = new Instruction(124); + i1.addBranch(false, 1); + i1.addBranch(false, 2); + i1.addBranch(true, 3); + i1.addBranch(true, 4); + final Instruction i2 = new Instruction(124); + i2.addBranch(false, 1); + i2.addBranch(true, 2); + i2.addBranch(false, 3); + i2.addBranch(true, 4); + + instruction = i1.merge(i2); + + assertEquals(CounterImpl.getInstance(1, 3), + instruction.getBranchCounter()); + } + + @Test + public void replaceBranches_should_calculate_coverage_on_new_branches() { + Instruction i1 = new Instruction(1); + Instruction i2 = new Instruction(2); + Instruction i3 = new Instruction(3); + i3.addBranch(true, 0); + + instruction = instruction.replaceBranches(Arrays.asList(i1, i2, i3)); + + assertEquals(CounterImpl.getInstance(2, 1), + instruction.getBranchCounter()); + } +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionsBuilderTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionsBuilderTest.java new file mode 100644 index 00000000..32dea10f --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/InstructionsBuilderTest.java @@ -0,0 +1,189 @@ +/******************************************************************************* + * 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: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.core.internal.analysis; + +import static org.junit.Assert.assertEquals; + +import java.util.Map; + +import org.jacoco.core.analysis.ISourceFileCoverage; +import org.jacoco.core.internal.flow.LabelInfo; +import org.junit.Before; +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.InsnNode; + +/** + * Unit tests for {@link InstructionsBuilder}. + */ +public class InstructionsBuilderTest { + + private InstructionsBuilder builder; + + @Before + public void setup() { + builder = new InstructionsBuilder(new boolean[] { false, true }); + } + + @Test + public void current_line_number_should_be_applied_to_instructions() { + InsnNode i1 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i1); + + builder.setCurrentLine(10); + InsnNode i2 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i2); + InsnNode i3 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i3); + + builder.setCurrentLine(20); + InsnNode i4 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i4); + + Map map = builder.getInstructions(); + assertEquals(ISourceFileCoverage.UNKNOWN_LINE, map.get(i1).getLine()); + assertEquals(10, map.get(i2).getLine()); + assertEquals(10, map.get(i3).getLine()); + assertEquals(20, map.get(i4).getLine()); + } + + @Test + public void null_probearray_should_not_mark_instruction_as_covered() { + builder = new InstructionsBuilder(null); + + InsnNode i1 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i1); + builder.addProbe(5, 0); + + Map map = builder.getInstructions(); + assertEquals(CounterImpl.COUNTER_1_0, + map.get(i1).getInstructionCounter()); + } + + @Test + public void unexecuted_probe_should_not_mark_instruction_as_covered() { + InsnNode i1 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i1); + builder.addProbe(0, 0); + + Map map = builder.getInstructions(); + assertEquals(CounterImpl.COUNTER_1_0, + map.get(i1).getInstructionCounter()); + } + + @Test + public void executed_probe_should_mark_instruction_as_covered() { + InsnNode i1 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i1); + builder.addProbe(1, 0); + + Map map = builder.getInstructions(); + assertEquals(CounterImpl.COUNTER_0_1, + map.get(i1).getInstructionCounter()); + } + + @Test + public void subsequent_instructions_should_be_linked_by_default() { + InsnNode i1 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i1); + + InsnNode i2 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i2); + + // mark i2 as covered + builder.addProbe(1, 0); + + // coverage should be propagated to i1 + Map map = builder.getInstructions(); + assertEquals(CounterImpl.COUNTER_0_1, + map.get(i1).getInstructionCounter()); + } + + @Test + public void subsequent_instructions_should_not_be_linked_when_noSuccessor_was_called() { + InsnNode i1 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i1); + builder.noSuccessor(); + + InsnNode i2 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i2); + + // mark i2 as covered + builder.addProbe(1, 0); + + // coverage should not be propagated to i1 + Map map = builder.getInstructions(); + assertEquals(CounterImpl.COUNTER_1_0, + map.get(i1).getInstructionCounter()); + } + + @Test + public void subsequent_instructions_should_be_linked_after_label_marked_as_successor() { + InsnNode i1 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i1); + + Label l = new Label(); + LabelInfo.setSuccessor(l); + builder.addLabel(l); + InsnNode i2 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i2); + + // mark i2 as covered + builder.addProbe(1, 0); + + // coverage should be propagated to i1 + Map map = builder.getInstructions(); + assertEquals(CounterImpl.COUNTER_0_1, + map.get(i1).getInstructionCounter()); + } + + @Test + public void subsequent_instructions_should_not_be_linked_after_label_not_marked_as_successor() { + InsnNode i1 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i1); + + builder.addLabel(new Label()); + InsnNode i2 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i2); + + // mark i2 as covered + builder.addProbe(1, 0); + + // coverage should not be propagated to i1 + Map map = builder.getInstructions(); + assertEquals(CounterImpl.COUNTER_1_0, + map.get(i1).getInstructionCounter()); + } + + @Test + public void jumps_should_propagate_coverage_status() { + InsnNode i1 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i1); + Label l2 = new Label(); + builder.addJump(l2, 0); + + builder.addLabel(l2); + InsnNode i2 = new InsnNode(Opcodes.NOP); + builder.addInstruction(i2); + + // mark i2 as covered + builder.addProbe(1, 0); + + // coverage should be propagated to i1 + Map map = builder.getInstructions(); + assertEquals(CounterImpl.COUNTER_0_1, + map.get(i1).getInstructionCounter()); + } + +} 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 d0484093..3260ae1e 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 @@ -884,14 +884,21 @@ public class MethodAnalyzerTest implements IProbeIdGenerator { private void runMethodAnalzer(IFilter filter) { LabelFlowAnalyzer.markLabels(method); - final MethodAnalyzer analyzer = new MethodAnalyzer("doit", "()V", null, - probes, filter, new FilterContextMock()); + InstructionsBuilder builder = new InstructionsBuilder(probes); + final MethodAnalyzer analyzer = new MethodAnalyzer(builder); + final MethodProbesAdapter probesAdapter = new MethodProbesAdapter( analyzer, this); // note that CheckMethodAdapter verifies that this test does not violate // contracts of ASM API analyzer.accept(method, new CheckMethodAdapter(probesAdapter)); - result = analyzer.getCoverage(); + + MethodCoverageImpl mc = new MethodCoverageImpl("doit", "V()", null); + MethodCoverageCalculator mcc = new MethodCoverageCalculator( + builder.getInstructions()); + filter.filter(method, new FilterContextMock(), mcc); + mcc.calculate(mc); + result = mc; } private void assertLine(int nr, int insnMissed, int insnCovered, diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageCalculatorTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageCalculatorTest.java new file mode 100644 index 00000000..776dfb60 --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/MethodCoverageCalculatorTest.java @@ -0,0 +1,224 @@ +/******************************************************************************* + * 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: + * Marc R. Hoffmann - initial API and implementation + * + *******************************************************************************/ +package org.jacoco.core.internal.analysis; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import org.jacoco.core.analysis.ISourceFileCoverage; +import org.junit.Before; +import org.junit.Test; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.InsnNode; + +/** + * Unit tests for {@link MethodCoverageCalculator}. + */ +public class MethodCoverageCalculatorTest { + + private Map instructions; + + // The purpose of this list is to link instruction nodes + private InsnList list; + + private MethodCoverageImpl coverage; + + @Before + public void setup() { + instructions = new HashMap(); + coverage = new MethodCoverageImpl("run", "()V", null); + list = new InsnList(); + } + + @Test + public void should_report_instructions() { + addInsn(1, true); + addInsn(2, true); + addInsn(2, false); + addInsn(3, false); + + MethodCoverageCalculator c = new MethodCoverageCalculator(instructions); + c.calculate(coverage); + + assertLine(1, 0, 1, 0, 0); + assertLine(2, 1, 1, 0, 0); + assertLine(3, 1, 0, 0, 0); + } + + @Test + public void should_report_instructions_with_branches() { + addInsn(1, false, false); + addInsn(2, false, false, true); + addInsn(3, false, true, true); + + MethodCoverageCalculator c = new MethodCoverageCalculator(instructions); + c.calculate(coverage); + + assertLine(1, 1, 0, 2, 0); + assertLine(2, 0, 1, 2, 1); + assertLine(3, 0, 1, 1, 2); + } + + @Test + public void should_ignore_single_instruction() { + addInsn(1, true); + InsnNode i1 = addInsn(1, false); + addInsn(2, true); + + MethodCoverageCalculator c = new MethodCoverageCalculator(instructions); + c.ignore(i1, i1); + c.calculate(coverage); + + assertLine(1, 0, 1, 0, 0); // only one instruction not filtered + assertLine(2, 0, 1, 0, 0); + } + + @Test + public void should_ignore_instruction_range() { + addInsn(1, true); + InsnNode i1 = addInsn(2, false); + addInsn(2, false); + addInsn(2, false); + addInsn(2, false); + InsnNode i2 = addInsn(2, false); + addInsn(3, true); + + MethodCoverageCalculator c = new MethodCoverageCalculator(instructions); + c.ignore(i1, i2); + c.calculate(coverage); + + assertLine(1, 0, 1, 0, 0); + assertLine(2, 0, 0, 0, 0); // all instructions filtered in line 2 + assertLine(3, 0, 1, 0, 0); + } + + @Test + public void should_merge_instructions() { + addInsn(1, true); + InsnNode i1 = addInsn(2, false, true); + InsnNode i2 = addInsn(2, true, false); + addInsn(3, true); + + MethodCoverageCalculator c = new MethodCoverageCalculator(instructions); + c.merge(i1, i2); + c.calculate(coverage); + + assertLine(1, 0, 1, 0, 0); + assertLine(2, 0, 1, 0, 2); // one fully covered instruction left + assertLine(3, 0, 1, 0, 0); + } + + @Test + public void should_merge_multiple_instructions() { + InsnNode i1 = addInsn(1, true, false, false); + InsnNode i2 = addInsn(1, false, true, false); + InsnNode i3 = addInsn(1, false, false, true); + + MethodCoverageCalculator c = new MethodCoverageCalculator(instructions); + c.merge(i1, i2); + c.merge(i2, i3); + c.calculate(coverage); + + assertLine(1, 0, 1, 0, 3); // one fully covered instruction left + } + + @Test + public void should_merge_instructions_redundant() { + addInsn(1, true); + InsnNode i1 = addInsn(2, false, true); + InsnNode i2 = addInsn(2, true, false); + addInsn(3, true); + + MethodCoverageCalculator c = new MethodCoverageCalculator(instructions); + c.merge(i1, i2); + c.merge(i2, i1); + c.calculate(coverage); + + assertLine(1, 0, 1, 0, 0); + assertLine(2, 0, 1, 0, 2); // one fully covered instruction left + assertLine(3, 0, 1, 0, 0); + } + + @Test + public void should_replace_branches() { + InsnNode i1 = addInsn(1); + InsnNode i2 = addInsn(2, true); + InsnNode i3 = addInsn(2, true); + InsnNode i4 = addInsn(2, false); + + MethodCoverageCalculator c = new MethodCoverageCalculator(instructions); + c.replaceBranches(i1, + new HashSet(Arrays.asList(i2, i3, i4))); + c.calculate(coverage); + + assertLine(1, 0, 1, 1, 2); // branches coverage status replaced + assertLine(2, 1, 2, 0, 0); // still in place + } + + @Test + public void should_replace_branches_with_merged_instructions() { + InsnNode i1 = addInsn(1, false, false, false); + InsnNode i2 = addInsn(2, true); + InsnNode i3 = addInsn(2, false); + InsnNode i4 = addInsn(2, false); + + MethodCoverageCalculator c = new MethodCoverageCalculator(instructions); + c.merge(i4, i3); + c.merge(i3, i2); + c.replaceBranches(i1, + new HashSet(Arrays.asList(i2, i3, i4))); + c.calculate(coverage); + + assertLine(1, 0, 1, 0, 3); + } + + @Test + public void should_work_without_lines() { + addInsn(ISourceFileCoverage.UNKNOWN_LINE, false); + addInsn(ISourceFileCoverage.UNKNOWN_LINE, false); + addInsn(ISourceFileCoverage.UNKNOWN_LINE, true); + + MethodCoverageCalculator c = new MethodCoverageCalculator(instructions); + c.calculate(coverage); + + assertEquals(ISourceFileCoverage.UNKNOWN_LINE, coverage.getFirstLine()); + assertEquals(ISourceFileCoverage.UNKNOWN_LINE, coverage.getLastLine()); + assertEquals(CounterImpl.getInstance(2, 1), + coverage.getInstructionCounter()); + } + + private void assertLine(int idx, int mi, int ci, int mb, int cb) { + assertEquals("instructions", CounterImpl.getInstance(mi, ci), + coverage.getLine(idx).getInstructionCounter()); + assertEquals("branches", CounterImpl.getInstance(mb, cb), + coverage.getLine(idx).getBranchCounter()); + } + + private InsnNode addInsn(int line, boolean... branches) { + Instruction i = new Instruction(line); + int idx = 0; + for (boolean covered : branches) { + i.addBranch(covered, idx++); + } + InsnNode node = new InsnNode(Opcodes.NOP); + list.add(node); + instructions.put(node, i); + return node; + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java deleted file mode 100644 index 950827c1..00000000 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/InstructionTest.java +++ /dev/null @@ -1,124 +0,0 @@ -/******************************************************************************* - * 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: - * Marc R. Hoffmann - initial API and implementation - * - *******************************************************************************/ -package org.jacoco.core.internal.flow; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; - -import org.junit.Before; -import org.junit.Test; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.InsnNode; - -/** - * Unit tests for {@link Instruction}. - */ -public class InstructionTest { - - private Instruction instruction; - - @Before - public void setup() { - instruction = new Instruction(new InsnNode(Opcodes.NOP), 123); - } - - @Test - public void testInit() { - final InsnNode node = new InsnNode(Opcodes.NOP); - instruction = new Instruction(node, 123); - assertSame(node, instruction.getNode()); - assertEquals(123, instruction.getLine()); - assertEquals(0, instruction.getBranches()); - assertEquals(0, instruction.getCoveredBranches()); - } - - @Test - public void testAddBranch() { - instruction.addBranch(); - assertEquals(1, instruction.getBranches()); - instruction.addBranch(); - assertEquals(2, instruction.getBranches()); - instruction.addBranch(); - assertEquals(3, instruction.getBranches()); - assertEquals(0, instruction.getCoveredBranches()); - } - - @Test - public void testSetPredecessor() { - final Instruction predecessor = new Instruction( - new InsnNode(Opcodes.NOP), 122); - instruction.setPredecessor(predecessor, 0); - assertEquals(1, predecessor.getBranches()); - } - - @Test - public void setCovered_should_mark_branch_in_predecessor() { - final Instruction i = new Instruction(new InsnNode(Opcodes.NOP), 122); - i.setCovered(2); - assertEquals(1, i.getCoveredBranches()); - assertEquals("{2}", i.toString()); - - final Instruction s1 = new Instruction(new InsnNode(Opcodes.NOP), 123); - s1.setPredecessor(i, 1); - s1.setCovered(0); - assertEquals("{0}", s1.toString()); - assertEquals(1, s1.getCoveredBranches()); - assertEquals("{1, 2}", i.toString()); - assertEquals(2, i.getCoveredBranches()); - - final Instruction s2 = new Instruction(new InsnNode(Opcodes.NOP), 124); - s2.setPredecessor(i, 0); - s2.setCovered(1); - assertEquals("{0}", s1.toString()); - assertEquals(1, s2.getCoveredBranches()); - assertEquals("{0, 1, 2}", i.toString()); - assertEquals(3, i.getCoveredBranches()); - } - - @Test - public void should_use_BitSet_to_hold_information_about_branches_of_big_switches() { - for (int branch = 0; branch < 256; branch++) { - instruction.setCovered(branch); - } - assertEquals(256, instruction.getCoveredBranches()); - } - - @Test - public void merge_should_add_covered_branches_from_another_instruction() { - final Instruction i1 = new Instruction(new InsnNode(Opcodes.NOP), 123); - i1.setCovered(0); - final Instruction i2 = new Instruction(new InsnNode(Opcodes.NOP), 123); - i2.setCovered(1); - i1.merge(i2); - assertEquals("{0, 1}", i1.toString()); - assertEquals(2, i1.getCoveredBranches()); - assertEquals("{1}", i2.toString()); - } - - @Test - public void testSetCoveredOnLongSequence() { - final Instruction first = new Instruction(new InsnNode(Opcodes.NOP), 0); - Instruction next = first; - for (int i = 0; i < 0x10000; i++) { - final Instruction insn = new Instruction(new InsnNode(Opcodes.NOP), - i); - insn.setPredecessor(next, 0); - next = insn; - } - - // The implementation must not cause an StackOverflowError even on very - // long sequences: - next.setCovered(0); - assertEquals(1, first.getCoveredBranches()); - } - -} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelInfoTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelInfoTest.java index 85007950..1ed75724 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelInfoTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/flow/LabelInfoTest.java @@ -17,11 +17,10 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import org.jacoco.core.internal.analysis.Instruction; import org.junit.Before; import org.junit.Test; import org.objectweb.asm.Label; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.InsnNode; /** * Unit tests for {@link LabelInfoTest}. @@ -161,8 +160,7 @@ public class LabelInfoTest { @Test public void testSetInstruction() { - final Instruction instruction = new Instruction( - new InsnNode(Opcodes.NOP), 123); + final Instruction instruction = new Instruction(123); LabelInfo.setInstruction(label, instruction); assertSame(instruction, LabelInfo.getInstruction(label)); } -- cgit v1.2.3