#![cfg(not(loom))]
use std::io;
use wireframe::codec::examples::HotlineFrameCodec;
use wireframe_testing::{
correlated_hotline_wire,
decode_frames_with_codec,
mismatched_total_size_wire,
oversized_hotline_wire,
sequential_hotline_wire,
truncated_hotline_header,
truncated_hotline_payload,
valid_hotline_frame,
valid_hotline_wire,
};
fn hotline_codec() -> HotlineFrameCodec { HotlineFrameCodec::new(4096) }
fn assert_decode_fails_with(wire: Vec<u8>, expected_error_substring: &str) -> io::Result<()> {
let codec = hotline_codec();
let result = decode_frames_with_codec(&codec, wire);
let err = result
.err()
.ok_or_else(|| io::Error::other("expected decode to fail but it succeeded"))?;
if !err.to_string().contains(expected_error_substring) {
return Err(io::Error::other(format!(
"expected error containing '{expected_error_substring}', got: {err}"
)));
}
Ok(())
}
fn assert_frame_count(
frames: &[wireframe::codec::examples::HotlineFrame],
expected: usize,
) -> io::Result<()> {
if frames.len() != expected {
return Err(io::Error::other(format!(
"expected {expected} frame(s), got {}",
frames.len()
)));
}
Ok(())
}
#[test]
fn valid_hotline_wire_decodes_successfully() -> io::Result<()> {
let wire = valid_hotline_wire(b"hello", 7);
let codec = hotline_codec();
let frames = decode_frames_with_codec(&codec, wire)?;
assert_frame_count(&frames, 1)?;
let frame = frames
.first()
.ok_or_else(|| io::Error::other("expected one decoded frame"))?;
if frame.transaction_id != 7 {
return Err(io::Error::other(format!(
"expected transaction_id 7, got {}",
frame.transaction_id
)));
}
if frame.payload.as_ref() != b"hello" {
return Err(io::Error::other("payload mismatch"));
}
Ok(())
}
#[test]
fn valid_hotline_frame_has_correct_metadata() {
let frame = valid_hotline_frame(b"data", 42);
assert_eq!(frame.transaction_id, 42);
assert_eq!(frame.payload.as_ref(), b"data");
}
#[test]
fn oversized_hotline_wire_rejected_by_decoder() -> io::Result<()> {
let wire = oversized_hotline_wire(4096);
assert_decode_fails_with(wire, "payload too large")
}
#[test]
fn mismatched_total_size_rejected_by_decoder() -> io::Result<()> {
let wire = mismatched_total_size_wire(b"test");
assert_decode_fails_with(wire, "invalid total size")
}
#[test]
fn truncated_header_produces_decode_error() -> io::Result<()> {
let wire = truncated_hotline_header();
assert_decode_fails_with(wire, "bytes remaining")
}
#[test]
fn truncated_payload_produces_decode_error() -> io::Result<()> {
let wire = truncated_hotline_payload(100);
assert_decode_fails_with(wire, "bytes remaining")
}
fn assert_transaction_ids(
frames: &[wireframe::codec::examples::HotlineFrame],
expected_ids: &[u32],
) -> io::Result<()> {
assert_frame_count(frames, expected_ids.len())?;
for (i, (frame, expected_id)) in frames.iter().zip(expected_ids.iter()).enumerate() {
if frame.transaction_id != *expected_id {
return Err(io::Error::other(format!(
"frame {i}: expected transaction_id {expected_id}, got {}",
frame.transaction_id
)));
}
}
Ok(())
}
#[test]
fn correlated_frames_share_transaction_id() -> io::Result<()> {
let wire = correlated_hotline_wire(42, &[b"a", b"b", b"c"]);
let codec = hotline_codec();
let frames = decode_frames_with_codec(&codec, wire)?;
assert_frame_count(&frames, 3)?;
assert_transaction_ids(&frames, &[42, 42, 42])
}
#[test]
fn sequential_frames_have_incrementing_ids() -> io::Result<()> {
let wire = sequential_hotline_wire(10, &[b"x", b"y", b"z"]);
let codec = hotline_codec();
let frames = decode_frames_with_codec(&codec, wire)?;
assert_frame_count(&frames, 3)?;
assert_transaction_ids(&frames, &[10, 11, 12])
}