Added more tests
This commit is contained in:
@@ -4,18 +4,37 @@
|
|||||||
# ============================================================================
|
# ============================================================================
|
||||||
# PipeWire audio server + WirePlumber session manager.
|
# PipeWire audio server + WirePlumber session manager.
|
||||||
# NOTE: PipeWire is designed to run as a user service, not system-wide.
|
# NOTE: PipeWire is designed to run as a user service, not system-wide.
|
||||||
# This script starts it for the auto-login user (danny) on tty1.
|
# This script prepares the runtime directory for the auto-login user.
|
||||||
# For the system-level boot, we just ensure the prerequisites are ready.
|
# The actual PipeWire startup is handled in the user's shell profile
|
||||||
# The actual PipeWire startup is handled in the user's shell profile.
|
# (~/.zprofile) which starts pipewire, pipewire-pulse, and wireplumber.
|
||||||
|
#
|
||||||
|
# The auto-login user is detected from /etc/inittab (--autologin <user>).
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
# Source system configuration
|
||||||
|
[ -f /etc/rc.conf ] && . /etc/rc.conf
|
||||||
|
|
||||||
|
# Detect the auto-login user from inittab
|
||||||
|
get_autologin_user() {
|
||||||
|
local user
|
||||||
|
user=$(grep -m1 -- '--autologin' /etc/inittab 2>/dev/null \
|
||||||
|
| sed 's/.*--autologin \([^ ]*\).*/\1/')
|
||||||
|
echo "${user:-root}"
|
||||||
|
}
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
start)
|
start)
|
||||||
echo " PipeWire: ready (will start with user session)"
|
AUTOLOGIN_USER=$(get_autologin_user)
|
||||||
# Ensure runtime directory exists for the user
|
AUTOLOGIN_UID=$(id -u "$AUTOLOGIN_USER" 2>/dev/null || echo 1000)
|
||||||
mkdir -p /run/user/1000
|
|
||||||
chown danny:danny /run/user/1000
|
echo " PipeWire: preparing runtime dir for ${AUTOLOGIN_USER} (uid ${AUTOLOGIN_UID})"
|
||||||
chmod 700 /run/user/1000
|
|
||||||
|
# Ensure XDG_RUNTIME_DIR exists for the user session
|
||||||
|
mkdir -p "/run/user/${AUTOLOGIN_UID}"
|
||||||
|
chown "${AUTOLOGIN_USER}:${AUTOLOGIN_USER}" "/run/user/${AUTOLOGIN_UID}"
|
||||||
|
chmod 700 "/run/user/${AUTOLOGIN_UID}"
|
||||||
|
|
||||||
|
echo " PipeWire: ready (will start with user session on tty1)"
|
||||||
;;
|
;;
|
||||||
stop)
|
stop)
|
||||||
echo " Stopping PipeWire..."
|
echo " Stopping PipeWire..."
|
||||||
|
|||||||
@@ -2,6 +2,57 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## V27 2026-03-20 07:00:00
|
||||||
|
|
||||||
|
**Add ISO build, boot chain verification, and fix installer bugs**
|
||||||
|
|
||||||
|
### Changes:
|
||||||
|
- Fixed `configs/rc.d/pipewire`: removed hardcoded `danny`/UID `1000`
|
||||||
|
- Now auto-detects the autologin user from `/etc/inittab` via `get_autologin_user()`
|
||||||
|
- Creates XDG_RUNTIME_DIR using the actual user's UID from `id -u`
|
||||||
|
- Works correctly for any username set during installation
|
||||||
|
- Fixed `src/iso/build-iso-arch.sh`: `mkdir -p install/configs` now runs BEFORE
|
||||||
|
copying zprofile into it (was after — silent failure, zprofile never reached the ISO)
|
||||||
|
- Also now copies inittab, rc.conf, and full rc.d/ directory into ISO's install/configs/
|
||||||
|
- Fixed `src/install/modules/disk.sh`: in `configure_boot()`, `mkdir -p EFI/Linux/`
|
||||||
|
now runs BEFORE `cp vmlinuz vmlinuz.efi` (was after — would fail on clean ESP)
|
||||||
|
- Added Test Suite 7 (Boot Chain Verification) — 20+ static checks that verify the
|
||||||
|
complete EFISTUB → init → autologin → zsh → dwl chain is correctly wired:
|
||||||
|
- `chain.efistub` — CONFIG_EFI_STUB=y in kernel config
|
||||||
|
- `chain.autologin` — --autologin in inittab
|
||||||
|
- `chain.inittab_sysinit/multi` — rc.sysinit and rc.multi referenced
|
||||||
|
- `chain.rc.sysinit/multi/shutdown` — scripts exist and are executable
|
||||||
|
- `chain.daemon_listed.*` — eudev/dbus/dhcpcd/pipewire in DAEMONS array
|
||||||
|
- `chain.zprofile_dwl` — zprofile contains `exec dwl`
|
||||||
|
- `chain.zprofile_tty1_guard` — only runs on /dev/tty1
|
||||||
|
- `chain.zprofile_wayland_guard` — won't double-launch
|
||||||
|
- `chain.zprofile_pipewire` — starts audio stack
|
||||||
|
- `chain.zprofile_nvidia_env` — GBM_BACKEND set for RTX 5090
|
||||||
|
- `chain.zprofile_xdg_runtime` — XDG_RUNTIME_DIR created
|
||||||
|
- `chain.pipewire_dynamic_user` — no hardcoded username
|
||||||
|
- `chain.installer_copies_zprofile` — installer deploys zprofile
|
||||||
|
- `chain.installer_updates_inittab` — installer updates autologin user
|
||||||
|
- `chain.boot_mkdir_before_cp` — mkdir before cp in configure_boot
|
||||||
|
- `chain.efibootmgr` — UEFI boot entry created
|
||||||
|
- `chain.nvidia_modules` — NVIDIA in MODULES array
|
||||||
|
- `chain.nvidia_modeset` — nvidia-drm modeset=1 set
|
||||||
|
- Added Test Suite 9 (ISO Build) — actually builds the ISO via `build-iso-arch.sh`:
|
||||||
|
- Checks prerequisites (mksquashfs, xorriso, mkfs.fat, mcopy)
|
||||||
|
- Builds ISO and verifies it was produced
|
||||||
|
- Mounts ISO and squashfs to verify all critical files are inside:
|
||||||
|
rc.conf, rc.d scripts, installer modules, zprofile, dpack binary, package repos
|
||||||
|
- Verifies the zprofile inside the ISO has `exec dwl`
|
||||||
|
- Renumbered QEMU boot test to Suite 10
|
||||||
|
|
||||||
|
### Plan deviation/changes:
|
||||||
|
- None
|
||||||
|
|
||||||
|
### What is missing/needs polish:
|
||||||
|
- ISO build requires sudo (test runner needs root for mount operations)
|
||||||
|
- QEMU boot test still depends on a bootable kernel being present
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## V26 2026-03-20 06:30:00
|
## V26 2026-03-20 06:30:00
|
||||||
|
|
||||||
**Fix test runner bugs and add missing test coverage**
|
**Fix test runner bugs and add missing test coverage**
|
||||||
|
|||||||
@@ -151,8 +151,8 @@ configure_boot() {
|
|||||||
|
|
||||||
# Copy kernel to ESP
|
# Copy kernel to ESP
|
||||||
if [ -f "${MOUNT_POINT}/boot/vmlinuz" ]; then
|
if [ -f "${MOUNT_POINT}/boot/vmlinuz" ]; then
|
||||||
cp "${MOUNT_POINT}/boot/vmlinuz" "${MOUNT_POINT}/boot/efi/EFI/Linux/vmlinuz.efi"
|
|
||||||
mkdir -p "${MOUNT_POINT}/boot/efi/EFI/Linux"
|
mkdir -p "${MOUNT_POINT}/boot/efi/EFI/Linux"
|
||||||
|
cp "${MOUNT_POINT}/boot/vmlinuz" "${MOUNT_POINT}/boot/efi/EFI/Linux/vmlinuz.efi"
|
||||||
ok "Kernel copied to ESP"
|
ok "Kernel copied to ESP"
|
||||||
else
|
else
|
||||||
warn "No kernel found — you'll need to install one before booting"
|
warn "No kernel found — you'll need to install one before booting"
|
||||||
|
|||||||
@@ -132,10 +132,13 @@ l3:3:wait:/etc/rc.d/rc.multi
|
|||||||
ca::ctrlaltdel:/sbin/shutdown -r now
|
ca::ctrlaltdel:/sbin/shutdown -r now
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Installer scripts
|
# Installer scripts and configs
|
||||||
|
mkdir -p "${ROOTFS}/install/configs"
|
||||||
cp -a "${PROJECT_ROOT}/src/install/"* "${ROOTFS}/install/" 2>/dev/null || true
|
cp -a "${PROJECT_ROOT}/src/install/"* "${ROOTFS}/install/" 2>/dev/null || true
|
||||||
cp "${PROJECT_ROOT}/configs/zprofile" "${ROOTFS}/install/configs/zprofile" 2>/dev/null || true
|
cp "${PROJECT_ROOT}/configs/zprofile" "${ROOTFS}/install/configs/zprofile" 2>/dev/null || true
|
||||||
mkdir -p "${ROOTFS}/install/configs"
|
cp "${PROJECT_ROOT}/configs/inittab" "${ROOTFS}/install/configs/inittab" 2>/dev/null || true
|
||||||
|
cp "${PROJECT_ROOT}/configs/rc.conf" "${ROOTFS}/install/configs/rc.conf" 2>/dev/null || true
|
||||||
|
cp -a "${PROJECT_ROOT}/configs/rc.d" "${ROOTFS}/install/configs/rc.d" 2>/dev/null || true
|
||||||
|
|
||||||
# Live shell profile with installer prompt
|
# Live shell profile with installer prompt
|
||||||
cat > "${ROOTFS}/root/.bash_profile" << 'PROFILE'
|
cat > "${ROOTFS}/root/.bash_profile" << 'PROFILE'
|
||||||
|
|||||||
@@ -498,10 +498,193 @@ for daemon in eudev syslog dbus dhcpcd pipewire; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# TEST SUITE 7: Package Signing (network test)
|
# TEST SUITE 7: Boot Chain Verification
|
||||||
|
# ============================================================================
|
||||||
|
# Verify that the complete boot-to-desktop chain is correctly wired:
|
||||||
|
# EFISTUB → init → rc.sysinit → rc.multi → agetty --autologin → zsh → dwl
|
||||||
|
# These are static checks — no running system required.
|
||||||
|
echo -e "\n${BOLD}=== Test Suite 7: Boot Chain Verification ===${NC}\n"
|
||||||
|
|
||||||
|
# 7.1 — Kernel has EFISTUB
|
||||||
|
if [ -f "$KCONFIG" ] && grep -q "^CONFIG_EFI_STUB=y" "$KCONFIG"; then
|
||||||
|
record_test "chain.efistub" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.efistub" "fail" "CONFIG_EFI_STUB not set — kernel won't boot as EFI binary"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 7.2 — inittab has auto-login
|
||||||
|
INITTAB="${PROJECT_ROOT}/configs/inittab"
|
||||||
|
if [ -f "$INITTAB" ] && grep -q -- '--autologin' "$INITTAB"; then
|
||||||
|
AUTOLOGIN_USER=$(grep -- '--autologin' "$INITTAB" | sed 's/.*--autologin \([^ ]*\).*/\1/' | head -1)
|
||||||
|
record_test "chain.autologin" "pass" "User: ${AUTOLOGIN_USER}"
|
||||||
|
else
|
||||||
|
record_test "chain.autologin" "fail" "No --autologin in inittab — user won't be logged in automatically"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 7.3 — inittab runs rc.sysinit and rc.multi
|
||||||
|
if [ -f "$INITTAB" ]; then
|
||||||
|
grep -q "rc.sysinit" "$INITTAB" && record_test "chain.inittab_sysinit" "pass" \
|
||||||
|
|| record_test "chain.inittab_sysinit" "fail" "inittab missing rc.sysinit"
|
||||||
|
grep -q "rc.multi" "$INITTAB" && record_test "chain.inittab_multi" "pass" \
|
||||||
|
|| record_test "chain.inittab_multi" "fail" "inittab missing rc.multi"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 7.4 — rc.sysinit and rc.multi exist and are executable
|
||||||
|
for rcscript in rc.sysinit rc.multi rc.shutdown; do
|
||||||
|
path="${PROJECT_ROOT}/configs/rc.d/${rcscript}"
|
||||||
|
if [ -x "$path" ]; then
|
||||||
|
record_test "chain.${rcscript}" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.${rcscript}" "fail" "Missing or not executable"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# 7.5 — rc.conf has DAEMONS array with required services
|
||||||
|
RC_CONF="${PROJECT_ROOT}/configs/rc.conf"
|
||||||
|
if [ -f "$RC_CONF" ]; then
|
||||||
|
for svc in eudev dbus dhcpcd pipewire; do
|
||||||
|
if grep -q "DAEMONS=.*${svc}" "$RC_CONF"; then
|
||||||
|
record_test "chain.daemon_listed.${svc}" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.daemon_listed.${svc}" "fail" "${svc} not in DAEMONS array — won't start at boot"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 7.6 — zprofile contains dwl auto-start on tty1
|
||||||
|
ZPROFILE="${PROJECT_ROOT}/configs/zprofile"
|
||||||
|
if [ -f "$ZPROFILE" ]; then
|
||||||
|
if grep -q 'exec dwl' "$ZPROFILE"; then
|
||||||
|
record_test "chain.zprofile_dwl" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.zprofile_dwl" "fail" "zprofile missing 'exec dwl' — desktop won't launch"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q '/dev/tty1' "$ZPROFILE"; then
|
||||||
|
record_test "chain.zprofile_tty1_guard" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.zprofile_tty1_guard" "fail" "zprofile missing tty1 check — dwl might launch on wrong tty"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q 'WAYLAND_DISPLAY' "$ZPROFILE"; then
|
||||||
|
record_test "chain.zprofile_wayland_guard" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.zprofile_wayland_guard" "fail" "zprofile missing WAYLAND_DISPLAY check — might double-launch"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q 'pipewire' "$ZPROFILE"; then
|
||||||
|
record_test "chain.zprofile_pipewire" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.zprofile_pipewire" "fail" "zprofile missing pipewire startup — no audio"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q 'GBM_BACKEND' "$ZPROFILE"; then
|
||||||
|
record_test "chain.zprofile_nvidia_env" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.zprofile_nvidia_env" "fail" "zprofile missing NVIDIA env vars — Wayland may fail on RTX 5090"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q 'XDG_RUNTIME_DIR' "$ZPROFILE"; then
|
||||||
|
record_test "chain.zprofile_xdg_runtime" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.zprofile_xdg_runtime" "fail" "zprofile missing XDG_RUNTIME_DIR setup"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
record_test "chain.zprofile_dwl" "fail" "zprofile file missing entirely"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 7.7 — rc.d/pipewire does NOT hardcode a username (should auto-detect)
|
||||||
|
PW_SCRIPT="${PROJECT_ROOT}/configs/rc.d/pipewire"
|
||||||
|
if [ -f "$PW_SCRIPT" ]; then
|
||||||
|
if grep -q 'get_autologin_user\|--autologin' "$PW_SCRIPT"; then
|
||||||
|
record_test "chain.pipewire_dynamic_user" "pass"
|
||||||
|
else
|
||||||
|
# Check if it still hardcodes 'danny'
|
||||||
|
if grep -q 'chown danny' "$PW_SCRIPT"; then
|
||||||
|
record_test "chain.pipewire_dynamic_user" "fail" "rc.d/pipewire hardcodes username 'danny'"
|
||||||
|
else
|
||||||
|
record_test "chain.pipewire_dynamic_user" "pass"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 7.8 — Installer copies zprofile to target user home
|
||||||
|
INSTALLER_USER="${PROJECT_ROOT}/src/install/modules/user.sh"
|
||||||
|
if [ -f "$INSTALLER_USER" ]; then
|
||||||
|
if grep -q 'zprofile' "$INSTALLER_USER"; then
|
||||||
|
record_test "chain.installer_copies_zprofile" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.installer_copies_zprofile" "fail" "Installer doesn't copy zprofile — target user won't auto-start dwl"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q -- '--autologin' "$INSTALLER_USER"; then
|
||||||
|
record_test "chain.installer_updates_inittab" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.installer_updates_inittab" "fail" "Installer doesn't update inittab autologin user"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 7.9 — Installer boot config: mkdir before cp, efibootmgr call
|
||||||
|
INSTALLER_DISK="${PROJECT_ROOT}/src/install/modules/disk.sh"
|
||||||
|
if [ -f "$INSTALLER_DISK" ]; then
|
||||||
|
# Check that mkdir comes before cp in configure_boot
|
||||||
|
if python3 -c "
|
||||||
|
import re, sys
|
||||||
|
with open('${INSTALLER_DISK}') as f:
|
||||||
|
content = f.read()
|
||||||
|
# Find configure_boot function
|
||||||
|
m = re.search(r'configure_boot\(\)\s*\{(.*?)\n\}', content, re.DOTALL)
|
||||||
|
if not m:
|
||||||
|
sys.exit(1)
|
||||||
|
body = m.group(1)
|
||||||
|
mkdir_pos = body.find('mkdir -p')
|
||||||
|
cp_pos = body.find('cp.*vmlinuz.*vmlinuz.efi') if 'cp' in body else body.find('cp ')
|
||||||
|
# Just check mkdir exists before the cp of vmlinuz
|
||||||
|
lines = body.split('\n')
|
||||||
|
mkdir_line = cp_line = -1
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
if 'mkdir -p' in line and 'EFI/Linux' in line:
|
||||||
|
mkdir_line = i
|
||||||
|
if 'vmlinuz.efi' in line and 'cp ' in line:
|
||||||
|
cp_line = i
|
||||||
|
if mkdir_line >= 0 and cp_line >= 0 and mkdir_line < cp_line:
|
||||||
|
sys.exit(0)
|
||||||
|
else:
|
||||||
|
sys.exit(1)
|
||||||
|
" 2>/dev/null; then
|
||||||
|
record_test "chain.boot_mkdir_before_cp" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.boot_mkdir_before_cp" "fail" "configure_boot: mkdir must come before cp to EFI/Linux/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q 'efibootmgr' "$INSTALLER_DISK"; then
|
||||||
|
record_test "chain.efibootmgr" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.efibootmgr" "fail" "Installer doesn't create UEFI boot entry"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 7.10 — NVIDIA kernel modules in rc.conf MODULES array
|
||||||
|
if [ -f "$RC_CONF" ]; then
|
||||||
|
if grep -q 'MODULES=.*nvidia' "$RC_CONF"; then
|
||||||
|
record_test "chain.nvidia_modules" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.nvidia_modules" "fail" "NVIDIA modules not in MODULES array — GPU won't work"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q 'nvidia-drm.*modeset=1\|modeset=1.*nvidia-drm' "$RC_CONF" || \
|
||||||
|
grep -q 'MODULE_PARAMS.*nvidia-drm.*modeset' "$RC_CONF"; then
|
||||||
|
record_test "chain.nvidia_modeset" "pass"
|
||||||
|
else
|
||||||
|
record_test "chain.nvidia_modeset" "fail" "nvidia-drm modeset=1 not set — Wayland DRM/KMS won't work"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# TEST SUITE 8: Package Signing (network test)
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
if [ "$QUICK_MODE" = false ] && [ -x "$DPACK" ]; then
|
if [ "$QUICK_MODE" = false ] && [ -x "$DPACK" ]; then
|
||||||
echo -e "\n${BOLD}=== Test Suite 7: Package Signing ===${NC}\n"
|
echo -e "\n${BOLD}=== Test Suite 8: Package Signing ===${NC}\n"
|
||||||
|
|
||||||
ZLIB_TOML="${PROJECT_ROOT}/src/repos/core/zlib/zlib.toml"
|
ZLIB_TOML="${PROJECT_ROOT}/src/repos/core/zlib/zlib.toml"
|
||||||
if [ -f "$ZLIB_TOML" ]; then
|
if [ -f "$ZLIB_TOML" ]; then
|
||||||
@@ -517,20 +700,148 @@ if [ "$QUICK_MODE" = false ] && [ -x "$DPACK" ]; then
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if [ "$QUICK_MODE" = true ]; then
|
if [ "$QUICK_MODE" = true ]; then
|
||||||
echo -e "\n${BOLD}=== Test Suite 7: Package Signing (SKIPPED) ===${NC}\n"
|
echo -e "\n${BOLD}=== Test Suite 8: Package Signing (SKIPPED) ===${NC}\n"
|
||||||
record_test "sign.zlib" "skip" "Quick mode"
|
record_test "sign.zlib" "skip" "Quick mode"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# TEST SUITE 8: QEMU Boot Test (skipped in quick mode)
|
# TEST SUITE 9: ISO Build
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
if [ "$QUICK_MODE" = false ] && [ -n "$OVMF_PATH" ]; then
|
echo -e "\n${BOLD}=== Test Suite 9: ISO Build ===${NC}\n"
|
||||||
echo -e "\n${BOLD}=== Test Suite 8: QEMU Boot Test ===${NC}\n"
|
|
||||||
|
|
||||||
ISO="${PROJECT_ROOT}/darkforge-live.iso"
|
ISO="${PROJECT_ROOT}/darkforge-live.iso"
|
||||||
|
|
||||||
|
# Check ISO build prerequisites
|
||||||
|
ISO_PREREQS_OK=true
|
||||||
|
for tool in mksquashfs xorriso mkfs.fat mcopy; do
|
||||||
|
if command -v "$tool" >/dev/null 2>&1; then
|
||||||
|
record_test "iso.prereq.${tool}" "pass"
|
||||||
|
else
|
||||||
|
record_test "iso.prereq.${tool}" "fail" "Not installed — needed for ISO build"
|
||||||
|
ISO_PREREQS_OK=false
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$QUICK_MODE" = false ] && [ "$ISO_PREREQS_OK" = true ]; then
|
||||||
|
# Build the ISO
|
||||||
|
echo -e " ${CYAN}Building ISO (this may take a few minutes)...${NC}"
|
||||||
|
t_start=$(date +%s)
|
||||||
|
if sudo bash "${PROJECT_ROOT}/src/iso/build-iso-arch.sh" > "${LOG_DIR}/iso-build.log" 2>&1; then
|
||||||
|
t_end=$(date +%s)
|
||||||
|
record_test "iso.build" "pass" "" "$((t_end - t_start))"
|
||||||
|
else
|
||||||
|
t_end=$(date +%s)
|
||||||
|
err=$(tail -10 "${LOG_DIR}/iso-build.log" | tr '\n' ' ' | tr '"' "'")
|
||||||
|
record_test "iso.build" "fail" "${err}" "$((t_end - t_start))"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check ISO was produced
|
||||||
if [ -f "$ISO" ]; then
|
if [ -f "$ISO" ]; then
|
||||||
echo " Testing ISO boot in QEMU (60s timeout)..."
|
ISO_SIZE=$(du -sh "$ISO" | cut -f1)
|
||||||
|
record_test "iso.exists" "pass" "Size: ${ISO_SIZE}"
|
||||||
|
|
||||||
|
# Verify ISO has EFI boot structure
|
||||||
|
if xorriso -indev "$ISO" -find / -name "BOOTX64.EFI" 2>/dev/null | grep -q "BOOTX64"; then
|
||||||
|
record_test "iso.has_efi_binary" "pass"
|
||||||
|
else
|
||||||
|
record_test "iso.has_efi_binary" "fail" "ISO missing EFI/BOOT/BOOTX64.EFI — won't UEFI boot"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify ISO has squashfs rootfs
|
||||||
|
if xorriso -indev "$ISO" -find / -name "rootfs.img" 2>/dev/null | grep -q "rootfs"; then
|
||||||
|
record_test "iso.has_rootfs" "pass"
|
||||||
|
else
|
||||||
|
record_test "iso.has_rootfs" "fail" "ISO missing LiveOS/rootfs.img"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Mount the squashfs and verify critical files are inside
|
||||||
|
SQFS_MNT=$(mktemp -d /tmp/darkforge-sqfs-XXXXX)
|
||||||
|
SQFS_EXTRACTED=false
|
||||||
|
|
||||||
|
# Extract squashfs from ISO to check contents
|
||||||
|
ISO_MNT=$(mktemp -d /tmp/darkforge-iso-XXXXX)
|
||||||
|
if sudo mount -o loop,ro "$ISO" "$ISO_MNT" 2>/dev/null; then
|
||||||
|
if [ -f "$ISO_MNT/LiveOS/rootfs.img" ]; then
|
||||||
|
if sudo mount -o loop,ro "$ISO_MNT/LiveOS/rootfs.img" "$SQFS_MNT" 2>/dev/null; then
|
||||||
|
SQFS_EXTRACTED=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$SQFS_EXTRACTED" = true ]; then
|
||||||
|
# Check that the live rootfs has all the critical files for the install chain
|
||||||
|
for check_file in \
|
||||||
|
"etc/rc.conf:rc.conf in live rootfs" \
|
||||||
|
"etc/rc.d/rc.sysinit:rc.sysinit in live rootfs" \
|
||||||
|
"etc/rc.d/rc.multi:rc.multi in live rootfs" \
|
||||||
|
"etc/rc.d/eudev:eudev daemon in live rootfs" \
|
||||||
|
"etc/rc.d/dbus:dbus daemon in live rootfs" \
|
||||||
|
"etc/rc.d/dhcpcd:dhcpcd daemon in live rootfs" \
|
||||||
|
"etc/rc.d/pipewire:pipewire daemon in live rootfs" \
|
||||||
|
"install/install.sh:installer script in live rootfs" \
|
||||||
|
"install/modules/disk.sh:disk module in live rootfs" \
|
||||||
|
"install/modules/user.sh:user module in live rootfs" \
|
||||||
|
"install/modules/locale.sh:locale module in live rootfs" \
|
||||||
|
"install/modules/packages.sh:packages module in live rootfs" \
|
||||||
|
"install/configs/zprofile:zprofile for target user in live rootfs"; do
|
||||||
|
fpath="${check_file%%:*}"
|
||||||
|
fdesc="${check_file##*:}"
|
||||||
|
if [ -f "$SQFS_MNT/$fpath" ]; then
|
||||||
|
record_test "iso.rootfs.${fpath##*/}" "pass"
|
||||||
|
else
|
||||||
|
record_test "iso.rootfs.${fpath##*/}" "fail" "Missing: ${fdesc}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check that the zprofile in the ISO has dwl auto-start
|
||||||
|
if [ -f "$SQFS_MNT/install/configs/zprofile" ]; then
|
||||||
|
if grep -q 'exec dwl' "$SQFS_MNT/install/configs/zprofile"; then
|
||||||
|
record_test "iso.rootfs.zprofile_has_dwl" "pass"
|
||||||
|
else
|
||||||
|
record_test "iso.rootfs.zprofile_has_dwl" "fail" "zprofile in ISO missing 'exec dwl'"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check that dpack binary is in the ISO
|
||||||
|
if [ -f "$SQFS_MNT/usr/bin/dpack" ]; then
|
||||||
|
record_test "iso.rootfs.dpack_binary" "pass"
|
||||||
|
else
|
||||||
|
record_test "iso.rootfs.dpack_binary" "fail" "dpack binary missing from ISO — installer can't use dpack"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check that package repos are in the ISO
|
||||||
|
if [ -d "$SQFS_MNT/var/lib/dpack/repos/core" ]; then
|
||||||
|
record_test "iso.rootfs.repos" "pass"
|
||||||
|
else
|
||||||
|
record_test "iso.rootfs.repos" "fail" "Package repos missing from ISO"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo umount "$SQFS_MNT" 2>/dev/null
|
||||||
|
else
|
||||||
|
record_test "iso.rootfs_mount" "skip" "Could not mount squashfs for inspection"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sudo umount "$ISO_MNT" 2>/dev/null
|
||||||
|
rmdir "$SQFS_MNT" "$ISO_MNT" 2>/dev/null
|
||||||
|
else
|
||||||
|
record_test "iso.exists" "fail" "ISO not produced by build script"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ "$QUICK_MODE" = true ]; then
|
||||||
|
record_test "iso.build" "skip" "Quick mode"
|
||||||
|
else
|
||||||
|
record_test "iso.build" "skip" "Missing ISO build prerequisites"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# TEST SUITE 10: QEMU Boot Test (skipped in quick mode)
|
||||||
|
# ============================================================================
|
||||||
|
if [ "$QUICK_MODE" = false ] && [ -n "${OVMF_PATH:-}" ] && [ -f "${ISO}" ]; then
|
||||||
|
echo -e "\n${BOLD}=== Test Suite 10: QEMU Boot Test ===${NC}\n"
|
||||||
|
|
||||||
|
echo -e " ${CYAN}Testing ISO boot in QEMU (60s timeout)...${NC}"
|
||||||
QEMU_DISK=$(mktemp /tmp/darkforge-qemu-XXXXX.qcow2)
|
QEMU_DISK=$(mktemp /tmp/darkforge-qemu-XXXXX.qcow2)
|
||||||
qemu-img create -f qcow2 "$QEMU_DISK" 20G >/dev/null 2>&1
|
qemu-img create -f qcow2 "$QEMU_DISK" 20G >/dev/null 2>&1
|
||||||
|
|
||||||
@@ -541,12 +852,13 @@ if [ "$QUICK_MODE" = false ] && [ -n "$OVMF_PATH" ]; then
|
|||||||
OVMF_FLAGS=""
|
OVMF_FLAGS=""
|
||||||
if echo "$OVMF_PATH" | grep -q "OVMF_CODE"; then
|
if echo "$OVMF_PATH" | grep -q "OVMF_CODE"; then
|
||||||
OVMF_VARS_TEMPLATE="$(dirname "$OVMF_PATH")/OVMF_VARS.fd"
|
OVMF_VARS_TEMPLATE="$(dirname "$OVMF_PATH")/OVMF_VARS.fd"
|
||||||
# Try 4m variant first
|
# Try 4m variant if regular not found
|
||||||
if [ ! -f "$OVMF_VARS_TEMPLATE" ]; then
|
if [ ! -f "$OVMF_VARS_TEMPLATE" ]; then
|
||||||
OVMF_VARS_TEMPLATE="$(dirname "$OVMF_PATH")/OVMF_VARS.4m.fd"
|
OVMF_VARS_TEMPLATE="$(dirname "$OVMF_PATH")/OVMF_VARS.4m.fd"
|
||||||
fi
|
fi
|
||||||
OVMF_VARS_COPY="/tmp/darkforge-ovmf-vars.fd"
|
OVMF_VARS_COPY="/tmp/darkforge-ovmf-vars.fd"
|
||||||
cp "$OVMF_VARS_TEMPLATE" "$OVMF_VARS_COPY" 2>/dev/null || dd if=/dev/zero of="$OVMF_VARS_COPY" bs=256K count=1 2>/dev/null
|
cp "$OVMF_VARS_TEMPLATE" "$OVMF_VARS_COPY" 2>/dev/null || \
|
||||||
|
dd if=/dev/zero of="$OVMF_VARS_COPY" bs=256K count=1 2>/dev/null
|
||||||
OVMF_FLAGS="-drive if=pflash,format=raw,readonly=on,file=${OVMF_PATH} -drive if=pflash,format=raw,file=${OVMF_VARS_COPY}"
|
OVMF_FLAGS="-drive if=pflash,format=raw,readonly=on,file=${OVMF_PATH} -drive if=pflash,format=raw,file=${OVMF_VARS_COPY}"
|
||||||
else
|
else
|
||||||
OVMF_FLAGS="-bios ${OVMF_PATH}"
|
OVMF_FLAGS="-bios ${OVMF_PATH}"
|
||||||
@@ -585,13 +897,14 @@ if [ "$QUICK_MODE" = false ] && [ -n "$OVMF_PATH" ]; then
|
|||||||
|
|
||||||
rm -f "$QEMU_DISK"
|
rm -f "$QEMU_DISK"
|
||||||
else
|
else
|
||||||
record_test "qemu.iso_exists" "fail" "No ISO found — build it first with src/iso/build-iso.sh"
|
echo -e "\n${BOLD}=== Test Suite 10: QEMU Boot Test (SKIPPED) ===${NC}\n"
|
||||||
record_test "qemu.kernel_boots" "skip" "No ISO"
|
if [ "$QUICK_MODE" = true ]; then
|
||||||
record_test "qemu.reaches_userspace" "skip" "No ISO"
|
record_test "qemu.kernel_boots" "skip" "Quick mode"
|
||||||
fi
|
elif [ -z "${OVMF_PATH:-}" ]; then
|
||||||
|
record_test "qemu.kernel_boots" "skip" "No OVMF firmware"
|
||||||
else
|
else
|
||||||
echo -e "\n${BOLD}=== Test Suite 8: QEMU Boot Test (SKIPPED) ===${NC}\n"
|
record_test "qemu.kernel_boots" "skip" "No ISO built"
|
||||||
record_test "qemu.kernel_boots" "skip" "Quick mode or no OVMF"
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user