Testing¶
Espilon ships with an automated test harness in espilon-test/ that validates the whole firmware stack against real hardware. It runs an embedded Management Protocol server, waits for a device to connect, compiles and injects test modules, runs commands, and writes a JSON report.
Running tests¶
cd framework/espilon-test
# free port 2626 from any previous runner first
lsof -ti:2626 | xargs -r kill -9 2>/dev/null
python runner.py --suite core --version v0.2.1 --devices espilon-c6
Runner flags¶
| Flag | Default | Purpose |
|---|---|---|
--suite |
core |
Suite to run (see below) |
--version |
dev |
Firmware version label (used in the report filename) |
--chip |
auto | Override the detected chip |
--devices |
all connected | Device id(s) to test |
--target |
none | Target device id for red-team tests (attacker + target pair) |
--profile |
wifi |
gprs selects cellular timing |
--emon |
off | Capture serial logs during the run |
--compare |
none | Compare two JSON reports: --compare new.json old.json |
Suites¶
| Suite | Tests | Approx time | Use |
|---|---|---|---|
smoke |
T1-T3 | ~30 s | Post-flash sanity check |
core |
T1-T8 | ~3 min | Standard pre-release validation |
network |
T9-T10 | ~2 min | mod_network / mod_recon changes |
ble |
T11 | ~1 min | BLE-capable chips only |
stress |
T12-T14 | ~10 min | Concurrency, crypto, load/unload cycles |
tunnel |
T20-T25 | ~5 min | C2 resilience |
full |
T1-T14, T20-T22, T25 | ~15 min | Release sign-off (excludes the long T23) |
redteam |
T1, T15-T19 | varies | Offensive tests; needs --target |
Core tests (T1-T8)¶
| Test | Validates |
|---|---|
| T1 | Boot, WiFi connect, C2 handshake, status response |
| T2 | Module lifecycle: inject, list, stop, purge |
| T3 | Syscalls via mod_basic: printf, NVS, hw_trng, HMAC-SHA256, get_local_ip |
| T4 | IRAM no-leak: heap drift under 2 KB over 10 load/unload cycles |
| T5 | Watchdog kills a hanging module; device still responds |
| T6 | Panic isolation: a crashing module does not take down a bystander (Xtensa only; skipped on RISC-V, which reboots) |
| T7 | NVS persist and autoload: a persisted module survives reboot |
| T8 | Built-in commands return valid output |
Further suites cover modules (T9-T11), stress (T12-T14), red team (T15-T19, paired boards), and tunnel resilience (T20-T25, including reconnect, mid-inject recovery, keepalive idle, and RTT baseline).
Chip capabilities¶
The harness knows each chip's capabilities (config.py): BLE, PSRAM, dual-core, IRAM size. BLE tests auto-skip on chips without BLE and on the ESP32-S3 rev2 (v0.2) BLE errata.
Reports¶
Results are written to results/<timestamp>_<version>_<chip>_<PASS|FAIL>.json with per-test status, timing, and details. With --emon, serial captures are attached under results/logs/.
Process naming
The emon monitor name matches the substring "daemon". Never kill it with
pkill -f emon - that can kill unrelated system daemons. Always kill by exact PID.