Files
RedBear-OS/local/scripts/test-smp-stress-qemu.sh
vasilito cee25393d8 fix: boot process improvements — dependency cycle, INIT_NOTIFY, probing loop, and log spam fixes
- Fix P15-8-init-cycle-detection.patch: replace visiting+error with seen+silent-skip
  to eliminate 11 false-positive 'dependency cycle detected' errors on shared deps
- Fix P0-daemon-fix-init-notify-unwrap.patch: remove eprintln! for missing
  INIT_NOTIFY (expected for oneshot_async services, ~7 daemons affected)
- Fix driver-manager hotplug loop: add PERMANENTLY_SKIPPED static set shared
  between hotplug handler and DriverConfig::probe() to stop infinite re-probing
  of Fatal/NotSupported/deferred-exhausted device+driver pairs (e.g. ided)
- Fix driver-manager log_timeline: suppress repeated EPIPE/ENOENT errors with
  AtomicI32 dedup and AtomicBool one-shot guards for boot timeline JSON
- Add driver-manager SIGTERM handler, ACPI bus registration, --status mode,
  driver reap loop, graceful shutdown, and reduced deferred retries (30→3)
2026-05-17 12:34:02 +03:00

256 lines
6.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# P19-1: Multi-Core Driver Stress Test for Red Bear OS
#
# Validates SMP stability under parallel I/O load:
# - 4 CPU cores exercising scheduler (P17)
# - Parallel disk I/O via dd (filesystem scheme)
# - Parallel scheme reads (IPC paths)
# - Concurrent process creation/teardown
# - Panic/hang detection
#
# Usage:
# ./local/scripts/test-smp-stress-qemu.sh [--check]
# ./local/scripts/test-smp-stress-qemu.sh --duration 60
#
# Options:
# --check Run full QEMU test (default)
# --duration N Stress duration in seconds (default: 30)
# --smp N Number of CPU cores (default: 4)
# --help Show this help
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
# Defaults
DURATION=30
SMP=4
ACTION="check"
IMAGE=""
FIRMWARE="/usr/share/edk2/x64/OVMF_CODE.4m.fd"
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
--check) ACTION="check"; shift ;;
--duration) DURATION="$2"; shift 2 ;;
--smp) SMP="$2"; shift 2 ;;
--image) IMAGE="$2"; shift 2 ;;
--help)
head -20 "$0" | grep '^#' | sed 's/^# \?//'
exit 0
;;
*) echo "Unknown argument: $1"; exit 1 ;;
esac
done
# Resolve image
if [[ -z "$IMAGE" ]]; then
IMAGE="$PROJECT_DIR/build/x86_64/redbear-mini.iso"
fi
if [[ ! -f "$IMAGE" ]]; then
echo "ERROR: Image not found: $IMAGE"
echo "Run: make live CONFIG_NAME=redbear-mini"
exit 1
fi
if [[ ! -f "$FIRMWARE" ]]; then
echo "ERROR: OVMF firmware not found: $FIRMWARE"
echo "Install: sudo pacman -S edk2-ovmf (or equivalent)"
exit 1
fi
echo "=== P19-1: Multi-Core Driver Stress Test ==="
echo "Image: $IMAGE"
echo "Firmware: $FIRMWARE"
echo "CPUs: $SMP"
echo "Duration: ${DURATION}s"
echo ""
# Create expect-based test script
export DURATION SMP IMAGE FIRMWARE
expect <<'EXPECT_SCRIPT'
log_user 1
set timeout 300
set duration $env(DURATION)
set smp $env(SMP)
set image $env(IMAGE)
set firmware $env(FIRMWARE)
proc expect_or_fail {pattern description} {
expect {
-nocase -re $pattern { return }
timeout {
puts stderr "\nERROR: timed out waiting for $description"
exit 1
}
eof {
puts stderr "\nERROR: QEMU exited while waiting for $description"
exit 1
}
}
}
# Launch QEMU with 4 CPUs, network, serial console
spawn qemu-system-x86_64 \
-name "Red Bear OS SMP Stress Test" \
-machine q35 \
-smp $smp \
-m 2048 \
-drive if=pflash,format=raw,readonly=on,file=$firmware \
-chardev stdio,id=debug,signal=off,mux=on \
-serial chardev:debug \
-mon chardev=debug \
-nographic \
-vga none \
-device virtio-net-pci,netdev=net0 \
-netdev user,id=net0 \
-drive file=$image,format=raw,if=none,id=drv0,snapshot=on \
-device virtio-blk-pci,drive=drv0 \
-enable-kvm \
-cpu host
# Wait for login prompt
puts "\n>>> Waiting for boot..."
expect_or_fail "login:" "login prompt"
# Login as root
send "root\r"
expect_or_fail "assword:" "password prompt"
send "password\r"
expect_or_fail "#|\\$" "shell prompt"
sleep 1
# --- Phase 1: Verify multi-core boot ---
puts "\n>>> Phase 1: Verifying multi-core boot..."
send "cat /scheme/sys/cpu.log 2>/dev/null || echo 'no cpu.log'\r"
expect_or_fail "#|\\$" "cpu.log output"
sleep 1
send "ls /scheme/sys/ 2>/dev/null | head -20\r"
expect_or_fail "#|\\$" "sys scheme listing"
sleep 1
# --- Phase 2: Parallel disk I/O stress ---
puts "\n>>> Phase 2: Starting parallel disk I/O stress (duration: ${duration}s)..."
# Launch 4 parallel dd writers to tmpfs (exercises filesystem scheme + IPC)
send "dd if=/dev/zero of=/tmp/stress-a bs=1M count=50 2>/tmp/stress-a.err &\r"
expect_or_fail "#|\\$" "dd writer A start"
sleep 0.5
send "dd if=/dev/zero of=/tmp/stress-b bs=1M count=50 2>/tmp/stress-b.err &\r"
expect_or_fail "#|\\$" "dd writer B start"
sleep 0.5
send "dd if=/dev/zero of=/tmp/stress-c bs=512 count=100000 2>/tmp/stress-c.err &\r"
expect_or_fail "#|\\$" "dd writer C start"
sleep 0.5
send "dd if=/dev/zero of=/tmp/stress-d bs=4k count=50000 2>/tmp/stress-d.err &\r"
expect_or_fail "#|\\$" "dd writer D start"
sleep 0.5
# --- Phase 3: Parallel reads (exercises IPC) ---
puts "\n>>> Phase 3: Starting parallel filesystem traversal..."
send "ls -laR / > /tmp/ls-out 2>/tmp/ls-err &\r"
expect_or_fail "#|\\$" "ls traversal start"
sleep 0.5
send "cat /etc/passwd > /dev/null 2>&1 &\r"
expect_or_fail "#|\\$" "passwd read start"
sleep 0.5
send "find /tmp -type f > /dev/null 2>&1 &\r"
expect_or_fail "#|\\$" "find traversal start"
sleep 0.5
# --- Phase 4: Wait for stress duration ---
puts "\n>>> Phase 4: Running stress for ${duration}s..."
sleep $duration
# --- Phase 5: Collect results ---
puts "\n>>> Phase 5: Collecting results..."
# Wait for background jobs and check status
send "wait 2>/dev/null; echo STRESS-WAIT-DONE\r"
expect_or_fail "STRESS-WAIT-DONE" "background jobs completion"
sleep 1
# Check if stress files were created
send "ls -la /tmp/stress-* 2>/dev/null; echo STRESS-FILES-DONE\r"
expect_or_fail "STRESS-FILES-DONE" "stress file listing"
sleep 1
# Verify reads work on stress files (read-back test)
send "dd if=/tmp/stress-a of=/dev/null bs=1M count=50 2>/tmp/readback-a.err; echo READBACK-A-STATUS=$?\r"
expect_or_fail "READBACK-A-STATUS=0" "readback A"
sleep 1
# --- Phase 6: Panic detection ---
puts "\n>>> Phase 6: Checking for panics..."
send "dmesg 2>/dev/null | grep -ic PANIC; echo PANIC-CHECK-DONE\r"
expect {
-re "(\[0-9\]+)\r\n.*PANIC-CHECK-DONE" {
set panic_count $expect_out(1,string)
if {$panic_count > 0} {
puts "\n>>> FAIL: $panic_count PANIC(S) detected in dmesg!"
puts "\n>>> Dumping panic context:"
send "dmesg | grep -i PANIC\r"
expect "#|\\$"
exit 1
} else {
puts "\n>>> PASS: No panics detected in dmesg"
}
}
timeout {
puts stderr "\nERROR: timed out during panic check"
exit 1
}
}
sleep 1
# --- Phase 7: Summary ---
puts "\n>>> Phase 7: Final system state..."
send "echo \"UPTIME:\"; uptime 2>/dev/null || cat /scheme/sys/time 2>/dev/null; echo UPTIME-DONE\r"
expect_or_fail "UPTIME-DONE" "uptime output"
sleep 1
send "echo \"PROCS:\"; ps 2>/dev/null || echo 'ps not available'; echo PROCS-DONE\r"
expect_or_fail "PROCS-DONE" "process listing"
sleep 1
# Clean shutdown
puts "\n>>> Shutting down..."
send "shutdown\r"
sleep 5
send "\r"
sleep 2
puts "\n"
puts "============================================"
puts " P19-1 SMP STRESS TEST: PASSED"
puts " CPUs: $smp | Duration: ${duration}s"
puts " No panics, no hangs, I/O completed"
puts "============================================"
expect eof
EXPECT_SCRIPT
exit_code=$?
if [[ $exit_code -eq 0 ]]; then
echo ""
echo "P19-1: PASSED"
else
echo ""
echo "P19-1: FAILED (exit code: $exit_code)"
fi
exit $exit_code