#!/bin/bash # SPDX-License-Identifier: BSD-3-Clause # # p2/run_guest.sh - push every P2 program into the running guest, execute it # with a timeout, and compare its stable output lines against the recorded # host-oracle reference in p2/expected/.txt. # # Prerequisites: # * p2/expected/.txt exists (run p2/oracle.sh first) # * the guest is running and reachable through scripts/vgpu_vm.py # # This talks to the live VM; run it only when no campaign cycle is using it. # # Usage: # ./run_guest.sh # all programs # ./run_guest.sh p2_seq5 ... # selected programs # P2_GUEST_TIMEOUT=600 ./run_guest.sh # # Exit status: 0 only if every strict program PASSes (the managed-memory # probe is informational: it must complete with STATUS OK, its content is # recorded but not diffed). set -u HERE="$(cd "$(dirname "$0")" && pwd)" REPO="$(cd "$HERE/../.." && pwd)" VMEXEC="${P2_VMEXEC:-$REPO/scripts/vgpu_vm.py}" FILTER='^(RESULT|CHECK|ERR|STATUS|P2PRINT|PROBE|MAIL)' TIMEOUT="${P2_GUEST_TIMEOUT:-300}" INFO_PROGS=" p2_managed_probe " GUEST_OUT="$HERE/guest" mkdir -p "$GUEST_OUT" PROGS=() if [ "$#" -gt 0 ]; then PROGS=("$@") else for b in "$HERE"/bin/p2_*; do PROGS+=("$(basename "$b")") done fi if [ ! -x "$VMEXEC" ] && [ ! -f "$VMEXEC" ]; then echo "ERROR: VM executor not found: $VMEXEC" >&2 exit 2 fi # Build any missing or stale binaries first (bin/ may be absent in a fresh # checkout; sources may be newer than a previously built binary). need_build=0 for name in "${PROGS[@]}"; do bin="$HERE/bin/$name" if [ ! -x "$bin" ] || [ "$HERE/src/$name.cu" -nt "$bin" ] || [ "$HERE/src/common.h" -nt "$bin" ]; then need_build=1 fi done if [ "$need_build" -eq 1 ]; then "$HERE/build.sh" || exit 2 fi for name in "${PROGS[@]}"; do if [ ! -x "$HERE/bin/$name" ]; then echo "ERROR: missing binary bin/$name - run p2/build.sh" >&2 exit 2 fi if [ ! -f "$HERE/expected/$name.txt" ]; then echo "ERROR: missing expected/$name.txt - run p2/oracle.sh" >&2 exit 2 fi done ping="$("$VMEXEC" exec "echo VMPING" 2>&1 || true)" if [[ "$ping" != *VMPING* ]]; then echo "ERROR: guest not reachable via $VMEXEC (is the VM running?)" >&2 exit 2 fi push_bin() { local name="$1" b64 total off size=70000 chunk out b64="$(base64 -w0 "$HERE/bin/$name")" total=${#b64} off=0 "$VMEXEC" exec "rm -f /tmp/$name.b64" >/dev/null 2>&1 while [ "$off" -lt "$total" ]; do chunk="${b64:$off:$size}" "$VMEXEC" exec "echo -n '$chunk' >> /tmp/$name.b64" >/dev/null 2>&1 off=$((off + size)) done out="$("$VMEXEC" exec "base64 -d /tmp/$name.b64 > /tmp/$name && chmod +x /tmp/$name && rm -f /tmp/$name.b64 && echo PUSH_OK" 2>&1)" [[ "$out" == *PUSH_OK* ]] } declare -a R_NAME R_STATUS R_NOTE echo "== P2 guest acceptance: $(date -u +%Y-%m-%dT%H:%M:%SZ) ==" echo "== timeout=${TIMEOUT}s, expected dir: $HERE/expected ==" for name in "${PROGS[@]}"; do gs="$GUEST_OUT/$name.txt" fail=0 note="" if ! push_bin "$name"; then R_NAME+=("$name"); R_STATUS+=("FAIL"); R_NOTE+=("push failed") continue fi "$VMEXEC" exec --timeout "$TIMEOUT" "/tmp/$name" > "$gs" 2>&1 rc=$? if [[ " $INFO_PROGS " == *" $name "* ]]; then if [ "$rc" -eq 0 ] && grep -q '^STATUS OK$' "$gs" && grep -q '^PROBE ' "$gs"; then note="$(grep -m1 '^PROBE ' "$gs" | cut -c1-70)" R_NAME+=("$name"); R_STATUS+=("INFO"); R_NOTE+=("$note") else R_NAME+=("$name"); R_STATUS+=("FAIL") R_NOTE+=("expected-failure probe did not complete cleanly (rc=$rc)") fi continue fi if [ "$rc" -ne 0 ]; then fail=1 note="guest exit=$rc" fi if ! grep -q '^STATUS OK$' "$gs"; then fail=1 note="${note:+$note; }no STATUS OK" fi grep -E "$FILTER" "$gs" | LC_ALL=C sort > "$gs.filtered" grep -E "$FILTER" "$HERE/expected/$name.txt" | LC_ALL=C sort > "$gs.expected" if ! cmp -s "$gs.filtered" "$gs.expected"; then fail=1 note="${note:+$note; }stable-line mismatch" if [ ! -s "$gs.filtered" ]; then note="${note:+$note; }no stable lines (timeout/hang?)" fi fi if [ "$fail" -eq 0 ]; then R_NAME+=("$name"); R_STATUS+=("PASS"); R_NOTE+=("") else R_NAME+=("$name"); R_STATUS+=("FAIL"); R_NOTE+=("$note") fi done echo printf '%-22s %-6s %s\n' "PROGRAM" "RESULT" "NOTES" printf '%-22s %-6s %s\n' "----------------------" "------" "-----" any_fail=0 for i in "${!R_NAME[@]}"; do printf '%-22s %-6s %s\n' "${R_NAME[$i]}" "${R_STATUS[$i]}" "${R_NOTE[$i]}" [ "${R_STATUS[$i]}" = "FAIL" ] && any_fail=1 done echo if [ "$any_fail" -ne 0 ]; then echo "P2: FAIL (guest output in $GUEST_OUT, diffs: *.filtered vs *.expected)" exit 1 fi echo "P2: PASS ($((${#R_NAME[@]})) programs; guest output in $GUEST_OUT)" exit 0