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
|
#!/usr/bin/env bash
set -euo pipefail
# Smoke test for ARM64 binary using QEMU user emulation
# Requires: qemu-user-static or qemu-aarch64-static
BIN="${1:-./build/mini-init-arm64}"
QEMU="${QEMU:-qemu-aarch64-static}"
ARM64_FALLBACK="${ARM64_FALLBACK:-${EP_ARM64_FALLBACK:-0}}"
# Check if QEMU is available
if ! command -v "$QEMU" &> /dev/null; then
echo "[test] ERROR: $QEMU not found. Install qemu-user-static or qemu-aarch64-static"
echo "[test] Debian/Ubuntu: sudo apt-get install -y qemu-user-static"
exit 1
fi
# Verify binary exists and is ARM64
if [ ! -f "$BIN" ]; then
echo "[test] ERROR: Binary not found: $BIN"
exit 1
fi
if ! file "$BIN" | grep -q "ARM aarch64"; then
echo "[test] ERROR: Binary is not ARM64: $BIN"
file "$BIN"
exit 1
fi
echo "[test] ARM64 smoke test using $QEMU"
echo "[test] Binary: $BIN"
# Sanity: verify helpers exist and are ARM64, and QEMU can run them standalone
if [ ! -f "build/arm64/helper-exit42" ] || [ ! -f "build/arm64/helper-sleeper" ]; then
echo "[test] ERROR: Helper binaries not found. Run: make build-arm64"
exit 1
fi
if ! file "build/arm64/helper-exit42" | grep -q "ARM aarch64"; then
echo "[test] ERROR: helper-exit42 is not ARM64"
file "build/arm64/helper-exit42"
exit 1
fi
set +e
"$QEMU" -- build/arm64/helper-exit42
helper_rc=$?
set -e
if [ "$helper_rc" -ne 42 ]; then
echo "[test] ERROR: QEMU failed to run helper-exit42 (rc=$helper_rc)"
exit 1
fi
# Optional: fallback mode to skip flaky QEMU epoll/signalfd path
if [ "$ARM64_FALLBACK" = "1" ]; then
echo "[test] WARNING: EP_ARM64_FALLBACK=1 set; running wait4-only smoke under QEMU"
echo "[test] 0) Version check"
set +e
timeout 5s "$QEMU" -- "$BIN" --version
rc=$?
set -e
if [ "$rc" -ne 0 ]; then
echo "[test] ERROR: --version failed under QEMU (rc=$rc)"
exit 1
fi
echo "[test] 1) Wait4-only path (helper-exit42)"
out="$(mktemp)"
err="$(mktemp)"
# shellcheck disable=SC2317,SC2329 # Function invoked via trap
cleanup_tmp() {
rm -f "$out" "$err"
}
trap cleanup_tmp EXIT
set +e
timeout 10s env EP_ARM64_FALLBACK=1 "$QEMU" -- "$BIN" -v -- ./build/arm64/helper-exit42 >"$out" 2>"$err"
rc=$?
set -e
if [ "$rc" -eq 42 ]; then
cat "$out"
cat "$err" >&2
echo "[test] OK (fallback smoke passed)"
exit 0
fi
# QEMU user-mode is known to be unstable for this binary; treat SIGILL/timeout as a non-fatal skip in fallback mode.
if [ "$rc" -eq 132 ] || [ "$rc" -eq 124 ]; then
echo "[test] WARNING: QEMU-user is unstable for mini-init-arm64 even in fallback mode (rc=$rc); skipping"
cat "$out"
cat "$err" >&2
exit 0
fi
echo "[test] ERROR: Expected exit 42, got $rc"
cat "$out"
cat "$err" >&2
exit 1
fi
# Test 1: Basic execution (help-like check)
echo "[test] 1) Basic execution"
set +e
timeout 10s "$QEMU" -- "$BIN" -v -- ./build/arm64/helper-exit42
rc=$?
set -e
if [ "$rc" -eq 42 ]; then
echo "[test] OK (got exit code 42)"
else
echo "[test] WARNING: Expected exit 42, got $rc"
fi
# Test 2: Graceful termination
echo "[test] 2) Graceful termination"
set -m
EP_GRACE_SECONDS=5 timeout 15s "$QEMU" -- "$BIN" -v -- ./build/arm64/helper-sleeper &
pid=$!
sleep 1
# Check if process is still running before sending signal
if kill -0 "$pid" 2>/dev/null; then
kill -TERM "$pid" 2>/dev/null || true
else
echo "[test] WARNING: Process already exited before signal"
fi
set +e
wait "$pid" 2>/dev/null || true
wait_rc=$?
set -e
echo "[test] rc=$wait_rc"
# Under QEMU without a shell, expect signal exit code (143 for TERM) or 137 on escalation
if [ "$wait_rc" -eq 143 ] || [ "$wait_rc" -eq 137 ]; then
echo "[test] OK (terminated by TERM/KILL as expected: $wait_rc)"
else
echo "[test] INFO: Got exit code $wait_rc (may vary under QEMU)"
fi
# Test 3: Escalation (simplified - may not work perfectly under QEMU)
echo "[test] 3) Escalation check (may be flaky under QEMU)"
EP_GRACE_SECONDS=1 timeout 10s "$QEMU" -- "$BIN" -v -- ./build/arm64/helper-sleeper &
pid=$!
sleep 1
# Check if process is still running before sending signal
if kill -0 "$pid" 2>/dev/null; then
kill -TERM "$pid" 2>/dev/null || true
else
echo "[test] WARNING: Process already exited before signal"
fi
set +e
wait "$pid" 2>/dev/null || true
wait_rc=$?
set -e
echo "[test] rc=$wait_rc"
if [ "$wait_rc" -eq 137 ] || [ "$wait_rc" -eq 143 ]; then
echo "[test] OK (got kill signal: $wait_rc)"
else
echo "[test] INFO: Got exit code $wait_rc (may vary under QEMU)"
fi
echo "[test] ARM64 smoke test completed"
|