|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +set -euo pipefail |
| 4 | + |
| 5 | +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 6 | +. "${SCRIPT_DIR}/common.sh" |
| 7 | + |
| 8 | +# Override timeout and sleep duration for macOS - emulation is significantly slower |
| 9 | +case "${OS_TYPE}" in |
| 10 | + Darwin) |
| 11 | + TIMEOUT=10800 |
| 12 | + DFB_SLEEP=180 |
| 13 | + ;; |
| 14 | + *) |
| 15 | + DFB_SLEEP=5 |
| 16 | + ;; |
| 17 | +esac |
| 18 | +export DFB_SLEEP |
| 19 | + |
| 20 | +cleanup |
| 21 | +trap cleanup EXIT |
| 22 | + |
| 23 | +# Download pre-built ext4.img with DirectFB if not present |
| 24 | +EXT4_URL="https://github.com/Mes0903/semu/raw/blob/ext4.img.bz2" |
| 25 | +EXT4_SHA1="83ed49c16d341bdf3210141d5f6d5842b77a6adc" |
| 26 | + |
| 27 | +if [ ! -f "ext4.img.bz2" ]; then |
| 28 | + echo "Downloading ext4.img.bz2 for DirectFB testing..." |
| 29 | + curl --progress-bar -O -L "${EXT4_URL}" |
| 30 | + echo "${EXT4_SHA1} ext4.img.bz2" | sha1sum -c - |
| 31 | +fi |
| 32 | + |
| 33 | +echo "Decompressing ext4.img.bz2 for DirectFB testing..." |
| 34 | +rm -f ext4.img |
| 35 | +bunzip2 -kf ext4.img.bz2 |
| 36 | + |
| 37 | +# NOTE: We want to capture the expect exit code and map |
| 38 | +# it to our MESSAGES array for meaningful error output. |
| 39 | +# Temporarily disable errexit for the expect call. |
| 40 | +set +e |
| 41 | +expect <<'DONE' |
| 42 | +set timeout $env(TIMEOUT) |
| 43 | +spawn make check |
| 44 | +
|
| 45 | +# Boot and login |
| 46 | +expect "buildroot login:" { send "root\r" } timeout { exit 1 } |
| 47 | +expect "# " { send "uname -a\r" } timeout { exit 2 } |
| 48 | +expect "riscv32 GNU/Linux" {} |
| 49 | +
|
| 50 | +# ---------------- vgpu basic checks ---------------- |
| 51 | +expect "# " { send "ls -la /dev/dri/ 2>/dev/null || true\r" } |
| 52 | +expect "# " { send "test -c /dev/dri/card0 && echo __VGPU_DRM_OK__ || echo __VGPU_DRM_MISSING__\r" } timeout { exit 3 } |
| 53 | +expect { |
| 54 | + -re "\r?\n__VGPU_DRM_OK__" {} |
| 55 | + -re "\r?\n__VGPU_DRM_MISSING__" { exit 3 } |
| 56 | + timeout { exit 3 } |
| 57 | +} |
| 58 | +
|
| 59 | +# virtio transport may be virtio-mmio, binding check should look at virtio_gpu driver directory |
| 60 | +expect "# " { |
| 61 | + send "sh -lc 'ls /sys/bus/virtio/drivers/virtio_gpu/virtio* >/dev/null 2>&1 && echo __VGPU_BIND_OK__ || echo __VGPU_BIND_BAD__'\r" |
| 62 | +} timeout { exit 3 } |
| 63 | +expect { |
| 64 | + -re "\r?\n__VGPU_BIND_OK__" {} |
| 65 | + -re "\r?\n__VGPU_BIND_BAD__" { |
| 66 | + send "ls -l /sys/bus/virtio/drivers/virtio_gpu/ 2>/dev/null || true\r" |
| 67 | + # emit literal $d via \u0024 to avoid Tcl variable substitution |
| 68 | + send "sh -lc 'for d in /sys/bus/virtio/devices/virtio*; do echo \u0024d; ls -l \u0024d/driver 2>/dev/null || true; done'\r" |
| 69 | + exit 3 |
| 70 | + } |
| 71 | + timeout { exit 3 } |
| 72 | +} |
| 73 | +
|
| 74 | +# Useful logs (non-fatal) |
| 75 | +expect "# " { send "dmesg | grep -Ei 'virtio.*gpu|drm.*virtio|scanout|number of scanouts' | tail -n 80 || true\r" } |
| 76 | +
|
| 77 | +# ---------------- DirectFB2 ---------------- |
| 78 | +# Strategy: |
| 79 | +# 1) Stop X11 if running (it holds the DRM device) |
| 80 | +# 2) Check run.sh exists at /root/run.sh |
| 81 | +# 3) cd to /root and source run.sh to set PATH/LD_LIBRARY_PATH |
| 82 | +# 4) Verify df_drivertest is in PATH |
| 83 | +# 5) Run df_drivertest and check for DirectFB init messages |
| 84 | +# |
| 85 | +# NOTE: df_drivertest may segfault when killed due to a race condition in DirectFB2's |
| 86 | +# fusion module (libfusion) during signal handling. When SIGTERM is sent, the signal |
| 87 | +# handler starts cleanup while the "Fusion Dispatch" thread may still be accessing |
| 88 | +# shared state, leading to a use-after-free crash. The test passes if DirectFB init |
| 89 | +# messages appear, even if the program crashes afterward during cleanup. |
| 90 | +
|
| 91 | +# Step 0: Stop X11 to release DRM device (it holds /dev/dri/card0) |
| 92 | +# Use pidof with fallback to ps/grep if pidof unavailable |
| 93 | +expect "# " { |
| 94 | + send "sh -lc '\ |
| 95 | + if command -v pidof >/dev/null 2>&1; then \ |
| 96 | + pidof Xorg >/dev/null 2>&1 && kill \u0024(pidof Xorg) 2>/dev/null || true; \ |
| 97 | + else \ |
| 98 | + ps | grep Xorg | grep -v grep | awk \"{print \u00241}\" | xargs kill 2>/dev/null || true; \ |
| 99 | + fi; \ |
| 100 | + sleep 1; echo __X11_STOPPED__'\r" |
| 101 | +} |
| 102 | +expect "__X11_STOPPED__" {} |
| 103 | +
|
| 104 | +# Step 1: Check run.sh exists |
| 105 | +expect "# " { send "test -f /root/run.sh && echo __RUNSH_OK__ || echo __DFB_RUNSH_MISSING__\r" } |
| 106 | +expect { |
| 107 | + -re "\r?\n__RUNSH_OK__" {} |
| 108 | + -re "\r?\n__DFB_RUNSH_MISSING__" { exit 4 } |
| 109 | + timeout { exit 4 } |
| 110 | +} |
| 111 | +
|
| 112 | +# Step 2: cd to /root and source run.sh |
| 113 | +expect "# " { send "cd /root && . ./run.sh >/dev/null 2>&1; echo __SRC_DONE__\r" } |
| 114 | +expect "__SRC_DONE__" {} |
| 115 | +
|
| 116 | +# Step 3: Verify df_drivertest is available |
| 117 | +expect "# " { send "command -v df_drivertest && echo __APP_OK__ || echo __APP_MISS__\r" } |
| 118 | +expect { |
| 119 | + -re "\r?\n__APP_OK__" {} |
| 120 | + -re "\r?\n__APP_MISS__" { exit 4 } |
| 121 | + timeout { exit 4 } |
| 122 | +} |
| 123 | +
|
| 124 | +# Step 4: Run df_drivertest and check output (run in background, kill after delay) |
| 125 | +expect "# " { send "df_drivertest >/tmp/dfb.log 2>&1 & sleep $env(DFB_SLEEP); kill \u0024! 2>/dev/null; head -30 /tmp/dfb.log\r" } |
| 126 | +# Check for DRMKMS init message |
| 127 | +expect "# " { send "grep -qi 'DRMKMS/System' /tmp/dfb.log && echo __DFB_OK__ || echo __DFB_FAIL__\r" } |
| 128 | +expect { |
| 129 | + -re "\r?\n__DFB_OK__" {} |
| 130 | + -re "\r?\n__DFB_FAIL__" { exit 4 } |
| 131 | + timeout { exit 4 } |
| 132 | +} |
| 133 | +DONE |
| 134 | + |
| 135 | +ret="$?" |
| 136 | +set -e # Re-enable errexit after capturing expect's return code |
| 137 | + |
| 138 | +MESSAGES=( |
| 139 | + "PASS: headless vgpu + DirectFB2 checks" |
| 140 | + "FAIL: boot/login prompt not found" |
| 141 | + "FAIL: shell prompt not found" |
| 142 | + "FAIL: virtio-gpu basic checks failed (/dev/dri/card0 or virtio_gpu binding)" |
| 143 | + "FAIL: DirectFB2 check failed (run.sh/df_drivertest missing or no DRMKMS init messages)" |
| 144 | +) |
| 145 | + |
| 146 | +# Clean up pre-built ext4.img so other tests can use their own |
| 147 | +if [ -f "ext4.img.bz2" ]; then |
| 148 | + rm -f ext4.img |
| 149 | +fi |
| 150 | + |
| 151 | +if [[ "${ret}" -eq 0 ]]; then |
| 152 | + print_success "${MESSAGES[0]}" |
| 153 | + exit 0 |
| 154 | +fi |
| 155 | + |
| 156 | +print_error "${MESSAGES[${ret}]:-FAIL: unknown error (exit code ${ret})}" |
| 157 | +exit "${ret}" |
0 commit comments