Compare commits

...

7 commits

7 changed files with 470 additions and 120 deletions

View file

@ -7,7 +7,6 @@ jobs:
strategy:
matrix:
java-version: [ 17, 21, 24 ]
kotlin-version: [ 1.9.25, 2.0.21, 2.1.20 ]
os: [ ubuntu-latest, windows-latest, macos-latest ]
runs-on: ${{ matrix.os }}
@ -36,4 +35,4 @@ jobs:
run: ./bld download
- name: Run tests
run: ./bld compile test
run: ./bld compile test

2
.idea/misc.xml generated
View file

@ -45,7 +45,7 @@
</option>
<option name="skipTestSources" value="false" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="17" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build" />
</component>
</project>

View file

@ -25,8 +25,8 @@ public class ExamplesBuild extends Project {
repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL);
scope(test)
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 1)))
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 1)));
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 2)))
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 2)));
}
public static void main(String[] args) {

View file

@ -2,6 +2,6 @@ bld.downloadExtensionJavadoc=false
bld.downloadExtensionSources=true
bld.downloadLocation=
bld.extension-exec=com.uwyn.rife2:bld-exec:1.0.5
bld.extension-pmd=com.uwyn.rife2:bld-pmd:1.2.2
bld.extension-pmd=com.uwyn.rife2:bld-pmd:1.2.3
bld.repositories=MAVEN_CENTRAL,MAVEN_LOCAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES
bld.version=2.2.1

View file

@ -23,6 +23,9 @@ import rife.bld.publish.PublishDeveloper;
import rife.bld.publish.PublishLicense;
import rife.bld.publish.PublishScm;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static rife.bld.dependencies.Repository.*;
@ -34,13 +37,13 @@ public class JacocoReportOperationBuild extends Project {
public JacocoReportOperationBuild() {
pkg = "rife.bld.extension";
name = "JacocoReportOperation";
version = version(0, 9, 10);
version = version(0, 9, 11, "SNAPSHOT");
javaRelease = 17;
downloadSources = true;
autoDownloadPurge = true;
repositories = List.of(MAVEN_LOCAL, MAVEN_CENTRAL, RIFE2_RELEASES, RIFE2_SNAPSHOTS);
var jacocoVersion = new VersionNumber(0, 8, 13);
@ -48,8 +51,8 @@ public class JacocoReportOperationBuild extends Project {
.include(dependency("org.jacoco", "jacoco", jacocoVersion).exclude("*", "org.jacoco.doc"))
.include(dependency("com.uwyn.rife2", "bld", version(2, 2, 1)));
scope(test)
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 1)))
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 1)))
.include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 2)))
.include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 2)))
.include(dependency("org.assertj", "assertj-core", version(3, 27, 3)));
javadocOperation()
@ -107,6 +110,32 @@ public class JacocoReportOperationBuild extends Project {
.command("scripts/cliargs.sh")
.execute();
}
super.test();
var testResultsDir = "build/test-results/test/";
var op = testOperation().fromProject(this);
op.testToolOptions().reportsDir(new File(testResultsDir));
Exception ex = null;
try {
op.execute();
} catch (Exception e) {
ex = e;
}
var xunitViewer = new File("/usr/bin/xunit-viewer");
if (xunitViewer.exists() && xunitViewer.canExecute()) {
var reportsDir = "build/reports/tests/test/";
Files.createDirectories(Path.of(reportsDir));
new ExecOperation()
.fromProject(this)
.command(xunitViewer.getPath(), "-r", testResultsDir, "-o", reportsDir + "index.html")
.execute();
}
if (ex != null) {
throw ex;
}
}
}

View file

@ -61,6 +61,10 @@ public class JacocoReportOperation extends AbstractOperation<JacocoReportOperati
* The location of the source files.
*/
final private Collection<File> sourceFiles_ = new ArrayList<>();
/**
* The test tool options.
*/
final private Collection<String> testToolOptions_ = new ArrayList<>();
/**
* The location of the CSV report.
*/
@ -212,6 +216,15 @@ public class JacocoReportOperation extends AbstractOperation<JacocoReportOperati
return csv(csv.toFile());
}
/**
* Returns the CSV report location.
*
* @return the CSV report location
*/
public File csv() {
return csv_;
}
/**
* Sets the file to write execution data to.
*
@ -243,6 +256,15 @@ public class JacocoReportOperation extends AbstractOperation<JacocoReportOperati
return destFile(destFile.toFile());
}
/**
* Returns the file to write execution data to.
*
* @return the file to write execution data to
*/
public File destFile() {
return destFile_;
}
/**
* Sets the source file encoding. The platform encoding is used by default.
*
@ -254,6 +276,15 @@ public class JacocoReportOperation extends AbstractOperation<JacocoReportOperati
return this;
}
/**
* Returns the source file encoding.
*
* @return the source file encoding
*/
public String encoding() {
return encoding_;
}
/**
* Sets the locations of the JaCoCo *.exec files to read.
*
@ -356,6 +387,10 @@ public class JacocoReportOperation extends AbstractOperation<JacocoReportOperati
"org.jacoco.agent-" + JaCoCo.VERSION.substring(0, JaCoCo.VERSION.lastIndexOf('.'))
+ "-runtime.jar").toFile(), "destfile=" + destFile_.getPath());
if (!testToolOptions_.isEmpty()) {
testOperation.testToolOptions().addAll(testToolOptions_);
}
testOperation.execute();
if (LOGGER.isLoggable(Level.INFO) && !silent()) {
@ -411,7 +446,7 @@ public class JacocoReportOperation extends AbstractOperation<JacocoReportOperati
/**
* Sets the location of the HTML report.
*
* @param html the html
* @param html the HTML
* @return this operation instance
*/
public JacocoReportOperation html(File html) {
@ -422,7 +457,7 @@ public class JacocoReportOperation extends AbstractOperation<JacocoReportOperati
/**
* Sets the location of the HTML report.
*
* @param html the html
* @param html the HTML
* @return this operation instance
*/
public JacocoReportOperation html(String html) {
@ -432,13 +467,31 @@ public class JacocoReportOperation extends AbstractOperation<JacocoReportOperati
/**
* Sets the location of the HTML report.
*
* @param html the html
* @param html the HTML
* @return this operation instance
*/
public JacocoReportOperation html(Path html) {
return html(html.toFile());
}
/**
* Returns the HTML report location.
*
* @return the HTML report location
*/
public File html() {
return html_;
}
/**
* Return the status of the quiet flag.
*
* @return {@code true} if enabled, {@code false} otherwise
*/
public boolean isQuiet() {
return silent();
}
private ExecFileLoader loadExecFiles() throws IOException {
var loader = new ExecFileLoader();
if (execFiles_.isEmpty() && LOGGER.isLoggable(Level.WARNING) && !silent()) {
@ -466,6 +519,15 @@ public class JacocoReportOperation extends AbstractOperation<JacocoReportOperati
return this;
}
/**
* Returns the name used for the report.
*
* @return the report name.
*/
public String name() {
return reportName_;
}
/**
* Suppresses all output.
*
@ -594,6 +656,47 @@ public class JacocoReportOperation extends AbstractOperation<JacocoReportOperati
return this;
}
/**
* Returns the tab stop width for the source pages.
*
* @return the tab stop width
*/
public int tabWidth() {
return tabWidth_;
}
/**
* Returns the test tool options.
*
* @return the test tool options
*/
public Collection<String> testToolOptions() {
return testToolOptions_;
}
/**
* Sets the test tool options.
*
* @param options The options to set
* @return this operation instance
* @see #testToolOptions(Collection)
*/
public JacocoReportOperation testToolOptions(String... options) {
return testToolOptions(List.of(options));
}
/**
* Sets the test tool options.
*
* @param options The options to set
* @return this operation instance
* @see #testToolOptions(String...)
*/
public JacocoReportOperation testToolOptions(Collection<String> options) {
testToolOptions_.addAll(options);
return this;
}
private void writeReports(IBundleCoverage bundle, ExecFileLoader loader)
throws IOException {
if (LOGGER.isLoggable(Level.INFO) && !silent()) {
@ -642,4 +745,13 @@ public class JacocoReportOperation extends AbstractOperation<JacocoReportOperati
public JacocoReportOperation xml(Path xml) {
return xml(xml.toFile());
}
/**
* Returns the XML report location.
*
* @return the XML report location
*/
public File xml() {
return xml_;
}
}

View file

@ -17,6 +17,8 @@
package rife.bld.extension;
import org.assertj.core.api.AutoCloseableSoftAssertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
@ -36,16 +38,16 @@ import static org.assertj.core.api.Assertions.assertThatCode;
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
class JacocoReportOperationTest {
final File csv;
final File html;
final File csvFile;
final File htmlDir;
final Path tempDir;
final File xml;
final File xmlFile;
JacocoReportOperationTest() throws IOException {
tempDir = Files.createTempDirectory("jacoco-test");
csv = (new File(tempDir.toFile(), "jacoco.csv"));
html = (new File(tempDir.toFile(), "html"));
xml = (new File(tempDir.toFile(), "jacoco.xml"));
csvFile = (new File(tempDir.toFile(), "jacoco.csv"));
htmlDir = (new File(tempDir.toFile(), "html"));
xmlFile = (new File(tempDir.toFile(), "jacoco.xml"));
}
static void deleteOnExit(File folder) {
@ -61,7 +63,7 @@ class JacocoReportOperationTest {
@Test
@EnabledOnOs(OS.LINUX)
void checkAllParamsTest() throws IOException {
void checkAllParams() throws IOException {
var supported = List.of("<execfiles>",
"--classfiles",
"--csv",
@ -79,131 +81,339 @@ class JacocoReportOperationTest {
}
@Test
void executeFailureTest() {
var op = new JacocoReportOperation().fromProject(new Project());
assertThatCode(op::execute).isInstanceOf(ExitStatusException.class);
@Nested
@DisplayName("Execute Tests")
class ExecuteTests {
@Test
void execute() throws Exception {
newJacocoReportOperation().execute();
assertThat(csvFile).exists();
assertThat(htmlDir).isDirectory();
assertThat(xmlFile).exists();
try (var softly = new AutoCloseableSoftAssertions()) {
try (var lines = Files.lines(xmlFile.toPath())) {
softly.assertThat(lines.anyMatch(s ->
s.contains("<counter type=\"INSTRUCTION\" missed=\"0\" covered=\"3\"/>"))).isTrue();
}
}
assertThat(Path.of(htmlDir.getPath(), "com.example", "Examples.java.html")).exists();
}
@Test
void executeFailure() {
var op = new JacocoReportOperation().fromProject(new Project());
assertThatCode(op::execute).isInstanceOf(ExitStatusException.class);
}
JacocoReportOperation newJacocoReportOperation() {
var op = new JacocoReportOperation()
.fromProject(new Project())
.csv(csvFile)
.html(htmlDir)
.xml(xmlFile)
.classFiles(new File("src/test/resources/Examples.class"))
.sourceFiles(new File("examples/src/main/java"))
.execFiles(new File("src/test/resources/jacoco.exec"));
deleteOnExit(tempDir.toFile());
return op;
}
}
@Test
void executeTest() throws Exception {
newJacocoReportOperation().execute();
assertThat(csv).exists();
assertThat(html).isDirectory();
assertThat(xml).exists();
try (var softly = new AutoCloseableSoftAssertions()) {
try (var lines = Files.lines(xml.toPath())) {
softly.assertThat(lines.anyMatch(s ->
s.contains("<counter type=\"INSTRUCTION\" missed=\"0\" covered=\"3\"/>"))).isTrue();
@Nested
@DisplayName("Options Tests")
class OptionsTests {
public static final String FOO = "foo";
private final File fooFile = new File(FOO);
@Test
void csvAsFile() {
var op = new JacocoReportOperation();
op.csv(fooFile);
assertThat(op.csv()).isEqualTo(fooFile);
}
@Test
void csvAsPath() {
var fooPath = fooFile.toPath();
var op = new JacocoReportOperation();
op.csv(fooPath);
assertThat(op.csv()).isEqualTo(fooFile);
}
@Test
void csvAsString() {
var op = new JacocoReportOperation();
op.csv(FOO);
assertThat(op.csv()).isEqualTo(fooFile);
}
@Test
void htmlAsFile() {
var op = new JacocoReportOperation();
op.html(fooFile);
assertThat(op.html()).isEqualTo(fooFile);
}
@Test
void htmlAsPath() {
var fooPath = fooFile.toPath();
var op = new JacocoReportOperation();
op.html(fooPath);
assertThat(op.html()).isEqualTo(fooFile);
}
@Test
void htmlAsString() {
var op = new JacocoReportOperation();
op.html(FOO);
assertThat(op.html()).isEqualTo(fooFile);
}
@Test
void quietIsFalse() {
var op = new JacocoReportOperation();
op.quiet(false);
assertThat(op.isQuiet()).isFalse();
}
@Test
void quietIsTrue() {
var op = new JacocoReportOperation();
op.quiet(true);
assertThat(op.isQuiet()).isTrue();
}
@Test
void reportName() {
var op = new JacocoReportOperation();
op.name(FOO);
assertThat(op.name()).isEqualTo(FOO);
}
@Test
void tabWidth() {
var op = new JacocoReportOperation();
op.tabWidth(4);
assertThat(op.tabWidth()).isEqualTo(4);
}
@Test
void xmlAsFile() {
var op = new JacocoReportOperation();
op.xml(fooFile);
assertThat(op.xml()).isEqualTo(fooFile);
}
@Test
void xmlAsPath() {
var fooPath = fooFile.toPath();
var op = new JacocoReportOperation();
op.xml(fooPath);
assertThat(op.xml()).isEqualTo(fooFile);
}
@Test
void xmlAsString() {
var op = new JacocoReportOperation();
op.xml(FOO);
assertThat(op.xml()).isEqualTo(fooFile);
}
@Nested
@DisplayName("Test Tool Options Tests")
class TestToolOptionsTests {
public static final String BAR = "bar";
@Test
void testToolOptionsAsArray() {
var op = new JacocoReportOperation();
op = op.testToolOptions(FOO, BAR);
assertThat(op.testToolOptions()).contains(FOO, BAR);
}
@Test
void testToolOptionsAsList() {
var op = new JacocoReportOperation();
op.testToolOptions(List.of(FOO, BAR));
assertThat(op.testToolOptions()).contains(FOO, BAR);
}
}
assertThat(Path.of(html.getPath(), "com.example", "Examples.java.html")).exists();
}
JacocoReportOperation newJacocoReportOperation() {
var op = new JacocoReportOperation()
.fromProject(new Project())
.csv(csv)
.html(html)
.xml(xml)
.classFiles(new File("src/test/resources/Examples.class"))
.sourceFiles(new File("examples/src/main/java"))
.execFiles(new File("src/test/resources/jacoco.exec"));
@Nested
@DisplayName("File Operation Tests")
class FilesOperationTests {
private final File barFile = new File("bar");
private final File fooFile = new File("foo");
private final JacocoReportOperation op = new JacocoReportOperation();
deleteOnExit(tempDir.toFile());
@Nested
@DisplayName("Class Files Tests")
class ClassFilesTests {
@Test
void classFilesAsFileArray() {
op.classFiles().clear();
assertThat(op.classFiles()).isEmpty();
op.classFiles(fooFile, barFile);
assertThat(op.classFiles()).contains(fooFile, barFile);
}
return op;
}
@Test
void classFilesAsFileList() {
op.classFiles().clear();
assertThat(op.classFiles()).isEmpty();
op.classFiles(List.of(fooFile, barFile));
assertThat(op.classFiles()).contains(fooFile, barFile);
}
@Test
void testClassFiles() {
var foo = new File("foo");
var bar = new File("bar");
@Test
void classFilesAsPathArray() {
op.classFiles().clear();
assertThat(op.classFiles()).isEmpty();
op.classFiles(fooFile.toPath(), barFile.toPath());
assertThat(op.classFiles()).contains(fooFile, barFile);
}
var op = new JacocoReportOperation().classFiles("foo", "bar");
assertThat(op.classFiles()).as("String...").contains(foo, bar);
op.classFiles().clear();
@Test
void classFilesAsPathList() {
op.classFiles().clear();
assertThat(op.classFiles()).isEmpty();
op.classFilesPaths(List.of(fooFile.toPath(), barFile.toPath()));
assertThat(op.classFiles()).contains(fooFile, barFile);
}
op = op.classFiles(foo, bar);
assertThat(op.classFiles()).as("File...").contains(foo, bar);
op.classFiles().clear();
@Test
void classFilesAsStringArray() {
op.classFiles().clear();
assertThat(op.classFiles()).isEmpty();
op.classFiles("foo", "bar");
assertThat(op.classFiles()).contains(fooFile, barFile);
}
op = op.classFiles(foo.toPath(), bar.toPath());
assertThat(op.classFiles()).as("Path...").contains(foo, bar);
op.classFiles().clear();
@Test
void classFilesAsStringList() {
op.classFiles().clear();
assertThat(op.classFiles()).isEmpty();
op.classFilesStrings(List.of("foo", "bar"));
assertThat(op.classFiles()).contains(fooFile, barFile);
}
}
op = op.classFilesStrings(List.of("foo", "bar"));
assertThat(op.classFiles()).as("List(String...)").contains(foo, bar);
op.classFiles().clear();
@Nested
@DisplayName("Exec Files Tests")
class ExecFilesTests {
private final File barFile = new File("bar");
private final File fooFile = new File("foo");
private final JacocoReportOperation op = new JacocoReportOperation();
op = op.classFiles(List.of(foo, bar));
assertThat(op.classFiles()).as("File...").contains(foo, bar);
op.classFiles().clear();
@Test
void execFilesAsFileArray() {
op.execFiles().clear();
assertThat(op.execFiles()).isEmpty();
op.execFiles(fooFile, barFile);
assertThat(op.execFiles()).contains(fooFile, barFile);
}
op = op.classFilesPaths(List.of(foo.toPath(), bar.toPath()));
assertThat(op.classFiles()).as("Path...").contains(foo, bar);
op.classFiles().clear();
}
@Test
void execFilesAsFileList() {
op.execFiles().clear();
assertThat(op.execFiles()).isEmpty();
op.execFiles(List.of(fooFile, barFile));
assertThat(op.execFiles()).contains(fooFile, barFile);
}
@Test
void testExecFiles() {
var foo = new File("foo");
var bar = new File("bar");
@Test
void execFilesAsPathArray() {
op.execFiles().clear();
assertThat(op.execFiles()).isEmpty();
op.execFiles(fooFile.toPath(), barFile.toPath());
assertThat(op.execFiles()).contains(fooFile, barFile);
}
var op = new JacocoReportOperation().execFiles("foo", "bar");
assertThat(op.execFiles()).as("String...").contains(foo, bar);
op.execFiles().clear();
@Test
void execFilesAsPathList() {
op.execFiles().clear();
assertThat(op.execFiles()).isEmpty();
op.execFilesPaths(List.of(fooFile.toPath(), barFile.toPath()));
assertThat(op.execFiles()).contains(fooFile, barFile);
op.execFiles().clear();
}
op = op.execFiles(foo, bar);
assertThat(op.execFiles()).as("File...").contains(foo, bar);
op.execFiles().clear();
@Test
void execFilesAsStringArray() {
op.execFiles().clear();
assertThat(op.execFiles()).isEmpty();
op.execFiles("foo", "bar");
assertThat(op.execFiles()).contains(fooFile, barFile);
}
op = op.execFiles(foo.toPath(), bar.toPath());
assertThat(op.execFiles()).as("Path...").contains(foo, bar);
op.execFiles().clear();
@Test
void execFilesAsStringList() {
op.execFiles().clear();
assertThat(op.execFiles()).isEmpty();
op.execFilesStrings(List.of("foo", "bar"));
assertThat(op.execFiles()).contains(fooFile, barFile);
}
}
op = op.execFilesStrings(List.of("foo", "bar"));
assertThat(op.execFiles()).as("List(String...)").contains(foo, bar);
op.execFiles().clear();
@Nested
@DisplayName("Source Files Tests")
class SourceFilesTests {
private final File barFile = new File("bar");
private final File fooFile = new File("foo");
private final JacocoReportOperation op = new JacocoReportOperation();
op = op.execFiles(List.of(foo, bar));
assertThat(op.execFiles()).as("File...").contains(foo, bar);
op.execFiles().clear();
@Test
void sourceFilesAsFileArray() {
op.sourceFiles().clear();
assertThat(op.sourceFiles()).isEmpty();
op.sourceFiles(fooFile, barFile);
assertThat(op.sourceFiles()).as("File...").contains(fooFile, barFile);
}
op = op.execFilesPaths(List.of(foo.toPath(), bar.toPath()));
assertThat(op.execFiles()).as("Path...").contains(foo, bar);
op.execFiles().clear();
}
@Test
void sourceFilesAsFileList() {
op.sourceFiles().clear();
assertThat(op.sourceFiles()).isEmpty();
op.sourceFiles(List.of(fooFile, barFile));
assertThat(op.sourceFiles()).as("File...").contains(fooFile, barFile);
}
@Test
void testSourceFiles() {
var foo = new File("foo");
var bar = new File("bar");
@Test
void sourceFilesAsPathList() {
op.sourceFiles().clear();
assertThat(op.sourceFiles()).isEmpty();
op.sourceFilesPaths(List.of(fooFile.toPath(), barFile.toPath()));
assertThat(op.sourceFiles()).as("Path...").contains(fooFile, barFile);
}
var op = new JacocoReportOperation().sourceFiles("foo", "bar");
assertThat(op.sourceFiles()).as("String...").contains(foo, bar);
op.sourceFiles().clear();
@Test
void sourceFilesAsStringArray() {
op.sourceFiles().clear();
assertThat(op.sourceFiles()).isEmpty();
op.sourceFiles("foo", "bar");
assertThat(op.sourceFiles()).as("String...").contains(fooFile, barFile);
}
op = op.sourceFiles(foo, bar);
assertThat(op.sourceFiles()).as("File...").contains(foo, bar);
op.sourceFiles().clear();
@Test
void sourceFilesAsStringList() {
op.sourceFiles().clear();
assertThat(op.sourceFiles()).isEmpty();
op.sourceFilesStrings(List.of("foo", "bar"));
assertThat(op.sourceFiles()).as("List(String...)").contains(fooFile, barFile);
}
op = op.sourceFiles(foo.toPath(), bar.toPath());
assertThat(op.sourceFiles()).as("Path...").contains(foo, bar);
op.sourceFiles().clear();
op = op.sourceFilesStrings(List.of("foo", "bar"));
assertThat(op.sourceFiles()).as("List(String...)").contains(foo, bar);
op.sourceFiles().clear();
op = op.sourceFiles(List.of(foo, bar));
assertThat(op.sourceFiles()).as("File...").contains(foo, bar);
op.sourceFiles().clear();
op = op.sourceFilesPaths(List.of(foo.toPath(), bar.toPath()));
assertThat(op.sourceFiles()).as("Path...").contains(foo, bar);
op.sourceFiles().clear();
@Test
void sourceFilesPathArray() {
op.sourceFiles().clear();
assertThat(op.sourceFiles()).isEmpty();
op.sourceFiles(fooFile.toPath(), barFile.toPath());
assertThat(op.sourceFiles()).as("Path...").contains(fooFile, barFile);
}
}
}
}