Skip to content

7.2 Testing Strategy

Wiki Keeper (Grok Bot) edited this page Oct 26, 2026 · 5 revisions

Testing Strategy

Test surfaces for protocol stability, backends, and the REST contract.

Suites

Area Location Notes
Wire compatibility tests/compatibility.rs, tests/fixtures/compatibility/ version window + legacy
Canonical encode tests/canonical.rs encoder unit/integration
Wire-v1 goldens tests/wire_v1_vectors.rs, test-vectors/wire-v1/ see 7.2.1
Property tests tests/wire_properties.rs see 7.2.2
ZMQ goldens tests/zmq_golden_readout.rs feature zmq
REST contract tests/server_contract.rs feature server; in-process router
Limits / validation src/models/limits_tests/, src/validation/ unit
Backend src/rust_backend.rs, src/zmq_backend.rs (feature zmq) unit incl. drain/reconnect
Structured ZMQ src/zmq_message/ (tests.rs, transport_tests.rs, framing_tests.rs, hybrid_live.rs) feature zmq; #55
Fuzz regressions tests/fuzz_regressions.rs stable replay of the fuzz invariants (#58); see Fuzzing
ap-check ci/ap-check workspace member; arbitrary_precision unification

Live-socket timing (#67, dd73547, LIM-1547; tests only). receive_drain_bound_returns_under_sustained_publish_load in src/zmq_backend.rs no longer floods a fixed 511 frames and sleeps 10 ms before one timed drain. The flooder now publishes until told to stop, and the test drains repeatedly for up to 5 s until a drain supersedes a flooded frame (counted from the first flooded frame, so warm-up duplicates don't count). It asserts that the worst drain stayed under 100 ms and that a backlog was actually drained. publisher_rejects_invalid_payloads_without_sending in src/zmq_message/framing_tests.rs sends an IpcMessage::Loss(2.0) sentinel and drains up to it before asserting silence, so duplicate Ping resends from expect_message can't arrive late.

Fuzzing

Added in #58 (LIM-1277). fuzz/ is a repository-only cargo-fuzz / libFuzzer harness in its own Cargo workspace, outside the crate's include list, so the published package gains no dependency, binary, or file. Every target calls a production entry point (see fuzz/README.md):

Target Entry point Checks
fuzz_ipc_message_json decode_ipc_message_json No panic; accepted messages pass Validate at ProtocolLimits::DEFAULT and round-trip canonically to identical bytes
fuzz_zmq_readout_frame zmq_readout::parse_readout_packet and the ZmqIpcBackend ingest path No panic; accepted iff len ≥ 8, (len − 8) % 4 == 0, and the float count is within the cap; bit-exact decoding; the backend cache changes only on accept
fuzz_zmq_message_frame ZmqMessageSubscriber::decode_frame_for_tests (the decoder try_recv runs, #[doc(hidden)], feature zmq) No panic; empty frame → UnexpectedFraming(Empty); other rejections are only Envelope or Validation; accepted messages agree with decode_ipc_message_json and fit STRUCTURED_MAX_FRAME_BYTES

The invariants live in fuzz/src/lib.rs, which the root crate also compiles into tests/fuzz_regressions.rs, so regression seeds, the committed vectors, and synthetic empty / truncated / random / oversize inputs replay on stable cargo test --all-features. scripts/fuzz-smoke.sh runs a bounded campaign (default 30 s per target) seeded in place from test-vectors/wire-v1/ and test-vectors/zmq/*.hex, plus fuzz/regressions/<target>/. Per the fuzz README, the initial 2026-10-19 campaigns found no panic or invariant violation, so no regression seed is committed yet.

The empty-frame check moved from the socket read path into the shared frame decoder in #58; try_recv behaviour is unchanged.

Decode classification flow

flowchart TD
  In["Incoming JSON"] --> Dec["decode_ipc_message_json"]
  Dec --> Cls["classify_wire_version"]
  Cls -->|"less than MIN_SUPPORTED"| TooOld["CompatibilityError::TooOld"]
  Cls -->|"in window"| Acc["accept + deserialize"]
  Cls -->|"greater than CURRENT"| TooNew["CompatibilityError::TooNew"]
Loading

Child pages

Clone this wiki locally