Added jacoco.exec generation

This commit is contained in:
Erik C. Thauvin 2023-08-10 22:06:11 -07:00
parent 8e94bb4d60
commit 9e6471c74b
4 changed files with 30 additions and 87 deletions

1
.idea/misc.xml generated
View file

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="EntryPointsManager"> <component name="EntryPointsManager">
<entry_points version="2.0"> <entry_points version="2.0">

View file

@ -23,9 +23,7 @@ import rife.bld.publish.PublishDeveloper;
import rife.bld.publish.PublishLicense; import rife.bld.publish.PublishLicense;
import rife.bld.publish.PublishScm; import rife.bld.publish.PublishScm;
import java.io.File;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import static rife.bld.dependencies.Repository.*; import static rife.bld.dependencies.Repository.*;
import static rife.bld.dependencies.Scope.*; import static rife.bld.dependencies.Scope.*;
@ -43,7 +41,7 @@ public class JacocoReportOperationBuild extends Project {
repositories = List.of(MAVEN_CENTRAL, RIFE2_RELEASES); repositories = List.of(MAVEN_CENTRAL, RIFE2_RELEASES);
var jacocoVersion = new VersionNumber(0, 8, 10); var jacocoVersion = new VersionNumber(0, 8, 10);
var rife2 = version(1,7,0); var rife2 = version(1, 7, 0);
scope(compile) scope(compile)
.include(dependency("org.jacoco", "jacoco", jacocoVersion).exclude("*", "org.jacoco.doc")) .include(dependency("org.jacoco", "jacoco", jacocoVersion).exclude("*", "org.jacoco.doc"))
.include(dependency("com.uwyn.rife2", "rife2", rife2)) .include(dependency("com.uwyn.rife2", "rife2", rife2))
@ -51,8 +49,8 @@ public class JacocoReportOperationBuild extends Project {
scope(runtime) scope(runtime)
.include(dependency("org.jacoco", "jacoco", jacocoVersion).exclude("*", "org.jacoco.doc")); .include(dependency("org.jacoco", "jacoco", jacocoVersion).exclude("*", "org.jacoco.doc"));
scope(test) scope(test)
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 9, 3))) .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 10, 0)))
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 9, 3))) .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 10, 0)))
.include(dependency("org.assertj:assertj-joda-time:2.2.0")); .include(dependency("org.assertj:assertj-joda-time:2.2.0"));
testOperation().mainClass("rife.bld.extension.JacocoReportOperationTest"); testOperation().mainClass("rife.bld.extension.JacocoReportOperationTest");
@ -63,8 +61,8 @@ public class JacocoReportOperationBuild extends Project {
.link("https://rife2.github.io/rife2/"); .link("https://rife2.github.io/rife2/");
publishOperation() publishOperation()
// .repository(version.isSnapshot() ? repository("rife2-snapshot") : repository("rife2")) .repository(version.isSnapshot() ? repository("rife2-snapshot") : repository("rife2"))
.repository(MAVEN_LOCAL) // .repository(MAVEN_LOCAL)
.info() .info()
.groupId("com.uwyn.rife2") .groupId("com.uwyn.rife2")
.artifactId("bld-jacoco-report") .artifactId("bld-jacoco-report")
@ -93,5 +91,4 @@ public class JacocoReportOperationBuild extends Project {
.ruleSets("config/pmd.xml") .ruleSets("config/pmd.xml")
.execute(); .execute();
} }
} }

View file

@ -16,24 +16,22 @@
package rife.bld.extension; package rife.bld.extension;
import org.jacoco.core.JaCoCo;
import org.jacoco.core.analysis.Analyzer; import org.jacoco.core.analysis.Analyzer;
import org.jacoco.core.analysis.CoverageBuilder; import org.jacoco.core.analysis.CoverageBuilder;
import org.jacoco.core.analysis.IBundleCoverage; import org.jacoco.core.analysis.IBundleCoverage;
import org.jacoco.core.data.ExecutionDataStore; import org.jacoco.core.data.ExecutionDataStore;
import org.jacoco.core.instr.Instrumenter;
import org.jacoco.core.runtime.OfflineInstrumentationAccessGenerator;
import org.jacoco.core.tools.ExecFileLoader; import org.jacoco.core.tools.ExecFileLoader;
import org.jacoco.report.*; import org.jacoco.report.*;
import org.jacoco.report.csv.CSVFormatter; import org.jacoco.report.csv.CSVFormatter;
import org.jacoco.report.html.HTMLFormatter; import org.jacoco.report.html.HTMLFormatter;
import org.jacoco.report.xml.XMLFormatter; import org.jacoco.report.xml.XMLFormatter;
import rife.bld.BaseProject; import rife.bld.BaseProject;
import rife.bld.operations.JUnitOperation; import rife.bld.operations.AbstractOperation;
import rife.bld.operations.exceptions.ExitStatusException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
@ -49,16 +47,14 @@ import java.util.logging.Logger;
* @author <a href="https://erik.thauvin.net/">Erik C. Thauvin</a> * @author <a href="https://erik.thauvin.net/">Erik C. Thauvin</a>
* @since 1.0 * @since 1.0
*/ */
public class JacocoReportOperation extends JUnitOperation { public class JacocoReportOperation extends AbstractOperation<JacocoReportOperation> {
private static final Logger LOGGER = Logger.getLogger(JacocoReportOperation.class.getName()); private static final Logger LOGGER = Logger.getLogger(JacocoReportOperation.class.getName());
private final List<File> classFiles = new ArrayList<>(); private final List<File> classFiles = new ArrayList<>();
private final List<File> execFiles = new ArrayList<>(); private final List<File> execFiles = new ArrayList<>();
private final List<File> instrumentedFiles = new ArrayList<>();
private final List<File> sourceFiles = new ArrayList<>(); private final List<File> sourceFiles = new ArrayList<>();
private File csv; private File csv;
private String encoding; private String encoding;
private File html; private File html;
private Instrumenter instrumenter;
private String name = "JaCoCo Coverage Report"; private String name = "JaCoCo Coverage Report";
private BaseProject project; private BaseProject project;
private boolean quiet; private boolean quiet;
@ -75,22 +71,6 @@ public class JacocoReportOperation extends JUnitOperation {
return builder.getBundle(name); return builder.getBundle(name);
} }
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
private void buildInstrumentedFiles(File dest) throws IOException {
var total = 0;
for (var f : classFiles) {
if (f.isFile()) {
total += instrument(f, new File(dest, f.getName()));
} else {
total += instrumentRecursive(f, dest);
}
}
if (LOGGER.isLoggable(Level.INFO) && !quiet) {
LOGGER.log(Level.INFO, "{0} classes instrumented to {1}.",
new Object[]{total, dest.getAbsolutePath()});
}
}
/** /**
* Sets the locations of Java class files. * Sets the locations of Java class files.
**/ **/
@ -117,7 +97,7 @@ public class JacocoReportOperation extends JUnitOperation {
/** /**
* Sets the locations of the JaCoCo *.exec files to read. * Sets the locations of the JaCoCo *.exec files to read.
**/ */
public JacocoReportOperation execFiles(File... execFiles) { public JacocoReportOperation execFiles(File... execFiles) {
this.execFiles.addAll(Arrays.stream(execFiles).toList()); this.execFiles.addAll(Arrays.stream(execFiles).toList());
return this; return this;
@ -125,21 +105,29 @@ public class JacocoReportOperation extends JUnitOperation {
/** /**
* Performs the operation execution that can be wrapped by the {@code #executeOnce} call. * Performs the operation execution that can be wrapped by the {@code #executeOnce} call.
*
* @since 1.5.10
*/ */
@Override @Override
public void execute() throws IOException { public void execute() throws IOException {
if (project == null && LOGGER.isLoggable(Level.SEVERE)) { if ((project == null) && LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.severe("A project must be specified."); LOGGER.severe("A project and version must be specified.");
} else { } else {
var buildJacocoReportsDir = Path.of(project.buildDirectory().getPath(), "reports", "jacoco", "test").toFile(); var buildJacocoReportsDir = Path.of(project.buildDirectory().getPath(), "reports", "jacoco", "test").toFile();
var buildJacocoExecDir = Path.of(project.buildDirectory().getPath(), "jacoco").toFile(); var buildJacocoExecDir = Path.of(project.buildDirectory().getPath(), "jacoco").toFile();
var buildJacocoClassesDir = Path.of(buildJacocoExecDir.getPath(), "classes").toFile(); var buildJacocoExec = Path.of(buildJacocoExecDir.getPath(), "jacoco.exec").toFile();
instrumenter = new Instrumenter(new OfflineInstrumentationAccessGenerator()); // project.testOperation().fromProject(project).javaOptions().javaAgent(
instrumenter.setRemoveSignatures(true); // Path.of(project.libBldDirectory().getPath(), "org.jacoco.agent-"
// + JaCoCo.VERSION.substring(0, JaCoCo.VERSION.lastIndexOf('.')) + "-runtime.jar").toFile(),
// "destfile=" + Path.of(buildJacocoExecDir.getPath(), "jacoco.exec"));
project.testOperation().fromProject(project).javaOptions().add("-javaagent:" +
Path.of(project.libBldDirectory().getPath(), "org.jacoco.agent-"
+ JaCoCo.VERSION.substring(0, JaCoCo.VERSION.lastIndexOf('.')) + "-runtime.jar")
+ "=destfile=" + Path.of(buildJacocoExecDir.getPath(), "jacoco.exec"));
try {
project.testOperation().execute();
} catch (InterruptedException | ExitStatusException e) {
throw new IOException(e);
}
if (sourceFiles.isEmpty()) { if (sourceFiles.isEmpty()) {
sourceFiles.add(project.srcDirectory()); sourceFiles.add(project.srcDirectory());
@ -163,15 +151,8 @@ public class JacocoReportOperation extends JUnitOperation {
csv = new File(buildJacocoReportsDir, "jacocoTestReport.csv"); csv = new File(buildJacocoReportsDir, "jacocoTestReport.csv");
} }
if (execFiles.isEmpty()) { if (execFiles.isEmpty() && (buildJacocoExec.exists())) {
//noinspection ResultOfMethodCallIgnored execFiles.add(buildJacocoExec);
buildJacocoClassesDir.mkdirs();
buildInstrumentedFiles(buildJacocoClassesDir);
var files = buildJacocoClassesDir.listFiles();
if (files != null) {
instrumentedFiles.addAll(Arrays.asList(files));
}
} }
//noinspection ResultOfMethodCallIgnored //noinspection ResultOfMethodCallIgnored
@ -186,7 +167,6 @@ public class JacocoReportOperation extends JUnitOperation {
/** /**
* Configure the operation from a {@link BaseProject}. * Configure the operation from a {@link BaseProject}.
*/ */
@Override
public JacocoReportOperation fromProject(BaseProject project) { public JacocoReportOperation fromProject(BaseProject project) {
this.project = project; this.project = project;
return this; return this;
@ -200,39 +180,6 @@ public class JacocoReportOperation extends JUnitOperation {
return this; return this;
} }
private int instrument(final File src, final File dest) throws IOException {
//noinspection ResultOfMethodCallIgnored
dest.getParentFile().mkdirs();
try (InputStream input = Files.newInputStream(src.toPath())) {
try (OutputStream output = Files.newOutputStream(dest.toPath())) {
return instrumenter.instrumentAll(input, output,
src.getAbsolutePath());
}
} catch (final IOException e) {
//noinspection ResultOfMethodCallIgnored
dest.delete();
throw e;
}
}
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
private int instrumentRecursive(final File src, final File dest)
throws IOException {
var total = 0;
if (src.isDirectory()) {
var listFiles = src.listFiles();
if (listFiles != null) {
for (var child : listFiles) {
total += instrumentRecursive(child,
new File(dest, child.getName()));
}
}
} else {
total += instrument(src, dest);
}
return total;
}
private ExecFileLoader loadExecFiles() throws IOException { private ExecFileLoader loadExecFiles() throws IOException {
var loader = new ExecFileLoader(); var loader = new ExecFileLoader();
if (execFiles.isEmpty() && LOGGER.isLoggable(Level.WARNING) && !quiet) { if (execFiles.isEmpty() && LOGGER.isLoggable(Level.WARNING) && !quiet) {
@ -294,7 +241,6 @@ public class JacocoReportOperation extends JUnitOperation {
return this; return this;
} }
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops") @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
private ISourceFileLocator sourceLocator() { private ISourceFileLocator sourceLocator() {
var multi = new MultiSourceFileLocator(tabWidth); var multi = new MultiSourceFileLocator(tabWidth);

View file

@ -17,10 +17,11 @@
package rife.bld.extension; package rife.bld.extension;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class JacocoReportOperationTest { class JacocoReportOperationTest {
@Test @Test
void executeTest() { void executeTest() {
assertThat(true).isTrue(); // TODO
} }
} }