Implemented qt port + e2e

This commit is contained in:
Martino Ferrari
2026-06-26 09:11:10 +02:00
parent 0d7d8f396b
commit 4702d0a217
146 changed files with 57272 additions and 128 deletions
+87 -11
View File
@@ -24,12 +24,14 @@ mkdir -p "${OUT_DIR}" "${WORK}"
SKIP_BUILD=0
ONLY=""
PDF_ONLY=0
CPP_COV=0
while [ $# -gt 0 ]; do
case "$1" in
--skip-build) SKIP_BUILD=1 ;;
--only) shift; ONLY="$1" ;;
--pdf-only) PDF_ONLY=1 ;;
--help|-h) echo "Usage: $0 [--skip-build] [--only <id>] [--pdf-only]"; exit 0 ;;
--cpp-coverage) CPP_COV=1 ;;
--help|-h) echo "Usage: $0 [--skip-build] [--only <id>] [--pdf-only] [--cpp-coverage]"; exit 0 ;;
*) echo "unknown arg $1" >&2; exit 2 ;;
esac
shift
@@ -156,6 +158,9 @@ while IFS='|' read -r ID WSPORT UDPPORT NET ORACLE TRIG CHECKS; do
timeout 120 "${MARTE_APP}" -l RealTimeLoader -f "${MCFG}" -s Running > "${APP_LOG}" 2>&1 &
APP_PID=$!
sleep 1
# APP_PID is the `timeout` wrapper; perf must target the real MARTeApp child.
APP_PERF_PID="$(pgrep -P "${APP_PID}" 2>/dev/null | head -1)"
[ -z "${APP_PERF_PID}" ] && APP_PERF_PID="${APP_PID}"
TRIGARG=""
[ -n "${TRIG}" ] && TRIGARG="-trigsig ${TRIG}"
@@ -166,6 +171,11 @@ while IFS='|' read -r ID WSPORT UDPPORT NET ORACLE TRIG CHECKS; do
echo " client FAILED (see client_${ID}.log)"
tail -3 "${OUT_DIR}/client_${ID}.log" | sed 's/^/ /'
fi
# Snapshot CPU/peak-RSS while the stack is still alive (peak RSS is only
# legible before exit), then tear it down.
[ -n "${HUB_PID}" ] && ${PY} "${SCRIPT_DIR}/proc_perf.py" "${HUB_PID}" streamhub "${WORK}/perf_${ID}_hub.json" || true
[ -n "${APP_PERF_PID}" ] && ${PY} "${SCRIPT_DIR}/proc_perf.py" "${APP_PERF_PID}" marte "${WORK}/perf_${ID}_marte.json" || true
cleanup
# validate + plot
@@ -183,33 +193,99 @@ trap - EXIT
cleanup
# ── Aggregate results.json ───────────────────────────────────────────────────
WORK="${WORK}" OUT_DIR="${OUT_DIR}" SCEN_IDS="${SCEN_IDS}" ${PY} - <<'PY'
import json, os
# Scenarios carrying a `known_issue` marker exercise a documented, not-yet-fixed
# chain gap: a raw FAIL is reclassified XFAIL (expected failure — does not break
# the green baseline) and a raw PASS becomes XPASS (the bug was unexpectedly
# fixed; the marker should be dropped). Overall is PASS when nothing FAILs and
# nothing unexpectedly XPASSes.
WORK="${WORK}" OUT_DIR="${OUT_DIR}" SCEN_IDS="${SCEN_IDS}" \
SCRIPT_DIR="${SCRIPT_DIR}" ${PY} - <<'PY'
import json, os, sys
work = os.environ["WORK"]; out = os.environ["OUT_DIR"]
ids = os.environ["SCEN_IDS"].split()
sys.path.insert(0, os.environ["SCRIPT_DIR"])
try:
from scenarios import SCENARIOS
known = {s["id"]: s.get("known_issue") for s in SCENARIOS}
except Exception:
known = {}
results = []
for sid in ids:
rec = {"id": sid}
st = os.path.join(work, f"status_{sid}.txt")
rec["status"] = open(st).read().strip() if os.path.exists(st) else "UNKNOWN"
raw = open(st).read().strip() if os.path.exists(st) else "UNKNOWN"
ki = known.get(sid)
if ki:
rec["known_issue"] = ki
if raw == "FAIL":
raw = "XFAIL" # expected failure — documented chain gap
elif raw == "PASS":
raw = "XPASS" # unexpectedly fixed — drop the marker
rec["status"] = raw
mp = os.path.join(work, f"metrics_{sid}.json")
if os.path.exists(mp):
rec["metrics"] = json.load(open(mp))
results.append(rec)
overall = all(r["status"] in ("PASS", "SKIP") for r in results) and bool(results)
# Green when no hard FAIL and no XPASS (an XPASS means a known_issue marker is
# now stale and must be removed — surfaced as a failure to force the cleanup).
overall = (bool(results)
and all(r["status"] in ("PASS", "SKIP", "XFAIL") for r in results))
doc = {"overall": "PASS" if overall else "FAIL", "scenarios": results}
with open(os.path.join(out, "results.json"), "w") as f:
json.dump(doc, f, indent=2)
print(f"\nresults.json: {sum(r['status']=='PASS' for r in results)} pass, "
f"{sum(r['status']=='FAIL' for r in results)} fail, "
f"{sum(r['status']=='SKIP' for r in results)} skip → {doc['overall']}")
c = lambda st: sum(r["status"] == st for r in results)
print(f"\nresults.json: {c('PASS')} pass, {c('FAIL')} fail, {c('SKIP')} skip, "
f"{c('XFAIL')} xfail, {c('XPASS')} xpass → {doc['overall']}")
PY
# ── Optional PDF ─────────────────────────────────────────────────────────────
# ── Unit tests + coverage ────────────────────────────────────────────────────
echo ""
echo "── Unit tests + coverage ──"
# Optional C++ line coverage: rebuild the project's libraries + GTest with gcov
# instrumentation in place (OPTIM/LFLAGS are the MARTe2-sanctioned override
# hooks), let collect.py run the instrumented GTest (emits .gcda) and lcov, then
# 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 ..."
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}" \
OPTIM="${COV_O}" LFLAGS="${COV_L}" 2>&1 | tail -1
for d in Test/Components/DataSources/UDPStreamer Test/Applications/StreamHub Test/GTest; do
make -C "${REPO_ROOT}/${d}" -f Makefile.gcc TARGET="${TARGET}" \
OPTIM="${COV_O}" LFLAGS="${COV_L}" 2>&1 | tail -1
done
CPP_COV_FLAG="--cpp-coverage"
fi
${PY} "${SCRIPT_DIR}/collect.py" --repo "${REPO_ROOT}" --target "${TARGET}" \
--out "${OUT_DIR}" --work "${WORK}" ${CPP_COV_FLAG} || true
if [ "${CPP_COV}" -eq 1 ]; then
echo " restoring non-instrumented build ..."
make -C "${REPO_ROOT}" -f Makefile.gcc clean >/dev/null 2>&1 || true
make -C "${REPO_ROOT}" -f Makefile.gcc core apps TARGET="${TARGET}" 2>&1 | tail -1
(cd "${SCRIPT_DIR}/client" && go build -o chain-client . >/dev/null 2>&1) || true
fi
# ── Consolidated report data (+ history/regression + trend plots) ────────────
${PY} "${SCRIPT_DIR}/report_build.py" --repo "${REPO_ROOT}" \
--results "${OUT_DIR}/results.json" --work "${WORK}" --out "${OUT_DIR}" || true
# ── PDF ──────────────────────────────────────────────────────────────────────
if command -v typst >/dev/null 2>&1 && [ -f "${SCRIPT_DIR}/E2E_Report.typ" ]; then
cp "${SCRIPT_DIR}/E2E_Report.typ" "${OUT_DIR}/" 2>/dev/null || true
(cd "${OUT_DIR}" && typst compile E2E_Report.typ E2E_Report.pdf 2>/dev/null) \
&& echo "PDF: ${OUT_DIR}/E2E_Report.pdf"
# Embedded waveform overviews live in WORK; the template references them by
# bare name, so stage them next to report_data.json before compiling.
cp "${WORK}"/wave_*.png "${OUT_DIR}/" 2>/dev/null || true
if (cd "${OUT_DIR}" && typst compile E2E_Report.typ E2E_Report.pdf); then
echo "PDF: ${OUT_DIR}/E2E_Report.pdf"
else
echo "typst compile failed (report_data.json present at ${OUT_DIR})"
fi
fi
echo "Done — artifacts in ${OUT_DIR} and ${WORK}"