mod common;
use common::create_or_get_queue_url;
use proptest::prelude::*;
use std::collections::HashSet;
use crate::common::local_aws_config;
proptest! {
#![proptest_config(ProptestConfig::with_cases(10))]
#[test]
fn prop_send_batch_roundtrip(
messages in prop::collection::vec(
"[a-zA-Z0-9 ]{1,1000}", // Alphanumeric + spaces, 1-1000 chars
1..10usize // 1-9 messages (SQS batch limit is 10)
)
) {
tokio::runtime::Runtime::new().unwrap().block_on(async {
let queue_url = create_or_get_queue_url("test-prop-roundtrip");
let dlq = dlq::DeadLetterQueue::from_config(local_aws_config().await);
let result = dlq.send_batch(&queue_url, &messages).await;
prop_assert!(result.is_ok(), "send_batch should succeed for valid input: {:?}", result);
let receive_output = dlq
.client
.receive_message()
.queue_url(&queue_url)
.max_number_of_messages(10)
.send()
.await
.unwrap();
let received = receive_output.messages.unwrap_or_default();
prop_assert_eq!(
received.len(),
messages.len(),
"Should receive same number of messages as sent"
);
let received_bodies: HashSet<_> =
received.iter()
.map(|m| m.body().unwrap_or("").to_string())
.collect();
let sent_bodies: HashSet<_> =
messages.iter()
.map(|s| s.to_string())
.collect();
prop_assert_eq!(received_bodies, sent_bodies, "Message content should be preserved");
Ok(())
})?;
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(10))]
#[test]
fn prop_send_unicode_content(
messages in prop::collection::vec(
"\\PC{1,500}", // Any unicode character, 1-500 chars
1..5usize // 1-4 messages
)
) {
tokio::runtime::Runtime::new().unwrap().block_on(async {
let queue_url = create_or_get_queue_url("test-prop-unicode");
let dlq = dlq::DeadLetterQueue::from_config(local_aws_config().await);
let result = dlq.send_batch(&queue_url, &messages).await;
prop_assert!(result.is_ok(), "send_batch should handle unicode content");
let receive_output = dlq
.client
.receive_message()
.queue_url(&queue_url)
.max_number_of_messages(10)
.send()
.await
.unwrap();
let received = receive_output.messages.unwrap_or_default();
prop_assert_eq!(received.len(), messages.len(), "Should preserve message count");
let received_bodies: HashSet<_> =
received.iter()
.map(|m| m.body().unwrap_or("").to_string())
.collect();
let sent_bodies: HashSet<_> =
messages.iter()
.map(|s| s.to_string())
.collect();
prop_assert_eq!(received_bodies, sent_bodies, "Unicode content should be preserved exactly");
Ok(())
})?;
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(10))]
#[test]
fn prop_send_various_batch_sizes(
batch_size in 1..10usize,
message_template in "[a-z]{10,50}"
) {
tokio::runtime::Runtime::new().unwrap().block_on(async {
let queue_url = create_or_get_queue_url("test-prop-sizes");
let dlq = dlq::DeadLetterQueue::from_config(local_aws_config().await);
let messages: Vec<String> = (0..batch_size)
.map(|i| format!("{}-{}", message_template, i))
.collect();
let result = dlq.send_batch(&queue_url, &messages).await;
prop_assert!(result.is_ok(), "send_batch should handle batch size {}", batch_size);
let receive_output = dlq
.client
.receive_message()
.queue_url(&queue_url)
.max_number_of_messages(10)
.send()
.await
.unwrap();
let received = receive_output.messages.unwrap_or_default();
prop_assert_eq!(received.len(), batch_size, "Should receive all {} messages", batch_size);
Ok(())
})?;
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(10))]
#[test]
fn prop_send_special_content(
messages in prop::collection::vec(
prop::string::string_regex(
r#"[ \t\n\r\{\}\[\]"'\\]{1,200}"# // Special chars, whitespace, JSON-like
).unwrap(),
1..5usize
).prop_filter("Filter out empty messages", |msgs| msgs.iter().all(|m| !m.is_empty()))
) {
tokio::runtime::Runtime::new().unwrap().block_on(async {
let queue_url = create_or_get_queue_url("test-prop-special");
let dlq = dlq::DeadLetterQueue::from_config(local_aws_config().await);
let result = dlq.send_batch(&queue_url, &messages).await;
prop_assert!(result.is_ok(), "send_batch should handle special characters");
let receive_output = dlq
.client
.receive_message()
.queue_url(&queue_url)
.max_number_of_messages(10)
.send()
.await
.unwrap();
let received = receive_output.messages.unwrap_or_default();
prop_assert_eq!(received.len(), messages.len());
let received_bodies: HashSet<_> =
received.iter()
.map(|m| m.body().unwrap_or("").to_string())
.collect();
let sent_bodies: HashSet<_> =
messages.iter()
.map(|s| s.to_string())
.collect();
prop_assert_eq!(received_bodies, sent_bodies, "Special characters should be preserved");
Ok(())
})?;
}
}