Files
ConformalLabpp/.gitea/workflows/cpp-tests.yml
Tarik Moussa 30a132de60 fix(coverage+validation): C2/C3 script gate, V1/V2/V4 JSON/XML errors, I2/I3/I4 tests
C2: Fix coverage.sh — remove || true from lcov capture/extract steps so real
    lcov failures are visible; empty coverage.info now exits with code 3.
C3: Add coverage gate to quality-gates CI job (SKIP_COVERAGE_GATE=1 ramp-up
    mode until I5 is resolved — fast suite covers ~9.6% not 80%). Thresholds:
    80% line / 70% branch / 90% function (agreed 2026-05-31).

V1: Wrap JSON parse + field extraction in try/catch — nlohmann parse_error and
    type_error now surface as std::runtime_error with the file path.
V2: Wrap stoi/stod in XML Solver parser — missing/non-numeric attributes throw
    std::runtime_error instead of leaking std::invalid_argument.
V4: Validate required JSON keys (dof_vector, solver, solver.*) before access —
    missing field produces a clear named-field error message.

I2: 6 serialization negative tests (missing file, malformed JSON, missing
    dof_vector, missing solver block, missing XML file, non-numeric XML attr).
I3: load_mesh throws on non-triangulated (quad) mesh — covers the
    is_triangle_mesh guard that was previously untested.
I4: spherical_hessian throws on edge DOFs — covers the logic_error guard.

290/290 tests pass (+8 new).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 14:43:00 +02:00

178 lines
7.5 KiB
YAML

name: C++ Tests
# Trigger keywords in commit message (checked via head_commit.message):
# /test-cgal — full CGAL test suite (277 tests, ~5 min build)
# /quality-gates — license, codespell, shellcheck, CGAL conventions
#
# ⚠ /ci-all was removed: the Pi runner (3-4 GB RAM) cannot sustain
# multiple Docker containers simultaneously. Use one keyword per commit.
#
# Examples:
# git commit -m "fix: correct angle formula /test-cgal"
# git commit -m "chore: update headers /quality-gates"
#
# test-fast always runs on every push — it is fast (< 5 s) and cheap.
on:
push:
branches:
- main
- "claude/**"
- "feature/**"
- "review/**"
pull_request:
# ─────────────────────────────────────────────────────────────────────────────
# Job 1 — test-fast
# Pure-math tests (Clausen, ImLi₂, Hyper-ideal geometry).
# No CGAL, no Boost. Eigen + GTest only. Runs on EVERY push.
# ─────────────────────────────────────────────────────────────────────────────
jobs:
test-fast:
runs-on: eulernest
container:
image: git.eulernest.eu/conformallab/ci-cpp:latest
options: "--memory=800m --memory-swap=1200m"
steps:
- uses: actions/checkout@v4
- name: Configure (tests-only)
run: cmake -S code -B build -DCMAKE_BUILD_TYPE=Release
- name: Build
run: nice -n 19 cmake --build build --target conformallab_tests -j$(nproc)
- name: Run tests
run: >
ctest --test-dir build
--output-on-failure
--output-junit test-results.xml
- name: Summary
if: always()
run: |
if [ -f test-results.xml ]; then
total=$(grep -o 'tests="[0-9]*"' test-results.xml | grep -o '[0-9]*' | head -1)
failed=$(grep -o 'failures="[0-9]*"' test-results.xml | grep -o '[0-9]*' | head -1)
skipped=$(grep -o 'skipped="[0-9]*"' test-results.xml | grep -o '[0-9]*' | head -1)
passed=$(( ${total:-0} - ${failed:-0} - ${skipped:-0} ))
echo "FAST ▸ TOTAL ${total:-0} | PASSED $passed | FAILED ${failed:-0} | SKIPPED ${skipped:-0}"
fi
# ─────────────────────────────────────────────────────────────────────────────
# Job 2 — test-cgal
#
# Trigger: include "/test-cgal" anywhere in the commit message.
#
# git commit -m "fix: correct angle formula /test-cgal"
#
# Why keyword-triggered (not automatic on every push):
# The Pi runner (3-4 GB RAM, swap heavily loaded) cannot sustain a
# CGAL build on every WIP commit. Adding the keyword to a commit
# message explicitly signals "this commit is ready for full testing".
#
# LOW_MEMORY_BUILD applies four RAM-saving measures so the build fits in
# a 2000 MB container: -O0, no PCH, unity batch 1, --no-keep-memory.
# See code/tests/cgal/CMakeLists.txt for the full explanation.
# ─────────────────────────────────────────────────────────────────────────────
test-cgal:
needs: test-fast
if: contains(github.event.head_commit.message, '/test-cgal')
runs-on: eulernest
container:
image: git.eulernest.eu/conformallab/ci-cpp:latest
# 2000 MB hard limit; 1000 MB swap headroom (memory-swap = RAM + swap).
# With LOW_MEMORY_BUILD peak per TU is ~150-200 MB → well within limit.
options: "--memory=2000m --memory-swap=3000m"
steps:
- uses: actions/checkout@v4
- name: Configure (LOW_MEMORY_BUILD — -O0, no PCH, unity batch 1)
run: |
cmake -S code -B build \
-DWITH_CGAL_TESTS=ON \
-DCMAKE_BUILD_TYPE=Release \
-DCONFORMALLAB_LOW_MEMORY_BUILD=ON
- name: Build CGAL-Tests
run: nice -n 19 cmake --build build --target conformallab_cgal_tests -j1
- name: Run CGAL-Tests
run: >
ctest --test-dir build
-R "^cgal\."
--output-on-failure
--output-junit cgal-results.xml
- name: Summary
if: always()
run: |
if [ -f cgal-results.xml ]; then
total=$(grep -o 'tests="[0-9]*"' cgal-results.xml | grep -o '[0-9]*' | head -1)
failed=$(grep -o 'failures="[0-9]*"' cgal-results.xml | grep -o '[0-9]*' | head -1)
skipped=$(grep -o 'skipped="[0-9]*"' cgal-results.xml | grep -o '[0-9]*' | head -1)
passed=$(( ${total:-0} - ${failed:-0} - ${skipped:-0} ))
echo "CGAL ▸ TOTAL ${total:-0} | PASSED $passed | FAILED ${failed:-0} | SKIPPED ${skipped:-0}"
fi
- name: Verify test-count consistency (doc/api/tests.md)
run: BUILD_DIR=build bash scripts/check-test-counts.sh
- name: End-to-end smoke test (scripts/try_it.sh)
run: bash scripts/try_it.sh
# ─────────────────────────────────────────────────────────────────────────────
# Job 3 — quality-gates
#
# Trigger: include "/quality-gates" anywhere in the commit message.
#
# git commit -m "chore: update docs /quality-gates"
#
# Cheap (~30 s): license headers, CGAL conventions, codespell, shellcheck.
# ─────────────────────────────────────────────────────────────────────────────
quality-gates:
if: contains(github.event.head_commit.message, '/quality-gates')
runs-on: eulernest
container:
image: git.eulernest.eu/conformallab/ci-cpp:latest
options: "--memory=600m --memory-swap=900m"
steps:
- uses: actions/checkout@v4
- name: Install codespell + shellcheck (job-local)
run: |
apt-get update -qq
apt-get install -y --no-install-recommends \
codespell shellcheck
- name: License headers (every C++ source carries MIT SPDX)
run: bash scripts/quality/license-headers.sh
- name: CGAL conventions (6 rules over CGAL public headers)
run: python3 scripts/quality/cgal-conventions.py
- name: codespell (docs + source comments + script messages)
run: bash scripts/quality/codespell.sh
- name: shellcheck (scripts/**/*.sh, severity=warning, strict)
run: bash scripts/quality/shellcheck.sh --strict
- name: Install lcov (coverage gate)
run: apt-get install -y --no-install-recommends lcov
- name: Coverage gate (fast-test suite, ramp-up mode)
# SKIP_COVERAGE_GATE=1: reports numbers but does not fail on threshold.
# Remove once I5 is resolved (coverage is wired to the full CGAL suite,
# not just the 26 fast tests). Threshold: 80% line / 70% branch / 90% func.
run: SKIP_COVERAGE_GATE=1 bash scripts/quality/coverage.sh
- name: Summary
if: always()
run: |
echo "QUALITY ▸ all gates passed."
echo " see scripts/quality/README.md for the full catalogue"
echo " (sanitizers, clang-tidy, coverage report in build-coverage/)"