Skip to content

test(io-board-interface): fuzz/property tests for StreamDecoder - #69

Merged
makers-pet merged 1 commit into
makerspet:mainfrom
smailzhu:fuzz/stream-decoder-tests
Sep 28, 2026
Merged

makers-pet merged 1 commit into
makerspet:mainfrom
smailzhu:fuzz/stream-decoder-tests

Conversation

@smailzhu

Copy link
Copy Markdown
Contributor

What

Fuzz/property tests for the CPU<->MCU frame StreamDecoder in
contributions/io-board-interface/xbattlax/. Tests only. No production changes.

Why

StreamDecoder.feed() parses untrusted serial bytes: noisy, arbitrarily
chunked, sometimes corrupt. This pins down its robustness so regressions fail CI.

Checks

  • feed() never raises; every emitted frame round-trips.
  • Residual buffer stays <= 523 bytes after each call.
  • Chunk-invariant: frames + residual buffer depend only on the concatenated
    stream, not on how it is split across calls.
  • Frames wrapped in non-magic noise are recovered exactly, in order.
  • Edge cases: oversized declared length, bad CRC then valid frame, 0- and
    512-byte payloads, a 512-byte frame fed one byte at a time, and the known
    stalled-header resync behavior.

Notes

  • Pure stdlib unittest, fixed seeds. Auto-discovered by the existing python
    CI job. No workflow change, no new dependency.
  • Failures print the seed, iteration, and offending stream.
  • A few assertions read the private _buffer to check the memory bound and
    residual state. Intentional white-box coverage.

Testing

Full io-board-interface suite passes in ~0.8s. Green on fork CI.

Harden the CPU<->MCU frame StreamDecoder against untrusted UART bytes with
deterministic, dependency-free stdlib unittest coverage (fixed seeds), auto-
discovered by the existing host CI python job:

- feed() never raises on arbitrary bytes; emitted frames round-trip; residual
  buffer stays < one max frame (<=523) after every call
- chunk-boundary invariance: frames + residual buffer depend only on the
  concatenated stream, not on how it is split across feed() calls
- valid frames separated by non-magic noise are recovered in order, exactly
- targeted cases: oversized declared length, bad CRC then valid frame, empty
  and max (512B) payloads, a 512B frame fed one byte at a time (bound check),
  and an explicit test documenting the known stalled-header resync limitation

Full suite runs in ~0.8s.
@smailzhu

Copy link
Copy Markdown
Contributor Author

@xbattlax heads-up — this adds tests under your io-board-interface subtree rather than a new folder, since they target your StreamDecoder directly and slot into the existing CI job. Happy to relocate if you'd prefer.

@xbattlax

Copy link
Copy Markdown
Contributor

Thanks for the heads-up. Keeping these tests under
contributions/io-board-interface/xbattlax/tests/ is the right location: they
exercise that reference decoder directly and are picked up by the existing
test command without another CI surface.

I checked the full diff at c62289c against the current decoder and ran the
complete io-board-interface suite locally: all 23 tests pass in 0.57 s. The
fixed seeds, chunk-boundary property, max-frame bound, and corrupt-frame
recovery cases are valuable additions.

One non-blocking follow-up: test_stalled_header_documents_known_limitation
correctly exposes a liveness gap, but we should avoid treating the stall itself
as a permanent contract. The MCU implementation has an explicit receive-gap
reset; the Python reference currently has no equivalent. I suggest leaving a
clear TODO or linked follow-up next to that test so a future timeout/reset fix
is understood as an improvement requiring the expectation to change, rather
than as a regression.

No relocation needed from my side. Thank you for strengthening this path.

@makers-pet
makers-pet merged commit 64049c0 into makerspet:main Sep 28, 2026
@makers-pet

Copy link
Copy Markdown
Collaborator

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants