C6-Reticulum-ASM/tests
2026-05-03 12:44:53 -06:00
..
announce implement announce validation 2026-05-03 02:49:22 -06:00
boot wire announce rx into main loop 2026-05-03 03:00:19 -06:00
clock clock: add now_ticks/now_ms/get_freq/delay_us; log_event emits real ms 2026-05-02 00:50:18 -06:00
crypto milestone-2: production HMAC-DRBG-SHA-256 RNG + Tier B ct proofs; close milestone 2026-05-02 23:51:41 -06:00
destination destination tests: add direct qemu hash vectors 2026-05-03 00:46:24 -06:00
flash implement qemu flash model 2026-05-03 01:41:23 -06:00
hardware implement c6 flash rom backend 2026-05-03 02:28:05 -06:00
harness implement link request subset 2026-05-03 03:22:45 -06:00
identity implement identity persistence 2026-05-03 02:05:28 -06:00
kiss kiss: codec + _main bridge end-to-end through qemu 2026-05-01 22:59:31 -06:00
link implement link packet dispatcher 2026-05-03 03:53:41 -06:00
log sha256: end-to-end KAT via 'S'-marker path in _main; FIPS B.1/B.2/empty pass 2026-05-02 01:16:08 -06:00
packet packet test: avoid 's' tag collision with x25519_scalar_mult dispatcher (use \x01 prefix) 2026-05-02 21:27:48 -06:00
resource implement resource advertisement parse 2026-05-03 12:44:53 -06:00
tools bootstrap agent coordination 2026-05-03 00:06:29 -06:00
transport add transport state model 2026-05-03 03:03:28 -06:00
uart uart_rx_byte + uart_rx_available: verified 2026-05-01 22:54:33 -06:00
conftest.py HwTarget: hardware test path against the Adafruit ESP32-C6 Feather 2026-05-02 22:40:14 -06:00
README.md Initialize project: ADRs, master plan, function registry, milestone-1 spec 2026-05-01 19:27:14 -06:00
requirements.txt milestone-1: harness, dispatcher, ADR-0008, build chain 2026-05-01 22:31:38 -06:00

Test harness

Host-side Python test harness, mandated by ADR-0005.

Layout

tests/
├── README.md                    (this file)
├── requirements.txt             (Python dependencies)
├── conftest.py                  (pytest fixtures, target selection)
├── harness/
│   ├── target.py                Target abstraction (Emu, Hw, Oracle)
│   ├── log_parser.py            ADR-0004 log format parser
│   ├── verify.py                ./verify dispatcher
│   └── fixtures.py              shared test data, KAT vectors
├── boot/                        per-function tests, mirroring src/boot/
├── clock/
├── uart/
├── log/
├── kiss/
├── packet/
├── crypto/                      (added in milestone 2)
├── identity/                    (added in milestone 3)
├── transport/                   (added in milestone 5)
└── tools/                       tests for tools/ (parse_spec.py, etc.)

Targets

A target is something a test can drive with input and read output from. The harness defines three:

EmuTarget

Drives qemu-system-riscv32 with a flashed .bin. Fast: a full test run is seconds. Default for agent work — most tests run here first, then on hw for confirmation.

Limitations: peripheral fidelity depends on qemu's C6 model. Functions that depend on hardware-specific behavior (RNG entropy, USB Serial/JTAG, certain GPIO modes) may be hw-only and are marked as such in their test file.

HwTarget

Drives a physical Adafruit ESP32-C6 Feather over USB-serial. Flashes via esptool.py per test run (or per session if test data does not change between cases). Slower (~10 s flash), but is ground truth for hardware-touching functions.

A test that passes on emu but fails on hw indicates either a qemu gap (document in docs/hardware/qemu-gaps.md) or an incorrect assumption in the asm.

OracleTarget

Runs a subprocess python3 -m RNS.Utilities.rnsd (or for cryptography, the relevant Python module from cryptography / pynacl) and uses it as a reference. Used for differential testing: test input is fed to both the C6 (emu or hw) and the oracle, and outputs are asserted byte-identical.

The oracle target is required for any function that has a reference implementation in upstream Python.

Test contract

Every test file exposes a verify(target: Target) -> VerifyResult entry point. VerifyResult is a dataclass:

@dataclass
class VerifyResult:
    function: str
    target: str          # "emu", "hw", or "oracle"
    passed: bool
    duration_ms: int
    cases: list[CaseResult]
    output: str          # captured log output

A function's overall verification passes only if verify returns passed=True on every applicable target.

Running tests

# Single function, default targets
./verify kiss_decode_byte

# Single function, JSON output (for agent consumption)
./verify --json kiss_decode_byte

# Specific target only
./verify --target emu kiss_decode_byte

# All functions (CI)
./verify --all

# All functions in a module
./verify --module kiss

Writing a test

Test files mirror src/ layout: tests/<module>/test_<function>.py.

A test:

  1. Loads the function's spec block (via tools/parse_spec.py).
  2. Defines a list of test cases (input → expected output, or input → expected log events).
  3. For each case: configures the target, sends the input, captures output, asserts equality.
  4. Returns a VerifyResult.

Cases include: positive cases, boundary cases, malformed inputs (parser must reject without crashing), and KAT vectors where the function category warrants them.

Continuous integration

The repository is local-only per ADR-0003 (no remote). CI runs locally via a pre-push git hook that invokes make ci, which is ./verify --all plus the static checks in tools/. A push fails if make ci is red.

If a remote is later added (would require a new ADR), the same make ci becomes the CI target on the remote.