#[cfg(test)]
mod tests {
use async_nats::{jetstream, HeaderMap};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
struct TestMessage {
id: String,
content: String,
value: i32,
}
impl TestMessage {
fn new(id: &str, content: &str, value: i32) -> Self {
Self {
id: id.to_string(),
content: content.to_string(),
value,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
struct ComplexMessage {
id: u64,
metadata: std::collections::HashMap<String, String>,
tags: Vec<String>,
nested: NestedData,
optional_field: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
struct NestedData {
timestamp: String,
status: String,
count: usize,
}
impl ComplexMessage {
fn new(id: u64) -> Self {
let mut metadata = std::collections::HashMap::new();
metadata.insert("type".to_string(), "test".to_string());
metadata.insert("version".to_string(), "1.0".to_string());
Self {
id,
metadata,
tags: vec!["urgent".to_string(), "test".to_string()],
nested: NestedData {
timestamp: "2024-01-01T00:00:00Z".to_string(),
status: "active".to_string(),
count: 42,
},
optional_field: Some("optional_value".to_string()),
}
}
}
#[test]
fn test_message_serialization_basic() {
let message = TestMessage::new("test-001", "basic test message", 123);
let serialized = serde_json::to_vec(&message).unwrap();
assert!(!serialized.is_empty());
let json_str = String::from_utf8(serialized.clone()).unwrap();
assert!(json_str.contains("test-001"));
assert!(json_str.contains("basic test message"));
assert!(json_str.contains("123"));
let deserialized: TestMessage = serde_json::from_slice(&serialized).unwrap();
assert_eq!(deserialized, message);
}
#[test]
fn test_message_serialization_complex() {
let message = ComplexMessage::new(9999);
let serialized = serde_json::to_vec(&message).unwrap();
assert!(!serialized.is_empty());
let json_str = String::from_utf8(serialized.clone()).unwrap();
assert!(json_str.contains("9999"));
assert!(json_str.contains("test"));
assert!(json_str.contains("1.0"));
assert!(json_str.contains("urgent"));
assert!(json_str.contains("2024-01-01T00:00:00Z"));
assert!(json_str.contains("active"));
assert!(json_str.contains("42"));
assert!(json_str.contains("optional_value"));
let deserialized: ComplexMessage = serde_json::from_slice(&serialized).unwrap();
assert_eq!(deserialized, message);
}
#[test]
fn test_message_serialization_edge_cases() {
let empty_message = TestMessage::new("", "", 0);
let serialized = serde_json::to_vec(&empty_message).unwrap();
assert!(!serialized.is_empty());
let large_message = TestMessage::new(
"large-id-with-many-characters-to-test-serialization-limits",
&"x".repeat(1000),
i32::MAX,
);
let serialized = serde_json::to_vec(&large_message).unwrap();
assert!(serialized.len() > 1000);
let negative_message = TestMessage::new("neg", "negative test", -42);
let serialized = serde_json::to_vec(&negative_message).unwrap();
let json_str = String::from_utf8(serialized).unwrap();
assert!(json_str.contains("-42"));
}
#[test]
fn test_message_serialization_with_special_characters() {
let special_message = TestMessage::new(
"id-with-uuid-12345678-1234-1234-1234-123456789abc",
"content with special chars: áéÃóú ñü €£¥ 䏿–‡ 🚀",
777,
);
let serialized = serde_json::to_vec(&special_message).unwrap();
assert!(!serialized.is_empty());
let deserialized: TestMessage = serde_json::from_slice(&serialized).unwrap();
assert_eq!(deserialized, special_message);
assert!(deserialized.content.contains("áéÃóú"));
assert!(deserialized.content.contains("䏿–‡"));
assert!(deserialized.content.contains("🚀"));
}
#[test]
fn test_optional_fields_serialization() {
let mut message_with_optional = ComplexMessage::new(1);
message_with_optional.optional_field = Some("present_value".to_string());
let serialized = serde_json::to_vec(&message_with_optional).unwrap();
let json_str = String::from_utf8(serialized.clone()).unwrap();
assert!(json_str.contains("present_value"));
message_with_optional.optional_field = None;
let serialized = serde_json::to_vec(&message_with_optional).unwrap();
let json_str = String::from_utf8(serialized.clone()).unwrap();
assert!(json_str.contains("null"));
let deserialized: ComplexMessage = serde_json::from_slice(&serialized).unwrap();
assert_eq!(deserialized.optional_field, None);
}
#[test]
fn test_vector_and_map_serialization() {
let mut message = ComplexMessage::new(2);
message.tags.clear();
message.metadata.clear();
let serialized = serde_json::to_vec(&message).unwrap();
let json_str = String::from_utf8(serialized.clone()).unwrap();
assert!(json_str.contains("[]")); assert!(json_str.contains("{}"));
message.tags = vec!["tag1".to_string(), "tag2".to_string(), "tag3".to_string()];
message
.metadata
.insert("key1".to_string(), "value1".to_string());
message
.metadata
.insert("key2".to_string(), "value2".to_string());
message
.metadata
.insert("key3".to_string(), "value3".to_string());
let serialized = serde_json::to_vec(&message).unwrap();
let json_str = String::from_utf8(serialized).unwrap();
assert!(json_str.contains("tag1"));
assert!(json_str.contains("tag2"));
assert!(json_str.contains("tag3"));
assert!(json_str.contains("key1"));
assert!(json_str.contains("value1"));
assert!(json_str.contains("key2"));
assert!(json_str.contains("value2"));
}
#[test]
fn test_header_map_functionality() {
let mut headers = HeaderMap::new();
assert_eq!(headers.len(), 0);
headers.insert("Content-Type", "application/json");
headers.insert("X-Request-ID", "req-12345");
headers.insert("X-Tenant", "tenant-abc");
assert_eq!(headers.len(), 3);
assert_eq!(
headers.get("Content-Type").unwrap().as_str(),
"application/json"
);
assert_eq!(headers.get("X-Request-ID").unwrap().as_str(), "req-12345");
assert_eq!(headers.get("X-Tenant").unwrap().as_str(), "tenant-abc");
assert!(headers.get("Non-Existent").is_none());
assert!(headers.get("content-type").is_none()); assert!(headers.get("CONTENT-TYPE").is_none()); }
#[test]
fn test_header_map_special_values() {
let mut headers = HeaderMap::new();
headers.insert("X-Empty", "");
headers.insert("X-Number", "42");
headers.insert("X-UUID", "12345678-1234-1234-1234-123456789abc");
headers.insert("X-Special-Chars", "value with spaces and symbols: !@#$%");
headers.insert("X-Unicode", "值 with 䏿–‡ and émojis 🎉");
assert_eq!(headers.get("X-Empty").unwrap().as_str(), "");
assert_eq!(headers.get("X-Number").unwrap().as_str(), "42");
assert!(headers.get("X-UUID").unwrap().as_str().contains("12345678"));
assert!(headers
.get("X-Special-Chars")
.unwrap()
.as_str()
.contains("!@#$%"));
assert!(headers.get("X-Unicode").unwrap().as_str().contains("䏿–‡"));
assert!(headers.get("X-Unicode").unwrap().as_str().contains("🎉"));
}
#[test]
fn test_subject_string_validation() {
let valid_subjects = vec![
"smith.intents.raw.fs.read.v1",
"smith.results.intent-123",
"smith.audit.execution.intent-456",
"simple",
"test.subject.with.many.segments",
"subject_with_underscores",
"subject-with-dashes",
"MixedCase.Subject",
"subject.123.with.numbers",
];
for subject in valid_subjects {
assert!(!subject.is_empty());
assert!(!subject.starts_with('.'));
assert!(!subject.ends_with('.'));
let subject_string = subject.to_string();
assert_eq!(subject, subject_string);
}
}
#[test]
fn test_raw_payload_variations() {
let payloads = [
Vec::new(),
"Hello, World!".as_bytes().to_vec(),
serde_json::to_vec(&serde_json::json!({
"type": "event",
"data": "test_data",
"timestamp": "2024-01-01T00:00:00Z"
}))
.unwrap(),
vec![0x00, 0x01, 0x02, 0x03, 0xFF, 0xEE, 0xDD, 0xCC],
vec![0x42; 10000],
"Test with special chars: áéÃóú ñü 䏿–‡ 🚀"
.as_bytes()
.to_vec(),
];
for (i, payload) in payloads.iter().enumerate() {
if i == 0 {
assert_eq!(payload.len(), 0);
} else {
assert!(!payload.is_empty());
}
let cloned_payload = payload.clone();
assert_eq!(payload, &cloned_payload);
}
}
#[test]
fn test_serialization_performance_characteristics() {
let small_message = TestMessage::new("small", "x", 1);
let medium_message = TestMessage::new(&"medium".repeat(10), &"x".repeat(100), 1000);
let large_message = TestMessage::new(&"large".repeat(100), &"x".repeat(10000), 1000000);
let small_serialized = serde_json::to_vec(&small_message).unwrap();
let medium_serialized = serde_json::to_vec(&medium_message).unwrap();
let large_serialized = serde_json::to_vec(&large_message).unwrap();
assert!(small_serialized.len() < medium_serialized.len());
assert!(medium_serialized.len() < large_serialized.len());
let _: TestMessage = serde_json::from_slice(&small_serialized).unwrap();
let _: TestMessage = serde_json::from_slice(&medium_serialized).unwrap();
let _: TestMessage = serde_json::from_slice(&large_serialized).unwrap();
}
#[test]
fn test_error_handling_scenarios() {
use std::collections::HashMap;
let float_values = vec![
0.0,
-0.0,
1.0,
-1.0,
f64::MIN,
f64::MAX,
];
for value in float_values {
let result = serde_json::to_vec(&value);
assert!(result.is_ok(), "Failed to serialize float value: {}", value);
}
let mut large_map = HashMap::new();
for i in 0..1000 {
large_map.insert(format!("key_{}", i), format!("value_{}", i));
}
let result = serde_json::to_vec(&large_map);
assert!(result.is_ok());
assert!(result.unwrap().len() > 10000); }
#[test]
fn test_publisher_struct_properties() {
use crate::Publisher;
fn _compile_time_api_check() {
let _ = Publisher::new as fn(jetstream::Context) -> Publisher;
}
}
#[test]
fn test_anyhow_result_usage() {
use anyhow::{Context, Result};
fn test_context_usage() -> Result<()> {
let payload = serde_json::to_vec(&"test").context("Failed to serialize message")?;
assert!(!payload.is_empty());
Ok(())
}
let result = test_context_usage();
assert!(result.is_ok());
}
#[test]
fn test_tracing_debug_compatibility() {
let subject = "test.subject.example";
let sequence = 12345u64;
let debug_msg = format!("Publishing message to subject: {}", subject);
assert!(debug_msg.contains("test.subject.example"));
let sequence_msg = format!(
"Message published to {} with sequence: {}",
subject, sequence
);
assert!(sequence_msg.contains("12345"));
}
#[test]
fn test_payload_conversion() {
let test_data = vec![0x01, 0x02, 0x03, 0xFF];
assert_eq!(test_data.len(), 4);
assert_eq!(test_data[0], 0x01);
assert_eq!(test_data[3], 0xFF);
let slice_data: &[u8] = &test_data;
assert_eq!(slice_data, test_data.as_slice());
let cloned_data = test_data.clone();
assert_eq!(cloned_data, test_data);
}
#[test]
fn test_error_context_formatting() {
use anyhow::Context;
let subject = "test.subject.error";
let error = std::io::Error::new(std::io::ErrorKind::PermissionDenied, "test error");
let result: anyhow::Result<()> = Err(error)
.with_context(|| format!("Failed to publish message to subject: {}", subject));
assert!(result.is_err());
let error_string = result.unwrap_err().to_string();
assert!(error_string.contains("Failed to publish message to subject"));
assert!(error_string.contains("test.subject.error"));
}
#[test]
fn test_sequence_number_handling() {
let test_sequences = [1u64, 42u64, 12345u64, u64::MAX];
for sequence in test_sequences {
assert_ne!(sequence, 0, "Sequence numbers should be positive");
let debug_msg = format!("Raw message published with sequence: {}", sequence);
assert!(!debug_msg.is_empty());
}
}
#[test]
fn test_concurrent_serialization_safety() {
use std::sync::Arc;
use std::thread;
let message = Arc::new(TestMessage::new("concurrent", "test", 42));
let mut handles = vec![];
for i in 0..5 {
let msg = message.clone();
let handle = thread::spawn(move || {
let serialized = serde_json::to_vec(&*msg).unwrap();
assert!(!serialized.is_empty());
(i, serialized.len())
});
handles.push(handle);
}
for handle in handles {
let (thread_id, size) = handle.join().unwrap();
assert!(size > 0);
assert!(thread_id < 5);
}
}
#[test]
fn test_memory_efficiency() {
let message = ComplexMessage::new(12345);
let serialized = serde_json::to_vec(&message).unwrap();
let json_string = serde_json::to_string(&message).unwrap();
assert_eq!(serialized.len(), json_string.len());
let deserialized: ComplexMessage = serde_json::from_slice(&serialized).unwrap();
assert_eq!(deserialized.id, 12345);
}
#[test]
fn test_publisher_clone_trait() {
fn assert_clone<T: Clone>() {}
assert_clone::<crate::Publisher>();
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<crate::Publisher>();
}
#[test]
fn test_serialization_edge_cases() {
#[derive(serde::Serialize)]
struct EmptyStruct {}
let empty = EmptyStruct {};
let serialized = serde_json::to_vec(&empty).unwrap();
assert_eq!(serialized, b"{}");
#[derive(serde::Serialize)]
struct WithOptional {
value: Option<String>,
}
let with_none = WithOptional { value: None };
let serialized = serde_json::to_vec(&with_none).unwrap();
assert!(String::from_utf8(serialized).unwrap().contains("null"));
let with_some = WithOptional {
value: Some("test".to_string()),
};
let serialized = serde_json::to_vec(&with_some).unwrap();
assert!(String::from_utf8(serialized).unwrap().contains("test"));
}
#[test]
fn test_large_message_handling() {
let large_content = "x".repeat(50000); let large_message = TestMessage::new("large", &large_content, 999);
let serialized = serde_json::to_vec(&large_message).unwrap();
assert!(serialized.len() > 50000);
let deserialized: TestMessage = serde_json::from_slice(&serialized).unwrap();
assert_eq!(deserialized.content.len(), 50000);
assert_eq!(deserialized.value, 999);
}
}