Repository navigation
7.2 Testing Strategy
Test surfaces for protocol stability, backends, and the REST contract.
| 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.
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.
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"]
- Home
- 1. Overview
- 1.1. Getting Started
- 1.2. Architecture Overview
- 1.3. Crate Exports and Module Map
- 2. Core Abstractions
- 2.1. IpcBackend Trait
- 2.2. HybridFlowBackend Trait
- 2.3. BackendFactory and BackendType
- 2.4. Error Handling
- 3. Backend Implementations
- 3.1. RustBackend
- 3.2. ZmqIpcBackend
- 3.3. ZMQ Readout Parsing and Golden Frames
- 3.4. Structured ZeroMQ IpcMessage Transport
- 4. IPC Protocol and Data Models
- 4.1. IpcMessage Protocol
- 4.2. Batch Data Types
- 4.3. NeuromodulatorSnapshot and Neuromodulator Packet
- 4.4. StimulusBatch and Runtime Ingress
- 4.5. Deserialization Hooks and Model Compat Aliases
- 5. Validation and Wire Compatibility
- 5.1. Validation Framework and ProtocolLimits
- 5.2. ValidationError and ValidationKind
- 5.3. WireCompatibility and Envelope Decoding
- 5.4. Canonical Wire-v1 Encoding
- 6. corpus_ipc_server HTTP Server
- 6.1. REST API Endpoints
- 6.2. Server Configuration and Deployment
- 7. Build, Dependencies, and Quality Gates
- 7.1. Cargo Features and Dependency Isolation
- 7.2. Testing Strategy
- 7.2.1. Wire-v1 Golden Test Vectors
- 7.2.2. Property-Based Wire Tests
- 7.3. CI, Coverage, and Release Qualification
- 8. Project History and Licensing
- 8.1. Naming History and Completed Renames
- 8.2. Licensing
- 9. Glossary