#!/usr/bin/env bash # Run EVERY external-validation harness in one shot, with a PASS/FAIL summary. # # The unit suite is partly self-referential (our parsers validate our # builders); these harnesses are the real oracle — independent implementations # (secsgem-py, secs4java8, Wireshark) judging our wire behaviour. This script # exists so they run routinely, not "when someone remembers". # # tools/run_interop.sh # everything # SKIP_SECS4J=1 tools/run_interop.sh # skip the (slow) Java image build # # Steps (each independently PASS/FAIL, all attempted, nonzero exit if any fail): # build compose builder (cmake + ninja, includes secs_gemd) # unit secsgem_tests (full C++ suite) # daemon-unit secs_gemd_tests (in-process gRPC service tests) # py-host secsgem-py active host vs C++ secs_server (31 checks) # conformance secs_conformance C++ host vs C++ secs_server (47 checks) # daemon gRPC tool + secsgem-py host vs secs_gemd (bridge proof) # spool spool persistence across a server restart # tshark Wireshark HSMS dissector on a live capture # secs4j secs4java8 Java host vs C++ secs_server (55 checks) # # Requires: docker compose. Runs from any cwd. set -u cd "$(dirname "${BASH_SOURCE[0]}")/.." declare -a NAMES RESULTS overall=0 note() { printf '\n\033[1m== %s ==\033[0m\n' "$*"; } record() { # record NAMES+=("$1"); RESULTS+=("$2") if [ "$2" -ne 0 ]; then overall=1; fi } compose() { docker compose "$@"; } stop_services() { compose stop server gemd server-spool >/dev/null 2>&1 || true; } trap stop_services EXIT # ---- build ----------------------------------------------------------------- # -j 2: unbounded ninja at -O3 OOM-kills cc1plus in memory-constrained Docker # VMs (macOS Docker Desktop). Two jobs is reliably safe and still fast. note "build (compose builder, -j 2)" compose run --rm builder bash -lc \ "cmake -S /app -B /app/build -G Ninja -DCMAKE_BUILD_TYPE=Release && \ cmake --build /app/build -j 2" build_rc=$? record build $build_rc if [ "$build_rc" -ne 0 ]; then echo "build failed — aborting (everything below needs the binaries)" exit 1 fi # ---- unit suites ----------------------------------------------------------- note "unit: secsgem_tests" compose run --rm builder /app/build/secsgem_tests; record unit $? note "daemon-unit: secs_gemd_tests" if compose run --rm builder test -x /app/build/secs_gemd_tests; then compose run --rm builder /app/build/secs_gemd_tests; record daemon-unit $? else echo "secs_gemd_tests not built (grpc missing from toolchain?) — FAIL" record daemon-unit 1 fi # ---- secsgem-py host vs C++ server ------------------------------------------ note "py-host: secsgem-py GemHostHandler vs secs_server" compose up -d --no-deps server sleep 2 compose run --rm --no-deps interop python3 host_vs_cpp_server.py --host server record py-host $? compose stop server >/dev/null 2>&1 # ---- C++ conformance host vs C++ server ------------------------------------- note "conformance: secs_conformance vs secs_server" compose up -d --no-deps server sleep 2 compose run --rm builder /app/build/secs_conformance --host server --port 5000 record conformance $? compose stop server >/dev/null 2>&1 # ---- daemon: gRPC tool + secsgem-py host vs secs_gemd ------------------------ note "daemon: gRPC + secsgem-py vs secs_gemd" compose up -d --no-deps gemd sleep 2 compose run --rm --no-deps interop \ python3 daemon_interop.py --grpc gemd:50051 --hsms-host gemd record daemon $? compose stop gemd >/dev/null 2>&1 # ---- spool persistence across restart --------------------------------------- note "spool: persistence across server restart" ( set -e compose up -d --no-deps server-spool sleep 2 compose run --rm --no-deps interop \ python3 spool_persistence_test.py --phase enqueue --host server-spool compose restart server-spool sleep 2 compose run --rm --no-deps interop \ python3 spool_persistence_test.py --phase drain --host server-spool ) record spool $? compose stop server-spool >/dev/null 2>&1 # ---- Wireshark dissector ------------------------------------------------------ note "tshark: Wireshark HSMS dissector" compose run --rm builder bash interop/tshark_validate.sh record tshark $? # ---- secs4java8 --------------------------------------------------------------- if [ "${SKIP_SECS4J:-0}" = "1" ]; then echo "secs4j skipped (SKIP_SECS4J=1)" else note "secs4j: secs4java8 host vs secs_server" bash interop/secs4j_validate.sh; record secs4j $? fi # ---- summary ----------------------------------------------------------------- printf '\n\033[1m== interop summary ==\033[0m\n' for i in "${!NAMES[@]}"; do if [ "${RESULTS[$i]}" -eq 0 ]; then printf ' \033[32mPASS\033[0m %s\n' "${NAMES[$i]}" else printf ' \033[31mFAIL\033[0m %s (exit %s)\n' "${NAMES[$i]}" "${RESULTS[$i]}" fi done exit $overall