feat(e2e): instrument-first coverage flow with double-run + new skip flags; port stress multi-fragment sizing

This commit is contained in:
Martino Ferrari
2026-07-01 21:07:03 +02:00
parent 83d0a060fe
commit b65ac06ce2
2 changed files with 122 additions and 22 deletions
+70 -5
View File
@@ -10,7 +10,9 @@
# against the analytic/fed oracle, renders plots, and aggregates results.json.
# Artifacts: Build/x86-linux/E2E/chain/ (report) and /tmp/chain_e2e/ (scratch).
#
# Usage: ./run_e2e.sh [--skip-build] [--only <id>] [--pdf-only]
# Usage: ./run_e2e.sh [--skip-build] [--only <id>] [--pdf-only] [--cpp-coverage]
# [--skip-coverage] [--skip-stress] [--skip-datasources]
# [--skip-recorder] [--skip-debug] [--skip-tcplogger]
set -u
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
@@ -25,13 +27,24 @@ SKIP_BUILD=0
ONLY=""
PDF_ONLY=0
CPP_COV=1
SKIP_STRESS=0
SKIP_DATASOURCES=0
SKIP_RECORDER=0
SKIP_DEBUG=0
SKIP_TCPLOGGER=0
while [ $# -gt 0 ]; do
case "$1" in
--skip-build) SKIP_BUILD=1 ;;
--only) shift; ONLY="$1" ;;
--pdf-only) PDF_ONLY=1 ;;
--cpp-coverage) CPP_COV=1 ;;
--help|-h) echo "Usage: $0 [--skip-build] [--only <id>] [--pdf-only] [--cpp-coverage]"; exit 0 ;;
--skip-coverage) CPP_COV=0 ;;
--skip-stress) SKIP_STRESS=1 ;;
--skip-datasources) SKIP_DATASOURCES=1 ;;
--skip-recorder) SKIP_RECORDER=1 ;;
--skip-debug) SKIP_DEBUG=1 ;;
--skip-tcplogger) SKIP_TCPLOGGER=1 ;;
--help|-h) echo "Usage: $0 [--skip-build] [--only <id>] [--pdf-only] [--cpp-coverage] [--skip-coverage] [--skip-stress] [--skip-datasources] [--skip-recorder] [--skip-debug] [--skip-tcplogger]"; exit 0 ;;
*) echo "unknown arg $1" >&2; exit 2 ;;
esac
shift
@@ -99,15 +112,23 @@ fi
# direct: kind|id|cfg|-|-|-|-|-
# recorder: kind|id|marte_cfg|hub_cfg|-|-|-|-
# debug/tcplogger: kind|id|cfg|cmd_port|udp_port|log_port|-|-
LIST="$(${PY} - "${ONLY}" <<'PY'
SKIP_KINDS=""
[ "${SKIP_DATASOURCES}" -eq 1 ] && SKIP_KINDS="${SKIP_KINDS}direct,"
[ "${SKIP_RECORDER}" -eq 1 ] && SKIP_KINDS="${SKIP_KINDS}recorder,"
[ "${SKIP_DEBUG}" -eq 1 ] && SKIP_KINDS="${SKIP_KINDS}debug,"
[ "${SKIP_TCPLOGGER}" -eq 1 ] && SKIP_KINDS="${SKIP_KINDS}tcplogger,"
LIST="$(${PY} - "${ONLY}" "${SKIP_KINDS}" <<'PY'
import sys, os
sys.path.insert(0, os.path.dirname(os.path.abspath("Test/E2E/suite/scenarios.py")))
sys.path.insert(0, os.path.join(os.getcwd(), "Test/E2E/suite"))
import scenarios as S
only = sys.argv[1] if len(sys.argv) > 1 else ""
skip_kinds = set(sys.argv[2].split(",")) if len(sys.argv) > 2 and sys.argv[2] else set()
for s in S.SCENARIOS:
if only and s["id"] != only:
continue
if s["kind"] in skip_kinds:
continue
kind = s["kind"]
if kind == "chain":
trig = s.get("trig_signal") or ""
@@ -129,6 +150,16 @@ PY
if [ -z "${LIST}" ]; then echo "no scenarios selected"; exit 1; fi
# run_scenario_matrix — runs the full scenario matrix (already computed into
# ${LIST}) against whatever binaries are currently built. Invoked once for the
# authoritative pass (normal binaries) and again, inside a subshell with
# OUT_DIR overridden, for the coverage-only re-run against instrumented
# binaries (see Phase 4 below). Running the coverage pass in a subshell means
# its SCEN_IDS/OUT_DIR/HUB_PID/APP_PID/trap mutations never leak back into the
# parent shell, so the primary pass's SCEN_IDS (consumed by the results.json
# aggregation step further down) is unaffected regardless of call order.
run_scenario_matrix() {
local RESULTS_SUFFIX="$1"
SCEN_IDS=""
HUB_PID=""; APP_PID=""
cleanup() {
@@ -329,6 +360,18 @@ done <<< "${LIST}"
trap - EXIT
cleanup
}
run_scenario_matrix "primary"
# ── Stress (Phase 3: normal binaries, always uninstrumented) ────────────────
if [ "${SKIP_STRESS}" -eq 0 ]; then
echo ""
echo "── Stress matrix ──"
STRESS_OUT="${OUT_DIR}/stress"
mkdir -p "${STRESS_OUT}"
${PY} "${SCRIPT_DIR}/stress_run.py" --marte "${MARTE_APP}" --hub "${STREAMHUB_EX}" \
--client "${CLIENT}" --work "/tmp/chain_stress" --out "${STRESS_OUT}" || true
fi
# ── Aggregate results.json ───────────────────────────────────────────────────
# Scenarios carrying a `known_issue` marker exercise a documented, not-yet-fixed
@@ -388,16 +431,38 @@ echo "── Unit tests + coverage ──"
# restore a clean build so later --skip-build runs aren't left instrumented.
CPP_COV_FLAG=""
if [ "${CPP_COV}" -eq 1 ]; then
echo " building instrumented (gcov) libraries + GTest ..."
echo " building instrumented (gcov) libraries + apps + GTest ..."
COV_O="--coverage"
COV_L="-Wl,--no-as-needed -fPIC --coverage"
make -C "${REPO_ROOT}" -f Makefile.gcc clean >/dev/null 2>&1 || true
make -C "${REPO_ROOT}" -f Makefile.gcc core TARGET="${TARGET}" \
# `apps` (StreamHub.ex) must be rebuilt here too, not just `core`: the
# coverage-pass E2E re-run below launches StreamHub, and `make clean` just
# removed the non-instrumented StreamHub.ex — without this it would 404 the
# WS port for every chain/recorder scenario in the coverage pass.
make -C "${REPO_ROOT}" -f Makefile.gcc core apps TARGET="${TARGET}" \
OPTIM="${COV_O}" LFLAGS="${COV_L}" 2>&1 | tail -1
for d in Test/Components/DataSources/UDPStreamer Test/Components/DataSources/UDPStreamerClient Test/Applications/StreamHub Test/GTest Test/Integration; do
make -C "${REPO_ROOT}/${d}" -f Makefile.gcc TARGET="${TARGET}" \
OPTIM="${COV_O}" LFLAGS="${COV_L}" 2>&1 | tail -1
done
# Coverage-only scenario re-run: the instrumented binaries above are only
# exercised so far by collect.py's unit-test binaries (MainGTest/Integration),
# which never touch the E2E-scenario-only code paths (e.g. StreamHub code
# only hit via the direct/recorder/debug E2E flows). Re-running the full
# scenario matrix here — against the SAME instrumented binaries, before
# collect.py's lcov capture — lets those .gcda files accumulate E2E-path
# coverage too. Run in a subshell with OUT_DIR overridden so the coverage
# pass's logs/results land in a discardable subdirectory and none of its
# SCEN_IDS/OUT_DIR/trap state leaks back into this shell (the authoritative
# results.json was already written above, from the primary pass).
echo " re-running scenario matrix under instrumented binaries (coverage pass) ..."
(
OUT_DIR="${OUT_DIR}/coverage_pass"
mkdir -p "${OUT_DIR}"
run_scenario_matrix "coverage"
) || true
CPP_COV_FLAG="--cpp-coverage"
fi