Skip to content

Commit ebe5ee1

Browse files
svaningelgemSteven Van Ingelgem
andauthored
Take only class files with in the report (#12)
* take only class files * Test case fails: good! * Only process our compiled class files. Nothing else. * Fix tests again --------- Co-authored-by: Steven Van Ingelgem <[email protected]>
1 parent 18e74fc commit ebe5ee1

File tree

12 files changed

+245
-154
lines changed

12 files changed

+245
-154
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
cache: 'maven'
3434

3535
- name: Build and test
36-
run: mvn -B verify
36+
run: mvn --ntp -B verify
3737

3838
- name: Upload test results
3939
if: always()

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ jobs:
4141
- name: Building
4242
run: |
4343
set -o pipefail
44-
mvn -B clean install | awk '/svaningelgem/ || !/Downloading|Downloaded|Progress/'
44+
mvn --ntp -B clean install | awk '/svaningelgem/ || !/Downloading|Downloaded|Progress/'
4545
4646
- name: Flatten pom.xml file
4747
run: |
4848
set -o pipefail
49-
mvn -B flatten:flatten | awk '/svaningelgem/ || !/Downloading|Downloaded|Progress/'
49+
mvn --ntp -B flatten:flatten | awk '/svaningelgem/ || !/Downloading|Downloaded|Progress/'
5050
5151
- name: Deploying to Central
5252
run: |

jacoco-console-reporter/src/main/java/io/github/svaningelgem/DirectoryNode.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
import lombok.RequiredArgsConstructor;
55
import org.jetbrains.annotations.NotNull;
66

7-
import java.util.*;
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
import java.util.Map;
10+
import java.util.TreeMap;
811
import java.util.stream.Collectors;
912

1013
/**

jacoco-console-reporter/src/main/java/io/github/svaningelgem/JacocoConsoleReporterMojo.java

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package io.github.svaningelgem;
22

3-
import lombok.Data;
4-
import lombok.RequiredArgsConstructor;
53
import org.apache.maven.plugin.AbstractMojo;
64
import org.apache.maven.plugin.MojoExecutionException;
75
import org.apache.maven.plugins.annotations.LifecyclePhase;
@@ -11,13 +9,16 @@
119
import org.jacoco.core.data.ExecutionDataReader;
1210
import org.jacoco.core.data.ExecutionDataStore;
1311
import org.jacoco.core.data.SessionInfoStore;
14-
import org.jetbrains.annotations.Contract;
1512
import org.jetbrains.annotations.NotNull;
16-
import org.jetbrains.annotations.Nullable;
1713

1814
import java.io.File;
1915
import java.io.FileInputStream;
2016
import java.io.IOException;
17+
import java.nio.file.FileVisitResult;
18+
import java.nio.file.Files;
19+
import java.nio.file.Path;
20+
import java.nio.file.SimpleFileVisitor;
21+
import java.nio.file.attribute.BasicFileAttributes;
2122
import java.util.*;
2223

2324
/**
@@ -129,6 +130,7 @@ public void execute() throws MojoExecutionException {
129130
additionalExecFiles.stream().map(File::getAbsoluteFile).forEach(collectedExecFilePaths::add);
130131
collectedExecFilePaths.add(jacocoExecFile.getAbsoluteFile());
131132
collectedClassesPaths.add(classesDirectory.getAbsoluteFile());
133+
getLog().info("Collected Classes: " + collectedClassesPaths);
132134
if (jacocoExecFile.exists()) {
133135
getLog().debug("Added exec file from current module: " + jacocoExecFile.getAbsolutePath());
134136
}
@@ -144,6 +146,10 @@ public void execute() throws MojoExecutionException {
144146
return;
145147
}
146148

149+
generateReport();
150+
}
151+
152+
private void generateReport() throws MojoExecutionException {
147153
try {
148154
getLog().debug("Loading execution data");
149155
ExecutionDataStore executionDataStore = loadExecutionData();
@@ -260,19 +266,16 @@ private void scanDirectoryForExecFiles(@NotNull File dir, List<String> execPatte
260266
* @return Populated execution data store with coverage information
261267
* @throws IOException if there are issues reading the JaCoCo execution files
262268
*/
263-
private @Nullable ExecutionDataStore loadExecutionData() throws IOException {
264-
collectedExecFilePaths.removeIf(Objects::isNull);
265-
collectedExecFilePaths.removeIf(f -> !f.exists());
266-
if (collectedExecFilePaths.isEmpty()) {
267-
getLog().warn("No coverage data found in this project; ensure JaCoCo plugin ran with tests.");
268-
return null;
269-
}
270-
269+
private @NotNull ExecutionDataStore loadExecutionData() throws IOException {
271270
ExecutionDataStore executionDataStore = new ExecutionDataStore();
272271
SessionInfoStore sessionInfoStore = new SessionInfoStore();
273272

274273
// Load all exec files
275274
for (File execFile : collectedExecFilePaths) {
275+
if (execFile == null || !execFile.exists()) {
276+
continue;
277+
}
278+
276279
loadExecFile(execFile, executionDataStore, sessionInfoStore);
277280
getLog().debug("Processed exec file: " + execFile);
278281
}
@@ -301,16 +304,30 @@ private void loadExecFile(File execFile, ExecutionDataStore executionDataStore,
301304
* @return A bundle containing all coverage information
302305
* @throws IOException if there are issues reading the class files
303306
*/
304-
private @Nullable IBundleCoverage analyzeCoverage(ExecutionDataStore executionDataStore) throws IOException {
305-
if (executionDataStore == null) return null;
306-
307+
private @NotNull IBundleCoverage analyzeCoverage(@NotNull ExecutionDataStore executionDataStore) throws IOException {
307308
CoverageBuilder coverageBuilder = new CoverageBuilder();
308309
Analyzer analyzer = new Analyzer(executionDataStore, coverageBuilder);
309310
for (File classPath : collectedClassesPaths) {
310-
if (classPath != null && classPath.exists()) {
311-
analyzer.analyzeAll(classPath);
311+
if (classPath == null || !classPath.exists()) {
312+
continue;
312313
}
314+
getLog().debug("Analyzing class files in: " + classPath.getAbsolutePath());
315+
Files.walkFileTree(classPath.toPath(), new SimpleFileVisitor<Path>() {
316+
@Override
317+
public @NotNull FileVisitResult visitFile(Path file, @NotNull BasicFileAttributes attrs) {
318+
String filePath = file.toString().toLowerCase(Locale.ENGLISH);
319+
if (filePath.endsWith(".class")) {
320+
try (FileInputStream in = new FileInputStream(file.toFile())) {
321+
analyzer.analyzeClass(in, file.toString());
322+
} catch (Exception e) {
323+
getLog().debug("Error analyzing class file: " + file + ": " + e.getMessage());
324+
}
325+
}
326+
return FileVisitResult.CONTINUE;
327+
}
328+
});
313329
}
330+
314331
return coverageBuilder.getBundle("Project");
315332
}
316333

@@ -320,13 +337,13 @@ private void loadExecFile(File execFile, ExecutionDataStore executionDataStore,
320337
*
321338
* @param root The root node of the directory tree containing coverage information
322339
*/
323-
private void printCoverageReport(@Nullable DirectoryNode root) {
340+
private void printCoverageReport(@NotNull DirectoryNode root) {
324341
printTree(root);
325342
printSummary(root);
326343
}
327344

328-
private void printSummary(@Nullable DirectoryNode root) {
329-
if (!showSummary || root == null) return;
345+
private void printSummary(@NotNull DirectoryNode root) {
346+
if (!showSummary) return;
330347

331348
CoverageMetrics total = root.getMetrics();
332349

@@ -359,8 +376,8 @@ private void printSummary(@Nullable DirectoryNode root) {
359376

360377
}
361378

362-
private void printTree(@Nullable DirectoryNode root) {
363-
if (!showTree || root == null) return;
379+
private void printTree(@NotNull DirectoryNode root) {
380+
if (!showTree) return;
364381

365382
// Print header
366383
getLog().info("Overall Coverage Summary");
@@ -388,9 +405,7 @@ private void printTree(@Nullable DirectoryNode root) {
388405
* @param bundle The bundle containing coverage data for all analyzed classes
389406
* @return The root node of the directory tree containing coverage information
390407
*/
391-
private @Nullable DirectoryNode buildDirectoryTree(@Nullable IBundleCoverage bundle) {
392-
if (bundle == null) return null;
393-
408+
private @NotNull DirectoryNode buildDirectoryTree(@NotNull IBundleCoverage bundle) {
394409
DirectoryNode root = new DirectoryNode("");
395410
for (IPackageCoverage packageCoverage : bundle.getPackages()) {
396411
String packageName = packageCoverage.getName().replace('.', '/');

jacoco-console-reporter/src/main/java/io/github/svaningelgem/SourceFileNode.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import lombok.Data;
44
import lombok.RequiredArgsConstructor;
5-
import org.jetbrains.annotations.NotNull;
65

76
/**
87
* A node representing a source file in the coverage tree.

jacoco-console-reporter/src/test/java/io/github/svaningelgem/BaseTestClass.java

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
package io.github.svaningelgem;
22

33
import lombok.var;
4+
import org.apache.maven.execution.DefaultMavenExecutionRequest;
5+
import org.apache.maven.execution.DefaultMavenExecutionResult;
6+
import org.apache.maven.execution.MavenExecutionRequest;
7+
import org.apache.maven.execution.MavenSession;
8+
import org.apache.maven.model.Build;
9+
import org.apache.maven.model.Model;
10+
import org.apache.maven.model.Plugin;
411
import org.apache.maven.plugin.testing.MojoRule;
12+
import org.apache.maven.project.MavenProject;
13+
import org.codehaus.plexus.PlexusContainer;
14+
import org.codehaus.plexus.util.xml.Xpp3Dom;
515
import org.jetbrains.annotations.Contract;
616
import org.jetbrains.annotations.NotNull;
717
import org.jetbrains.annotations.Nullable;
@@ -11,12 +21,17 @@
1121
import org.junit.rules.TemporaryFolder;
1222

1323
import java.io.File;
24+
import java.io.IOException;
25+
import java.io.InputStream;
26+
import java.nio.file.Files;
27+
import java.nio.file.StandardCopyOption;
1428
import java.util.ArrayList;
1529
import java.util.List;
1630
import java.util.Locale;
1731
import java.util.Random;
1832

19-
import static org.junit.Assert.*;
33+
import static org.junit.Assert.assertTrue;
34+
import static org.junit.Assert.fail;
2035

2136
public class BaseTestClass {
2237
protected final static Random RANDOM = new Random();
@@ -30,7 +45,9 @@ public class BaseTestClass {
3045
@Rule
3146
public TemporaryFolder temporaryFolder = new TemporaryFolder();
3247

33-
protected final File testProjectDir = new File("../test-project");
48+
protected final File mainProjectDir = new File(".").getAbsoluteFile();
49+
protected final File mainProjectClasses = new File(mainProjectDir, "target/classes");
50+
protected final File testProjectDir = new File("../test-project").getAbsoluteFile();
3451
protected final File testProjectJacocoExec = new File(testProjectDir, "target/jacoco.exec");
3552
protected final File testProjectClasses = new File(testProjectDir, "target/classes");
3653
protected final File pom = new File(getBasedir(), "src/test/resources/unit/pom.xml");
@@ -48,6 +65,29 @@ public void setUp() throws Exception {
4865
fileCounter = 0;
4966

5067
mojo = (JacocoConsoleReporterMojo) rule.lookupConfiguredMojo(pom.getParentFile(), "report");
68+
// Setting the defaults
69+
mojo.deferReporting = true;
70+
mojo.showFiles = false;
71+
mojo.showTree = true;
72+
mojo.showSummary = true;
73+
mojo.scanModules = false;
74+
mojo.weightClassCoverage = 0.1;
75+
mojo.weightMethodCoverage = 0.1;
76+
mojo.weightBranchCoverage = 0.4;
77+
mojo.weightLineCoverage = 0.4;
78+
79+
// Create a real project with JaCoCo plugin
80+
MavenProject project = createProjectWithJacocoPlugin(null);
81+
mojo.project = project;
82+
83+
// Create a real MavenSession with this as the only project
84+
List<MavenProject> projects = new ArrayList<>();
85+
projects.add(project);
86+
mojo.mavenSession = createRealMavenSession(projects);
87+
88+
// Configure mojo
89+
mojo.baseDir = temporaryFolder.getRoot();
90+
5191
log = new MyLog();
5292
mojo.setLog(log);
5393
}
@@ -171,4 +211,86 @@ protected void addFiles(DirectoryNode toNode, @Nullable CoverageMetrics defaultC
171211
toNode.getSourceFiles().add(file);
172212
}
173213
}
214+
215+
/**
216+
* Helper method to copy a directory
217+
*/
218+
protected void copyDirectory(@NotNull File sourceDir, File destDir) throws IOException {
219+
if (!sourceDir.exists() || !sourceDir.isDirectory()) {
220+
return;
221+
}
222+
223+
if (!destDir.exists()) {
224+
destDir.mkdirs();
225+
}
226+
227+
File[] files = sourceDir.listFiles();
228+
if (files == null) return;
229+
230+
for (File file : files) {
231+
File destFile = new File(destDir, file.getName());
232+
if (file.isDirectory()) {
233+
copyDirectory(file, destFile);
234+
} else {
235+
Files.copy(file.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
236+
}
237+
}
238+
}
239+
240+
/**
241+
* Helper method to copy a resource from the classpath to a file
242+
*/
243+
protected void copyResourceToFile(String resourcePath, File destFile) throws IOException {
244+
try (InputStream is = getClass().getResourceAsStream(resourcePath)) {
245+
if (is == null) {
246+
throw new IOException("Resource not found: " + resourcePath);
247+
}
248+
Files.copy(is, destFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
249+
}
250+
}
251+
252+
/**
253+
* Creates a real MavenProject with JaCoCo plugin configuration
254+
*/
255+
@Contract("_ -> new")
256+
protected @NotNull MavenProject createProjectWithJacocoPlugin(String destFile) {
257+
Model model = new Model();
258+
model.setGroupId("test.group");
259+
model.setArtifactId("test-artifact");
260+
model.setVersion("1.0.0");
261+
262+
Build build = new Build();
263+
model.setBuild(build);
264+
265+
Plugin plugin = new Plugin();
266+
plugin.setGroupId("org.jacoco");
267+
plugin.setArtifactId("jacoco-maven-plugin");
268+
plugin.setVersion("0.8.12");
269+
270+
if (destFile != null) {
271+
Xpp3Dom configuration = new Xpp3Dom("configuration");
272+
Xpp3Dom destFileNode = new Xpp3Dom("destFile");
273+
destFileNode.setValue(destFile);
274+
configuration.addChild(destFileNode);
275+
plugin.setConfiguration(configuration);
276+
}
277+
278+
build.addPlugin(plugin);
279+
280+
return new MavenProject(model);
281+
}
282+
283+
/**
284+
* Creates a real MavenSession with multiple projects
285+
*/
286+
protected @NotNull MavenSession createRealMavenSession(List<MavenProject> projects) {
287+
PlexusContainer container = rule.getContainer();
288+
MavenExecutionRequest request = new DefaultMavenExecutionRequest();
289+
return new MavenSession(
290+
container,
291+
request,
292+
new DefaultMavenExecutionResult(),
293+
projects
294+
);
295+
}
174296
}

jacoco-console-reporter/src/test/java/io/github/svaningelgem/FileSystemNodeTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package io.github.svaningelgem;
22

33
import org.junit.Test;
4-
import static org.junit.Assert.*;
4+
5+
import static org.junit.Assert.assertEquals;
6+
import static org.junit.Assert.assertTrue;
57

68
public class FileSystemNodeTest {
79

0 commit comments

Comments
 (0)