diff --git a/Cargo.toml b/Cargo.toml index 40b1512..549c644 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ description = "MUC implementation allowing participants to play the Hanabi game. [dependencies] async-trait = "^0.1" +chrono = "0.4.22" env_logger = "^0.9" futures = "^0.3" lazy_static = "^1.4" diff --git a/src/component.rs b/src/component.rs index fc0bcdd..7822304 100644 --- a/src/component.rs +++ b/src/component.rs @@ -75,11 +75,15 @@ impl Component { } } -#[derive(Debug)] +enum Expect { + Element(Element), + Callback(Box), +} + pub struct TestComponent { in_buffer: Vec, out_buffer: Vec, - expect_buffer: Vec, + expect_buffer: Vec, } impl TestComponent { @@ -93,7 +97,12 @@ impl TestComponent { /// Adds elements to be expected, in the order they're being added pub fn expect>(&mut self, el: E) { - self.expect_buffer.push(el.into()) + self.expect_buffer.push(Expect::Element(el.into())) + } + + pub fn expect_with(&mut self, callback: F) { + self.expect_buffer + .push(Expect::Callback(Box::new(callback))) } /// Asserts expected output and actual output are the same @@ -104,11 +113,15 @@ impl TestComponent { match (out, expected) { (None, None) => break, - (Some(out), Some(expected)) => { - assert_eq!(String::from(&expected), String::from(&out)) - } - (Some(out), None) => assert_eq!(format!(""), String::from(&out)), - (None, Some(expected)) => assert_eq!(String::from(&expected), format!("")), + (Some(out), Some(expected)) => match expected { + Expect::Element(el) => assert_eq!(String::from(&el), String::from(&out)), + Expect::Callback(cb) => cb(out), + }, + (Some(out), None) => panic!("Missing matching expected element: {:?}", out), + (None, Some(expected)) => match expected { + Expect::Element(el) => panic!("Missing matching sent element: {:?}", el), + Expect::Callback(_) => panic!("Missing matching sent element"), + }, } } } diff --git a/src/tests.rs b/src/tests.rs index 2e996d1..b9e5e6e 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -22,6 +22,7 @@ use std::str::FromStr; use lazy_static::lazy_static; use xmpp_parsers::{ + delay::Delay, iq::{Iq, IqType}, message::{Message, MessageType, Subject as MessageSubject}, muc::{ @@ -105,18 +106,35 @@ async fn test_0045_join_presence_empty_room() { .into()]), ); - let mut subjects = BTreeMap::new(); - subjects.insert(String::from("en"), MessageSubject::from_str("").unwrap()); - component.expect(Message { - // Set by the first participant - from: Some(Jid::Full(to)), - to: Some(Jid::Full(from)), - id: None, - type_: MessageType::Groupchat, - bodies: BTreeMap::new(), - subjects, - thread: None, - payloads: Vec::new(), + component.expect_with(move |el| { + let roomjid = COMPONENT_JID.clone().with_node("room"); + + let mut subjects = BTreeMap::new(); + subjects.insert(String::from("en"), MessageSubject::from_str("").unwrap()); + let expected: Element = Message { + // Set by the first participant + from: Some(Jid::Full(to)), + to: Some(Jid::Full(from)), + id: None, + type_: MessageType::Groupchat, + bodies: BTreeMap::new(), + subjects, + thread: None, + payloads: Vec::new(), + } + .into(); + + let mut out = Message::try_from(el).unwrap(); + assert_eq!(out.payloads.len(), 1); + let delay = Delay::try_from(out.payloads[0].clone()).unwrap(); + // Ensure delay is issued from the room JID. Ignore stamp as it'll always vary. + assert_eq!(delay.from, Some(Jid::Bare(roomjid))); + + out.payloads = vec![]; + assert_eq!( + String::from(&expected), + String::from(&Into::::into(out)) + ); }); handle_stanza(&mut component, &mut rooms).await.unwrap(); diff --git a/src/types.rs b/src/types.rs index 24b1e0d..e5ffc9f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -19,8 +19,11 @@ use crate::error::Error; use std::collections::HashMap; use std::iter::IntoIterator; +use chrono; use log::debug; use xmpp_parsers::{ + date::DateTime, + delay::Delay, message::{Message, MessageType, Subject}, muc::{ user::{Affiliation, Item as MucItem, Role, Status as MucStatus}, @@ -101,6 +104,12 @@ impl Room { .subjects .insert(String::from("en"), Subject(String::from(""))); subject.type_ = MessageType::Groupchat; + subject.payloads = vec![Delay { + from: Some(Jid::Bare(self.jid.clone())), + stamp: DateTime::from_utc(chrono::Utc::now()), + data: None, + } + .into()]; component.send_stanza(subject).await?; }