This is an automated email from the ASF dual-hosted git repository.
janhoy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new db49e40825a SOLR-18338 Enable jacoco for code coverage (#4712)
db49e40825a is described below
commit db49e40825a5350283a7f6d8d660cd3e942cd0fc
Author: Jan Høydahl <[email protected]>
AuthorDate: Fri Aug 7 19:41:02 2026 +0200
SOLR-18338 Enable jacoco for code coverage (#4712)
Co-authored-by: David Smiley <[email protected]>
---
build.gradle | 8 +++
changelog/unreleased/jacoco-test-coverage.yml | 12 ++++
dev-docs/gradle-help/tests.txt | 24 +++++++
gradle/libs.versions.toml | 2 +
gradle/testing/coverage.gradle.kts | 83 ++++++++++++++++++++++
gradle/testing/defaults-tests.gradle | 3 +
.../randomization/policies/solr-tests.policy | 2 +
7 files changed, 134 insertions(+)
diff --git a/build.gradle b/build.gradle
index 80c97fe1a0f..789b782b1c2 100644
--- a/build.gradle
+++ b/build.gradle
@@ -23,6 +23,7 @@ plugins {
id 'solr.build-infra'
alias(libs.plugins.owasp.dependencycheck)
+ alias(libs.plugins.barfuin.jacocolog) apply false
alias(libs.plugins.benmanes.versions)
alias(libs.plugins.kotlin.multiplatform) apply false
alias(libs.plugins.littlerobots.versioncatalogupdate) apply false
@@ -155,6 +156,13 @@ apply from:
file('gradle/testing/alternative-jdk-support.gradle')
apply from: file('gradle/java/jar-manifest.gradle')
apply from: file('gradle/testing/retry-test.gradle')
+def withCoverage = gradle.startParameter.taskNames.any {
+ it == 'coverage' || it.endsWith(':coverage')
+} || providers.gradleProperty('tests.coverage').getOrElse('false').toBoolean()
+if (withCoverage) {
+ apply from: file('gradle/testing/coverage.gradle.kts')
+}
+
// Publishing and releasing
apply from: file('gradle/maven/defaults-maven.gradle')
diff --git a/changelog/unreleased/jacoco-test-coverage.yml
b/changelog/unreleased/jacoco-test-coverage.yml
new file mode 100644
index 00000000000..f66852b1b70
--- /dev/null
+++ b/changelog/unreleased/jacoco-test-coverage.yml
@@ -0,0 +1,12 @@
+# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc
+
+title: >
+ Add opt-in jacoco test coverage reporting to the Gradle build. Run the
"coverage" task
+ (or pass -Ptests.coverage=true) to record per-module coverage reports, and
run
+ "gradlew coverage" at the root for an aggregated report across all modules.
+type: other
+authors:
+ - name: Jan Høydahl
+links:
+ - name: SOLR-18338
+ url: https://issues.apache.org/jira/browse/SOLR-18338
diff --git a/dev-docs/gradle-help/tests.txt b/dev-docs/gradle-help/tests.txt
index c1f79cfebc9..c0c354bfed1 100644
--- a/dev-docs/gradle-help/tests.txt
+++ b/dev-docs/gradle-help/tests.txt
@@ -155,3 +155,27 @@ Using these additional options will make the results more
sparse, so it may be u
to increase the top-N count:
gradlew -p solr/core test -Ptests.profile=true -Ptests.profile.count=100
+
+
+Test coverage
+-------------
+
+Coverage is opt-in. Running the "coverage" task (or passing
-Ptests.coverage=true)
+will run the tests with jacoco instrumentation to record code coverage.
+
+Example (single module):
+
+gradlew -p solr/core coverage
+open solr/core/build/reports/jacoco/test/html/index.html
+
+If you want to use test filtering to just check a particular test, specify
+the "test" task explicitly before "coverage":
+
+gradlew -p solr/core test --tests TestDemo coverage
+open solr/core/build/reports/jacoco/test/html/index.html
+
+Running the "coverage" task on the root project runs all tests and produces
+an aggregated report across all modules:
+
+gradlew coverage
+open build/reports/jacoco/testCodeCoverageReport/html/index.html
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index e8a77111618..0c06757df4b 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -52,6 +52,7 @@ asciidoctor-mathjax = "0.0.9"
# @keep Asciidoctor tabs version used in ref-guide
asciidoctor-tabs = "1.0.0-beta.6"
azagniotov-langdetect = "12.5.2"
+barfuin-jacocolog = "4.0.2"
# @keep bats-assert version used in packaging
bats-assert = "2.0.0"
# @keep bats-core version used in packaging
@@ -201,6 +202,7 @@ threeten-bp = "1.7.3"
xerial-snappy = "1.1.10.8"
[plugins]
+barfuin-jacocolog = { id = "org.barfuin.gradle.jacocolog", version.ref =
"barfuin-jacocolog" }
benmanes-versions = { id = "com.github.ben-manes.versions", version.ref =
"benmanes-versions" }
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref =
"kotlin" }
diffplug-spotless = { id = "com.diffplug.spotless", version.ref =
"diffplug-spotless" }
diff --git a/gradle/testing/coverage.gradle.kts
b/gradle/testing/coverage.gradle.kts
new file mode 100644
index 00000000000..cb3487f6237
--- /dev/null
+++ b/gradle/testing/coverage.gradle.kts
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This adds jacoco code coverage to test tasks, along with an aggregated
+// coverage report for all projects.
+//
+// Coverage is opt-in and this script is only applied (from build.gradle, to
+// the root project) when the 'coverage' task is explicitly requested or
+// -Ptests.coverage=true is passed; see settings.gradle.
+
+// Set up an aggregated coverage report over all projects with tests.
+// Logs a coverage summary to the console after report tasks.
+plugins.apply("org.barfuin.gradle.jacocolog")
+plugins.apply("jacoco-report-aggregation")
+
+configure<ReportingExtension> {
+ reports.create<JacocoCoverageReport>("testCodeCoverageReport") {
+ testSuiteName.set("test")
+ }
+}
+
+subprojects.filter { it.file("src/test").exists() }.forEach { subproject ->
+ dependencies.add("jacocoAggregation", subproject)
+}
+
+val aggregatedReport = tasks.named<JacocoReport>("testCodeCoverageReport") {
+ // XML report is consumed by CI tooling.
+ reports.xml.required.set(true)
+ doLast {
+ logger.lifecycle("Aggregated code coverage report at:
${reports.html.entryPoint}\n")
+ }
+}
+
+tasks.register("coverage") {
+ dependsOn(aggregatedReport)
+}
+
+allprojects {
+ plugins.withType<JavaPlugin> {
+ // Applies the jacoco plugin and logs a coverage summary to the console.
+ plugins.apply("org.barfuin.gradle.jacocolog")
+
+ val jacocoTestReport = tasks.named<JacocoReport>("jacocoTestReport") {
+ // XML report is consumed by CI tooling.
+ reports.xml.required.set(true)
+ doLast {
+ logger.lifecycle("Code coverage report at:
${reports.html.entryPoint}\n")
+ }
+ }
+
+ val testTasks = tasks.withType<Test>()
+
+ tasks.register("coverage") {
+ dependsOn(testTasks)
+ dependsOn(jacocoTestReport)
+ }
+
+ testTasks.configureEach {
+ // Configure the jacoco data file to be within the test task's
+ // working directory.
+ extensions.configure(JacocoTaskExtension::class) {
+ setDestinationFile(providers.provider {
workingDir.resolve("jacoco.exec") })
+ }
+
+ // Test reports run after the test task, if it's run at all.
+ finalizedBy(jacocoTestReport)
+ }
+ }
+}
diff --git a/gradle/testing/defaults-tests.gradle
b/gradle/testing/defaults-tests.gradle
index 06e22fdbc6b..fbe118548d5 100644
--- a/gradle/testing/defaults-tests.gradle
+++ b/gradle/testing/defaults-tests.gradle
@@ -55,6 +55,9 @@ allprojects {
// Other settings.
[propName: 'tests.neverUpToDate', value: true,
description: "Make test tasks always fail the up-to-date checks
(rerun) even if the inputs have not changed."],
+ // The coverage flag is acted upon in settings.gradle and
gradle/testing/coverage.gradle.kts;
+ // it is registered here so that it is always listed by 'gradlew
testOpts'.
+ [propName: 'tests.coverage', value: false, description: "Enables
jacoco test coverage.", includeInReproLine: false],
]
// Resolves test option's value.
diff --git a/gradle/testing/randomization/policies/solr-tests.policy
b/gradle/testing/randomization/policies/solr-tests.policy
index fe21f45a04c..8709e2c0127 100644
--- a/gradle/testing/randomization/policies/solr-tests.policy
+++ b/gradle/testing/randomization/policies/solr-tests.policy
@@ -79,6 +79,8 @@ grant {
permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
// needed by jacoco to dump coverage
permission java.lang.RuntimePermission "shutdownHooks";
+ // needed by jacoco to write the per-jvm code coverage output
+ permission java.io.FilePermission "${user.dir}${/}jacoco.exec", "write";
// needed by org.apache.logging.log4j
permission java.lang.RuntimePermission "getenv.*";
permission java.lang.RuntimePermission "getClassLoader";