This is an automated email from the ASF dual-hosted git repository.
moonchen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 4c69f8582b ci: modernize the coverage helper script (#13305)
4c69f8582b is described below
commit 4c69f8582b3005fca44c79d5fc0f189f032ddb72
Author: Mo Chen <[email protected]>
AuthorDate: Mon Jun 22 22:17:49 2026 -0500
ci: modernize the coverage helper script (#13305)
Rework ci/coverage to drive an out-of-source CMake build and an optional
autest run (AUTEST='*/tls/*' or AUTEST=all) when gathering coverage, and
report via gcov/gcovr.
---
ci/coverage | 178 +++++++++++++++++++++++++++++++++---------------------------
1 file changed, 98 insertions(+), 80 deletions(-)
diff --git a/ci/coverage b/ci/coverage
index 29b9aac0b4..97a83ffbba 100755
--- a/ci/coverage
+++ b/ci/coverage
@@ -16,93 +16,111 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-LCOV=${LCOV:-lcov}
-GENHTML=${GENHTML:-genhtml}
-
-TMPDIR=${TMPDIR:-/tmp}
-BUILDID="org.apache.trafficserver.$$"
-
-SRCROOT=${SRCROOT:-$(cd $(dirname $0)/.. && pwd)} # where the source lives
-OBJROOT=${OBJROOT:-"$TMPDIR/$BUILDID/obj"} # where we are building
-DSTROOT=${DSTROOT:-"$TMPDIR/$BUILDID/dst"} # where we are installing
-
-# Force low make parallelization so that the build can complete in a VM with
-# only a small amount of memory.
-NPROCS=${NPROCS:-2}
-
-mkdir -p $SRCROOT
-mkdir -p $OBJROOT
-mkdir -p $DSTROOT
-
-autogen() {
- (
- cd "$SRCROOT"
- [ configure -nt configure.ac -a Makefile.in -nt Makefile.am ] ||
autoreconf -fi
- )
-}
+# Build ATS with gcov instrumentation, run the unit tests (and optionally
+# autests), and produce a coverage report with gcovr.
+#
+# Usage:
+# ci/coverage [extra cmake args...]
+#
+# Environment overrides:
+# BUILDDIR build tree (default: $SRCROOT/build-coverage)
+# PREFIX install prefix (default: /tmp/ts-coverage)
+# NPROCS build parallelism (default: nproc)
+# GCOVR gcovr command (default: gcovr, falls back to uvx
gcovr)
+# AUTEST run autests too if set to a -f/--filter basename glob,
+# e.g. AUTEST='tls_*' or AUTEST=all for the whole suite
+#
+# Requires: cmake, ninja or make, gcc/gcov, and gcovr (pip install gcovr).
+
+set -e
+
+SRCROOT=${SRCROOT:-$(cd "$(dirname "$0")"/.. && pwd)}
+BUILDDIR=${BUILDDIR:-$SRCROOT/build-coverage}
+PREFIX=${PREFIX:-/tmp/ts-coverage}
+NPROCS=${NPROCS:-$(nproc 2>/dev/null || echo 4)}
+
+GCOVR=${GCOVR:-gcovr}
+if ! command -v "${GCOVR%% *}" >/dev/null 2>&1; then
+ if command -v uvx >/dev/null 2>&1; then
+ GCOVR="uvx gcovr"
+ else
+ echo "gcovr not found; install it with 'pip install gcovr'" >&2
+ exit 1
+ fi
+fi
+
+# --coverage instruments compile and link. Atomic profile updates keep the
+# counters sane in ATS's heavily threaded runtime, and absolute paths in the
+# notes files let gcovr resolve sources from any working directory.
+COVERAGE_FLAGS="-g -O0 --coverage -fprofile-update=atomic -fprofile-abs-path"
configure() {
- (
- cd $OBJROOT
- $SRCROOT/configure \
- --prefix=$DSTROOT \
- --enable-debug \
- --enable-coverage \
- --enable-werror \
- --enable-example-plugins \
- --enable-test-tools \
- --enable-experimental-plugins \
- CC="$CC" \
- CXX="$CXX" \
- "$@"
- )
+ # Enabling autest pulls in Python3/uv/nc and the proxy-verifier toolchain at
+ # configure time, so only ask for it when AUTEST actually selects a run.
+ local autest_args=()
+ if [ -n "$AUTEST" ]; then
+ autest_args=(-DENABLE_AUTEST=ON)
+ fi
+
+ cmake -S "$SRCROOT" -B "$BUILDDIR" \
+ -DCMAKE_BUILD_TYPE=Debug \
+ -DCMAKE_INSTALL_PREFIX="$PREFIX" \
+ -DCMAKE_COMPILE_WARNING_AS_ERROR=OFF \
+ -DBUILD_TESTING=ON \
+ "${autest_args[@]}" \
+ -DBUILD_EXPERIMENTAL_PLUGINS=ON \
+ -DENABLE_EXAMPLE=ON \
+ -DCMAKE_CXX_FLAGS_DEBUG="$COVERAGE_FLAGS" \
+ -DCMAKE_C_FLAGS_DEBUG="$COVERAGE_FLAGS" \
+ "$@"
}
build() {
- ( cd $OBJROOT && $MAKE -j $NPROCS )
- ( cd $OBJROOT && $MAKE install )
+ cmake --build "$BUILDDIR" -j "$NPROCS"
+ cmake --install "$BUILDDIR"
}
-regress() {
- ( cd $OBJROOT && $MAKE check ) && \
- $DSTROOT/bin/traffic_server -k -K -R 1
+run_tests() {
+ # Reset counters so the report reflects exactly this run.
+ find "$BUILDDIR" -name '*.gcda' -delete
+
+ ctest --test-dir "$BUILDDIR" -j "$NPROCS"
+
+ if [ -n "$AUTEST" ]; then
+ local filter_args=()
+ if [ "$AUTEST" != all ]; then
+ # Quote the pattern: the parallel runner fnmatches it against each test's
+ # basename (e.g. 'tls_*'), so it must reach autest verbatim rather than
be
+ # glob-expanded by the shell first.
+ filter_args=(-f "$AUTEST")
+ fi
+ # Match ctest's parallelism: -j routes autest.sh through
autest-parallel.py,
+ # which already aims --sandbox at a per-build-tree path under /tmp, so
+ # concurrent coverage runs in separate build trees don't trample each
other.
+ (cd "$BUILDDIR/tests" && ./autest.sh -j "$NPROCS" "${filter_args[@]}")
+ fi
}
-CC=${CC:-gcc}
-CXX=${CXX:-g++}
-MAKE=${MAKE:-make}
-export CC CXX MAKE
-
-case $VERBOSE in
- Y*) set -x ;;
- y*) set -x ;;
- 1) set -x ;;
- *) set +x ;;
-esac
-
-autogen || exit 1
-configure "$@" || exit 1
-build || exit 1
-
-$LCOV --quiet --capture --initial --directory $OBJROOT --output-file
initial.info
-
-regress
-
-$LCOV --quiet --capture --directory $OBJROOT --output-file tests.info
-
-# The --add-tracefile option refuses to create an output file with
-# --output-file (contrary to documentation). Capture the combined
-# coverage from stdout instead.
-$LCOV \
- --add-tracefile initial.info \
- --add-tracefile tests.info \
-> combined.info
-
-# genhtml will puke because it can't find the original TSConfig files.
-# We don't need to bother generation anything for /usr/include.
-$LCOV --remove combined.info \
- 'TsConfigSyntax.*' \
- 'TsConfigGrammar.*' \
- '/usr/include/*' > coverage.info
+report() {
+ cd "$SRCROOT"
+ # no_working_dir_found: vendored/generated objects whose recorded cwd is
+ # gone. merge-use-line-min: sources compiled into both a library and a
+ # unit-test binary produce slightly different function records.
+ # suspicious_hits: hot-path counters legitimately reach billions of hits
+ # over a full test run, tripping gcovr's corruption heuristic (gcc #68080).
+ $GCOVR -r . "$BUILDDIR" -j "$NPROCS" \
+ --gcov-ignore-errors=no_working_dir_found \
+ --gcov-ignore-parse-errors=suspicious_hits.warn_once_per_file \
+ --merge-mode-functions=merge-use-line-min \
+ --exclude 'lib/' --exclude '.*/unit_tests/' --exclude 'build.*/' \
+ --print-summary \
+ --html-details coverage.html \
+ --json coverage.json \
+ --xml coverage.xml
+ echo "Reports written: coverage.html coverage.json coverage.xml"
+}
-$GENHTML --output-directory coverage.html coverage.info
+configure "$@"
+build
+run_tests
+report