test(adr-110): cross-language wire-format conformance gate
Iter 21 — ultra-opt for protocol correctness across the two production decoders. Pin the same 32-byte canonical hex in both Python and Rust tests; if either decoder drifts from the wire, ONE of the tests starts failing — and it's clear which side moved. Canonical packet: COM9 sync-pkt #1 from §A0.12 live capture, expressed as exact little-endian bytes: 10a111c5 09 01 06 00 magic + node + ver + flags + rsvd f26db70100000000 local_us = 28_798_450 c5aca50100000000 epoch_us = 27_634_885 1400000000000000 sequence = 20 + reserved Python test: archive/v1/tests/unit/test_esp32_binary_parser.py::TestSyncPacketParser ::test_canonical_wire_bytes_match_rust_decoder — decodes the pinned hex, asserts every field including the §A0.10 1,163,565 µs offset. Rust test: v2/crates/wifi-densepose-hardware/src/sync_packet.rs::tests ::canonical_wire_bytes_match_python_decoder — decodes the same bytes, asserts the same fields, then re-encodes via to_bytes() and asserts the round-trip produces the EXACT same 32 bytes. So this also catches drift in the Rust encoder. Test counts after this iter: Rust sync_packet: 15/15 green (was 14) Python SyncPacketParser: 7/7 green (was 6) Branch contract: if a future PR changes the firmware wire format, BOTH tests must be updated atomically with the new canonical hex. CI will gate this naturally. Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
parent
40bd6b81b8
commit
82be960de5
|
|
@ -364,3 +364,35 @@ class TestSyncPacketParser:
|
|||
assert csi_magic == ESP32BinaryParser.MAGIC
|
||||
assert sync_magic == SyncPacketParser.MAGIC
|
||||
assert csi_magic != sync_magic
|
||||
|
||||
def test_canonical_wire_bytes_match_rust_decoder(self):
|
||||
"""ADR-110 iter 21 — cross-language wire-format conformance gate.
|
||||
|
||||
These exact bytes also appear pinned in the Rust hardware crate's
|
||||
`canonical_wire_bytes_match_python_decoder` test (same field
|
||||
values, encoded by Rust's `SyncPacket::to_bytes`). If Python's
|
||||
hardcoded hex stops matching what Rust produces from the equivalent
|
||||
SyncPacket struct, ONE of the decoders has drifted from the wire.
|
||||
|
||||
Canonical packet: COM9 sync-pkt #1 from §A0.12 live capture.
|
||||
"""
|
||||
canonical = bytes.fromhex(
|
||||
"10a111c509010600" # magic LE + node=9 + ver=1 + flags=0x06 + reserved
|
||||
"f26db70100000000" # local_us = 28_798_450 (LE u64)
|
||||
"c5aca50100000000" # epoch_us = 27_634_885 (LE u64)
|
||||
"1400000000000000" # sequence = 20 (LE u32) + 4 reserved bytes
|
||||
)
|
||||
assert len(canonical) == SyncPacketParser.SIZE == 32
|
||||
|
||||
pkt = SyncPacketParser.parse(canonical)
|
||||
assert pkt.node_id == 9
|
||||
assert pkt.proto_ver == 1
|
||||
assert pkt.flags_raw == 0x06
|
||||
assert pkt.is_leader is False
|
||||
assert pkt.is_valid is True
|
||||
assert pkt.smoothed_used is True
|
||||
assert pkt.local_us == 28_798_450
|
||||
assert pkt.epoch_us == 27_634_885
|
||||
assert pkt.sequence == 20
|
||||
# Recovered offset matches §A0.10's measured 1.16-second boot delta.
|
||||
assert pkt.local_us - pkt.epoch_us == 1_163_565
|
||||
|
|
|
|||
|
|
@ -425,4 +425,47 @@ mod tests {
|
|||
assert_eq!(pkt.to_bytes().len(), SYNC_PACKET_SIZE);
|
||||
assert_eq!(SYNC_PACKET_SIZE, 32);
|
||||
}
|
||||
|
||||
/// ADR-110 iter 21 — cross-language wire-format conformance gate.
|
||||
///
|
||||
/// These exact bytes are ALSO pinned in the Python test
|
||||
/// `test_canonical_wire_bytes_match_rust_decoder` in
|
||||
/// `archive/v1/tests/unit/test_esp32_binary_parser.py`. If this
|
||||
/// canonical hex stops matching what Python emits for the same
|
||||
/// SyncPacket fields, ONE of the decoders has drifted from the wire.
|
||||
///
|
||||
/// Canonical packet: COM9 sync-pkt #1 from §A0.12 live capture.
|
||||
#[test]
|
||||
fn canonical_wire_bytes_match_python_decoder() {
|
||||
// Exact bytes matching the Python pin (hex-decoded by hand to bytes).
|
||||
let canonical: [u8; 32] = [
|
||||
0x10, 0xa1, 0x11, 0xc5, // magic 0xC511A110 (LE u32)
|
||||
0x09, // node_id = 9
|
||||
0x01, // proto_ver = 1
|
||||
0x06, // flags: bit1=is_valid, bit2=smoothed_used
|
||||
0x00, // reserved
|
||||
0xf2, 0x6d, 0xb7, 0x01, 0x00, 0x00, 0x00, 0x00, // local_us = 28_798_450
|
||||
0xc5, 0xac, 0xa5, 0x01, 0x00, 0x00, 0x00, 0x00, // epoch_us = 27_634_885
|
||||
0x14, 0x00, 0x00, 0x00, // sequence = 20
|
||||
0x00, 0x00, 0x00, 0x00, // reserved
|
||||
];
|
||||
let decoded = SyncPacket::from_bytes(&canonical).unwrap();
|
||||
assert_eq!(decoded.node_id, 9);
|
||||
assert_eq!(decoded.proto_ver, 1);
|
||||
assert_eq!(decoded.flags.to_byte(), 0x06);
|
||||
assert!(!decoded.flags.is_leader);
|
||||
assert!(decoded.flags.is_valid);
|
||||
assert!(decoded.flags.smoothed_used);
|
||||
assert_eq!(decoded.local_us, 28_798_450);
|
||||
assert_eq!(decoded.epoch_us, 27_634_885);
|
||||
assert_eq!(decoded.sequence, 20);
|
||||
// §A0.10's measured 1.16-second boot delta.
|
||||
assert_eq!(decoded.local_minus_epoch_us(), 1_163_565);
|
||||
|
||||
// Round-trip: re-encoding the decoded struct must produce the same
|
||||
// canonical bytes — this is what catches any drift in to_bytes.
|
||||
let re_encoded = decoded.to_bytes();
|
||||
assert_eq!(re_encoded, canonical,
|
||||
"Rust to_bytes drifted from the canonical pin — Python decoder will break");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue