Host tests¶
The host tests check the host services that awtrix-linux is built on: file storage,
persistence, name resolution and button input. They live in
tests/host/ and test the code in
src/platform/linux/host/. They
use real temporary files and localhost DNS, and need no device, MQTT broker, public network,
vendor SDK or external test framework.
The repository has other test suites too; the overview lists them all.
Running them¶
The project CMake build includes these tests, so ctest --preset host runs them with everything
else (see Building from source). They also build on their
own:
cmake -S tests/host -B .cache/platform-host-tests -G Ninja -DCMAKE_BUILD_TYPE=Debug
cmake --build .cache/platform-host-tests
ctest --test-dir .cache/platform-host-tests --output-on-failure
On Linux they build with ASan and UBSan (the address and undefined-behaviour sanitizers). These
catch, among other things, stale memory access during delayed resolver destruction.
-DAWTRIX_SANITIZE=OFF turns them off.
| CTest name | Source | Built |
|---|---|---|
host-store |
test_store.cpp |
always |
host-resolver |
test_resolver.cpp |
always |
host-persistence |
test_persistence.cpp |
always |
host-buttons |
test_host_buttons.cpp |
only inside the project build, which provides the core library |
What they cover¶
Storage (host-store)¶
- Binary and empty files, bounded reads.
- Path containment and traversal attempts; symlinks where the system allows them.
- Quota failures that keep the existing content.
- The filesystem reserve: uploads and script sources stay out of it, settings may still use it.
- Script state may use at most three quarters of the reserve and at most 64 KiB per script.
- Atomic replacement while readers are running.
- A failed script-state write stays buffered until a later flush succeeds. With a reserve, that flush waits for more free space or a smaller store.
- The trusted command-line asset reader, separately from data-directory access.
The device and host use fs::usage, fs::openRead, fs::fileSize and fs::isFile for asset
access. The host maps device paths into its configured data directory and rejects symlinks and
escaping paths. The shared ScriptStore<Files> implements script::IScriptFiles; its file
backend supplies filesystem operations and the host's upload reserve and retry state. Stored
script filenames allow 1–64 bytes, with no slash, backslash, colon, NUL or ... This storage
rule also applies when loading files already on disk; API script names follow their own narrower
validation. Removing a script removes its source and state while retaining its sound files.
Resolver (host-resolver)¶
Literal addresses, cache identity, cancellation, invalid input and non-blocking destruction with work still pending. The test waits for delayed workers before it exits, so the sanitizers can see stale memory access.
Persistence (host-persistence)¶
The test forces real directory and disk-space errors and checks that:
- each failed document keeps its latest value for a retry;
- a successful retry clears only its own pending status;
- a retry keeps the old content on disk until it succeeds;
- credentials never reach the persistence log.
A failed save of settings, configuration, app order or radio stations stays visible through
host::persistence::pending / hasPending. flushPending has to run periodically and succeed
before a clean shutdown is reported. This retry state lives in memory; it is not a journal that
survives a crash.
Buttons (host-buttons)¶
HostButtonInput against the real engine: actions queue until the engine ticks, several events
in one frame each count, press and release edges stay in order, left/right/select map to the shared
navigation commands (including rotation and swapped buttons), blockNavigation, the 300 ms
double press that toggles the display, and a script that consumes a button before any default
action.
Limits of what is tested¶
The data root is set at startup. Path containment assumes the service owner controls that root and its parent directories; it is not a boundary against another local user who can replace those directories while the service runs. Atomic replacement of one file does not make several files one transactional snapshot. Disk errors are reported to the caller; behaviour on power loss depends on the real storage and is not covered here.