Merge branch 'gemini/ticket-tests': ticket codec + gossip wire-type unit tests
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -285,3 +285,53 @@ impl RoomState for IrohGossipState {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::network::PeerState;
|
||||
use iroh::SecretKey;
|
||||
|
||||
fn sample_peer_state() -> PeerState {
|
||||
let secret = SecretKey::generate();
|
||||
let public = secret.public();
|
||||
let addr = iroh::EndpointAddr::from(public);
|
||||
PeerState {
|
||||
name: "TestPeerGossip".to_string(),
|
||||
is_muted: true,
|
||||
addr,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gossip_message_leave_round_trip() {
|
||||
let original = GossipMessage::Leave;
|
||||
let serialized = serde_json::to_string(&original).unwrap();
|
||||
let deserialized: GossipMessage = serde_json::from_str(&serialized).unwrap();
|
||||
assert!(matches!(deserialized, GossipMessage::Leave));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gossip_payload_announce_round_trip() {
|
||||
let peer_state = sample_peer_state();
|
||||
let author = peer_state.addr.id;
|
||||
let payload = GossipPayload {
|
||||
author,
|
||||
msg: GossipMessage::Announce(peer_state.clone()),
|
||||
};
|
||||
|
||||
let serialized = serde_json::to_string(&payload).unwrap();
|
||||
let deserialized: GossipPayload = serde_json::from_str(&serialized).unwrap();
|
||||
|
||||
assert_eq!(deserialized.author, author);
|
||||
match deserialized.msg {
|
||||
GossipMessage::Announce(state) => {
|
||||
assert_eq!(state, peer_state);
|
||||
}
|
||||
GossipMessage::Leave => {
|
||||
panic!("Expected GossipMessage::Announce, got Leave");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,3 +139,63 @@ pub trait RoomState: Send + Sync {
|
||||
|
||||
pub mod iroh_impl;
|
||||
pub mod gossip;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use iroh::{SecretKey, EndpointAddr};
|
||||
|
||||
fn sample_peer_state() -> PeerState {
|
||||
let secret = SecretKey::generate();
|
||||
let public = secret.public();
|
||||
let addr = EndpointAddr::from(public);
|
||||
PeerState {
|
||||
name: "TestPeer".to_string(),
|
||||
is_muted: false,
|
||||
addr,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ticket_round_trip() {
|
||||
let state = sample_peer_state();
|
||||
let topic_id = [7u8; 32];
|
||||
let original_ticket = PeerSpeakTicket {
|
||||
host_addr: state.addr.clone(),
|
||||
topic_id,
|
||||
};
|
||||
let ticket_str = original_ticket.to_string();
|
||||
let parsed_ticket = ticket_str.parse::<PeerSpeakTicket>().unwrap();
|
||||
assert_eq!(parsed_ticket.host_addr.id, original_ticket.host_addr.id);
|
||||
assert_eq!(parsed_ticket.topic_id, original_ticket.topic_id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_malformed_rejection() {
|
||||
// empty string
|
||||
let res1 = "".parse::<PeerSpeakTicket>();
|
||||
assert!(matches!(res1, Err(NetError::InvalidTicket(_))));
|
||||
|
||||
// non-base64 garbage
|
||||
let res2 = "!!!not base64!!!".parse::<PeerSpeakTicket>();
|
||||
assert!(matches!(res2, Err(NetError::InvalidTicket(_))));
|
||||
|
||||
// valid URL-safe-base64 that decodes to non-JSON bytes
|
||||
let bad_json = b"hello world";
|
||||
let encoded = base64::Engine::encode(
|
||||
&base64::engine::general_purpose::URL_SAFE_NO_PAD,
|
||||
bad_json,
|
||||
);
|
||||
let res3 = encoded.parse::<PeerSpeakTicket>();
|
||||
assert!(matches!(res3, Err(NetError::InvalidTicket(_))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_peer_state_serde_round_trip() {
|
||||
let original = sample_peer_state();
|
||||
let serialized = serde_json::to_string(&original).unwrap();
|
||||
let deserialized: PeerState = serde_json::from_str(&serialized).unwrap();
|
||||
assert_eq!(original, deserialized);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user