#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_wildcard_matching() {
let matcher = WildcardMatcher::new();
assert!(matcher.pattern_matches("logs.*", "logs.error"));
assert!(matcher.pattern_matches("logs.*", "logs.info"));
assert!(!matcher.pattern_matches("logs.*", "metrics.cpu"));
assert!(matcher.pattern_matches("*.*", "logs.error"));
}
#[test]
fn test_event_store() {
let store = EventStore::new(100);
let topic = Topic("test".to_string());
for i in 0..10 {
let event = Event {
topic: "test".to_string(),
data: serde_json::json!({"index": i}),
timestamp: i,
};
store.store(topic.clone(), event);
}
let replayed = store.replay(&topic, 5);
assert_eq!(replayed.len(), 5);
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod coverage_tests {
use super::*;
#[test]
fn test_topic_creation_and_traits() {
let topic1 = Topic("test.topic".to_string());
let topic2 = Topic("test.topic".to_string());
let topic3 = Topic("other.topic".to_string());
let topic1_clone = topic1.clone();
assert_eq!(topic1_clone.0, topic1.0);
assert_eq!(topic1, topic2);
assert_ne!(topic1, topic3);
let mut map = HashMap::new();
map.insert(topic1.clone(), 1);
assert_eq!(map.get(&topic2), Some(&1));
assert_eq!(map.get(&topic3), None);
let debug_str = format!("{:?}", topic1);
assert!(debug_str.contains("test.topic"));
}
#[test]
fn test_event_creation_and_traits() {
let event = Event {
topic: "test.topic".to_string(),
data: serde_json::json!({"key": "value", "number": 42}),
timestamp: 1234567890,
};
let event_clone = event.clone();
assert_eq!(event_clone.topic, event.topic);
assert_eq!(event_clone.data, event.data);
assert_eq!(event_clone.timestamp, event.timestamp);
let debug_str = format!("{:?}", event);
assert!(debug_str.contains("test.topic"));
let json = serde_json::to_string(&event).unwrap();
let deserialized: Event = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized.topic, event.topic);
assert_eq!(deserialized.timestamp, event.timestamp);
}
#[test]
fn test_pubsub_broker_default() {
let broker = PubSubBroker::default();
let stats = broker.get_topic_stats();
assert!(stats.is_empty());
}
#[test]
fn test_pubsub_broker_unsubscribe_from_nonexistent_topic() {
let broker = PubSubBroker::new();
let agent_id = Uuid::new_v4();
let topic = Topic("nonexistent".to_string());
broker.unsubscribe(agent_id, &topic);
let stats = broker.get_topic_stats();
assert!(stats.is_empty());
}
#[test]
fn test_pubsub_broker_get_topic_stats_with_subscribers() {
let broker = PubSubBroker::new();
let topic1 = Topic("topic.one".to_string());
let topic2 = Topic("topic.two".to_string());
let stats = broker.get_topic_stats();
assert!(stats.is_empty());
broker.topics.entry(topic1.clone()).or_default();
broker.topics.entry(topic2.clone()).or_default();
let stats = broker.get_topic_stats();
assert_eq!(stats.len(), 2);
assert!(stats.contains_key("topic.one"));
assert!(stats.contains_key("topic.two"));
}
#[test]
fn test_topic_stats_traits() {
let stats = TopicStats {
topic_name: "test.topic".to_string(),
subscriber_count: 5,
};
let stats_clone = stats.clone();
assert_eq!(stats_clone.topic_name, stats.topic_name);
assert_eq!(stats_clone.subscriber_count, stats.subscriber_count);
let debug_str = format!("{:?}", stats);
assert!(debug_str.contains("test.topic"));
assert!(debug_str.contains("5"));
}
#[test]
fn test_pubsub_error_display() {
let err = PubSubError::NoSubscribers;
let display_str = format!("{}", err);
assert!(display_str.contains("No subscribers"));
let debug_str = format!("{:?}", err);
assert!(debug_str.contains("NoSubscribers"));
}
#[test]
fn test_pubsub_error_serialization_variant() {
let bad_data = vec![0xFFu8; 16]; let result: Result<String, _> = bincode::deserialize(&bad_data);
if let Err(e) = result {
let pubsub_err = PubSubError::Serialization(e);
let display_str = format!("{}", pubsub_err);
assert!(display_str.contains("Serialization error"));
}
}
#[test]
fn test_wildcard_matcher_default() {
let matcher = WildcardMatcher::default();
assert!(matcher.matches("any.topic").is_empty());
}
#[test]
fn test_wildcard_matcher_add_pattern() {
let mut matcher = WildcardMatcher::new();
let agent1 = Uuid::new_v4();
let agent2 = Uuid::new_v4();
matcher.add_pattern("logs.*".to_string(), agent1);
matcher.add_pattern("metrics.*".to_string(), agent2);
matcher.add_pattern("logs.*".to_string(), agent2);
let logs_agents = matcher.matches("logs.error");
assert!(logs_agents.contains(&agent1));
assert!(logs_agents.contains(&agent2));
assert_eq!(logs_agents.len(), 2);
let metrics_agents = matcher.matches("metrics.cpu");
assert!(metrics_agents.contains(&agent2));
assert_eq!(metrics_agents.len(), 1);
let no_match = matcher.matches("other.topic");
assert!(no_match.is_empty());
}
#[test]
fn test_wildcard_pattern_matching_edge_cases() {
let matcher = WildcardMatcher::new();
assert!(!matcher.pattern_matches("a.b.c", "a.b"));
assert!(!matcher.pattern_matches("a.b", "a.b.c"));
assert!(matcher.pattern_matches("exact.match", "exact.match"));
assert!(matcher.pattern_matches("*.second", "first.second"));
assert!(matcher.pattern_matches("first.*", "first.anything"));
assert!(matcher.pattern_matches("*.*", "any.thing"));
assert!(matcher.pattern_matches("*.*.*", "a.b.c"));
assert!(!matcher.pattern_matches("exact.match", "exact.other"));
}
#[test]
fn test_event_store_trim_on_max_exceeded() {
let store = EventStore::new(5);
let topic = Topic("test".to_string());
for i in 0..10 {
let event = Event {
topic: "test".to_string(),
data: serde_json::json!({"index": i}),
timestamp: i as u64,
};
store.store(topic.clone(), event);
}
let all_events = store.replay(&topic, 0);
assert_eq!(all_events.len(), 5);
let timestamps: Vec<u64> = all_events.iter().map(|e| e.timestamp).collect();
assert!(timestamps.iter().all(|&t| t >= 5));
}
#[test]
fn test_event_store_replay_with_different_topics() {
let store = EventStore::new(100);
let topic1 = Topic("topic1".to_string());
let topic2 = Topic("topic2".to_string());
for i in 0..5 {
let event1 = Event {
topic: "topic1".to_string(),
data: serde_json::json!({"topic": 1, "index": i}),
timestamp: i as u64,
};
store.store(topic1.clone(), event1);
let event2 = Event {
topic: "topic2".to_string(),
data: serde_json::json!({"topic": 2, "index": i}),
timestamp: i as u64,
};
store.store(topic2.clone(), event2);
}
let topic1_events = store.replay(&topic1, 0);
assert_eq!(topic1_events.len(), 5);
assert!(topic1_events.iter().all(|e| e.topic == "topic1"));
let topic2_events = store.replay(&topic2, 0);
assert_eq!(topic2_events.len(), 5);
assert!(topic2_events.iter().all(|e| e.topic == "topic2"));
}
#[test]
fn test_event_store_replay_with_since_filter() {
let store = EventStore::new(100);
let topic = Topic("test".to_string());
for i in 0..10 {
let event = Event {
topic: "test".to_string(),
data: serde_json::json!({"index": i}),
timestamp: i as u64 * 100, };
store.store(topic.clone(), event);
}
let recent_events = store.replay(&topic, 500);
assert_eq!(recent_events.len(), 5);
let all_events = store.replay(&topic, 0);
assert_eq!(all_events.len(), 10);
let future_events = store.replay(&topic, 1000);
assert_eq!(future_events.len(), 0);
}
#[test]
fn test_event_store_empty_replay() {
let store = EventStore::new(100);
let topic = Topic("empty".to_string());
let events = store.replay(&topic, 0);
assert!(events.is_empty());
}
#[test]
fn test_stored_event_clone() {
let event = Event {
topic: "test".to_string(),
data: serde_json::json!({"key": "value"}),
timestamp: 12345,
};
let stored = StoredEvent {
event: event.clone(),
topic: Topic("test".to_string()),
timestamp: 12345,
};
let stored_clone = stored.clone();
assert_eq!(stored_clone.timestamp, stored.timestamp);
assert_eq!(stored_clone.topic, stored.topic);
}
}