Testing
Check XTOS with host builds, QEMU guests, and explicit markers.
On this page
Check scope
The source baseline is OpenXTOS commit dd313955ad57542bcd2af8827157d1bbd0cf5e83. Run host commands from the repository root. BUILD_ROOT defaults to .build and must stay the same for build and checks.
Use git show HEAD:path to inspect files at the documented commit. Uncommitted changes are not part of that commit.
| Check | Entry point | Result |
|---|---|---|
| Build | build_system.sh, build_system_arm64.sh, build_system_riscv64.sh | Produces the kernel, BusyBox, libraries, and initramfs; does not prove boot success. |
| x86_64 | scripts/verify_system.sh | Checks QEMU exit, real-time configuration, modules, SDK tests, and tools, and requires XTOS_SYSTEM_TEST=PASS. |
| Cross-architecture basic boot | verify_system_arm64.sh, verify_system_riscv64.sh | Checks kernel, init, version, and boot output; it is not full guest acceptance. |
| Cross-architecture strict check | verify_guest_arm64.sh, verify_guest_riscv64.sh | Checks realtime, configuration, three modules, three tests, markers, and panic. Failed: 0 is required. |
git rev-parse HEAD
git status --short
BUILD_ROOT="${BUILD_ROOT:-$PWD/.build}"
printf 'build_root=%s\n' "$BUILD_ROOT"x86_64 self-test
build_system.sh produces images/xtos-bzImage, images/xtos-rootfs.cpio.gz, and images/kernel.config. verify_system.sh passes console=ttyS0, rdinit=/init, and xtos.selftest=1 to QEMU.
. ./scripts/reproducible_env.sh
JOBS=$(nproc) ./scripts/build_system.sh
QEMU_TIMEOUT=300 ./scripts/verify_system.sh| Check | Pass condition |
|---|---|
| QEMU | Status is 0; a timeout is not a pass. |
| System marker | After removing serial CR characters, a standalone XTOS_SYSTEM_TEST=PASS line exists. |
| Failure scan | The log contains neither XTOS_SYSTEM_TEST=FAIL nor Kernel panic. |
| Host output | Success prints system_qemu=pass log=…; failure prints system_qemu=fail exit=… and returns 1. |
| Log | $BUILD_ROOT/system-qemu.log, normally .build/system-qemu.log. |
The guest /usr/bin/xtos-selftest uses set -eu.
It requires /sys/kernel/realtime=1 and CONFIG_PREEMPT_RT=y plus CONFIG_XTOS_SCHED=y in /proc/config.gz, loads xtos_bci_core, xtos_bci_buffer, and openbci_cyton, runs test_rt, test_spsc, and test_signal, checks status=ok in the CSV JSON, and checks a nonempty signal-benchmark output.
Cross-architecture guests
On the host, build the matching architecture first. ARM64 uses kernel-install-arm64/Image, rootfs-arm64, and ttyAMA0. RISC-V64 uses kernel-install-riscv64/Image, rootfs-riscv64, ttyS0, and /usr/share/qemu/opensbi-riscv64-generic-fw_dynamic.bin.
JOBS=$(nproc) ./scripts/build_system_arm64.sh
QEMU_TIMEOUT=300 ./scripts/verify_guest_arm64.sh
JOBS=$(nproc) ./scripts/build_system_riscv64.sh
QEMU_TIMEOUT=360 ./scripts/verify_guest_riscv64.shverify_guest_* copies the built rootfs, replaces /init in the copy with system/rootfs/xtos-guest-check, and creates initramfs-arm64-guestcheck.cpio.gz or initramfs-riscv64-guestcheck.cpio.gz.
Adding init= to an ordinary initramfs is not the same check.
| Architecture | Log | Result |
|---|---|---|
| ARM64 | $BUILD_ROOT/qemu-arm64-guestcheck-output.txt | 14 checks, Failed: 0, ARM64 in-guest validation PASSED, status 0. |
| RISC-V64 | $BUILD_ROOT/qemu-riscv64-guestcheck-output.txt | 15 checks, Failed: 0, RISC-V 64 in-guest validation PASSED, status 0. |
Guest markers
xtos-guest-check mounts proc, sysfs, and devtmpfs before printing status. It continues and prints DONE; DONE means the script reached the end, not that every check passed. The host script checks each marker and increments failures for missing markers.
| Marker | Checks |
|---|---|
| XTOS_GUEST_CHECK=START | The dedicated /init ran. |
| realtime=1 | Guest /sys/kernel/realtime is 1. |
| preempt_rt=y, xtos_sched=y | Both entries are y in /proc/config.gz. |
| module_xtos_bci_core=ok | modprobe succeeded and /sys/module/xtos_bci_core exists. |
| module_xtos_bci_buffer=ok | The buffer module loaded and is visible in sysfs. |
| module_openbci_cyton=ok | The driver loaded; this does not prove physical-device binding. |
| xtos_modules=pass | All three module checks passed. |
| guest_test_rt=pass | /bin/test_rt exists, is executable, and returns 0. |
| guest_test_spsc=pass | /bin/test_spsc exists, is executable, and returns 0. |
| guest_test_signal=pass | /bin/test_signal exists, is executable, and returns 0. |
| guest_userspace=pass | The three guest tests passed. |
| XTOS_GUEST_CHECK=DONE | The check ended, followed by sync and poweroff -f. |
| OpenSBI | RISC-V64 firmware boot marker. |
| No Kernel panic | The log has no panic. |
The guest verifiers save output with tee and judge markers; the QEMU output-pipeline status is ignored by the scripts. Inspect the shutdown at the end of the log. The guest checker hides the three test outputs; run a failing test separately in an interactive guest.
Interactive guest
On the host, run run_system.sh for the ordinary x86_64 console; it does not pass xtos.selftest=1.
Running xtos-selftest manually does not power off; automatic /init mode powers off after completion.
Read /run/pipeline.json and /run/signal-benchmark.json before shutdown.
./scripts/run_system.shuname -r
uname -m
cat /sys/kernel/realtime
zcat /proc/config.gz | grep -E '^CONFIG_(PREEMPT_RT|XTOS_SCHED|XTOS_BCI|XTOS_BCI_OPENBCI)='
/usr/bin/xtos-selftest
selftest_status=$?
printf 'selftest_exit=%s\n' "$selftest_status"
cat /run/pipeline.json
cat /run/signal-benchmark.json/usr/libexec/xtos/test_rt
/usr/libexec/xtos/test_spsc
/usr/libexec/xtos/test_signaltest_rt covers scheduling, CPU affinity, invalid arguments, and permission boundaries, including expected permission errors for real-time scheduling or locked memory. test_spsc covers empty/full states, ordering, invalid frames, and concurrency. test_signal covers timestamps, DFT power, filters, SSVEP, and P300. Passing does not establish a hardware worst-case scheduling-latency bound.
Save logs
Verifiers overwrite fixed log files. Copy logs to a new directory before rerunning, and record the source commit, toolchain, QEMU version, BUILD_ROOT, and timeout. A result record includes commands, script status, guest markers, and failure output.
BUILD_ROOT="${BUILD_ROOT:-$PWD/.build}"
evidence_dir=$(mktemp -d "$HOME/xtos-evidence.XXXXXX")
git rev-parse HEAD > "$evidence_dir/source-commit.txt"
git status --short > "$evidence_dir/worktree.txt"
for logfile in system-qemu.log qemu-arm64-guestcheck-output.txt qemu-riscv64-guestcheck-output.txt; do
if [ -f "$BUILD_ROOT/$logfile" ]; then
cp -p "$BUILD_ROOT/$logfile" "$evidence_dir/"
fi
done
printf 'evidence=%s\n' "$evidence_dir"- QEMU checks software boot, guest configuration, module loading, and user-space tests.
- The CSV fixture and signal benchmark use software input, not a real EEG device.
- A loadable module does not prove device registration, serial binding, sample units, or end-to-end acquisition.
- Target-hardware latency, jitter, sustained load, and OpenBCI connection need separate measurements.
Source: scripts/verify_system.sh, scripts/verify_system_arm64.sh, scripts/verify_system_riscv64.sh, scripts/verify_guest_arm64.sh, scripts/verify_guest_riscv64.sh, system/rootfs/init, system/rootfs/xtos-guest-check, system/rootfs/usr/bin/xtos-selftest, and the three SDK C tests.