XTOS / OPEN SOURCE REAL-TIME SYSTEMOPEN SOURCE · VERSION 0.9.0 · BUILD FROM SOURCE
DocsTesting

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.

CheckEntry pointResult
Buildbuild_system.sh, build_system_arm64.sh, build_system_riscv64.shProduces the kernel, BusyBox, libraries, and initramfs; does not prove boot success.
x86_64scripts/verify_system.shChecks QEMU exit, real-time configuration, modules, SDK tests, and tools, and requires XTOS_SYSTEM_TEST=PASS.
Cross-architecture basic bootverify_system_arm64.sh, verify_system_riscv64.shChecks kernel, init, version, and boot output; it is not full guest acceptance.
Cross-architecture strict checkverify_guest_arm64.sh, verify_guest_riscv64.shChecks realtime, configuration, three modules, three tests, markers, and panic. Failed: 0 is required.
Host: record the commit, worktree status, and artifact directory.
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.

Host: build and run the strict x86_64 self-test.
. ./scripts/reproducible_env.sh
JOBS=$(nproc) ./scripts/build_system.sh
QEMU_TIMEOUT=300 ./scripts/verify_system.sh
CheckPass condition
QEMUStatus is 0; a timeout is not a pass.
System markerAfter removing serial CR characters, a standalone XTOS_SYSTEM_TEST=PASS line exists.
Failure scanThe log contains neither XTOS_SYSTEM_TEST=FAIL nor Kernel panic.
Host outputSuccess 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.

Host: build and run the strict guest check for each required architecture.
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.sh

verify_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.

ArchitectureLogResult
ARM64$BUILD_ROOT/qemu-arm64-guestcheck-output.txt14 checks, Failed: 0, ARM64 in-guest validation PASSED, status 0.
RISC-V64$BUILD_ROOT/qemu-riscv64-guestcheck-output.txt15 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.

MarkerChecks
XTOS_GUEST_CHECK=STARTThe dedicated /init ran.
realtime=1Guest /sys/kernel/realtime is 1.
preempt_rt=y, xtos_sched=yBoth entries are y in /proc/config.gz.
module_xtos_bci_core=okmodprobe succeeded and /sys/module/xtos_bci_core exists.
module_xtos_bci_buffer=okThe buffer module loaded and is visible in sysfs.
module_openbci_cyton=okThe driver loaded; this does not prove physical-device binding.
xtos_modules=passAll 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=passThe three guest tests passed.
XTOS_GUEST_CHECK=DONEThe check ended, followed by sync and poweroff -f.
OpenSBIRISC-V64 firmware boot marker.
No Kernel panicThe 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.

Host: start the interactive x86_64 guest.
./scripts/run_system.sh
Guest: inspect the running kernel, configuration, self-test status, and JSON.
uname -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
x86_64 guest paths; ARM64/RISC-V64 use /bin/test_rt, /bin/test_spsc, and /bin/test_signal.
/usr/libexec/xtos/test_rt
/usr/libexec/xtos/test_spsc
/usr/libexec/xtos/test_signal

test_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.

Host: save existing logs and worktree status.
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.