diff --git a/v2/crates/wifi-densepose-bfld/tests/frame_trailing_bytes.rs b/v2/crates/wifi-densepose-bfld/tests/frame_trailing_bytes.rs new file mode 100644 index 00000000..3dc11efb --- /dev/null +++ b/v2/crates/wifi-densepose-bfld/tests/frame_trailing_bytes.rs @@ -0,0 +1,105 @@ +//! `BfldFrame::from_bytes` trailing-bytes contract. Pins the current +//! behavior: the parser reads exactly `header.payload_len` bytes after the +//! header and silently ignores anything past `BFLD_HEADER_SIZE + +//! header.payload_len`. This matches how the parser is used in iter-4 +//! through iter-15: callers hand a sliced buffer that may include framing +//! noise (UDP MTU padding, ESP-NOW trailer alignment), and the parser +//! extracts only what the header declares. +//! +//! If a future iter decides to tighten this (reject trailing bytes as +//! `MalformedFrame`), updating this test makes the policy change deliberate +//! and traceable rather than silent. + +#![cfg(feature = "std")] + +use wifi_densepose_bfld::{BfldFrame, BfldFrameHeader, BfldPayload, BFLD_HEADER_SIZE}; + +fn frame_with_typed_payload() -> BfldFrame { + let payload = BfldPayload { + compressed_angle_matrix: vec![0x11; 32], + amplitude_proxy: vec![0x22; 16], + phase_proxy: vec![0x33; 16], + snr_vector: vec![0x44; 8], + csi_delta: None, + vendor_extension: vec![], + }; + BfldFrame::from_payload(BfldFrameHeader::empty(), &payload) +} + +#[test] +fn parser_accepts_buffer_with_one_trailing_byte() { + let frame = frame_with_typed_payload(); + let mut bytes = frame.to_bytes(); + let canonical_len = bytes.len(); + bytes.push(0xFF); + let parsed = BfldFrame::from_bytes(&bytes).expect("trailing byte must be tolerated"); + assert_eq!( + parsed.payload.len(), + { parsed.header.payload_len } as usize, + "parsed payload size must equal header.payload_len, not buffer.len() - HEADER", + ); + // Implicit: the trailing 0xFF byte is NOT in parsed.payload. + assert_ne!(parsed.payload.last().copied(), Some(0xFF)); + let _ = canonical_len; // sanity anchor +} + +#[test] +fn parser_accepts_many_trailing_bytes() { + let frame = frame_with_typed_payload(); + let mut bytes = frame.to_bytes(); + bytes.extend_from_slice(&[0xCC; 256]); + let parsed = BfldFrame::from_bytes(&bytes).expect("256 trailing bytes must be tolerated"); + assert_eq!(parsed.payload.len(), { parsed.header.payload_len } as usize); +} + +#[test] +fn parsed_payload_round_trips_back_to_typed_payload_with_trailing_bytes_present() { + // The trailing-bytes parser leniency must not corrupt the section parser + // downstream. After from_bytes + parse_payload, the typed payload should + // match the original BfldPayload byte-for-byte. + let original_payload = BfldPayload { + compressed_angle_matrix: vec![0x11; 32], + amplitude_proxy: vec![0x22; 16], + phase_proxy: vec![0x33; 16], + snr_vector: vec![0x44; 8], + csi_delta: None, + vendor_extension: vec![], + }; + let frame = BfldFrame::from_payload(BfldFrameHeader::empty(), &original_payload); + let mut bytes = frame.to_bytes(); + bytes.extend_from_slice(&[0xEE; 64]); + let parsed_frame = BfldFrame::from_bytes(&bytes).unwrap(); + let parsed_payload = parsed_frame.parse_payload().expect("typed payload parse"); + assert_eq!(parsed_payload, original_payload); +} + +#[test] +fn header_only_buffer_at_exactly_header_size_with_zero_payload_len_succeeds() { + let header = BfldFrameHeader::empty(); + let frame = BfldFrame::new(header, Vec::new()); + let bytes = frame.to_bytes(); + assert_eq!(bytes.len(), BFLD_HEADER_SIZE, "empty-payload frame is exactly header size"); + let parsed = BfldFrame::from_bytes(&bytes).expect("parse"); + assert!(parsed.payload.is_empty()); +} + +#[test] +fn header_only_buffer_with_trailing_bytes_but_zero_payload_len_ignores_them() { + let header = BfldFrameHeader::empty(); + let frame = BfldFrame::new(header, Vec::new()); + let mut bytes = frame.to_bytes(); + bytes.extend_from_slice(&[0xAA; 100]); + let parsed = BfldFrame::from_bytes(&bytes).expect("parse"); + assert_eq!({ parsed.header.payload_len }, 0); + assert!(parsed.payload.is_empty(), "trailing bytes must not leak into payload"); +} + +#[test] +fn trailing_bytes_do_not_affect_crc_validation_when_payload_intact() { + let frame = frame_with_typed_payload(); + let mut bytes = frame.to_bytes(); + let crc_before_extension = { frame.header.payload_crc32 }; + bytes.extend_from_slice(&[0xFF; 32]); + let parsed = BfldFrame::from_bytes(&bytes).expect("CRC over payload-only must still match"); + assert_eq!({ parsed.header.payload_crc32 }, crc_before_extension); +}