summaryrefslogtreecommitdiffstats
path: root/tools/cuda-ab/p2/run_guest.sh
blob: 50a2b2f9877a9d2bb242a6548a1ab25e48397ee5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#!/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/<name>.txt.
#
# Prerequisites:
#   * p2/expected/<name>.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