Branch: ocp-emea-demo
Server<S: Sender, const N> is generic over mctp_lib::Sender. I2C transport is just one Sender impl + a caller of server.inbound(). No mocking framework, feature flags, or cfg(test) shims needed.
services/mctp/server/tests/ ├── common/ │ └── mod.rs ← shared BufferSender, transfer(), DirectClient ├── echo.rs ← already exists; refactor to use common/ ├── dispatch.rs ← already exists; add missing cases ├── server_unit.rs ← NEW: Layer 2 unit tests └── integration.rs ← NEW: Layer 4 multi-fragment / concurrency
BufferSender<'_> from echo.rs and dispatch.rs into tests/common/mod.rsDroppingBufferSender (discards writes, always returns Ok) for tests that only care about inbound routingtransfer(from, to) helper into commonDirectClient<'a, S, N> into common (wraps &RefCell as MctpClient)req() + unbind() — handle allocation/deallocationlistener() duplicate msg_type — expect AlreadyBound errortry_recv() before any inbound() — returns Noneinbound(raw_pkt) + try_recv() — full routing path (use mctp_lib::fragment::Fragmenter to build raw pkts)register_recv() + update(now + timeout) — timeout fires RecvResult::TimedOutset_eid() / get_eid() — EID round-tripsend() with payload > MAX_PAYLOAD — expect NoSpace errorMctpOp::Send via response path (no handle, HAS_EID flag, explicit tag)MctpOp::Unbind for never-allocated handle → errorMctpOp::Recv when no message ready → TimedOut (gap noted in code comment)get_mtu()=64, send 200-byte payload, verify reassemblyMctpListener::recv() — called after inbound, returns payloadMctpReqChannel::send() + recv() — full request-response cycledrop_handle mid-flight — verify outstanding entry is cleared| Concern | Owner crate |
|---|---|
| MCTP-over-I2C framing/PEC | openprot-mctp-transport-i2c |
| MctpI2cReceiver::decode | openprot-mctp-transport-i2c |
| I2cClientBlocking mock | i2c service tests |
| IpcI2cClient / handle::I2C wiring | target/platform integration |