Skip to content

Commit 13f29eb

Browse files
Godinmarchof
authored andcommitted
Preserve empty class and sourcefile nodes in XML report (bazel-contrib#817)
1 parent 0152b7a commit 13f29eb

File tree

22 files changed

+284
-53
lines changed

22 files changed

+284
-53
lines changed

jacoco-maven-plugin/src/org/jacoco/maven/ReportSupport.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,9 @@ private void logBundleInfo(final IBundleCoverage bundle,
222222
c.getName()));
223223
}
224224
}
225-
if (bundle.getClassCounter().getTotalCount() > 0
226-
&& bundle.getLineCounter().getTotalCount() == 0) {
227-
log.warn("To enable source code annotation class files have to be compiled with debug information.");
225+
if (!bundle.isEmpty() && bundle.getLineCounter().getTotalCount() == 0) {
226+
log.warn(
227+
"To enable source code annotation class files have to be compiled with debug information.");
228228
}
229229
}
230230

org.jacoco.ant/src/org/jacoco/ant/ReportTask.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,7 @@ private void logBundleInfo(final IBundleCoverage bundle,
593593
}
594594

595595
private void checkForMissingDebugInformation(final ICoverageNode node) {
596-
if (node.getClassCounter().getTotalCount() > 0
597-
&& node.getLineCounter().getTotalCount() == 0) {
596+
if (!node.isEmpty() && node.getLineCounter().getTotalCount() == 0) {
598597
log(format(
599598
"To enable source code annotation class files for bundle '%s' have to be compiled with debug information.",
600599
node.getName()), Project.MSG_WARN);

org.jacoco.core.test/src/org/jacoco/core/analysis/CoverageBuilderTest.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
import static org.junit.Assert.assertEquals;
1515
import static org.junit.Assert.assertNotNull;
16-
import static org.junit.Assert.assertTrue;
1716

1817
import java.util.Arrays;
1918
import java.util.Collection;
@@ -106,13 +105,10 @@ public void testCreateClassCovered() {
106105
}
107106

108107
@Test
109-
public void testIgnoreClassesWithoutCode() {
110-
final MethodCoverageImpl method = new MethodCoverageImpl("doit", "()V",
111-
null);
112-
addClass(123L, false, "Sample", null, method);
108+
public void should_not_ignore_empty_classes() {
109+
addClass(123L, false, "Empty", null);
113110

114-
final Collection<IClassCoverage> classes = coverageBuilder.getClasses();
115-
assertTrue(classes.isEmpty());
111+
assertEquals(1, coverageBuilder.getClasses().size());
116112
}
117113

118114
@Test(expected = IllegalStateException.class)

org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassCoverageImplTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public void testEmptyClass() {
9393
assertEquals(CounterImpl.COUNTER_0_0, node.getInstructionCounter());
9494
assertEquals(CounterImpl.COUNTER_0_0, node.getBranchCounter());
9595
assertEquals(CounterImpl.COUNTER_0_0, node.getMethodCounter());
96-
assertEquals(CounterImpl.COUNTER_1_0, node.getClassCounter());
96+
assertEquals(CounterImpl.COUNTER_0_0, node.getClassCounter());
9797
}
9898

9999
@Test

org.jacoco.core/src/org/jacoco/core/analysis/CoverageBuilder.java

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -98,23 +98,19 @@ public Collection<IClassCoverage> getNoMatchClasses() {
9898
// === ICoverageVisitor ===
9999

100100
public void visitCoverage(final IClassCoverage coverage) {
101-
// Only consider classes that actually contain code:
102-
if (coverage.getInstructionCounter().getTotalCount() > 0) {
103-
final String name = coverage.getName();
104-
final IClassCoverage dup = classes.put(name, coverage);
105-
if (dup != null) {
106-
if (dup.getId() != coverage.getId()) {
107-
throw new IllegalStateException(
108-
"Can't add different class with same name: "
109-
+ name);
110-
}
111-
} else {
112-
final String source = coverage.getSourceFileName();
113-
if (source != null) {
114-
final SourceFileCoverageImpl sourceFile = getSourceFile(
115-
source, coverage.getPackageName());
116-
sourceFile.increment(coverage);
117-
}
101+
final String name = coverage.getName();
102+
final IClassCoverage dup = classes.put(name, coverage);
103+
if (dup != null) {
104+
if (dup.getId() != coverage.getId()) {
105+
throw new IllegalStateException(
106+
"Can't add different class with same name: " + name);
107+
}
108+
} else {
109+
final String source = coverage.getSourceFileName();
110+
if (source != null) {
111+
final SourceFileCoverageImpl sourceFile = getSourceFile(source,
112+
coverage.getPackageName());
113+
sourceFile.increment(coverage);
118114
}
119115
}
120116
}

org.jacoco.core/src/org/jacoco/core/analysis/CoverageNodeImpl.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ public ICounter getCounter(final CounterEntity entity) {
143143
throw new AssertionError(entity);
144144
}
145145

146+
public boolean isEmpty() {
147+
return getInstructionCounter().getTotalCount() == 0;
148+
}
149+
146150
public ICoverageNode getPlainCopy() {
147151
final CoverageNodeImpl copy = new CoverageNodeImpl(elementType, name);
148152
copy.instructionCounter = CounterImpl.getInstance(instructionCounter);

org.jacoco.core/src/org/jacoco/core/analysis/ICoverageNode.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,13 @@ enum CounterEntity {
131131
*/
132132
ICounter getCounter(CounterEntity entity);
133133

134+
/**
135+
* Checks whether this is an empty node.
136+
*
137+
* @return <code>true</code> if this node does not contain instructions
138+
*/
139+
boolean isEmpty();
140+
134141
/**
135142
* Creates a plain copy of this node. While {@link ICoverageNode}
136143
* implementations may contain heavy data structures, the copy returned by
@@ -141,4 +148,4 @@ enum CounterEntity {
141148
*/
142149
ICoverageNode getPlainCopy();
143150

144-
}
151+
}

org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ private void addMethodCoverage(final String name, final String desc,
113113
signature);
114114
mcc.calculate(mc);
115115

116-
if (mc.getInstructionCounter().getTotalCount() > 0) {
116+
if (!mc.isEmpty()) {
117117
// Only consider methods that actually contain code
118118
coverage.addMethod(mc);
119119
}

org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassCoverageImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ public ClassCoverageImpl(final String name, final long id,
4747
this.id = id;
4848
this.noMatch = noMatch;
4949
this.methods = new ArrayList<IMethodCoverage>();
50-
this.classCounter = CounterImpl.COUNTER_1_0;
5150
}
5251

5352
/**
@@ -59,10 +58,11 @@ public ClassCoverageImpl(final String name, final long id,
5958
public void addMethod(final IMethodCoverage method) {
6059
this.methods.add(method);
6160
increment(method);
62-
// As class is considered as covered when at least one method is
63-
// covered:
61+
// Class is considered as covered when at least one method is covered:
6462
if (methodCounter.getCoveredCount() > 0) {
6563
this.classCounter = CounterImpl.COUNTER_0_1;
64+
} else {
65+
this.classCounter = CounterImpl.COUNTER_1_0;
6666
}
6767
}
6868

org.jacoco.doc/docroot/doc/changes.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ <h3>New Features</h3>
5151
(GitHub <a href="https://github.com/jacoco/jacoco/issues/818">#818</a>).</li>
5252
<li>HTML report shows message when analyzed class does not match executed
5353
(GitHub <a href="https://github.com/jacoco/jacoco/issues/819">#819</a>).</li>
54+
<li>Empty class and sourcefile nodes are preserved and available in XML report
55+
(GitHub <a href="https://github.com/jacoco/jacoco/issues/817">#817</a>).</li>
5456
</ul>
5557

5658
<h3>Fixed Bugs</h3>

org.jacoco.report.test/src/org/jacoco/report/ReportStructureTestDriver.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
import java.io.IOException;
1515
import java.io.Reader;
16+
import java.io.StringReader;
17+
import java.util.Arrays;
1618
import java.util.Collection;
1719
import java.util.Collections;
1820
import java.util.List;
@@ -45,7 +47,7 @@ public class ReportStructureTestDriver {
4547

4648
public Reader getSourceFile(String packageName, String fileName)
4749
throws IOException {
48-
return null;
50+
return new StringReader("");
4951
}
5052

5153
public int getTabWidth() {
@@ -84,11 +86,30 @@ public ReportStructureTestDriver() {
8486
sourceFileCoverageImpl.increment(classCoverage);
8587
sourceFileCoverage = sourceFileCoverageImpl;
8688

89+
final ClassCoverageImpl emptyClassInNonEmptyPackage = new ClassCoverageImpl(
90+
"org/jacoco/example/Empty", 0, false);
91+
emptyClassInNonEmptyPackage.setSourceFileName("Empty.java");
92+
final SourceFileCoverageImpl emptySourceInNonEmptyPackage = new SourceFileCoverageImpl(
93+
"Empty.java", "org/jacoco/example");
94+
95+
final ClassCoverageImpl emptyClassInEmptyPackage = new ClassCoverageImpl(
96+
"empty/Empty", 0, false);
97+
emptyClassInEmptyPackage.setSourceFileName("Empty.java");
98+
final SourceFileCoverageImpl emptySourceInEmptyPackage = new SourceFileCoverageImpl(
99+
"Empty.java", "empty");
100+
final PackageCoverageImpl emptyPackage = new PackageCoverageImpl(
101+
"empty",
102+
Collections.<IClassCoverage> singletonList(
103+
emptyClassInEmptyPackage),
104+
Collections.<ISourceFileCoverage> singletonList(
105+
emptySourceInEmptyPackage));
106+
87107
packageCoverage = new PackageCoverageImpl("org/jacoco/example",
88-
Collections.singleton(classCoverage),
89-
Collections.singleton(sourceFileCoverage));
108+
Arrays.asList(classCoverage, emptyClassInNonEmptyPackage),
109+
Arrays.asList(sourceFileCoverage,
110+
emptySourceInNonEmptyPackage));
90111
bundleCoverage = new BundleCoverageImpl("bundle",
91-
Collections.singleton(packageCoverage));
112+
Arrays.asList(packageCoverage, emptyPackage));
92113
}
93114

94115
public void sendNestedGroups(IReportVisitor reportVisitor)

org.jacoco.report.test/src/org/jacoco/report/csv/CSVFormatterTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public void testStructureWithGroup() throws IOException {
6464
assertEquals(
6565
"group/bundle,org.jacoco.example,FooClass,10,15,1,2,0,3,1,2,0,1",
6666
lines.get(1));
67+
assertEquals(2, lines.size());
6768
}
6869

6970
@Test
@@ -77,16 +78,17 @@ public void testStructureWithNestedGroups() throws IOException {
7778
assertEquals(
7879
"report/bundle,org.jacoco.example,FooClass,10,15,1,2,0,3,1,2,0,1",
7980
lines.get(2));
81+
assertEquals(3, lines.size());
8082
}
8183

8284
@Test
8385
public void testStructureWithBundleOnly() throws IOException {
8486
driver.sendBundle(visitor);
8587
final List<String> lines = getLines();
8688
assertEquals(HEADER, lines.get(0));
87-
assertEquals(
88-
"bundle,org.jacoco.example,FooClass,10,15,1,2,0,3,1,2,0,1",
89+
assertEquals("bundle,org.jacoco.example,FooClass,10,15,1,2,0,3,1,2,0,1",
8990
lines.get(1));
91+
assertEquals(2, lines.size());
9092
}
9193

9294
@Test

org.jacoco.report.test/src/org/jacoco/report/csv/CSVGroupHandlerTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public void testVisitBundle() throws Exception {
5151
assertEquals(
5252
"bundle,org.jacoco.example,FooClass,10,15,1,2,0,3,1,2,0,1",
5353
reader.readLine());
54+
assertEquals("no more lines expected", null, reader.readLine());
5455
}
5556

5657
@Test
@@ -61,6 +62,7 @@ public void testVisitGroup() throws Exception {
6162
assertEquals(
6263
"group/bundle,org.jacoco.example,FooClass,10,15,1,2,0,3,1,2,0,1",
6364
reader.readLine());
65+
assertEquals("no more lines expected", null, reader.readLine());
6466
}
6567

6668
private BufferedReader getResultReader() {

org.jacoco.report.test/src/org/jacoco/report/html/HTMLFormatterTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,36 @@ public void testStructureWithGroup() throws IOException {
6565
driver.sendGroup(formatter.createVisitor(output));
6666
output.assertFile("index.html");
6767
output.assertFile("bundle/index.html");
68+
6869
output.assertFile("bundle/org.jacoco.example/index.html");
70+
output.assertFile("bundle/org.jacoco.example/index.source.html");
6971
output.assertFile("bundle/org.jacoco.example/FooClass.html");
72+
output.assertFile("bundle/org.jacoco.example/FooClass.java.html");
73+
output.assertNoFile("bundle/org.jacoco.example/Empty.html");
74+
output.assertNoFile("bundle/org.jacoco.example/Empty.java.html");
75+
76+
output.assertNoFile("bundle/empty/index.html");
77+
output.assertNoFile("bundle/empty/index.source.html");
78+
output.assertNoFile("bundle/empty/Empty.html");
79+
output.assertNoFile("bundle/empty/Empty.java.html");
7080
}
7181

7282
@Test
7383
public void testStructureWithBundleOnly() throws IOException {
7484
driver.sendBundle(formatter.createVisitor(output));
7585
output.assertFile("index.html");
86+
7687
output.assertFile("org.jacoco.example/index.html");
88+
output.assertFile("org.jacoco.example/index.source.html");
7789
output.assertFile("org.jacoco.example/FooClass.html");
90+
output.assertFile("org.jacoco.example/FooClass.java.html");
91+
output.assertNoFile("org.jacoco.example/Empty.html");
92+
output.assertNoFile("org.jacoco.example/Empty.java.html");
93+
94+
output.assertNoFile("empty/index.html");
95+
output.assertNoFile("empty/index.source.html");
96+
output.assertNoFile("empty/Empty.html");
97+
output.assertNoFile("empty/Empty.java.html");
7898
}
7999

80100
@Test
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Evgeny Mandrikov - initial API and implementation
10+
*
11+
*******************************************************************************/
12+
package org.jacoco.report.internal.html.page;
13+
14+
import org.jacoco.core.analysis.IBundleCoverage;
15+
import org.jacoco.core.analysis.IClassCoverage;
16+
import org.jacoco.core.analysis.IPackageCoverage;
17+
import org.jacoco.core.analysis.ISourceFileCoverage;
18+
import org.jacoco.core.internal.analysis.BundleCoverageImpl;
19+
import org.jacoco.core.internal.analysis.ClassCoverageImpl;
20+
import org.jacoco.core.internal.analysis.CounterImpl;
21+
import org.jacoco.core.internal.analysis.MethodCoverageImpl;
22+
import org.jacoco.core.internal.analysis.PackageCoverageImpl;
23+
import org.junit.Before;
24+
import org.junit.Test;
25+
import org.w3c.dom.Document;
26+
27+
import java.util.Arrays;
28+
import java.util.Collections;
29+
30+
import static org.junit.Assert.assertEquals;
31+
32+
/**
33+
* Unit tests for {@link BundlePage}.
34+
*/
35+
public class BundlePageTest extends PageTestBase {
36+
37+
@Before
38+
@Override
39+
public void setup() throws Exception {
40+
super.setup();
41+
}
42+
43+
@Test
44+
public void should_render_non_empty_packages() throws Exception {
45+
final ClassCoverageImpl classCoverage = new ClassCoverageImpl(
46+
"example/Class", 0, false);
47+
final MethodCoverageImpl methodCoverage = new MethodCoverageImpl("m",
48+
"()V", null);
49+
methodCoverage.increment(CounterImpl.COUNTER_1_0,
50+
CounterImpl.COUNTER_0_0, 42);
51+
classCoverage.addMethod(methodCoverage);
52+
final IPackageCoverage nonEmptyPackage = new PackageCoverageImpl(
53+
"example",
54+
Collections.<IClassCoverage> singleton(classCoverage),
55+
Collections.<ISourceFileCoverage> emptySet());
56+
57+
final IPackageCoverage emptyPackage = new PackageCoverageImpl("empty",
58+
Collections.<IClassCoverage> emptySet(),
59+
Collections.<ISourceFileCoverage> emptySet());
60+
61+
final IBundleCoverage node = new BundleCoverageImpl("bundle",
62+
Arrays.asList(nonEmptyPackage, emptyPackage));
63+
64+
final BundlePage page = new BundlePage(node, null, null, rootFolder,
65+
context);
66+
page.render();
67+
68+
final Document doc = support.parse(output.getFile("index.html"));
69+
assertEquals("el_package", support.findStr(doc,
70+
"/html/body/table[1]/tbody/tr[1]/td[1]/a/@class"));
71+
assertEquals("example", support.findStr(doc,
72+
"/html/body/table[1]/tbody/tr[1]/td[1]/a"));
73+
assertEquals("1",
74+
support.findStr(doc, "count(/html/body/table[1]/tbody/tr)"));
75+
}
76+
77+
}

0 commit comments

Comments
 (0)