| #! /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. |
| |
| # 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() { |
| # 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() { |
| cmake --build "$BUILDDIR" -j "$NPROCS" |
| cmake --install "$BUILDDIR" |
| } |
| |
| 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 |
| } |
| |
| 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" |
| } |
| |
| configure "$@" |
| build |
| run_tests |
| report |