From 6dab9b295332ac2e1f2a439612ff3cfde1ddeeee Mon Sep 17 00:00:00 2001 From: vasilito Date: Mon, 20 Jul 2026 09:01:14 +0900 Subject: [PATCH] tests: migrate remaining QEMU runtime proofs to qemu-login-expect.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the remaining expect-based test scripts (phase1-6 runtime, usb, wifi, bluetooth, dbus, greeter, live-iso, posix) to the stdlib python harness, completing the migration started in 9ec00d4c81. Each script now prefers booting the live ISO when present (falling back to harddrive.img with snapshot=on), and retries up to 5 times when QEMU exits early or is killed (rc 3 / 137) — the host-contention failure mode recorded in the 2026-07-20 runtime-proof status. qemu-login-expect.py: treat an incomplete step sequence as a failure even when a pass marker was seen partway through — partial sequences must not count as a pass. --- local/scripts/qemu-login-expect.py | 9 + local/scripts/test-bluetooth-qemu.sh | 111 +++++++---- local/scripts/test-bt-runtime.sh | 56 ++++-- local/scripts/test-dbus-qemu.sh | 81 +++----- local/scripts/test-greeter-qemu.sh | 97 +++++----- local/scripts/test-live-iso-qemu.sh | 39 ++-- .../scripts/test-phase1-desktop-substrate.sh | 173 +++++++++--------- local/scripts/test-phase1-runtime.sh | 134 ++++++++------ local/scripts/test-phase2-runtime.sh | 92 ++++++---- .../scripts/test-phase3-runtime-substrate.sh | 82 ++++++--- local/scripts/test-phase3-runtime.sh | 92 ++++++---- local/scripts/test-phase4-runtime.sh | 56 ++++-- local/scripts/test-phase4-wayland-qemu.sh | 91 +++++---- local/scripts/test-phase5-cs-runtime.sh | 55 ++++-- local/scripts/test-phase5-gpu-runtime.sh | 57 ++++-- local/scripts/test-phase5-network-qemu.sh | 89 +++++---- local/scripts/test-phase6-kde-qemu.sh | 90 +++++---- local/scripts/test-posix-runtime.sh | 54 ++++-- local/scripts/test-usb-qemu.sh | 82 ++++++--- local/scripts/test-usb-runtime.sh | 54 ++++-- local/scripts/test-wifi-passthrough-qemu.sh | 95 ++++++---- local/scripts/test-wifi-runtime.sh | 62 +++++-- 22 files changed, 1104 insertions(+), 647 deletions(-) diff --git a/local/scripts/qemu-login-expect.py b/local/scripts/qemu-login-expect.py index a94bb7701a..76a2cf05f4 100644 --- a/local/scripts/qemu-login-expect.py +++ b/local/scripts/qemu-login-expect.py @@ -151,6 +151,15 @@ def main() -> int: if state["failed"]: print(f"ERROR: a --fail marker appeared; see {args.log}", file=sys.stderr) return 1 + if i < len(steps): + # The step sequence did not run to completion (timeout or early death + # before every expect step matched). Pass markers seen partway through + # must not count as a pass: a fully completed sequence is required. + if state["died_early"]: + print(f"ERROR: qemu exited before the check completed; see {args.log}", file=sys.stderr) + return 3 + print(f"ERROR: step sequence did not complete; see {args.log}", file=sys.stderr) + return 1 if args.pass_marker and len(state["passes"]) != len(args.pass_marker): if state["died_early"]: print(f"ERROR: qemu exited before the check completed; see {args.log}", file=sys.stderr) diff --git a/local/scripts/test-bluetooth-qemu.sh b/local/scripts/test-bluetooth-qemu.sh index 34db86501e..d568390316 100755 --- a/local/scripts/test-bluetooth-qemu.sh +++ b/local/scripts/test-bluetooth-qemu.sh @@ -57,6 +57,7 @@ firmware="$(find_uefi_firmware)" || { arch="${ARCH:-$(uname -m)}" image="build/$arch/redbear-bluetooth-experimental/harddrive.img" +iso="build/$arch/redbear-bluetooth-experimental.iso" extra="build/$arch/redbear-bluetooth-experimental/extra.img" extra_qemu_args="${filtered_args[*]:-}" @@ -66,12 +67,23 @@ else combined_qemu_args="${extra_qemu_args}" fi -if [[ ! -f "$image" ]]; then - echo "ERROR: missing image $image" >&2 +boot_media="" +if [[ -f "$iso" ]]; then + boot_media="iso" +elif [[ -f "$image" ]]; then + boot_media="harddrive" +else + echo "ERROR: no bootable image found ($iso or $image)" >&2 echo "Build it first with: ./local/scripts/build-redbear.sh redbear-bluetooth-experimental" >&2 exit 1 fi +if [[ "$boot_media" == "iso" ]]; then + boot_args=(-cdrom "$iso") +else + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) +fi + if [[ ! -f "$extra" ]]; then truncate -s 1g "$extra" fi @@ -91,35 +103,70 @@ echo " test-bluetooth-runtime.sh" echo if [[ "$check_mode" -eq 1 ]]; then - expect </dev/null 2>&1 && echo __BT_OK__ || echo __BT_FAIL__\r" -expect { "__BT_OK__" { } "__BT_FAIL__" { puts "FAIL: bt check"; exit 1 } timeout { puts "FAIL: timeout"; exit 1 } eof { puts "FAIL: eof"; exit 1 } } -puts "ALL BT CHECKS PASSED" -EXPECT_SCRIPT - exit $? + + attempt=1 + while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 300 \ + --log "build/${arch}/${CONFIG}/bt-runtime-check.log" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:assword:" \ + --step "send:password" \ + --step "expect:Type 'help' for available commands." \ + --step "send:echo __READY__" \ + --step "expect:__READY__" \ + --step "send:redbear-bluetooth-battery-check --json >/dev/null 2>&1 && echo __BT_OK__ || echo __BT_FAIL__" \ + --pass_marker "__BT_OK__" \ + --fail_marker "__BT_FAIL__" \ + -- \ + qemu-system-x86_64 -name "Red Bear OS" -device qemu-xhci -smp 4 -m 2048 -bios "$firmware" -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device virtio-net,netdev=net0 -netdev user,id=net0 -nographic -vga none "${boot_args[@]}" -enable-kvm -cpu host || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + exit "$rc" + done + echo "ALL BT CHECKS PASSED" + exit 0 } case "$MODE" in diff --git a/local/scripts/test-dbus-qemu.sh b/local/scripts/test-dbus-qemu.sh index 9044a094bc..b03fc30c2f 100755 --- a/local/scripts/test-dbus-qemu.sh +++ b/local/scripts/test-dbus-qemu.sh @@ -158,59 +158,38 @@ GUEST_EOF chmod +x "$GUEST_SCRIPT" if [[ "$CHECK_MODE" -eq 1 ]]; then - if ! command -v expect >/dev/null 2>&1; then - echo "test-dbus-qemu: --check mode requires 'expect' (install tcllib/expect)" >&2 - exit 2 - fi - echo "test-dbus-qemu: launching QEMU with D-Bus checks (non-interactive)" - # Use expect to boot the guest, wait for login, run checks, capture output - expect <<'EXPECT_EOF' > "$OUTPUT_FILE" 2>&1 -set timeout 120 -spawn qemu-system-x86_64 \ - -drive file="$::env(IMAGE)" \ - -m 2G \ - -smp 2 \ - -nographic \ - -no-reboot - -expect { - "login:" { } - timeout { puts "FAIL: timed out waiting for login prompt"; exit 1 } -} - -sleep 2 -send "root\r" - -expect { - "#" { } - timeout { puts "FAIL: timed out waiting for shell prompt"; exit 1 } -} - -sleep 1 - -# Read and send the check script line by line -set fp [open "/tmp/dbus-check.sh" r] -while {[gets $fp line] >= 0} { - send "$line\r" - expect { - "#" { } - timeout { puts "FAIL: timed out during check execution"; exit 1 } - } -} -close $fp - -sleep 2 -send "poweroff\r" - -expect { - "Power down" { } - timeout { } -} - -exit 0 -EXPECT_EOF + # Boot the guest, wait for login, send the D-Bus check script as a single + # bulk transfer, and wait for the completion marker. The helper's send + # appends \r after the text; the multi-line script content executes + # line-by-line in the guest shell, producing the same PASS/FAIL output. + attempt=1 + while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 120 \ + --log "$OUTPUT_FILE" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:#" \ + --step "send:$(cat "$GUEST_SCRIPT")" \ + --step "expect:=== D-Bus Validation Complete ===" \ + --pass_marker "=== D-Bus Validation Complete ===" \ + -- \ + qemu-system-x86_64 -drive file="$IMAGE" -m 2G -smp 2 -nographic -no-reboot || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + rm -f "$GUEST_SCRIPT" + exit "$rc" + done FAILED=$(grep -c "FAIL" "$OUTPUT_FILE" 2>/dev/null || true) PASSED=$(grep -c "PASS" "$OUTPUT_FILE" 2>/dev/null || true) diff --git a/local/scripts/test-greeter-qemu.sh b/local/scripts/test-greeter-qemu.sh index 982efbb64c..e908615b5d 100755 --- a/local/scripts/test-greeter-qemu.sh +++ b/local/scripts/test-greeter-qemu.sh @@ -50,14 +50,26 @@ if [[ -z "$firmware" ]]; then fi arch="${ARCH:-$(uname -m)}" +iso="build/$arch/redbear-full.iso" image="build/$arch/redbear-full/harddrive.img" -if [[ ! -f "$image" ]]; then - echo "ERROR: missing image $image" >&2 +boot_media="" +if [[ -f "$iso" ]]; then + boot_media="iso" +elif [[ -f "$image" ]]; then + boot_media="harddrive" +else + echo "ERROR: no bootable image found ($iso or $image)" >&2 echo "Build it first with: ./local/scripts/build-redbear.sh redbear-full" >&2 exit 1 fi +if [[ "$boot_media" == "iso" ]]; then + boot_args=(-cdrom "$iso") +else + boot_args=(-drive file="$image",format=raw,if=none,id=drv0 -device nvme,drive=drv0,serial=NVME_SERIAL) +fi + if [[ "$check_mode" -eq 0 ]]; then exec qemu-system-x86_64 \ -name "Red Bear Greeter Validation" \ @@ -67,55 +79,52 @@ if [[ "$check_mode" -eq 0 ]]; then -bios "$firmware" \ -chardev stdio,id=debug,signal=off,mux=on \ -serial chardev:debug \ - -mon chardev=debug \ + -mon chardev:debug \ -machine q35 \ -device ich9-intel-hda -device hda-output \ -device virtio-net,netdev=net0 \ -netdev user,id=net0 \ -vga none \ -device virtio-gpu \ - -drive file="$image",format=raw,if=none,id=drv0 \ - -device nvme,drive=drv0,serial=NVME_SERIAL \ + "${boot_args[@]}" \ -enable-kvm -cpu host fi -expect </dev/null || true +sleep 1 -proc expect_or_fail {pattern description} { - expect { - -nocase -re \$pattern { return } - timeout { - puts stderr "ERROR: timed out waiting for \$description" - exit 1 - } - eof { - puts stderr "ERROR: QEMU exited while waiting for \$description" - exit 1 - } - } -} - -expect_or_fail {login:} {login prompt} -send "root\r" -expect_or_fail {assword:} {password prompt} -send "password\r" -expect_or_fail {Type 'help' for available commands\.} {shell startup banner} -send "redbear-greeter-check\r" -expect_or_fail {Red Bear Greeter Runtime Check} {greeter check banner} -expect_or_fail {GREETER_HELLO=ok} {greeter hello marker} -send "redbear-greeter-check --invalid root wrong\r" -expect_or_fail {GREETER_INVALID=ok} {invalid-login marker} -send "redbear-greeter-check --valid root password\r" -expect_or_fail {GREETER_VALID=ok} {valid-login marker} -send "shutdown\r" -expect { - eof { exit 0 } - timeout { - puts stderr "ERROR: timed out waiting for QEMU shutdown" - exit 1 - } -} -EOF +attempt=1 +while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 240 \ + --log "build/$arch/redbear-full/greeter-check.log" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:assword:" \ + --step "send:password" \ + --step "expect:Type 'help' for available commands." \ + --step "send:redbear-greeter-check" \ + --step "expect:Red Bear Greeter Runtime Check" \ + --step "expect:GREETER_HELLO=ok" \ + --step "send:redbear-greeter-check --invalid root wrong" \ + --step "expect:GREETER_INVALID=ok" \ + --step "send:redbear-greeter-check --valid root password" \ + --step "expect:GREETER_VALID=ok" \ + --step "send:shutdown" \ + --pass_marker "GREETER_VALID=ok" \ + -- \ + qemu-system-x86_64 -name "Red Bear Greeter Validation" -device qemu-xhci -smp 4 -m 2048 -bios "$firmware" -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device ich9-intel-hda -device hda-output -device virtio-net,netdev=net0 -netdev user,id=net0 -vga none -device virtio-gpu "${boot_args[@]}" -enable-kvm -cpu host || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + exit "$rc" +done +pkill -f "qemu-system-x86_64.*$image" 2>/dev/null || true +echo "Greeter runtime validation completed via guest runtime check" diff --git a/local/scripts/test-live-iso-qemu.sh b/local/scripts/test-live-iso-qemu.sh index eb380f937e..c1a328c9ed 100755 --- a/local/scripts/test-live-iso-qemu.sh +++ b/local/scripts/test-live-iso-qemu.sh @@ -68,16 +68,31 @@ done for config in "${configs[@]}"; do echo "=== Boot-testing $config ===" - expect <&2 + boot_media="" + if [[ -f "$iso" ]]; then + boot_media="iso" + elif [[ -f "$image" ]]; then + boot_media="harddrive" + else + echo "ERROR: no bootable image found ($iso or $image)" >&2 echo "Build it first with: ./local/scripts/build-redbear.sh $config" >&2 exit 1 fi @@ -202,87 +208,86 @@ run_qemu_checks() { truncate -s 1g "$extra" fi - expect </scheme/null && echo __EVDVD_OK__ || echo __EVDVD_FAIL__\r" -expect { - "__EVDVD_OK__" { } - "__EVDVD_FAIL__" { puts "FAIL: evdevd missing"; exit 1 } -} -send "test -e /scheme/evdev && echo __EVDEV_SCH_OK__ || echo __EVDEV_SCH_FAIL__\r" -expect { - "__EVDEV_SCH_OK__" { } - "__EVDEV_SCH_FAIL__" { puts "FAIL: /scheme/evdev missing"; exit 1 } -} - send "which udev-shim >/scheme/null && echo __UDEV_OK__ || echo __UDEV_FAIL__\r" -expect { - "__UDEV_OK__" { } - "__UDEV_FAIL__" { puts "FAIL: udev-shim missing"; exit 1 } -} -send "test -e /scheme/udev && echo __UDEV_SCH_OK__ || echo __UDEV_SCH_FAIL__\r" -expect { - "__UDEV_SCH_OK__" { } - "__UDEV_SCH_FAIL__" { puts "FAIL: /scheme/udev missing"; exit 1 } -} - send "test -e /lib/firmware && echo __FW_DIR_OK__ || echo __FW_DIR_FAIL__\r" - expect { - "__FW_DIR_OK__" { } - "__FW_DIR_FAIL__" { puts "FAIL: /lib/firmware missing"; exit 1 } -} - send "test -e /usr/bin/redox-drm && echo __DRM_OK__ || echo __DRM_FAIL__\r" -expect { - "__DRM_OK__" { } - "__DRM_FAIL__" { puts "FAIL: redox-drm missing"; exit 1 } -} - send "test -e /scheme/drm && echo __DRM_SCH_OK__ || echo __DRM_SCH_FAIL__\r" - expect { - "__DRM_SCH_OK__" { } - "__DRM_SCH_FAIL__" { - send "if lspci 2>/dev/null | grep -E '(VGA compatible controller|3D controller)' | grep -E '(8086:|1002:)' >/dev/null 2>&1; then echo __DRM_GPU_EXPECTED__; else echo __DRM_GPU_SKIP__; fi\r" - expect { - "__DRM_GPU_EXPECTED__" { puts "FAIL: /scheme/drm missing with supported AMD/Intel GPU present"; exit 1 } - "__DRM_GPU_SKIP__" { } - } - } -} - send "redbear-info --json\r" - expect "\"virtio_net_present\": true" - expect "scheme firmware is registered" -expect "scheme udev is registered" -send "echo __PHASE1_DONE__\r" -expect "__PHASE1_DONE__" -send "shutdown\r" -expect eof -EOF + if [[ "$boot_media" == "iso" ]]; then + boot_args=(-cdrom "$iso") + else + boot_args=(-drive file="$image",format=raw,if=none,id=drv0 -device nvme,drive=drv0,serial=NVME_SERIAL) + fi + + pkill -f "qemu-system-x86_64.*$config" 2>/dev/null || true + sleep 1 + + attempt=1 + while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 300 \ + --log "build/$arch/$config/phase1-desktop-check.log" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:assword:" \ + --step "send:password" \ + --step "expect:Type 'help' for available commands." \ + --step "send:echo __READY__" \ + --step "expect:__READY__" \ + --step "send:test -e /usr/include/sys/signalfd.h && echo __SIGNAFD_OK__ || echo __SIGNAFD_FAIL__" \ + --step "expect:__SIGNAFD_OK__" \ + --step "send:test -e /usr/include/sys/timerfd.h && echo __TIMERFD_OK__ || echo __TIMERFD_FAIL__" \ + --step "expect:__TIMERFD_OK__" \ + --step "send:test -e /usr/include/sys/eventfd.h && echo __EVENTFD_OK__ || echo __EVENTFD_FAIL__" \ + --step "expect:__EVENTFD_OK__" \ + --step "send:test -e /usr/lib/libwayland-client.so && echo __WAYLAND_LIB_OK__ || echo __WAYLAND_LIB_FAIL__" \ + --step "expect:__WAYLAND_LIB_OK__" \ + --step "send:which evdevd >/scheme/null && echo __EVDVD_OK__ || echo __EVDVD_FAIL__" \ + --step "expect:__EVDVD_OK__" \ + --step "send:test -e /scheme/evdev && echo __EVDEV_SCH_OK__ || echo __EVDEV_SCH_FAIL__" \ + --step "expect:__EVDEV_SCH_OK__" \ + --step "send:which udev-shim >/scheme/null && echo __UDEV_OK__ || echo __UDEV_FAIL__" \ + --step "expect:__UDEV_OK__" \ + --step "send:test -e /scheme/udev && echo __UDEV_SCH_OK__ || echo __UDEV_SCH_FAIL__" \ + --step "expect:__UDEV_SCH_OK__" \ + --step "send:test -e /lib/firmware && echo __FW_DIR_OK__ || echo __FW_DIR_FAIL__" \ + --step "expect:__FW_DIR_OK__" \ + --step "send:test -e /usr/bin/redox-drm && echo __DRM_OK__ || echo __DRM_FAIL__" \ + --step "expect:__DRM_OK__" \ + --step "send:test -e /scheme/drm && echo __DRM_SCH_OK__ || echo __DRM_SCH_FAIL__" \ + --step "expect:__DRM_SCH_" \ + --step "send:if lspci 2>/dev/null | grep -E '(VGA compatible controller|3D controller)' | grep -E '(8086:|1002:)' >/dev/null 2>&1; then echo __DRM_GPU_EXPECTED__; else echo __DRM_GPU_SKIP__; fi" \ + --step "expect:__DRM_GPU_" \ + --step "send:redbear-info --json" \ + --step 'expect:"virtio_net_present": true' \ + --step "expect:scheme firmware is registered" \ + --step "expect:scheme udev is registered" \ + --step "send:echo __PHASE1_DONE__" \ + --step "expect:__PHASE1_DONE__" \ + --step "send:shutdown" \ + --pass_marker "__PHASE1_DONE__" \ + --fail_marker "__SIGNAFD_FAIL__" \ + --fail_marker "__TIMERFD_FAIL__" \ + --fail_marker "__EVENTFD_FAIL__" \ + --fail_marker "__WAYLAND_LIB_FAIL__" \ + --fail_marker "__EVDVD_FAIL__" \ + --fail_marker "__EVDEV_SCH_FAIL__" \ + --fail_marker "__UDEV_FAIL__" \ + --fail_marker "__UDEV_SCH_FAIL__" \ + --fail_marker "__FW_DIR_FAIL__" \ + --fail_marker "__DRM_FAIL__" \ + --fail_marker "__DRM_GPU_EXPECTED__" \ + -- \ + qemu-system-x86_64 -name "Red Bear OS x86_64" -device qemu-xhci -smp 4 -m 2048 -bios "$firmware" -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device ich9-intel-hda -device hda-output -device virtio-net,netdev=net0 -netdev user,id=net0 -object filter-dump,id=f1,netdev=net0,file="build/$arch/$config/network.pcap" -display none -vga none "${boot_args[@]}" -drive file="$extra",format=raw,if=none,id=drv1 -device nvme,drive=drv1,serial=NVME_EXTRA -enable-kvm -cpu host || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + exit "$rc" + done + pkill -f "qemu-system-x86_64.*$image" 2>/dev/null || true + echo "Phase 1 desktop substrate runtime validation completed via guest runtime check" } usage() { diff --git a/local/scripts/test-phase1-runtime.sh b/local/scripts/test-phase1-runtime.sh index 7bfa4bb6c4..21a56f25c7 100755 --- a/local/scripts/test-phase1-runtime.sh +++ b/local/scripts/test-phase1-runtime.sh @@ -142,17 +142,29 @@ run_qemu_checks() { exit 2 } - local arch image extra + local arch image iso extra arch="${ARCH:-$(uname -m)}" image="build/$arch/$config/harddrive.img" + iso="build/$arch/$config.iso" extra="build/$arch/$config/extra.img" - if [[ ! -f "$image" ]]; then - echo "ERROR: missing image $image" >&2 + boot_media="" + if [[ -f "$iso" ]]; then + boot_media="iso" + elif [[ -f "$image" ]]; then + boot_media="harddrive" + else + echo "ERROR: no bootable image found ($iso or $image)" >&2 echo "Build it first with: ./local/scripts/build-redbear.sh $config" >&2 exit 2 fi + if [[ "$boot_media" == "iso" ]]; then + boot_args=(-cdrom "$iso") + else + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) + fi + if [[ ! -f "$extra" ]]; then truncate -s 1g "$extra" fi @@ -160,63 +172,63 @@ run_qemu_checks() { # All Phase 1 check binaries use exit code 0 for pass, 1 for fail. # redbear-info --probe exits 0 if all services present, non-zero otherwise. # relibc POSIX tests use exit code 0/1. - expect </dev/null 2>&1; then echo \"\\\${t}:PASS\"; else echo \"\\\${t}:FAIL\"; POSIX_FAIL=1; fi; done; echo __POSIX_DONE__\\\$POSIX_FAIL__\r" -expect { - "__POSIX_DONE__0__" { } - "__POSIX_DONE__1__" { puts "FAIL: one or more relibc POSIX tests failed"; exit 1 } - timeout { puts "FAIL: timed out before POSIX test completion"; exit 1 } - eof { puts "FAIL: guest exited before POSIX test completion"; exit 1 } -} - -# Phase 1 check binaries — exit code is authoritative -send "redbear-phase1-evdev-check --json >/dev/null 2>&1 && echo __EVDV_OK__ || echo __EVDV_FAIL__\r" -expect { - "__EVDV_OK__" { } - "__EVDV_FAIL__" { puts "FAIL: evdevd check failed"; exit 1 } -} - -send "redbear-phase1-udev-check --json >/dev/null 2>&1 && echo __UDEV_OK__ || echo __UDEV_FAIL__\r" -expect { - "__UDEV_OK__" { } - "__UDEV_FAIL__" { puts "FAIL: udev-shim check failed"; exit 1 } -} - -send "redbear-phase1-firmware-check --json >/dev/null 2>&1 && echo __FW_OK__ || echo __FW_FAIL__\r" -expect { - "__FW_OK__" { } - "__FW_FAIL__" { puts "FAIL: firmware-loader check failed"; exit 1 } -} - -send "redbear-phase1-drm-check --json >/dev/null 2>&1 && echo __DRM_OK__ || echo __DRM_FAIL__\r" -expect { - "__DRM_OK__" { } - "__DRM_FAIL__" { puts "FAIL: DRM check failed"; exit 1 } -} - -send "redbear-info --probe >/dev/null 2>&1 && echo __PROBE_OK__ || echo __PROBE_FAIL__\r" -expect { - "__PROBE_OK__" { } - "__PROBE_FAIL__" { puts "FAIL: redbear-info --probe reported gaps"; exit 1 } -} - -send "echo __PHASE1_RUNTIME_DONE__\r" -expect "__PHASE1_RUNTIME_DONE__" -send "shutdown\r" -expect eof -EXPECT_SCRIPT + attempt=1 + while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 300 \ + --log "build/$arch/$config/phase1-check.log" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:assword:" \ + --step "send:password" \ + --step "expect:Type 'help' for available commands." \ + --step "send:echo __READY__" \ + --step "expect:__READY__" \ + --step "send:cd /home/user/relibc-phase1-tests && POSIX_FAIL=0; for t in test_signalfd_wayland test_timerfd_qt6 test_eventfd_qt6 test_shm_open_qt6 test_sem_open_qt6 test_waitid_qt6; do echo \"POSIX:\$t\"; if ./\$t >/dev/null 2>&1; then echo \"\${t}:PASS\"; else echo \"\${t}:FAIL\"; POSIX_FAIL=1; fi; done; echo __POSIX_DONE__\$POSIX_FAIL__" \ + --step "expect:__POSIX_DONE__0__" \ + --step "send:redbear-phase1-evdev-check --json >/dev/null 2>&1 && echo __EVDV_OK__ || echo __EVDV_FAIL__" \ + --step "expect:__EVDV_OK__" \ + --step "send:redbear-phase1-udev-check --json >/dev/null 2>&1 && echo __UDEV_OK__ || echo __UDEV_FAIL__" \ + --step "expect:__UDEV_OK__" \ + --step "send:redbear-phase1-firmware-check --json >/dev/null 2>&1 && echo __FW_OK__ || echo __FW_FAIL__" \ + --step "expect:__FW_OK__" \ + --step "send:redbear-phase1-drm-check --json >/dev/null 2>&1 && echo __DRM_OK__ || echo __DRM_FAIL__" \ + --step "expect:__DRM_OK__" \ + --step "send:redbear-info --probe >/dev/null 2>&1 && echo __PROBE_OK__ || echo __PROBE_FAIL__" \ + --step "expect:__PROBE_OK__" \ + --step "send:echo __PHASE1_RUNTIME_DONE__" \ + --step "expect:__PHASE1_RUNTIME_DONE__" \ + --step "send:shutdown" \ + --pass_marker "__POSIX_DONE__0__" \ + --pass_marker "__EVDV_OK__" \ + --pass_marker "__UDEV_OK__" \ + --pass_marker "__FW_OK__" \ + --pass_marker "__DRM_OK__" \ + --pass_marker "__PROBE_OK__" \ + --pass_marker "__PHASE1_RUNTIME_DONE__" \ + --fail_marker "__POSIX_DONE__1__" \ + --fail_marker "__EVDV_FAIL__" \ + --fail_marker "__UDEV_FAIL__" \ + --fail_marker "__FW_FAIL__" \ + --fail_marker "__DRM_FAIL__" \ + --fail_marker "__PROBE_FAIL__" \ + -- \ + qemu-system-x86_64 -name "Red Bear OS x86_64" -device qemu-xhci -smp 4 -m 2048 -bios "$firmware" -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device ich9-intel-hda -device hda-output -device virtio-net,netdev=net0 -netdev user,id=net0 -display none -vga none "${boot_args[@]}" -drive file="$extra",format=raw,if=none,id=drv1,snapshot=on -device nvme,drive=drv1,serial=NVME_EXTRA -enable-kvm -cpu host || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + exit "$rc" + done + pkill -f "qemu-system-x86_64.*$config" 2>/dev/null || true + echo "Phase 1 runtime substrate validation completed via guest runtime check" + exit 0 } usage() { @@ -259,4 +271,4 @@ case "${1:-}" in usage exit 1 ;; -esac \ No newline at end of file +esac diff --git a/local/scripts/test-phase2-runtime.sh b/local/scripts/test-phase2-runtime.sh index 8e58d4a1ac..83e13ff563 100644 --- a/local/scripts/test-phase2-runtime.sh +++ b/local/scripts/test-phase2-runtime.sh @@ -75,54 +75,74 @@ run_qemu_checks() { exit 2 } - local arch image extra + local arch image iso extra arch="${ARCH:-$(uname -m)}" image="build/$arch/$config/harddrive.img" + iso="build/$arch/$config.iso" extra="build/$arch/$config/extra.img" - if [[ ! -f "$image" ]]; then - echo "ERROR: missing image $image" >&2 + boot_media="" + if [[ -f "$iso" ]]; then + boot_media="iso" + elif [[ -f "$image" ]]; then + boot_media="harddrive" + else + echo "ERROR: no bootable image found ($iso or $image)" >&2 echo "Build it first with: ./local/scripts/build-redbear.sh $config" >&2 exit 2 fi + if [[ "$boot_media" == "iso" ]]; then + boot_args=(-cdrom "$iso") + else + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) + fi + if [[ ! -f "$extra" ]]; then truncate -s 1g "$extra" fi - expect </dev/null 2>&1 && echo __PHASE2_BIN_OK__ || echo __PHASE2_BIN_FAIL__\r" -expect { - "__PHASE2_BIN_OK__" { } - "__PHASE2_BIN_FAIL__" { puts "FAIL: redbear-phase2-wayland-check is missing"; exit 1 } - timeout { puts "FAIL: timed out while checking for redbear-phase2-wayland-check"; exit 1 } - eof { puts "FAIL: guest exited before Phase 2 binary check completed"; exit 1 } -} - -send "redbear-phase2-wayland-check --json >/dev/null 2>&1 && echo __PHASE2_OK__ || echo __PHASE2_FAIL__\r" -expect { - "__PHASE2_OK__" { } - "__PHASE2_FAIL__" { puts "FAIL: redbear-phase2-wayland-check reported failures"; exit 1 } - timeout { puts "FAIL: timed out while running redbear-phase2-wayland-check"; exit 1 } - eof { puts "FAIL: guest exited before Phase 2 check completed"; exit 1 } -} - -send "echo __PHASE2_RUNTIME_DONE__\r" -expect "__PHASE2_RUNTIME_DONE__" -send "shutdown\r" -expect eof -EXPECT_SCRIPT + attempt=1 + while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 300 \ + --log "build/$arch/$config/phase2-check.log" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:assword:" \ + --step "send:password" \ + --step "expect:Type 'help' for available commands." \ + --step "send:echo __READY__" \ + --step "expect:__READY__" \ + --step "send:command -v redbear-phase2-wayland-check >/dev/null 2>&1 && echo __PHASE2_BIN_OK__ || echo __PHASE2_BIN_FAIL__" \ + --step "expect:__PHASE2_BIN_OK__" \ + --step "send:redbear-phase2-wayland-check --json >/dev/null 2>&1 && echo __PHASE2_OK__ || echo __PHASE2_FAIL__" \ + --step "expect:__PHASE2_OK__" \ + --step "send:echo __PHASE2_RUNTIME_DONE__" \ + --step "expect:__PHASE2_RUNTIME_DONE__" \ + --step "send:shutdown" \ + --pass_marker "__PHASE2_BIN_OK__" \ + --pass_marker "__PHASE2_OK__" \ + --pass_marker "__PHASE2_RUNTIME_DONE__" \ + --fail_marker "__PHASE2_BIN_FAIL__" \ + --fail_marker "__PHASE2_FAIL__" \ + -- \ + qemu-system-x86_64 -name "Red Bear OS x86_64" -device qemu-xhci -smp 4 -m 2048 -bios "$firmware" -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device ich9-intel-hda -device hda-output -device virtio-net,netdev=net0 -netdev user,id=net0 -display none -vga none "${boot_args[@]}" -drive file="$extra",format=raw,if=none,id=drv1,snapshot=on -device nvme,drive=drv1,serial=NVME_EXTRA -enable-kvm -cpu host || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + exit "$rc" + done + pkill -f "qemu-system-x86_64.*$config" 2>/dev/null || true + echo "Phase 2 Wayland runtime validation completed via guest runtime check" + exit 0 } usage() { diff --git a/local/scripts/test-phase3-runtime-substrate.sh b/local/scripts/test-phase3-runtime-substrate.sh index 121e34b554..bee2f3b357 100644 --- a/local/scripts/test-phase3-runtime-substrate.sh +++ b/local/scripts/test-phase3-runtime-substrate.sh @@ -98,45 +98,73 @@ run_qemu_checks() { exit 1 } - local arch image extra + local arch image iso extra arch="${ARCH:-$(uname -m)}" image="build/$arch/$config/harddrive.img" + iso="build/$arch/$config.iso" extra="build/$arch/$config/extra.img" - if [[ ! -f "$image" ]]; then - echo "ERROR: missing image $image" >&2 + local boot_media boot_args + boot_media="" + if [[ -f "$iso" ]]; then + boot_media="iso" + elif [[ -f "$image" ]]; then + boot_media="harddrive" + else + echo "ERROR: no bootable image found ($iso or $image)" >&2 echo "Build it first with: ./local/scripts/build-redbear.sh $config" >&2 exit 1 fi + if [[ "$boot_media" == "iso" ]]; then + boot_args=(-cdrom "$iso") + else + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) + fi + if [[ ! -f "$extra" ]]; then truncate -s 1g "$extra" fi - expect <&2 + boot_media="" + if [[ -f "$iso" ]]; then + boot_media="iso" + elif [[ -f "$image" ]]; then + boot_media="harddrive" + else + echo "ERROR: no bootable image found ($iso or $image)" >&2 echo "Build it first with: ./local/scripts/build-redbear.sh $config" >&2 exit 2 fi + if [[ "$boot_media" == "iso" ]]; then + boot_args=(-cdrom "$iso") + else + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) + fi + if [[ ! -f "$extra" ]]; then truncate -s 1g "$extra" fi - expect </dev/null 2>&1 && echo __PHASE3_BIN_OK__ || echo __PHASE3_BIN_FAIL__\r" -expect { - "__PHASE3_BIN_OK__" { } - "__PHASE3_BIN_FAIL__" { puts "FAIL: redbear-phase3-kwin-check is missing"; exit 1 } - timeout { puts "FAIL: timed out while checking for redbear-phase3-kwin-check"; exit 1 } - eof { puts "FAIL: guest exited before Phase 3 binary check completed"; exit 1 } -} - -send "redbear-phase3-kwin-check --json >/dev/null 2>&1 && echo __PHASE3_OK__ || echo __PHASE3_FAIL__\r" -expect { - "__PHASE3_OK__" { } - "__PHASE3_FAIL__" { puts "FAIL: redbear-phase3-kwin-check reported failures"; exit 1 } - timeout { puts "FAIL: timed out while running redbear-phase3-kwin-check"; exit 1 } - eof { puts "FAIL: guest exited before Phase 3 check completed"; exit 1 } -} - -send "echo __PHASE3_RUNTIME_DONE__\r" -expect "__PHASE3_RUNTIME_DONE__" -send "shutdown\r" -expect eof -EXPECT_SCRIPT + attempt=1 + while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 300 \ + --log "build/$arch/$config/phase3-check.log" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:assword:" \ + --step "send:password" \ + --step "expect:Type 'help' for available commands." \ + --step "send:echo __READY__" \ + --step "expect:__READY__" \ + --step "send:command -v redbear-phase3-kwin-check >/dev/null 2>&1 && echo __PHASE3_BIN_OK__ || echo __PHASE3_BIN_FAIL__" \ + --step "expect:__PHASE3_BIN_OK__" \ + --step "send:redbear-phase3-kwin-check --json >/dev/null 2>&1 && echo __PHASE3_OK__ || echo __PHASE3_FAIL__" \ + --step "expect:__PHASE3_OK__" \ + --step "send:echo __PHASE3_RUNTIME_DONE__" \ + --step "expect:__PHASE3_RUNTIME_DONE__" \ + --step "send:shutdown" \ + --pass_marker "__PHASE3_BIN_OK__" \ + --pass_marker "__PHASE3_OK__" \ + --pass_marker "__PHASE3_RUNTIME_DONE__" \ + --fail_marker "__PHASE3_BIN_FAIL__" \ + --fail_marker "__PHASE3_FAIL__" \ + -- \ + qemu-system-x86_64 -name "Red Bear OS x86_64" -device qemu-xhci -smp 4 -m 2048 -bios "$firmware" -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device ich9-intel-hda -device hda-output -device virtio-net,netdev=net0 -netdev user,id=net0 -display none -vga none "${boot_args[@]}" -drive file="$extra",format=raw,if=none,id=drv1,snapshot=on -device nvme,drive=drv1,serial=NVME_EXTRA -enable-kvm -cpu host || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + exit "$rc" + done + pkill -f "qemu-system-x86_64.*$config" 2>/dev/null || true + echo "Phase 3 desktop session preflight completed via guest runtime check" + exit 0 } usage() { diff --git a/local/scripts/test-phase4-runtime.sh b/local/scripts/test-phase4-runtime.sh index b175791c90..917510c0f5 100644 --- a/local/scripts/test-phase4-runtime.sh +++ b/local/scripts/test-phase4-runtime.sh @@ -57,25 +57,53 @@ run_guest_checks() { run_qemu_checks() { local arch="${ARCH:-x86_64}" local image="build/${arch}/${CONFIG}/harddrive.img" + local iso="build/${arch}/${CONFIG}.iso" local firmware="${FIRMWARE_PATH:-/usr/share/ovmf/x64/OVMF.fd}" - if [[ ! -f "$image" ]]; then echo "$PROG: image not found: $image (build with: make all CONFIG_NAME=$CONFIG)"; exit 1; fi + if [[ -f "$iso" ]]; then + boot_args=(-cdrom "$iso") + elif [[ -f "$image" ]]; then + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) + else + echo "$PROG: no bootable image found ($iso or $image) (build with: make all CONFIG_NAME=$CONFIG)"; exit 1 + fi if [[ ! -f "$firmware" ]]; then echo "$PROG: firmware not found: $firmware"; exit 1; fi - expect </dev/null 2>&1 && echo __P4_OK__ || echo __P4_FAIL__\r" -expect { "__P4_OK__" { } "__P4_FAIL__" { puts "FAIL: Phase 4"; exit 1 } timeout { puts "FAIL: timeout"; exit 1 } eof { puts "FAIL: eof"; exit 1 } } -puts "ALL PHASE 4 CHECKS PASSED" -EXPECT_SCRIPT - exit $? + + attempt=1 + while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 300 \ + --log "build/${arch}/${CONFIG}/phase4-check.log" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:assword:" \ + --step "send:password" \ + --step "expect:Type 'help' for available commands." \ + --step "send:echo __READY__" \ + --step "expect:__READY__" \ + --step "send:redbear-phase4-kde-check --json >/dev/null 2>&1 && echo __P4_OK__ || echo __P4_FAIL__" \ + --step "expect:__P4_OK__" \ + --pass_marker "__P4_OK__" \ + --fail_marker "__P4_FAIL__" \ + -- \ + qemu-system-x86_64 -name "Red Bear OS" -device qemu-xhci -smp 4 -m 2048 -bios "$firmware" -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device virtio-net,netdev=net0 -netdev user,id=net0 -display none -vga none "${boot_args[@]}" -enable-kvm -cpu host || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + exit "$rc" + done + echo "ALL PHASE 4 CHECKS PASSED" + exit 0 } case "$MODE" in guest) run_guest_checks ;; -qemu) export FIRMWARE_PATH="${FIRMWARE_PATH:-/usr/share/ovmf/x64/OVMF.fd}"; run_qemu_checks ;; + qemu) export FIRMWARE_PATH="${FIRMWARE_PATH:-/usr/share/ovmf/x64/OVMF.fd}"; run_qemu_checks ;; *) usage ;; esac diff --git a/local/scripts/test-phase4-wayland-qemu.sh b/local/scripts/test-phase4-wayland-qemu.sh index 24944b399e..daef6a566a 100644 --- a/local/scripts/test-phase4-wayland-qemu.sh +++ b/local/scripts/test-phase4-wayland-qemu.sh @@ -79,14 +79,26 @@ fi arch="${ARCH:-$(uname -m)}" image="build/$arch/redbear-full/harddrive.img" +iso="build/$arch/redbear-full.iso" extra="build/$arch/redbear-full/extra.img" -if [[ ! -f "$image" ]]; then - echo "ERROR: missing image $image" >&2 +boot_media="" +if [[ -f "$iso" ]]; then + boot_media="iso" +elif [[ -f "$image" ]]; then + boot_media="harddrive" +else + echo "ERROR: no bootable image found ($iso or $image)" >&2 echo "Build it first with: ./local/scripts/build-redbear.sh redbear-full" >&2 exit 1 fi +if [[ "$boot_media" == "iso" ]]; then + boot_args=(-cdrom "$iso") +else + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) +fi + if [[ ! -f "$extra" ]]; then truncate -s 1g "$extra" fi @@ -106,36 +118,51 @@ echo " active desktop direction is redbear-full -> kwin_wayland" echo if [[ "$check_mode" -eq 1 ]]; then - expect </tmp/redbear-phase4-session.log ^>/tmp/redbear-phase4-session.log &\r" - expect "#" - send "sleep 10\r" - expect "#" - send "redbear-phase4-wayland-check\r" - expect "Red Bear OS Phase 4 Wayland Runtime Check" -expect "redbear-validation-session" -expect "wayland-session" -expect "/home/root/.qt6-bootstrap-minimal.ok" -expect "/home/root/.qt6-plugin-minimal.ok" -expect "/home/root/.qt6-wayland-smoke-minimal.ok" -expect "/home/root/.qt6-wayland-smoke-offscreen.ok" -expect "/home/root/.qt6-wayland-smoke-wayland.ok" -expect "/home/root/.qt6-wayland-smoke.ok" -expect "qt6-wayland-smoke" -expect "virtio_net_present" -send "shutdown\r" -expect eof -EOF + log="build/$arch/redbear-full/phase4-wayland-check.log" + attempt=1 + while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 240 \ + --log "$log" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:assword:" \ + --step "send:password" \ + --step "expect:Type 'help' for available commands." \ + --step "send:rm -f /home/root/.wayland-session.started /home/root/.qt6-wayland-smoke.ok /home/root/.qt6-wayland-smoke.err /home/root/.qt6-plugin-minimal.ok /home/root/.qt6-plugin-minimal.err /home/root/.qt6-plugin-minimal.log /home/root/.qt6-bootstrap-minimal.ok /home/root/.qt6-bootstrap-minimal.err /home/root/.qt6-bootstrap-minimal.log /home/root/.qt6-wayland-smoke-minimal.ok /home/root/.qt6-wayland-smoke-offscreen.ok /home/root/.qt6-wayland-smoke-wayland.ok /home/root/.qt6-wayland-smoke.log /home/root/.qt6-wayland-smoke-minimal.log /home/root/.qt6-wayland-smoke-offscreen.log /home/root/.qt6-wayland-smoke-wayland.log /tmp/redbear-phase4-session.log" \ + --step "expect:#" \ + --step "send:redbear-validation-session >/tmp/redbear-phase4-session.log ^>/tmp/redbear-phase4-session.log &" \ + --step "expect:#" \ + --step "send:sleep 10" \ + --step "expect:#" \ + --step "send:redbear-phase4-wayland-check" \ + --step "expect:Red Bear OS Phase 4 Wayland Runtime Check" \ + --step "expect:redbear-validation-session" \ + --step "expect:wayland-session" \ + --step "expect:/home/root/.qt6-bootstrap-minimal.ok" \ + --step "expect:/home/root/.qt6-plugin-minimal.ok" \ + --step "expect:/home/root/.qt6-wayland-smoke-minimal.ok" \ + --step "expect:/home/root/.qt6-wayland-smoke-offscreen.ok" \ + --step "expect:/home/root/.qt6-wayland-smoke-wayland.ok" \ + --step "expect:/home/root/.qt6-wayland-smoke.ok" \ + --step "expect:qt6-wayland-smoke" \ + --step "expect:virtio_net_present" \ + --step "send:shutdown" \ + --pass_marker "virtio_net_present" \ + -- \ + qemu-system-x86_64 -name "Red Bear OS x86_64" -device qemu-xhci -smp 4 -m 2048 -bios "$firmware" -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device ich9-intel-hda -device hda-output -device virtio-net,netdev=net0 -netdev user,id=net0 -object filter-dump,id=f1,netdev=net0,file="build/$arch/redbear-full/network.pcap" -vga none -device virtio-vga-gl -display egl-headless "${boot_args[@]}" -drive file="$extra",format=raw,if=none,id=drv1 -device nvme,drive=drv1,serial=NVME_EXTRA -enable-kvm -cpu host $QEMUFLAGS || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + exit "$rc" + done exit 0 fi diff --git a/local/scripts/test-phase5-cs-runtime.sh b/local/scripts/test-phase5-cs-runtime.sh index 495a459356..fe275432f7 100755 --- a/local/scripts/test-phase5-cs-runtime.sh +++ b/local/scripts/test-phase5-cs-runtime.sh @@ -79,14 +79,22 @@ require_qemu_path() { run_qemu_checks() { local arch="${ARCH:-x86_64}" + local iso="build/${arch}/${CONFIG}.iso" local image="build/${arch}/${CONFIG}/harddrive.img" local firmware="${FIRMWARE_PATH:-/usr/share/ovmf/x64/OVMF.fd}" + require_qemu_path "$iso" "iso path" require_qemu_path "$image" "image path" require_qemu_path "$firmware" "firmware path" - if [[ ! -f "$image" ]]; then - echo "$PROG: image not found: $image (build with: make all CONFIG_NAME=$CONFIG)" + local boot_args=() + if [[ -f "$iso" ]]; then + boot_args=(-cdrom "$iso") + elif [[ -f "$image" ]]; then + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) + else + echo "$PROG: no bootable image found ($iso or $image)" + echo "$PROG: build with: make all CONFIG_NAME=$CONFIG" exit 1 fi @@ -95,18 +103,37 @@ run_qemu_checks() { exit 1 fi - env RBOS_PHASE5_CS_IMAGE="$image" RBOS_PHASE5_CS_FIRMWARE="$firmware" expect <<'EXPECT_SCRIPT' -log_user 1; set timeout 300 -spawn qemu-system-x86_64 -name {Red Bear OS} -device qemu-xhci -smp 4 -m 2048 -bios $env(RBOS_PHASE5_CS_FIRMWARE) -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device virtio-net,netdev=net0 -netdev user,id=net0 -nographic -vga none -drive file=$env(RBOS_PHASE5_CS_IMAGE),format=raw,if=none,id=drv0 -device nvme,drive=drv0,serial=NVME_SERIAL -enable-kvm -cpu host -expect "login:"; send "root\r" -expect "assword:"; send "password\r" -expect "Type 'help' for available commands." -send "echo __READY__\r"; expect "__READY__" -send "redbear-phase5-cs-check --json >/dev/null 2>&1 && echo __P5CS_OK__ || echo __P5CS_FAIL__\r" -expect { "__P5CS_OK__" { } "__P5CS_FAIL__" { puts "FAIL: Phase 5 CS"; exit 1 } timeout { puts "FAIL: timeout"; exit 1 } eof { puts "FAIL: eof"; exit 1 } } -puts "ALL PHASE 5 CS CHECKS PASSED" -EXPECT_SCRIPT - exit $? + attempt=1 + while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 300 \ + --log "build/${arch}/${CONFIG}/phase5-cs-check.log" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:assword:" \ + --step "send:password" \ + --step "expect:Type 'help' for available commands." \ + --step "send:echo __READY__" \ + --step "expect:__READY__" \ + --step "send:redbear-phase5-cs-check --json >/dev/null 2>&1 && echo __P5CS_OK__ || echo __P5CS_FAIL__" \ + --pass_marker "__P5CS_OK__" \ + --fail_marker "__P5CS_FAIL__" \ + -- \ + qemu-system-x86_64 -name "Red Bear OS" -device qemu-xhci -smp 4 -m 2048 -bios "$firmware" -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device virtio-net,netdev=net0 -netdev user,id=net0 -nographic -vga none "${boot_args[@]}" -enable-kvm -cpu host || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + exit "$rc" + done + echo "ALL PHASE 5 CS CHECKS PASSED" + exit 0 } case "$MODE" in diff --git a/local/scripts/test-phase5-gpu-runtime.sh b/local/scripts/test-phase5-gpu-runtime.sh index b69daa1767..74cbd22d02 100644 --- a/local/scripts/test-phase5-gpu-runtime.sh +++ b/local/scripts/test-phase5-gpu-runtime.sh @@ -56,22 +56,53 @@ run_guest_checks() { run_qemu_checks() { local arch="${ARCH:-x86_64}" + local iso="build/${arch}/${CONFIG}.iso" local image="build/${arch}/${CONFIG}/harddrive.img" local firmware="${FIRMWARE_PATH:-/usr/share/ovmf/x64/OVMF.fd}" - if [[ ! -f "$image" ]]; then echo "$PROG: image not found: $image (build with: make all CONFIG_NAME=$CONFIG)"; exit 1; fi + + local boot_args=() + if [[ -f "$iso" ]]; then + boot_args=(-cdrom "$iso") + elif [[ -f "$image" ]]; then + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) + else + echo "$PROG: no bootable image found ($iso or $image)" + echo "$PROG: build with: make all CONFIG_NAME=$CONFIG" + exit 1 + fi if [[ ! -f "$firmware" ]]; then echo "$PROG: firmware not found: $firmware"; exit 1; fi - expect </dev/null 2>&1 && echo __P5_OK__ || echo __P5_FAIL__\r" -expect { "__P5_OK__" { } "__P5_FAIL__" { puts "FAIL: Phase 5"; exit 1 } timeout { puts "FAIL: timeout"; exit 1 } eof { puts "FAIL: eof"; exit 1 } } -puts "ALL PHASE 5 CHECKS PASSED" -EXPECT_SCRIPT - exit $? + + attempt=1 + while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 300 \ + --log "build/${arch}/${CONFIG}/phase5-gpu-check.log" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:assword:" \ + --step "send:password" \ + --step "expect:Type 'help' for available commands." \ + --step "send:echo __READY__" \ + --step "expect:__READY__" \ + --step "send:redbear-phase5-gpu-check --json >/dev/null 2>&1 && echo __P5_OK__ || echo __P5_FAIL__" \ + --pass_marker "__P5_OK__" \ + --fail_marker "__P5_FAIL__" \ + -- \ + qemu-system-x86_64 -name "Red Bear OS" -device qemu-xhci -smp 4 -m 2048 -bios "$firmware" -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device virtio-net,netdev=net0 -netdev user,id=net0 -nographic -vga none "${boot_args[@]}" -enable-kvm -cpu host || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + exit "$rc" + done + echo "ALL PHASE 5 CHECKS PASSED" + exit 0 } case "$MODE" in diff --git a/local/scripts/test-phase5-network-qemu.sh b/local/scripts/test-phase5-network-qemu.sh index 34b80f8093..242b07c6e2 100644 --- a/local/scripts/test-phase5-network-qemu.sh +++ b/local/scripts/test-phase5-network-qemu.sh @@ -54,13 +54,20 @@ firmware="$(find_uefi_firmware)" || { } arch="${ARCH:-$(uname -m)}" -image="build/$arch/redbear-full/harddrive.img" -extra="build/$arch/redbear-full/extra.img" +config="redbear-full" +iso="build/$arch/$config.iso" +image="build/$arch/$config/harddrive.img" +extra="build/$arch/$config/extra.img" extra_qemu_args="${filtered_args[*]:-}" -if [[ ! -f "$image" ]]; then - echo "ERROR: missing image $image" >&2 - echo "Build it first with: ./local/scripts/build-redbear.sh redbear-full" >&2 +boot_args=() +if [[ -f "$iso" ]]; then + boot_args=(-cdrom "$iso") +elif [[ -f "$image" ]]; then + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) +else + echo "ERROR: no bootable image found ($iso or $image)" >&2 + echo "Build it first with: ./local/scripts/build-redbear.sh $config" >&2 exit 1 fi @@ -69,35 +76,49 @@ if [[ ! -f "$extra" ]]; then fi if [[ "$check_mode" -eq 1 ]]; then - expect <&2 +boot_media="" +if [[ -f "$iso" ]]; then + boot_media="iso" +elif [[ -f "$image" ]]; then + boot_media="harddrive" +else + echo "ERROR: no bootable image found ($iso or $image)" >&2 echo "Build it first with: ./local/scripts/build-redbear.sh redbear-full" >&2 exit 1 fi @@ -99,38 +105,53 @@ if [[ ! -f "$extra" ]]; then truncate -s 1g "$extra" fi +if [[ "$boot_media" == "iso" ]]; then + boot_args=(-cdrom "$iso") +else + boot_args=(-drive file="$image",format=raw,if=none,id=drv0 -device nvme,drive=drv0,serial=NVME_SERIAL) +fi + if [[ "$check_mode" -eq 1 ]]; then report_solid_recipe_blockers - expect </dev/null || true + sleep 1 + + attempt=1 + while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 240 \ + --log "build/$arch/redbear-full/phase6-kde-check.log" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:assword:" \ + --step "send:password" \ + --step "expect:Type 'help' for available commands." \ + --step "send:redbear-phase6-kde-check" \ + --step "expect:Red Bear OS Phase 6 KDE Runtime Check" \ + --step "expect:redbear-kde-session" \ + --step "expect:kwin_wayland" \ + --step "expect:PHASE6_UPOWER_ENUMERATE=" \ + --step "expect:PHASE6_UDISKS2_OBJECTS=" \ + --step "expect:PHASE6_SOLID_RUNTIME=" \ + --step "expect:virtio_net_present" \ + --step "send:shutdown" \ + --pass_marker "virtio_net_present" \ + -- \ + qemu-system-x86_64 -name "Red Bear OS x86_64" -device qemu-xhci -smp 4 -m 2048 -bios "$firmware" -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device ich9-intel-hda -device hda-output -device virtio-net,netdev=net0 -netdev user,id=net0 -object filter-dump,id=f1,netdev=net0,file="build/$arch/redbear-full/network.pcap" -nographic -vga none -device virtio-gpu "${boot_args[@]}" -drive file="$extra",format=raw,if=none,id=drv1 -device nvme,drive=drv1,serial=NVME_EXTRA -enable-kvm -cpu host $extra_qemu_args || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + exit "$rc" + done + pkill -f "qemu-system-x86_64.*$image" 2>/dev/null || true + echo "Phase 6 KDE runtime validation completed via guest runtime check" exit 0 fi @@ -142,7 +163,7 @@ exec qemu-system-x86_64 \ -bios "$firmware" \ -chardev stdio,id=debug,signal=off,mux=on \ -serial chardev:debug \ - -mon chardev=debug \ + -mon chardev:debug \ -machine q35 \ -device ich9-intel-hda -device hda-output \ -device virtio-net,netdev=net0 \ @@ -150,8 +171,7 @@ exec qemu-system-x86_64 \ -object filter-dump,id=f1,netdev=net0,file="build/$arch/redbear-full/network.pcap" \ -vga none \ -device virtio-gpu \ - -drive file="$image",format=raw,if=none,id=drv0 \ - -device nvme,drive=drv0,serial=NVME_SERIAL \ + "${boot_args[@]}" \ -drive file="$extra",format=raw,if=none,id=drv1 \ -device nvme,drive=drv1,serial=NVME_EXTRA \ -enable-kvm -cpu host \ diff --git a/local/scripts/test-posix-runtime.sh b/local/scripts/test-posix-runtime.sh index 1d617a517f..fcac73cf12 100644 --- a/local/scripts/test-posix-runtime.sh +++ b/local/scripts/test-posix-runtime.sh @@ -78,21 +78,49 @@ run_guest_checks() { run_qemu_checks() { local arch="${ARCH:-x86_64}" local image="build/${arch}/${CONFIG}/harddrive.img" + local iso="build/${arch}/${CONFIG}.iso" local firmware="${FIRMWARE_PATH:-/usr/share/ovmf/x64/OVMF.fd}" - if [[ ! -f "$image" ]]; then echo "$PROG: image not found: $image"; exit 1; fi + if [[ -f "$iso" ]]; then + boot_args=(-cdrom "$iso") + elif [[ -f "$image" ]]; then + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) + else + echo "$PROG: no bootable image found ($iso or $image)"; exit 1 + fi if [[ ! -f "$firmware" ]]; then echo "$PROG: firmware not found: $firmware"; exit 1; fi - expect </dev/null 2>&1; then echo \"\\\${t}:PASS\"; else echo \"\\\${t}:FAIL\"; POSIX_FAIL=1; fi; done; echo __POSIX_DONE__\\\$POSIX_FAIL__\r" -expect { "__POSIX_DONE__0__" { } "__POSIX_DONE__1__" { puts "FAIL: POSIX tests"; exit 1 } timeout { puts "FAIL: timeout"; exit 1 } eof { puts "FAIL: eof"; exit 1 } } -puts "ALL POSIX TESTS PASSED" -EXPECT_SCRIPT - exit $? + + attempt=1 + while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 300 \ + --log "build/${arch}/${CONFIG}/posix-check.log" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:assword:" \ + --step "send:password" \ + --step "expect:Type 'help' for available commands." \ + --step "send:echo __READY__" \ + --step "expect:__READY__" \ + --step "send:cd /home/user/relibc-phase1-tests && POSIX_FAIL=0; for t in test_signalfd_wayland test_timerfd_qt6 test_eventfd_qt6 test_shm_open_qt6 test_sem_open_qt6 test_waitid_qt6; do echo \"POSIX:\$t\"; if ./\$t >/dev/null 2>&1; then echo \"\${t}:PASS\"; else echo \"\${t}:FAIL\"; POSIX_FAIL=1; fi; done; echo __POSIX_DONE__\$POSIX_FAIL__" \ + --step "expect:__POSIX_DONE__0__" \ + --pass_marker "__POSIX_DONE__0__" \ + --fail_marker "__POSIX_DONE__1__" \ + -- \ + qemu-system-x86_64 -name "Red Bear OS" -device qemu-xhci -smp 4 -m 2048 -bios "$firmware" -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device virtio-net,netdev=net0 -netdev user,id=net0 -display none -vga none "${boot_args[@]}" -enable-kvm -cpu host || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + exit "$rc" + done + echo "ALL POSIX TESTS PASSED" + exit 0 } case "$MODE" in diff --git a/local/scripts/test-usb-qemu.sh b/local/scripts/test-usb-qemu.sh index d3f7136670..aef8b66886 100755 --- a/local/scripts/test-usb-qemu.sh +++ b/local/scripts/test-usb-qemu.sh @@ -89,13 +89,19 @@ firmware="$(find_uefi_firmware)" || { } arch="${ARCH:-$(uname -m)}" +iso="build/$arch/$config.iso" image="build/$arch/$config/harddrive.img" extra="build/$arch/$config/extra.img" usb_img="build/$arch/$config/usb-test-storage.img" log_file="build/$arch/$config/usb-stack-check.log" -if [[ ! -f "$image" ]]; then - echo "ERROR: missing image $image" >&2 +boot_media="" +if [[ -f "$iso" ]]; then + boot_media="iso" +elif [[ -f "$image" ]]; then + boot_media="harddrive" +else + echo "ERROR: no bootable image found ($iso or $image)" >&2 echo "Build it first with: ./local/scripts/build-redbear.sh $config" >&2 exit 1 fi @@ -108,6 +114,12 @@ if [[ ! -f "$usb_img" ]]; then truncate -s 64M "$usb_img" fi +if [[ "$boot_media" == "iso" ]]; then + boot_args=(-cdrom "$iso") +else + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) +fi + expected_sector_b64="$(seed_usb_image "$usb_img")" pkill -f "qemu-system-x86_64.*$image" 2>/dev/null || true @@ -115,35 +127,49 @@ sleep 1 rm -f "$log_file" -set +e -expect </dev/null || true +# Milestone-derivation bridge: the helper logs real guest output. Reconstruct the +# MILESTONE:* markers the original TCL-side log injection emitted so the existing +# grep-based verdict checks below keep working unchanged. +grep -aq "interrupt delivery" "$log_file" && printf 'MILESTONE:XHCI_IRQ\n' >> "$log_file" +grep -aq "USB HID driver spawned" "$log_file" && printf 'MILESTONE:USB_HID\n' >> "$log_file" +grep -aq "USB SCSI driver spawned" "$log_file" && printf 'MILESTONE:USB_SCSI\n' >> "$log_file" +grep -aq "DISK CONTENT:" "$log_file" && printf 'MILESTONE:USB_READBACK\n' >> "$log_file" +grep -aq "Type 'help' for available commands." "$log_file" && printf 'MILESTONE:SHELL\n' >> "$log_file" + failures=0 echo "--- USB Stack Validation: $config ---" diff --git a/local/scripts/test-usb-runtime.sh b/local/scripts/test-usb-runtime.sh index 07f0fc7486..d15a4f670c 100644 --- a/local/scripts/test-usb-runtime.sh +++ b/local/scripts/test-usb-runtime.sh @@ -50,21 +50,49 @@ run_guest_checks() { run_qemu_checks() { local arch="${ARCH:-x86_64}" local image="build/${arch}/${CONFIG}/harddrive.img" + local iso="build/${arch}/${CONFIG}.iso" local firmware="${FIRMWARE_PATH:-/usr/share/ovmf/x64/OVMF.fd}" - if [[ ! -f "$image" ]]; then echo "$PROG: image not found: $image"; exit 1; fi + if [[ -f "$iso" ]]; then + boot_args=(-cdrom "$iso") + elif [[ -f "$image" ]]; then + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) + else + echo "$PROG: no bootable image found ($iso or $image)"; exit 1 + fi if [[ ! -f "$firmware" ]]; then echo "$PROG: firmware not found: $firmware"; exit 1; fi - expect </dev/null 2>&1 && echo __USB_OK__ || echo __USB_FAIL__\r" -expect { "__USB_OK__" { } "__USB_FAIL__" { puts "FAIL: usb"; exit 1 } timeout { puts "FAIL: timeout"; exit 1 } eof { puts "FAIL: eof"; exit 1 } } -puts "ALL USB CHECKS PASSED" -EXPECT_SCRIPT - exit $? + + attempt=1 + while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 300 \ + --log "build/${arch}/${CONFIG}/usb-check.log" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:assword:" \ + --step "send:password" \ + --step "expect:Type 'help' for available commands." \ + --step "send:echo __READY__" \ + --step "expect:__READY__" \ + --step "send:redbear-usb-check --json >/dev/null 2>&1 && echo __USB_OK__ || echo __USB_FAIL__" \ + --step "expect:__USB_OK__" \ + --pass_marker "__USB_OK__" \ + --fail_marker "__USB_FAIL__" \ + -- \ + qemu-system-x86_64 -name "Red Bear OS" -device qemu-xhci -smp 4 -m 2048 -bios "$firmware" -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device virtio-net,netdev=net0 -netdev user,id=net0 -display none -vga none "${boot_args[@]}" -enable-kvm -cpu host || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + exit "$rc" + done + echo "ALL USB CHECKS PASSED" + exit 0 } case "$MODE" in diff --git a/local/scripts/test-wifi-passthrough-qemu.sh b/local/scripts/test-wifi-passthrough-qemu.sh index d5e621c0f0..0d2d5fa131 100644 --- a/local/scripts/test-wifi-passthrough-qemu.sh +++ b/local/scripts/test-wifi-passthrough-qemu.sh @@ -93,12 +93,19 @@ firmware="$(find_uefi_firmware)" || { } arch="${ARCH:-$(uname -m)}" -image="build/$arch/redbear-full/harddrive.img" -extra="build/$arch/redbear-full/extra.img" +config="redbear-full" +iso="build/$arch/$config.iso" +image="build/$arch/$config/harddrive.img" +extra="build/$arch/$config/extra.img" -if [[ ! -f "$image" ]]; then - echo "ERROR: missing image $image" >&2 - echo "Build it first with: ./local/scripts/build-redbear.sh redbear-full" >&2 +boot_args=() +if [[ -f "$iso" ]]; then + boot_args=(-cdrom "$iso") +elif [[ -f "$image" ]]; then + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) +else + echo "ERROR: no bootable image found ($iso or $image)" >&2 + echo "Build it first with: ./local/scripts/build-redbear.sh $config" >&2 exit 1 fi @@ -110,41 +117,49 @@ vfio_arg="vfio-pci,host=${host_pci}" if [[ "$check_mode" -eq 1 ]]; then capture_output="${capture_output:-$(pwd)/wifi-passthrough-capture.json}" - expect < "$capture_output" echo "capture_output=$capture_output" exit 0 fi diff --git a/local/scripts/test-wifi-runtime.sh b/local/scripts/test-wifi-runtime.sh index 5f9b22209a..9d2b588d54 100644 --- a/local/scripts/test-wifi-runtime.sh +++ b/local/scripts/test-wifi-runtime.sh @@ -54,24 +54,56 @@ run_guest_checks() { run_qemu_checks() { local arch="${ARCH:-x86_64}" + local iso="build/${arch}/${CONFIG}.iso" local image="build/${arch}/${CONFIG}/harddrive.img" local firmware="${FIRMWARE_PATH:-/usr/share/ovmf/x64/OVMF.fd}" - if [[ ! -f "$image" ]]; then echo "$PROG: image not found: $image"; exit 1; fi + + local boot_args=() + if [[ -f "$iso" ]]; then + boot_args=(-cdrom "$iso") + elif [[ -f "$image" ]]; then + boot_args=(-drive file="$image",format=raw,if=none,id=drv0,snapshot=on -device nvme,drive=drv0,serial=NVME_SERIAL) + else + echo "$PROG: no bootable image found ($iso or $image)" + exit 1 + fi if [[ ! -f "$firmware" ]]; then echo "$PROG: firmware not found: $firmware"; exit 1; fi - expect </dev/null 2>&1 && echo __WF_OK__ || echo __WF_FAIL__\r" -expect { "__WF_OK__" { } "__WF_FAIL__" { puts "FAIL: wifi check"; exit 1 } timeout { puts "FAIL: timeout"; exit 1 } eof { puts "FAIL: eof"; exit 1 } } -send "redbear-phase5-wifi-link-check --json >/dev/null 2>&1 && echo __WL_OK__ || echo __WL_FAIL__\r" -expect { "__WL_OK__" { } "__WL_FAIL__" { puts "FAIL: wifi link"; exit 1 } timeout { puts "FAIL: timeout"; exit 1 } eof { puts "FAIL: eof"; exit 1 } } -puts "ALL WI-FI CHECKS PASSED" -EXPECT_SCRIPT - exit $? + + attempt=1 + while true; do + rc=0 + python3 local/scripts/qemu-login-expect.py \ + --timeout 300 \ + --log "build/${arch}/${CONFIG}/wifi-runtime-check.log" \ + --step "expect:login:" \ + --step "send:root" \ + --step "expect:assword:" \ + --step "send:password" \ + --step "expect:Type 'help' for available commands." \ + --step "send:echo __READY__" \ + --step "expect:__READY__" \ + --step "send:redbear-phase5-wifi-check --json >/dev/null 2>&1 && echo __WF_OK__ || echo __WF_FAIL__" \ + --step "expect:__WF_OK__" \ + --step "send:redbear-phase5-wifi-link-check --json >/dev/null 2>&1 && echo __WL_OK__ || echo __WL_FAIL__" \ + --pass_marker "__WF_OK__" \ + --pass_marker "__WL_OK__" \ + --fail_marker "__WF_FAIL__" \ + --fail_marker "__WL_FAIL__" \ + -- \ + qemu-system-x86_64 -name "Red Bear OS" -device qemu-xhci -smp 4 -m 2048 -bios "$firmware" -chardev stdio,id=debug,signal=off,mux=on -serial chardev:debug -mon chardev:debug -machine q35 -device virtio-net,netdev=net0 -netdev user,id=net0 -nographic -vga none "${boot_args[@]}" -enable-kvm -cpu host || rc=$? + if [[ $rc -eq 0 ]]; then + break + fi + if [[ ( $rc -eq 3 || $rc -eq 137 ) && $attempt -lt 5 ]]; then + attempt=$((attempt + 1)) + echo "QEMU exited before completing the check; retrying (attempt $attempt/5)" + sleep 2 + continue + fi + exit "$rc" + done + echo "ALL WI-FI CHECKS PASSED" + exit 0 } case "$MODE" in