Connector framework — verification¶
Test cases verifying the connector framework requirements. Each test
directive :verifies: one or more requirements from
Connector framework (or building blocks from
Connector framework — architecture (arc42)). The four-layer test pyramid from the
architecture’s quality strategy is reflected by the section grouping
below: unit, codec, transport integration, MQTT integration, workspace
end-to-end, and loom concurrency.
Implementation tests (Rust #[test]) and the verification artefacts
on this page trace 1:1 — once the implementation lands, each test
body cites the Rust test path that runs it.
Unit tests¶
Per-crate, no IPC, parallel-safe.
Property test ( |
Unit test asserting that every valid transition between
|
Unit-level coverage of the topic-match predicate independent of any
broker or iceoryx2 service: every (subscription pattern, incoming
topic) pair is asserted against the MQTT 3.1.1 wildcard semantics
(single-level |
Asserts that constructing a |
Codec tests¶
|
Encoding a value larger than the provided buffer returns
|
Receiving a payload that fails |
Transport integration tests¶
Iceoryx2 services are real; tests run with --test-threads=1; each
test scopes its own Node name.
End-to-end zero-copy round-trip through a real iceoryx2 service:
|
Sending N envelopes through a single |
Captures wall-clock time before and after |
|
Three round-trip tests with channels parameterised at distinct
|
|
Two |
MQTT integration tests¶
Embedded rumqttd per-test fixture on an ephemeral port; iceoryx2
services per test as before; one tokio runtime per test.
Plugin → gateway → broker → gateway → plugin round-trip with
|
Same as TEST_0130 but with |
Publish with |
Subscribe with |
Subscribe with |
|
|
While the connector is |
Drives the connector through every legal transition in
Health and reconnect lifecycle (ARCH_0012) and asserts a |
Configure |
Configure a tiny inbound-bridge capacity. Block the inbound
gateway item from draining (e.g. by holding |
EtherCAT integration tests¶
EtherCAT tests come in two flavours: software tests (unit + raw-frame
mock) parallel-safe on any host, and hardware-in-the-loop tests marked
[bench] that require an EK1100 + EL-series fixture on the CI test
bench. The mock implementation lives in
taktora-connector-ethercat/tests/mock/ and replays canned EtherCAT
frame responses so bring-up, PDO mapping, and WKC scenarios can be
exercised without hardware. Bench tests run only when invoked as
cargo test --features ethercat-bench.
Compile-time test confirming that
|
Unit test constructing |
Construct an |
Mock-frame test: start an |
Unit test that |
Mock-frame test observing the SDO write sequence during bring-up:
the gateway emits writes to |
Unit test that |
Mock-frame test: stall the gateway’s tokio sidecar for 5 cycles
by holding a mutex on the bridge. After release, exactly one
tx_rx cycle runs (not five) — the skipped ticks are dropped, not
queued for catch-up. The asserted behaviour matches
|
Two mock-frame scenarios. (1) Default options: the gateway
completes bring-up without emitting any BWR to |
Mock-frame test: drive the gateway to OP with the mock reporting
the expected WKC on every cycle for 10 consecutive cycles;
|
Mock-frame test: configure a degradation threshold of N=3 cycles;
inject N consecutive cycles with WKC below the expected value;
the gateway transitions to |
Structural test using |
Unit test that |
Mock-frame test: configure a tiny outbound-bridge capacity. Stall
the tokio sidecar from draining. The plugin’s |
Mock-frame test: configure a tiny inbound-bridge capacity. Block
the inbound gateway item from draining. Drive a flood of inbound
process-image updates through the mock; the gateway emits one or
more |
Hardware-bench test |
Pure-logic test of the |
Property test for the same round-trip as PDI bit-slice byte-aligned ... (TEST_0216) but
covering |
Construct two |
When the application registers N channel descriptors in order
|
With a |
With a |
Compose Outbound end-to-end (plugin... (TEST_0220) and Inbound end-to-end (PDI sli... (TEST_0221) via a |
Workspace end-to-end tests¶
Full stack exercised via taktora-connector-host examples or
assert_cmd-driven binary smoke tests.
Single-binary integration: |
Two binaries: a plugin process running |
While the connector is mid-traffic, send SIGINT; the host returns
from |
With one channel configured, observe the iceoryx2 service for the duration of a normal session: the only envelopes that flow are user-payload envelopes (no “ping”, “version”, or “shutdown handshake”). Asserts the framework’s no-control-plane invariant. |
Zenoh reference connector¶
Layer-1 (pure-logic) tests run in default CI against
MockZenohSession and require no real zenoh crate.
Layer-2 (zenoh-integration feature gate) and Layer-3
(ZENOH_TEST_ROUTER env-gated client mode) tests run on
dedicated CI jobs; they :status: draft until those jobs
land.
Unit test asserting that constructing a |
Compile-fail test ensuring |
Drive a |
End-to-end query test: plugin A calls
|
Encoding a value larger than the envelope’s payload returns
|
With |
With |
With |
Walk the mock session through |
Regression-guard for the explicit anti-requirement
NO ReconnectPolicy on Zenoh... (REQ_0441) (which is status:rejected because the project
deliberately excludes Static check that |
Build the crate twice — once with default features, once with
|
CI matrix builds the crate on Linux, macOS, and Windows
(default features) and runs |
Layer-2 integration test ( |
Layer-3 env-gated test: when |
Static check that the |
CAN (SocketCAN) reference connector¶
Verification artefacts for the CAN reference connector. Layer-1
(pure-logic) cases use MockCanInterface; layer-2 cases gated on
socketcan-integration require a Linux host with the vcan
kernel module loaded (modprobe vcan && ip link add dev vcan0 type
vcan && ip link set up vcan0).
Compile-time API surface check that |
Property test ( |
Layer-1 end-to-end test: |
As Classical CAN round-trip vi... (TEST_0502) but with |
Open three inbound readers on the same mock iface with
distinct |
Gateway owns two mock ifaces ( |
Drive |
Two-iface gateway. Inject an error-passive error frame on
|
Static check that the SocketCAN sockets and any tokio runtime
handle live entirely inside the |
With |
With |
Build the crate twice — once with default features, once with
|
Layer-2 integration test ( |
Regression-guard for the explicit anti-requirement
NO plugin-visible error-fra... (REQ_0643). Inject error frames of every classified
kind (error-warning, error-passive, bus-off) via
|
Add 8 channels to the same mock iface in a known order; assert
the RX dispatch loop and the TX drain loop iterate them in
that insertion order on every cycle. Assert no per-cycle heap
allocation: instrument a |
Loom concurrency tests¶
Run with cargo test --features loom under cfg(loom).
Loom model of |
Loom model with multiple threads attempting transitions
simultaneously (e.g. the tokio task reporting |
Cross-cutting traceability¶
ID |
Title |
Status |
Verifies |
|---|---|---|---|
ExponentialBackoff invariants |
open |
||
ConnectorHealth state-machine transitions |
open |
||
MqttRouting wildcard demux predicate |
open |
||
ChannelDescriptor validation |
open |
||
JsonCodec round-trip property test |
open |
||
Codec encode error on undersized buffer |
open |
||
Codec decode error propagation |
open |
||
ChannelWriter → ChannelReader round-trip |
open |
||
Sequence-number monotonicity |
open |
||
Timestamp populated at send |
open |
||
Correlation ID round-trip |
open |
||
Per-channel size — 4 KB, 64 KB, 1 MB |
open |
||
Payload-overflow rejection |
open |
||
Service naming derived from descriptor |
open |
||
QoS 0 round-trip |
open |
||
QoS 1 round-trip |
open |
||
Retained-message publish + subscribe |
open |
||
Wildcard subscription with `+` |
open |
||
Wildcard subscription with `#` |
open |
||
Username/password authentication |
open |
||
TLS connection (developer-machine only) |
open |
||
Reconnect after broker bounce |
open |
||
HealthEvent emitted on every transition |
open |
||
Outbound bridge saturation → BackPressure |
open |
||
Inbound bridge saturation → DroppedInbound |
open |
||
In-process gateway smoke |
open |
||
Separate-process gateway smoke |
open |
||
SIGINT clean exit within 5-second budget |
open |
||
No control-plane envelopes flow |
open |
||
Bridge handoff under arbitrary interleaving |
open |
||
Health state-machine under concurrent updates |
open |
||
Zero allocations in steady-state dispatch |
open |
||
Cap exhaustion and oversize alloc both fail-closed |
open |
||
Steady-state cap behaviour under burst |
open |
||
lock() then alloc panics |
open |
||
Counter accuracy |
open |
||
Concurrent alloc/dealloc safety smoke |
open |
||
Histogram percentile accuracy |
open |
||
Per-task max jitter under synthetic period violation |
open |
||
Overrun counter increments exactly per overrun cycle |
open |
||
Push and pull stat paths agree |
open |
||
Allocation-free telemetry update |
open |
||
EthercatConnector trait surface |
open |
||
EthercatRouting field round-trip |
open |
||
Single MainDevice per gateway instance |
open |
||
Bus reaches OP before traffic accepted |
open |
||
Static PDO map accepted from options |
open |
||
PDO mapping applied during PRE-OP to SAFE-OP |
open |
||
Cycle time configurable |
open |
||
Missed ticks are skipped not queued |
open |
||
Distributed Clocks bring-up is opt-in |
open |
||
Up requires OP and matching working counter |
open |
||
Working-counter mismatch transitions to Degraded |
open |
||
Tokio sidecar contained inside connector crate |
open |
||
Bridge channels are bounded with configurable capacity |
open |
||
Outbound bridge saturation surfaces as BackPressure |
open |
||
Inbound bridge saturation surfaces as DroppedInbound |
open |
||
Gateway opens raw socket on Linux with CAP_NET_RAW |
open |
||
PDI bit-slice byte-aligned round-trip |
open |
||
PDI bit-slice unaligned round-trip |
open |
||
Adjacent PDI bit slices do not interfere |
open |
||
Per-channel routing registry has stable iteration order |
open |
||
Outbound end-to-end (plugin send → PDI slice via mock) |
open |
||
Inbound end-to-end (PDI slice via mock → plugin recv) |
open |
||
Loopback round-trip (plugin → mock → plugin) |
open |
||
Harness builds and runs on Linux non-RT |
open |
||
NDJSON schema validation |
open |
||
Harness telemetry agrees with stats_snapshot |
open |
||
ZenohRouting field validation |
open |
||
ZenohConnector implements Connector with ZenohRouting |
open |
||
Pub/sub end-to-end against MockZenohSession |
open |
||
Query round-trip against MockZenohSession |
open |
REQ_0420; REQ_0421; REQ_0422; REQ_0423; REQ_0424; REQ_0426; REQ_0427 |
|
Codec failure paths for queries |
open |
||
Outbound bridge saturation surfaces as BackPressure |
open |
||
Inbound bridge saturation surfaces as DroppedInbound |
open |
||
Query timeout emits 0x03 terminator |
open |
||
Health state machine on MockZenohSession lifecycle |
implemented |
||
REQ_0441 anti-req — no ReconnectPolicy on session loss |
implemented |
||
zenoh-integration feature gates the real zenoh dep |
implemented |
||
Cross-platform support |
implemented |
||
Two-peer real session pub/sub |
draft |
||
Client-mode router smoke |
draft |
||
Tokio sidecar contained inside taktora-connector-zenoh |
implemented |
||
parse() accepts a representative Beckhoff EL3001 ESI |
open |
||
Parser compiles under no_std + alloc |
open |
||
Parser is independent of ethercrab |
open |
||
Vendor-specific elements survive as RawXml |
open |
||
Parse errors carry line and column |
open |
||
Name sanitisation handles ESI naming edge cases |
open |
||
Revision collision produces distinct idents |
open |
||
PDO entry dedup collapses structurally identical layouts |
open |
||
TokenStream emission, not string formatting |
open |
||
EL3001 backend output snapshot |
open |
||
Generated registry covers every emitted device |
open |
||
Generated module compiles under no_std + alloc |
open |
||
Backend is the sole ethercrab consumer in the toolchain |
open |
||
Object-dictionary emission gated by feature flag |
open |
||
EsiDevice trait shape compiles for a hand-written device |
open |
||
EsiConfigurable async trait shape compiles |
open |
||
ethercat-esi-rt is the trait home, not taktora-internal |
open |
||
Builder writes a parseable Rust file to OUT_DIR |
open |
||
cargo rerun-if-changed emitted per ESI input |
open |
||
Output passes prettyplease formatting |
open |
||
cargo esi expand emits a single device's code |
open |
||
cargo esi list enumerates devices |
open |
||
CLI output matches build helper output byte-for-byte |
open |
||
Verifier passes on matching ESI + SII pair |
open |
||
Verifier reports the differing field |
open |
||
Verifier reuses ethercat-esi parser |
open |
||
Verifier exit codes follow the documented matrix |
open |
||
Repeated codegen runs produce byte-identical output |
open |
||
Input-file ordering does not affect output |
open |
||
Layering integrity check (Cargo.toml audit) |
open |