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

Reply via email to