test: cover chat wire type + history cap
GossipMessage::Chat serde round-trips (normal, empty strings, u64::MAX ts,
unicode/emoji), GossipPayload{Chat} round-trip, and push_chat history-cap
behaviour (single, below cap order-preserved, above cap drops oldest keeping
the newest CHAT_HISTORY_MAX in order). Gemini, senior-audited.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1553,4 +1553,65 @@ mod tests {
|
||||
Some(Sound::Reconnected)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_push_chat_single() {
|
||||
use super::{push_chat, ChatEntry};
|
||||
let mut messages = Vec::new();
|
||||
let entry = ChatEntry {
|
||||
name: "Alice".to_string(),
|
||||
text: "Hello".to_string(),
|
||||
mine: true,
|
||||
};
|
||||
push_chat(&mut messages, entry);
|
||||
assert_eq!(messages.len(), 1);
|
||||
assert_eq!(messages[0].name, "Alice");
|
||||
assert_eq!(messages[0].text, "Hello");
|
||||
assert!(messages[0].mine);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_push_chat_below_cap() {
|
||||
use super::{push_chat, ChatEntry, CHAT_HISTORY_MAX};
|
||||
let mut messages = Vec::new();
|
||||
for i in 0..CHAT_HISTORY_MAX - 10 {
|
||||
push_chat(
|
||||
&mut messages,
|
||||
ChatEntry {
|
||||
name: format!("User{}", i),
|
||||
text: format!("Msg{}", i),
|
||||
mine: i % 2 == 0,
|
||||
},
|
||||
);
|
||||
}
|
||||
assert_eq!(messages.len(), CHAT_HISTORY_MAX - 10);
|
||||
assert_eq!(messages[0].name, "User0");
|
||||
assert_eq!(messages[0].text, "Msg0");
|
||||
assert_eq!(messages[messages.len() - 1].name, format!("User{}", CHAT_HISTORY_MAX - 11));
|
||||
assert_eq!(messages[messages.len() - 1].text, format!("Msg{}", CHAT_HISTORY_MAX - 11));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_push_chat_above_cap() {
|
||||
use super::{push_chat, ChatEntry, CHAT_HISTORY_MAX};
|
||||
let mut messages = Vec::new();
|
||||
let total_pushes = CHAT_HISTORY_MAX + 5;
|
||||
for i in 0..total_pushes {
|
||||
push_chat(
|
||||
&mut messages,
|
||||
ChatEntry {
|
||||
name: format!("User{}", i),
|
||||
text: format!("Msg{}", i),
|
||||
mine: i % 2 == 0,
|
||||
},
|
||||
);
|
||||
}
|
||||
assert_eq!(messages.len(), CHAT_HISTORY_MAX);
|
||||
// The first 5 should be dropped. First remaining should be index 5.
|
||||
assert_eq!(messages[0].name, "User5");
|
||||
assert_eq!(messages[0].text, "Msg5");
|
||||
// The last remaining should be index total_pushes - 1.
|
||||
assert_eq!(messages[messages.len() - 1].name, format!("User{}", total_pushes - 1));
|
||||
assert_eq!(messages[messages.len() - 1].text, format!("Msg{}", total_pushes - 1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,5 +372,84 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gossip_message_chat_round_trip() {
|
||||
// Test normal chat message
|
||||
let original = GossipMessage::Chat {
|
||||
name: "Alice".to_string(),
|
||||
text: "Hello".to_string(),
|
||||
ts: 123456789,
|
||||
};
|
||||
let serialized = serde_json::to_string(&original).unwrap();
|
||||
let deserialized: GossipMessage = serde_json::from_str(&serialized).unwrap();
|
||||
if let GossipMessage::Chat { name, text, ts } = deserialized {
|
||||
assert_eq!(name, "Alice");
|
||||
assert_eq!(text, "Hello");
|
||||
assert_eq!(ts, 123456789);
|
||||
} else {
|
||||
panic!("Expected GossipMessage::Chat");
|
||||
}
|
||||
|
||||
// Test empty strings and large timestamp
|
||||
let original_empty = GossipMessage::Chat {
|
||||
name: "".to_string(),
|
||||
text: "".to_string(),
|
||||
ts: u64::MAX,
|
||||
};
|
||||
let serialized_empty = serde_json::to_string(&original_empty).unwrap();
|
||||
let deserialized_empty: GossipMessage = serde_json::from_str(&serialized_empty).unwrap();
|
||||
if let GossipMessage::Chat { name, text, ts } = deserialized_empty {
|
||||
assert_eq!(name, "");
|
||||
assert_eq!(text, "");
|
||||
assert_eq!(ts, u64::MAX);
|
||||
} else {
|
||||
panic!("Expected GossipMessage::Chat");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gossip_payload_chat_round_trip() {
|
||||
let peer_state = sample_peer_state();
|
||||
let author = peer_state.addr.id;
|
||||
let payload = GossipPayload {
|
||||
author,
|
||||
msg: GossipMessage::Chat {
|
||||
name: "Bob".to_string(),
|
||||
text: "Hi there".to_string(),
|
||||
ts: 987654321,
|
||||
},
|
||||
};
|
||||
|
||||
let serialized = serde_json::to_string(&payload).unwrap();
|
||||
let deserialized: GossipPayload = serde_json::from_str(&serialized).unwrap();
|
||||
|
||||
assert_eq!(deserialized.author, author);
|
||||
if let GossipMessage::Chat { name, text, ts } = deserialized.msg {
|
||||
assert_eq!(name, "Bob");
|
||||
assert_eq!(text, "Hi there");
|
||||
assert_eq!(ts, 987654321);
|
||||
} else {
|
||||
panic!("Expected GossipMessage::Chat");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gossip_chat_unicode_round_trip() {
|
||||
let original = GossipMessage::Chat {
|
||||
name: "🎙 User".to_string(),
|
||||
text: "héllo 🎙 世界".to_string(),
|
||||
ts: 1717171717,
|
||||
};
|
||||
let serialized = serde_json::to_string(&original).unwrap();
|
||||
let deserialized: GossipMessage = serde_json::from_str(&serialized).unwrap();
|
||||
if let GossipMessage::Chat { name, text, ts } = deserialized {
|
||||
assert_eq!(name, "🎙 User");
|
||||
assert_eq!(text, "héllo 🎙 世界");
|
||||
assert_eq!(ts, 1717171717);
|
||||
} else {
|
||||
panic!("Expected GossipMessage::Chat");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user