#!/usr/bin/env bash # scripts/check-test-counts.sh # # CI gate that verifies the totals in `doc/api/tests.md` match the # actual `ctest` output. Catches the canonical test-count document # going stale even if no other doc hardcodes the number. # # Usage: # bash scripts/check-test-counts.sh # # Exit codes: # 0 totals match # 1 totals diverge — prints diff and which file to fix # 2 prerequisites missing (cmake not found, tests.md missing, …) # # This script is meant to be cheap enough to run on every PR (~30 s on # a typical CI runner). It re-uses the existing build-cgal/ directory # if one is present; otherwise it builds a throwaway build-counts/. set -euo pipefail cd "$(dirname "${BASH_SOURCE[0]}")/.." # repo root TESTS_MD="doc/api/tests.md" if [ ! -f "$TESTS_MD" ]; then echo "FAIL: $TESTS_MD not found" >&2 exit 2 fi command -v cmake >/dev/null || { echo "FAIL: cmake not in PATH" >&2; exit 2; } command -v ctest >/dev/null || { echo "FAIL: ctest not in PATH" >&2; exit 2; } # ── Build ─────────────────────────────────────────────────────────────────── # Re-use existing build-cgal/ if it exists with the right flags; otherwise # create a throwaway build-counts/ directory. BUILD_DIR="" if [ -f build-cgal/CMakeCache.txt ] && grep -q "WITH_CGAL_TESTS:.*=ON\|WITH_CGAL:.*=ON" build-cgal/CMakeCache.txt; then BUILD_DIR=build-cgal else BUILD_DIR=build-counts cmake -S code -B "$BUILD_DIR" -DWITH_CGAL_TESTS=ON -DCMAKE_BUILD_TYPE=Release >/dev/null fi cmake --build "$BUILD_DIR" -j"$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 2)" >/dev/null # ── Get actual counts ─────────────────────────────────────────────────────── cd "$BUILD_DIR" actual_cgal=$(ctest -R "^cgal" 2>&1 | grep "tests passed" | sed -E 's/.*out of ([0-9]+).*/\1/') actual_fast=$(ctest -E "^cgal" 2>&1 | grep "tests passed" | sed -E 's/.*out of ([0-9]+).*/\1/') cd - >/dev/null # ── Get claimed counts from tests.md ──────────────────────────────────────── # Expected format (in this order): # **Total: tests, 0 skipped.** (non-CGAL section) # ... # **Total: tests, 0 skipped.** (CGAL section) claimed_fast=$(grep -E "\*\*Total: [0-9]+ tests, 0 skipped\.\*\*" "$TESTS_MD" \ | head -n 1 | sed -E 's/.*Total: ([0-9]+) tests.*/\1/') claimed_cgal=$(grep -E "\*\*Total: [0-9]+ tests, 0 skipped\.\*\*" "$TESTS_MD" \ | tail -n 1 | sed -E 's/.*Total: ([0-9]+) tests.*/\1/') # ── Compare ──────────────────────────────────────────────────────────────── ok=1 if [ "${actual_fast}" != "${claimed_fast}" ]; then echo "MISMATCH: non-CGAL — $TESTS_MD claims ${claimed_fast}, ctest reports ${actual_fast}" ok=0 fi if [ "${actual_cgal}" != "${claimed_cgal}" ]; then echo "MISMATCH: CGAL — $TESTS_MD claims ${claimed_cgal}, ctest reports ${actual_cgal}" ok=0 fi if [ "$ok" -eq 0 ]; then cat <