Files
erofs-freebsd-out-tree/tests/pre15/fixtures/B21-manual-run.sh
T
2026-08-18 09:20:44 +02:00

259 lines
9.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -eu
evidence=${1:?evidence directory is required}
root=/work/erofs-freebsd-pre
dut=$root/repo-pre-15
base=/work/build/vm-freebsd-build.qcow2.bp
askpass=/work/build/.repo22-ssh-askpass
module=${B21_MODULE:-$root/planning/pre15/evidence/20260816T-B21-abi15-build/B21-erofs-zstdio0.ko}
source_tree=${B21_FREEBSD_SRC:-/work/dev-freebsd-releng}
owned_pid=
port=
loaded=0
mounted=0
md_units=
test ! -e "$evidence"
mkdir -p "$evidence"
: >"$evidence/cleanup.log"
ssh_args=(env DISPLAY=:0 SSH_ASKPASS="$askpass" SSH_ASKPASS_REQUIRE=force ssh
-n
-o BatchMode=no -o PubkeyAuthentication=no
-o PreferredAuthentications=keyboard-interactive,password
-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR -o ConnectTimeout=5)
scp_args=(env DISPLAY=:0 SSH_ASKPASS="$askpass" SSH_ASKPASS_REQUIRE=force scp
-O -q -o BatchMode=no -o PubkeyAuthentication=no
-o PreferredAuthentications=keyboard-interactive,password
-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
-o LogLevel=ERROR -o ConnectTimeout=5)
guest()
{
timeout -k 5 60 "${ssh_args[@]}" -p "$port" [email protected] "$@"
}
capture()
{
local name=$1
shift
set +e
guest "$@" >"$evidence/$name.stdout" 2>"$evidence/$name.stderr"
local rc=$?
set -e
printf '%s\n' "$rc" >"$evidence/$name.rc"
}
scp_to()
{
local source_path=$1
local destination_path=$2
timeout -k 5 60 "${scp_args[@]}" -P "$port" "$source_path" \
"[email protected]:$destination_path"
}
cleanup()
{
set +e
local cleanup_rc=0
if test "$mounted" = 1; then guest umount /mnt/pre15-b21 >>"$evidence/cleanup.log" 2>&1 || cleanup_rc=1; fi
for md in $md_units; do guest mdconfig -d -u "$md" >>"$evidence/cleanup.log" 2>&1 || cleanup_rc=1; done
if test "$loaded" = 1; then guest kldunload /root/B21-erofs-zstdio0.ko >>"$evidence/cleanup.log" 2>&1 || cleanup_rc=1; fi
if test -n "$owned_pid" && kill -0 "$owned_pid" 2>/dev/null; then
test "$owned_pid" != 26318 || exit 99
kill "$owned_pid" 2>/dev/null
wait "$owned_pid" 2>/dev/null
fi
test ! -e "$evidence/owned-overlay.qcow2" || unlink "$evidence/owned-overlay.qcow2"
python3 - "$port" <<'PY'
import socket
import sys
if not sys.argv[1]:
raise SystemExit(0)
with socket.socket() as sock:
sock.settimeout(0.2)
raise SystemExit(0 if sock.connect_ex(("127.0.0.1", int(sys.argv[1]))) else 1)
PY
test $? = 0 || cleanup_rc=1
stat -c 'path=%n size=%s inode=%i mode=%f mtime=%Y ctime=%Z' "$base" \
>"$evidence/base-metadata-after.txt"
cmp -s "$evidence/base-metadata-before.txt" "$evidence/base-metadata-after.txt" || cleanup_rc=1
if test "$cleanup_rc" = 0 && test ! -e "$evidence/owned-overlay.qcow2"; then
printf '%s\n' PASS >"$evidence/cleanup.status"
else
printf '%s\n' FAIL >"$evidence/cleanup.status"
fi
}
trap cleanup EXIT HUP INT TERM
test -x "$askpass"
test -f "$module"
test -f "$base"
stat -c 'path=%n size=%s inode=%i mode=%f mtime=%Y ctime=%Z' "$base" \
>"$evidence/base-metadata-before.txt"
git -C "$dut" rev-parse HEAD >"$evidence/dut-head.txt"
{
git -C "$source_tree" log -1 --format='%H %cs %s'
sed -n '76,77p' "$source_tree/sys/sys/param.h"
sed -n '53,54p' "$source_tree/sys/conf/newvers.sh"
} >"$evidence/source-identity.txt"
printf '%s\n' 'SSH options precede [email protected] and the remote command' \
>"$evidence/transport-contract.txt"
python3 -B "$dut/tests/pre15/fixtures/B21-super-generate.py" \
--spec "$dut/tests/pre15/fixtures/B21-super-spec.json" \
--output "$evidence/first" --work "$evidence/first-work" \
>"$evidence/generate-first.stdout" 2>"$evidence/generate-first.stderr"
python3 -B "$dut/tests/pre15/fixtures/B21-super-generate.py" \
--spec "$dut/tests/pre15/fixtures/B21-super-spec.json" \
--output "$evidence/second" --work "$evidence/second-work" \
>"$evidence/generate-second.stdout" 2>"$evidence/generate-second.stderr"
cmp "$evidence/first/fixture-index.json" "$evidence/second/fixture-index.json"
python3 -B "$dut/tests/pre15/fixtures/B21-super-oracle.py" \
--fixtures "$evidence/first" --report "$evidence/oracle.json" \
>"$evidence/oracle.stdout" 2>"$evidence/oracle.stderr"
python3 - "$evidence/first/fixture-index.json" "$evidence/oracle.json" \
"$evidence/matrix.tsv" <<'PY'
import json
import sys
from pathlib import Path
index = json.loads(Path(sys.argv[1]).read_text())
oracle = json.loads(Path(sys.argv[2]).read_text())
assert index["case_count"] == 13 and oracle["passed_count"] == 13
rows = ["id\texpected_errno\treject"]
for fixture, result in zip(index["cases"], oracle["results"], strict=True):
rows.append(
f"{fixture['id']}\t{result['actual_errno']}\t"
f"{fixture['expected_reject']}"
)
Path(sys.argv[3]).write_text("\n".join(rows) + "\n")
PY
tar -C "$evidence/first" -czf "$evidence/fixtures.tar.gz" .
qemu-img create -f qcow2 -F qcow2 -b "$base" \
"$evidence/owned-overlay.qcow2" >"$evidence/qemu-img.stdout" \
2>"$evidence/qemu-img.stderr"
port=$(python3 - <<'PY'
import socket
with socket.socket() as sock:
sock.bind(("127.0.0.1", 0))
port = sock.getsockname()[1]
if port == 9222:
raise SystemExit("protected port selected")
print(port)
PY
)
printf '%s\n' "$port" >"$evidence/owned-port.txt"
qemu-system-x86_64 -accel tcg,thread=multi -cpu qemu64 -m 6144 -smp 4 \
-drive "file=$evidence/owned-overlay.qcow2,if=virtio,format=qcow2" \
-netdev "user,id=net0,hostfwd=tcp:127.0.0.1:$port-:22" \
-device virtio-net-pci,netdev=net0 -display none \
-serial "file:$evidence/serial.log" -monitor none \
>"$evidence/qemu.stdout" 2>"$evidence/qemu.stderr" &
owned_pid=$!
printf '%s\n' "$owned_pid" >"$evidence/owned-pid.txt"
test "$owned_pid" != 26318
ready=0
for attempt in $(seq 1 180); do
if ! kill -0 "$owned_pid" 2>/dev/null; then exit 21; fi
set +e
guest true >"$evidence/readiness.stdout" 2>"$evidence/readiness.stderr"
readiness_rc=$?
set -e
printf '%s\n' "$readiness_rc" >"$evidence/readiness.rc"
if test "$readiness_rc" = 0; then ready=1; break; fi
sleep 1
done
printf 'attempts=%s ready=%s\n' "$attempt" "$ready" >"$evidence/readiness.txt"
test "$ready" = 1
capture guest-uname uname -a
capture guest-freebsd-version freebsd-version -kru
capture guest-osreldate sysctl -n kern.osreldate
capture guest-kldstat-before kldstat
capture guest-kldstat-module-before kldstat -q -m erofs
capture guest-dmesg-before dmesg
test "$(cat "$evidence/guest-kldstat-module-before.rc")" = 1
scp_to "$module" /root/B21-erofs-zstdio0.ko \
>"$evidence/upload-module.stdout" 2>"$evidence/upload-module.stderr"
scp_to "$dut/tests/pre15/fixtures/B21-qemu-probe.c" /root/B21-qemu-probe.c \
>"$evidence/upload-probe.stdout" 2>"$evidence/upload-probe.stderr"
scp_to "$evidence/fixtures.tar.gz" /root/B21-fixtures.tar.gz \
>"$evidence/upload-fixtures.stdout" 2>"$evidence/upload-fixtures.stderr"
capture guest-module-file file /root/B21-erofs-zstdio0.ko
capture guest-module-sha256 sha256 -q /root/B21-erofs-zstdio0.ko
capture guest-prepare sh -c \
'rm -rf /root/B21-fixtures /mnt/pre15-b21; mkdir /root/B21-fixtures /mnt/pre15-b21; tar -xzf /root/B21-fixtures.tar.gz -C /root/B21-fixtures; cc -O2 -Wall -Wextra -Werror -std=c17 -o /root/B21-qemu-probe /root/B21-qemu-probe.c'
test "$(cat "$evidence/guest-prepare.rc")" = 0
capture B21-kldload kldload /root/B21-erofs-zstdio0.ko
test "$(cat "$evidence/B21-kldload.rc")" = 0
loaded=1
capture guest-kldstat-after-load kldstat
capture guest-kldstat-module-after-load kldstat -q -m erofs
capture guest-dmesg-after-load dmesg
test "$(cat "$evidence/guest-kldstat-module-after-load.rc")" = 0
printf 'id\texpected_errno\tactual_errno\treject\n' \
>"$evidence/qemu-matrix.tsv"
while IFS="$(printf '\t')" read -r id expected_errno reject; do
test "$id" != id || continue
set +e
md=$(guest mdconfig -a -t vnode -f "/root/B21-fixtures/$id.erofs" \
2>"$evidence/$id-md.stderr")
md_rc=$?
set -e
printf '%s\n' "$md_rc" >"$evidence/$id-md.rc"
test "$md_rc" = 0
md_units="$md_units $md"
set +e
probe_result=$(guest /root/B21-qemu-probe "/dev/$md" /mnt/pre15-b21 \
2>"$evidence/$id-probe.stderr")
probe_rc=$?
set -e
printf '%s\n' "$probe_rc" >"$evidence/$id-probe.rc"
printf '%s\n' "$probe_result" >"$evidence/$id-probe.stdout"
actual_errno=$(printf '%s\n' "$probe_result" | \
sed -n 's/.*errno=\([0-9][0-9]*\).*/\1/p')
test -n "$actual_errno"
printf '%s\t%s\t%s\t%s\n' "$id" "$expected_errno" "$actual_errno" \
"$reject" >>"$evidence/qemu-matrix.tsv"
test "$actual_errno" = "$expected_errno"
if test "$actual_errno" = 0; then
mounted=1
guest find /mnt/pre15-b21 -mindepth 1 -maxdepth 1 -print \
>"$evidence/$id-readdir.txt"
guest umount /mnt/pre15-b21
mounted=0
fi
guest mdconfig -d -u "$md"
md_units=$(printf '%s\n' "$md_units" | sed "s/ $md//")
done <"$evidence/matrix.tsv"
capture guest-dmesg-after dmesg
capture guest-kldstat-after kldstat
capture guest-kldstat-module-after kldstat -q -m erofs
diff -u "$evidence/guest-dmesg-before.stdout" \
"$evidence/guest-dmesg-after.stdout" >"$evidence/dmesg.diff" || true
if grep -Eqi 'panic:|lock order reversal|witness.*warning|use-after-free' \
"$evidence/dmesg.diff"; then
exit 10
fi
guest kldunload /root/B21-erofs-zstdio0.ko >"$evidence/guest-kldunload.stdout" \
2>"$evidence/guest-kldunload.stderr"
loaded=0
capture guest-kldstat-module-clean kldstat -q -m erofs
capture guest-mount-clean mount -p
capture guest-md-clean mdconfig -l
test "$(cat "$evidence/guest-kldstat-module-clean.rc")" = 1
test ! -s "$evidence/guest-md-clean.stdout"
test -z "$(awk '$3 == "erofs" { print }' "$evidence/guest-mount-clean.stdout")"
printf '%s\n' reached >"$evidence/target.marker"
printf '%s\n' 'B21_PASS TC172-super-trust 13/13' >"$evidence/RESULT.txt"