use bytes::Bytes;
use proptest::prelude::*;
use proptest::test_runner::TestRunner;
use vortex_protocol::tlv::download_piece::DownloadPiece;
use vortex_protocol::tlv::Tag;
use vortex_protocol::Vortex;
fn generate_value_bytes(tag: Tag) -> Bytes {
match tag {
Tag::DownloadPiece => {
let task_id = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
let piece_id = 42;
let download_piece = DownloadPiece::new(task_id.to_string(), piece_id);
download_piece.into()
}
Tag::Close => {
vec![].into()
}
Tag::Error => {
format!("{}test error", 1u8).into_bytes().into()
}
Tag::Reserved(_) => {
vec![].into()
}
_ => {
vec![].into()
}
}
}
fn arb_packet() -> impl Strategy<Value = Vortex> {
let arb_tag = prop_oneof![Just(Tag::DownloadPiece), Just(Tag::Close), Just(Tag::Error)];
arb_tag.prop_map(|tag| {
let value = generate_value_bytes(tag);
Vortex::new(tag, value).expect("Failed to create packet")
})
}
fn run_test<F>(test: F)
where
F: Fn(Vortex) -> Result<(), TestCaseError>,
{
let config = ProptestConfig {
max_shrink_iters: 0, cases: 100, failure_persistence: None, ..Default::default()
};
let mut runner = TestRunner::new(config);
runner.run(&arb_packet(), test).unwrap();
}
#[test]
fn test_roundtrip_serialization() {
run_test(|packet| {
let id = packet.id();
let tag = packet.tag();
let length = packet.length();
let serialized: Bytes = packet.into();
let deserialized: Vortex = serialized.try_into().expect("Failed to deserialize packet");
prop_assert_eq!(id, deserialized.id());
prop_assert_eq!(tag, deserialized.tag());
prop_assert_eq!(length, deserialized.length());
Ok(())
});
}
#[test]
fn test_packet_length() {
run_test(|packet| {
let length = packet.length();
let bytes: Bytes = packet.into();
prop_assert_eq!(bytes.len(), length + 6); Ok(())
});
}
#[test]
fn test_packet_value_constraints() {
run_test(|packet| {
let tag = packet.tag();
let bytes: Bytes = packet.into();
prop_assert!(bytes.len() >= 6);
prop_assert!(matches!(
tag,
Tag::DownloadPiece | Tag::PieceContent | Tag::Error | Tag::Close
));
Ok(())
});
}