#!/usr/bin/env bash # run_stress.sh — Capacity/stress harness for the streaming chain. # # MARTe2 app (FileReader -> IOGAM -> UDPStreamer) # -> UDPS -> StreamHub(s) -> chain-client(s) (stress: liveness + zoom latency) # -> proc_perf (cpu/peakRSS) -> per-case gate -> stress_results.json # # It sweeps one load axis at a time (signal size/count, subscriber fan-out, source # count, WS-client count, zoom request rate — see stress.py) and gates each case on # survival + liveness (hard) and RSS + zoom-p95 latency (soft). This is the # capacity sibling of run_chain_e2e.sh (which gates waveform correctness). # # Usage: ./run_stress.sh [--skip-build] [--only ] [--axis ] set -u SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)" TARGET=x86-linux BUILD_DIR="${REPO_ROOT}/Build/${TARGET}" OUT_DIR="${BUILD_DIR}/E2E/chain/stress" WORK="/tmp/chain_stress" mkdir -p "${OUT_DIR}" "${WORK}" SKIP_BUILD=0 ONLY="" AXIS="" while [ $# -gt 0 ]; do case "$1" in --skip-build) SKIP_BUILD=1 ;; --only) shift; ONLY="$1" ;; --axis) shift; AXIS="$1" ;; --help|-h) echo "Usage: $0 [--skip-build] [--only ] [--axis ]"; exit 0 ;; *) echo "unknown arg $1" >&2; exit 2 ;; esac shift done ENV_SCRIPT="${REPO_ROOT}/env.sh" [ -f "${ENV_SCRIPT}" ] || { echo "ERROR: ${ENV_SCRIPT} not found" >&2; exit 1; } : "${LD_LIBRARY_PATH:=}" source "${ENV_SCRIPT}" COMP="${MARTe2_Components_DIR}/Build/${TARGET}/Components" export LD_LIBRARY_PATH="\ ${BUILD_DIR}/Components/DataSources/UDPStreamer:\ ${BUILD_DIR}/Components/Interfaces/UDPStream:\ ${MARTe2_DIR}/Build/${TARGET}/Core:\ ${COMP}/DataSources/LinuxTimer:\ ${COMP}/DataSources/FileDataSource:\ ${COMP}/GAMs/IOGAM:\ ${LD_LIBRARY_PATH:-}" MARTE_APP="${MARTe2_DIR}/Build/${TARGET}/App/MARTeApp.ex" STREAMHUB_EX="${BUILD_DIR}/StreamHub/StreamHub.ex" CLIENT="${SCRIPT_DIR}/client/chain-client" PY="python3" # ── Build ──────────────────────────────────────────────────────────────────── if [ "${SKIP_BUILD}" -eq 0 ]; then echo "── Building components ──" make -C "${REPO_ROOT}/Source/Components/Interfaces/UDPStream" -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -1 make -C "${REPO_ROOT}/Source/Components/DataSources/UDPStreamer" -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -1 make -C "${REPO_ROOT}/Source/Applications/StreamHub" -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -1 fi if [ ! -x "${CLIENT}" ] || [ "${SKIP_BUILD}" -eq 0 ]; then echo "── Building chain-client ──" (cd "${SCRIPT_DIR}/client" && go build -o chain-client .) || { echo "client build failed"; exit 1; } fi [ -x "${MARTE_APP}" ] || { echo "ERROR: MARTeApp.ex not found at ${MARTE_APP}" >&2; exit 1; } [ -x "${STREAMHUB_EX}" ] || { echo "ERROR: StreamHub.ex not found" >&2; exit 1; } # ── Validate the matrix, then run ──────────────────────────────────────────── ${PY} "${SCRIPT_DIR}/stress.py" >/dev/null || { echo "stress matrix invalid"; exit 1; } ARGS=(--marte "${MARTE_APP}" --hub "${STREAMHUB_EX}" --client "${CLIENT}" --work "${WORK}" --out "${OUT_DIR}") [ -n "${ONLY}" ] && ARGS+=(--only "${ONLY}") [ -n "${AXIS}" ] && ARGS+=(--axis "${AXIS}") ${PY} "${SCRIPT_DIR}/stress_run.py" "${ARGS[@]}" RC=$? echo "" echo "Done — results in ${OUT_DIR}/stress_results.json, logs in ${OUT_DIR}" exit ${RC}