233 lines
5.8 KiB
Rust
233 lines
5.8 KiB
Rust
use super::room::Room;
|
|
use super::event::Event;
|
|
|
|
use rand::{self, Rng};
|
|
use rand::distributions::Alphanumeric;
|
|
use crossbeam_channel::{unbounded, Sender, Receiver};
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct MockRoom {
|
|
since: String,
|
|
room_id: String,
|
|
events_s: Sender<Vec<Event>>,
|
|
events_r: Receiver<Vec<Event>>,
|
|
pub sender: String,
|
|
}
|
|
|
|
impl MockRoom {
|
|
pub fn create(sender: String) -> MockRoom {
|
|
MockRoom::join(sender, rands())
|
|
}
|
|
|
|
pub fn join(sender: String, room_id: String) -> MockRoom {
|
|
let (s, r) = unbounded();
|
|
s.send(vec![]).ok().unwrap();
|
|
let mut mr = MockRoom {
|
|
since: "".to_string(),
|
|
room_id: room_id.clone(),
|
|
events_s: s,
|
|
events_r: r,
|
|
sender: sender,
|
|
};
|
|
mr.send_as(mr.sender.clone(), format!(r#"{{
|
|
"displayname": "{}",
|
|
"membership": "join"
|
|
}}"#, mr.sender.clone())).unwrap();
|
|
mr
|
|
}
|
|
|
|
pub fn room(&self) -> impl Room {
|
|
self.clone()
|
|
}
|
|
|
|
pub fn send_as(&mut self, id: String, message: String) -> Result<String, &str> {
|
|
let since = rands();
|
|
let e = Event{
|
|
sender: id,
|
|
since: since.clone(),
|
|
body: message,
|
|
};
|
|
let mut events = self.events_r.recv().ok().unwrap();
|
|
events.push(e);
|
|
self.events_s.send(events).ok().unwrap();
|
|
Ok(since.clone())
|
|
}
|
|
|
|
}
|
|
|
|
impl Room for MockRoom {
|
|
fn sync(&mut self) -> Vec<Event> {
|
|
let mut unseen: Vec<Event> = vec![];
|
|
let mut since = self.since.clone();
|
|
let events = self.events_r.recv().ok().unwrap();
|
|
for e in &events {
|
|
if e.since == self.since {
|
|
unseen.clear();
|
|
since = self.since.clone();
|
|
} else {
|
|
unseen.push(e.clone());
|
|
since = e.since.clone();
|
|
}
|
|
}
|
|
self.events_s.send(events).ok().unwrap();
|
|
self.since = since;
|
|
return unseen;
|
|
}
|
|
|
|
fn send(&mut self, message: String) -> Result<String, &str> {
|
|
self.send_as(self.sender.clone(), message)
|
|
}
|
|
|
|
fn room_id(&self) -> String {
|
|
self.room_id.clone()
|
|
}
|
|
|
|
fn rollback(&mut self, since: String) {
|
|
self.since = since;
|
|
}
|
|
|
|
fn since(&self) -> String {
|
|
self.since.clone()
|
|
}
|
|
}
|
|
|
|
impl Drop for MockRoom {
|
|
fn drop(&mut self) {
|
|
println!("MockRoom::drop not impl");
|
|
}
|
|
}
|
|
|
|
pub fn rands() -> String {
|
|
rand::thread_rng()
|
|
.sample_iter(&Alphanumeric)
|
|
.take(10)
|
|
.collect::<String>()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::Room;
|
|
use super::MockRoom;
|
|
use super::Event;
|
|
use super::rands;
|
|
|
|
fn _dummy() -> MockRoom {
|
|
let mut r = MockRoom::create(rands());
|
|
r.since = "1".to_string();
|
|
let mut events = r.events_r.recv().ok().unwrap();
|
|
for i in 0..5 {
|
|
events.push(Event{
|
|
sender: i.to_string(),
|
|
since: i.to_string(),
|
|
body: i.to_string(),
|
|
});
|
|
}
|
|
r.events_s.send(events).ok().unwrap();
|
|
r
|
|
}
|
|
|
|
#[test]
|
|
fn randstest() {
|
|
let a = rands();
|
|
let b = rands();
|
|
assert!(a != b, "a == {} == b == {}", a, b);
|
|
}
|
|
|
|
#[test]
|
|
fn create() {
|
|
let mut r: MockRoom = MockRoom::create(rands());
|
|
println!("{:?}", r.sync());
|
|
}
|
|
|
|
#[test]
|
|
fn join() {
|
|
let rid = "a".to_string();
|
|
let mut r: MockRoom = MockRoom::join(rands(), rid.to_string());
|
|
assert!(r.room_id == rid);
|
|
let events = r.sync();
|
|
let mut found = false;
|
|
for e in &events {
|
|
let j = e.join();
|
|
if j.is_some() {
|
|
found = true;
|
|
}
|
|
}
|
|
assert!(found);
|
|
}
|
|
|
|
#[test]
|
|
fn since_tracking_push_two() {
|
|
let mut r = _dummy();
|
|
r.sync();
|
|
let mut sinces = vec![];
|
|
for _ in 0..10 {
|
|
sinces.push(r.send("0".to_string()).ok().unwrap());
|
|
sinces.push(r.send("0".to_string()).ok().unwrap());
|
|
r.sync();
|
|
assert!(r.since == *sinces.last().unwrap());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn since_tracking_push_one() {
|
|
let mut r = _dummy();
|
|
r.sync();
|
|
let mut sinces = vec![];
|
|
for _ in 0..10 {
|
|
sinces.push(r.send("0".to_string()).ok().unwrap());
|
|
r.sync();
|
|
assert!(r.since == *sinces.last().unwrap());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn since_tracking_push_none() {
|
|
let mut r = _dummy();
|
|
r.sync();
|
|
let mut sinces = vec![];
|
|
sinces.push(r.send("0".to_string()).ok().unwrap());
|
|
assert!(r.sync().len() == 1);
|
|
assert!(r.since == *sinces.last().unwrap(), "after one send: want {:?}, got {:?}: {:?}", *sinces.last().unwrap(), r.since, sinces);
|
|
assert!(r.sync().len() == 0);
|
|
assert!(r.since == *sinces.last().unwrap(), "after no send: want {:?}, got {:?}: {:?}", *sinces.last().unwrap(), r.since, sinces);
|
|
}
|
|
|
|
#[test]
|
|
fn sync() {
|
|
let mut r = _dummy();
|
|
let events = r.sync();
|
|
assert!(events.len() == 3, "want {}, got {}: {:?}", 3, events.len(), events);
|
|
assert!(events[0].sender == "2");
|
|
assert!(events[0].body == "2");
|
|
assert!(events[0].since == "2");
|
|
assert!(r.since == "4", "want since==4, got {}", r.since);
|
|
}
|
|
|
|
#[test]
|
|
fn send() {
|
|
let mut r = _dummy();
|
|
let message = "message".to_string();
|
|
r.sync();
|
|
assert!(r.send(message.clone()).ok().unwrap().len() > 0);
|
|
assert!(r.since == "4");
|
|
let events = r.sync();
|
|
assert!(events.len() == 1);
|
|
assert!(events[0].body == message, "want {}, got {}: {:?}", message, events[0].body, events);
|
|
assert!(r.since != "4");
|
|
}
|
|
|
|
#[test]
|
|
fn rollback() {
|
|
let mut r = _dummy();
|
|
let was = r.since.to_string();
|
|
let events = r.sync();
|
|
assert!(events.len() == 3);
|
|
assert!(r.since == "4");
|
|
r.rollback(was.to_string());
|
|
assert!(r.since == was);
|
|
let events = r.sync();
|
|
assert!(events.len() == 3);
|
|
assert!(r.since == "4");
|
|
}
|
|
}
|