use crate::carrier::{
CarrierRefusal, FrameDecoder, MAX_CARRIER_FRAME_BYTES, OpaqueBytes, decode_envelope,
encode_frame,
};
#[test]
fn envelope_is_big_endian_and_preserves_empty_and_opaque_payloads() {
assert_eq!(encode_frame(&[]), Ok(vec![0, 0, 0, 0]));
let payload = [0x1f, 0x8b, 0x08, 0x00, 0xff, 0x00];
let encoded = encode_frame(&payload);
assert_eq!(
encoded,
Ok(vec![0, 0, 0, 6, 0x1f, 0x8b, 0x08, 0x00, 0xff, 0x00])
);
if let Ok(envelope) = encoded {
assert_eq!(
decode_envelope(&envelope),
Ok(OpaqueBytes::from(&payload[..]))
);
}
}
#[test]
fn strict_decoder_reports_every_truncated_prefix_length() {
let prefix = [0, 0, 0, 1];
for received in 0..4 {
assert_eq!(
decode_envelope(&prefix[..received]),
Err(CarrierRefusal::TruncatedLengthPrefix { received })
);
}
}
#[test]
fn strict_decoder_distinguishes_short_and_trailing_bodies() {
assert_eq!(
decode_envelope(&[0, 0, 0, 3, 1, 2]),
Err(CarrierRefusal::TruncatedFrame {
announced: 3,
received: 2,
})
);
assert_eq!(
decode_envelope(&[0, 0, 0, 1, 7, 8]),
Err(CarrierRefusal::TrailingFrameBytes {
announced: 1,
received: 2,
})
);
}
#[test]
fn incremental_decoder_handles_arbitrary_splits_and_concatenated_stream_frames() {
let first = encode_frame(&[1, 2, 3]);
let second = encode_frame(&[4, 5]);
let (Ok(first), Ok(second)) = (first, second) else {
return;
};
let stream: Vec<u8> = first.into_iter().chain(second).collect();
let mut decoder = FrameDecoder::new();
let mut frames = Vec::new();
for byte in &stream {
if let Ok(decoded) = decoder.push(std::slice::from_ref(byte)) {
frames.extend(decoded);
}
}
assert_eq!(
frames,
vec![
OpaqueBytes::from(&[1, 2, 3][..]),
OpaqueBytes::from(&[4, 5][..])
]
);
assert_eq!(decoder.finish(), Ok(()));
}
#[test]
fn oversized_prefix_is_refused_before_payload_allocation_and_is_fatal() {
let announced = u32::try_from(MAX_CARRIER_FRAME_BYTES + 1).unwrap_or(u32::MAX);
let mut decoder = FrameDecoder::new();
let refusal = CarrierRefusal::FrameTooLarge {
announced,
maximum: MAX_CARRIER_FRAME_BYTES,
};
assert_eq!(decoder.push(&announced.to_be_bytes()), Err(refusal));
assert_eq!(decoder.payload_allocation_count(), 0);
assert_eq!(decoder.buffered_payload_capacity(), 0);
assert_eq!(decoder.push(&[0, 0, 0, 0]), Err(refusal));
assert_eq!(decoder.finish(), Err(refusal));
}
#[test]
fn truncated_incremental_body_becomes_fatal_at_end_of_input() {
let mut decoder = FrameDecoder::new();
assert_eq!(decoder.push(&[0, 0, 0, 2, 9]), Ok(Vec::new()));
let refusal = CarrierRefusal::TruncatedFrame {
announced: 2,
received: 1,
};
assert_eq!(decoder.finish(), Err(refusal));
assert_eq!(decoder.push(&[10]), Err(refusal));
}