RATIS-1985. Calculate code coverage (#1000)
diff --git a/.github/workflows/post-commit.yml b/.github/workflows/post-commit.yml
index 677171e..9978caa 100644
--- a/.github/workflows/post-commit.yml
+++ b/.github/workflows/post-commit.yml
@@ -16,6 +16,8 @@
on:
- push
- pull_request
+env:
+ WITH_COVERAGE: true
jobs:
build:
runs-on: ubuntu-20.04
@@ -38,6 +40,14 @@
java-version: 8
- name: Run a full build
run: ./dev-support/checks/build.sh -Prelease assembly:single
+ - name: Store binaries for tests
+ uses: actions/upload-artifact@v3
+ with:
+ name: ratis-bin
+ path: |
+ ratis-assembly/target/apache-ratis-*.tar.gz
+ !ratis-assembly/target/apache-ratis-*-src.tar.gz
+ retention-days: 1
- name: Store source tarball for compilation
uses: actions/upload-artifact@v3
with:
@@ -140,6 +150,11 @@
key: maven-repo-${{ hashFiles('**/pom.xml') }}
restore-keys: |
maven-repo-
+ - name: Setup java
+ uses: actions/setup-java@v3
+ with:
+ distribution: 'temurin'
+ java-version: 8
- name: Run tests
run: ./dev-support/checks/unit.sh -P${{ matrix.profile }}-tests
- name: Summary of failures
@@ -202,8 +217,10 @@
with:
name: findbugs
path: target/findbugs
- sonar:
- name: sonar
+ coverage:
+ needs:
+ - build
+ - unit
runs-on: ubuntu-20.04
if: (github.repository == 'apache/ratis' || github.repository == 'apache/incubator-ratis') && github.event_name != 'pull_request'
steps:
@@ -225,8 +242,24 @@
with:
distribution: 'temurin'
java-version: 17
+ - name: Download artifacts
+ uses: actions/download-artifact@v3
+ with:
+ path: target/artifacts
+ - name: Untar binaries
+ run: |
+ mkdir -p ratis-assembly/target
+ tar xzvf target/artifacts/ratis-bin/apache-ratis*.tar.gz -C ratis-assembly/target
+ - name: Calculate combined coverage
+ run: ./dev-support/checks/coverage.sh
- name: Upload coverage to Sonar
run: ./dev-support/checks/sonar.sh
env:
SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ - name: Archive build results
+ uses: actions/upload-artifact@v3
+ if: always()
+ with:
+ name: ${{ github.job }}
+ path: target/${{ github.job }}
diff --git a/dev-support/checks/build.sh b/dev-support/checks/build.sh
index 4a71ba6..6add1ae 100755
--- a/dev-support/checks/build.sh
+++ b/dev-support/checks/build.sh
@@ -18,6 +18,14 @@
source "${DIR}/../find_maven.sh"
+: ${WITH_COVERAGE:="false"}
+
+MAVEN_OPTIONS='-V -B -Dmaven.javadoc.skip=true -DskipTests --no-transfer-progress'
+
+if [[ "${WITH_COVERAGE}" != "true" ]]; then
+ MAVEN_OPTIONS="${MAVEN_OPTIONS} -Djacoco.skip"
+fi
+
export MAVEN_OPTS="-Xmx4096m"
-${MVN} -V -B -Dmaven.javadoc.skip=true -DskipTests --no-transfer-progress clean install "$@"
+${MVN} ${MAVEN_OPTIONS} clean install "$@"
exit $?
diff --git a/dev-support/checks/coverage.sh b/dev-support/checks/coverage.sh
new file mode 100755
index 0000000..a2fab9b
--- /dev/null
+++ b/dev-support/checks/coverage.sh
@@ -0,0 +1,61 @@
+#!/usr/bin/env bash
+# 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 script merges combined jacoco files (output of unit.sh)
+# and generates a report in HTML and XML formats
+
+DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+cd "$DIR/../.." || exit 1
+
+source "${DIR}/../find_maven.sh"
+
+REPORT_DIR="$DIR/../../target/coverage"
+
+mkdir -p "$REPORT_DIR"
+
+JACOCO_VERSION=$(${MVN} help:evaluate -Dexpression=jacoco.version -q -DforceStdout)
+
+#Install jacoco cli
+${MVN} --non-recursive --no-transfer-progress \
+ org.apache.maven.plugins:maven-dependency-plugin:3.6.1:copy \
+ -Dartifact=org.jacoco:org.jacoco.cli:${JACOCO_VERSION}:jar:nodeps
+
+jacoco() {
+ java -jar target/dependency/org.jacoco.cli-${JACOCO_VERSION}-nodeps.jar "$@"
+}
+
+# merge all jacoco-combined.exec files
+jacoco merge $(find target -name jacoco-combined.exec) --destfile "$REPORT_DIR/jacoco-all.exec"
+
+rm -fr target/coverage-classes target/coverage-sources
+mkdir -p target/coverage-classes target/coverage-sources
+
+# unzip all classes from the build
+find ratis-assembly/target/apache-ratis* -name 'ratis-*.jar' \
+ | grep -v -E 'examples|proto|test|thirdparty' \
+ | xargs -n1 unzip -o -q -d target/coverage-classes
+
+# copy all sources
+for d in $(find ratis* -type d -name java); do
+ cp -r "$d"/org target/coverage-sources/
+done
+
+# generate the reports
+jacoco report "$REPORT_DIR/jacoco-all.exec" \
+ --sourcefiles target/coverage-sources \
+ --classfiles target/coverage-classes \
+ --html "$REPORT_DIR/all" \
+ --xml "$REPORT_DIR/all.xml"
diff --git a/dev-support/checks/findbugs.sh b/dev-support/checks/findbugs.sh
index b6e51db..17c669b 100755
--- a/dev-support/checks/findbugs.sh
+++ b/dev-support/checks/findbugs.sh
@@ -18,6 +18,8 @@
source "${DIR}/../find_maven.sh"
+: ${WITH_COVERAGE:="false"}
+
MAVEN_OPTIONS='-B -fae --no-transfer-progress'
if ! type unionBugs >/dev/null 2>&1 || ! type convertXmlToText >/dev/null 2>&1; then
@@ -26,6 +28,10 @@
exit $?
fi
+if [[ "${WITH_COVERAGE}" != "true" ]]; then
+ MAVEN_OPTIONS="${MAVEN_OPTIONS} -Djacoco.skip"
+fi
+
#shellcheck disable=SC2086
${MVN} ${MAVEN_OPTIONS} test-compile spotbugs:spotbugs
rc=$?
diff --git a/dev-support/checks/unit.sh b/dev-support/checks/unit.sh
index 0d0c122..f7a4f30 100755
--- a/dev-support/checks/unit.sh
+++ b/dev-support/checks/unit.sh
@@ -23,6 +23,7 @@
: ${FAIL_FAST:="false"}
: ${ITERATIONS:="1"}
+: ${WITH_COVERAGE:="false"}
declare -i ITERATIONS
if [[ ${ITERATIONS} -le 0 ]]; then
@@ -33,7 +34,7 @@
mkdir -p "$REPORT_DIR"
export MAVEN_OPTS="-Xmx4096m"
-MAVEN_OPTIONS='-B --no-transfer-progress'
+MAVEN_OPTIONS='-V -B --no-transfer-progress'
if [[ "${FAIL_FAST}" == "true" ]]; then
MAVEN_OPTIONS="${MAVEN_OPTIONS} --fail-fast -Dsurefire.skipAfterFailureCount=1"
@@ -41,6 +42,10 @@
MAVEN_OPTIONS="${MAVEN_OPTIONS} --fail-at-end"
fi
+if [[ "${WITH_COVERAGE}" != "true" ]]; then
+ MAVEN_OPTIONS="${MAVEN_OPTIONS} -Djacoco.skip"
+fi
+
rc=0
for i in $(seq 1 ${ITERATIONS}); do
if [[ ${ITERATIONS} -gt 1 ]]; then
@@ -77,4 +82,9 @@
fi
done
+if [[ "${WITH_COVERAGE}" == "true" ]]; then
+ # Archive combined jacoco records
+ mvn -B -N jacoco:merge -Djacoco.destFile="${REPORT_DIR}/jacoco-combined.exec"
+fi
+
exit ${rc}
diff --git a/pom.xml b/pom.xml
index 8841644..6848807 100644
--- a/pom.xml
+++ b/pom.xml
@@ -222,6 +222,7 @@
<slf4j.version>2.0.7</slf4j.version>
<junit.jupiter.version>5.10.1</junit.jupiter.version>
+ <jacoco.version>0.8.11</jacoco.version>
</properties>
<dependencyManagement>
@@ -642,7 +643,8 @@
<reuseForks>false</reuseForks>
<trimStackTrace>false</trimStackTrace>
<forkedProcessTimeoutInSeconds>600</forkedProcessTimeoutInSeconds>
- <argLine>-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError</argLine>
+ <!-- @argLine is filled by jacoco maven plugin. @{} means late evaluation -->
+ <argLine>-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError @{argLine}</argLine>
<systemPropertyVariables>
<ratis.log.dir>${project.build.directory}/log</ratis.log.dir>
<ratis.tmp.dir>${project.build.directory}/tmp</ratis.tmp.dir>
@@ -723,6 +725,12 @@
<artifactId>maven-bundle-plugin</artifactId>
<version>${maven-bundle-plugin.version}</version>
</plugin>
+
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>${jacoco.version}</version>
+ </plugin>
</plugins>
</pluginManagement>
@@ -835,6 +843,32 @@
</execution>
</executions>
</plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <configuration>
+ <fileSets>
+ <fileSet>
+ <directory>${project.basedir}</directory>
+ <includes>
+ <include>**/jacoco.exec</include>
+ </includes>
+ <useDefaultExcludes>false</useDefaultExcludes>
+ </fileSet>
+ </fileSets>
+ </configuration>
+ <executions>
+ <execution>
+ <id>default-prepare-agent</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ <configuration>
+ <includes>org.apache.ratis.*</includes>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
diff --git a/ratis-common/src/main/java/org/apache/ratis/conf/ConfUtils.java b/ratis-common/src/main/java/org/apache/ratis/conf/ConfUtils.java
index a642ebb..c1fb926 100644
--- a/ratis-common/src/main/java/org/apache/ratis/conf/ConfUtils.java
+++ b/ratis-common/src/main/java/org/apache/ratis/conf/ConfUtils.java
@@ -373,7 +373,7 @@
return;
}
final String fieldName = f.getName();
- if ("LOG".equals(fieldName)) {
+ if ("LOG".equals(fieldName) || "$jacocoData".equals(fieldName)) {
return;
}
if (!"PREFIX".equals(fieldName)) {