2020-04-06 11:12:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test_it {
|
|
|
|
#![allow(unused)]
|
|
|
|
|
|
|
|
use std::fs;
|
|
|
|
use std::path::Path;
|
2020-04-06 19:29:38 +00:00
|
|
|
use std::panic;
|
|
|
|
use std::convert::TryFrom;
|
|
|
|
use std::str::FromStr;
|
|
|
|
use std::time::Duration;
|
2020-04-06 11:12:02 +00:00
|
|
|
|
2020-04-06 19:29:38 +00:00
|
|
|
use crate::identifiers::{RoomId, UserId};
|
2020-04-06 13:11:38 +00:00
|
|
|
use crate::events::{
|
|
|
|
collections::all::RoomEvent,
|
|
|
|
room::{
|
|
|
|
power_levels::PowerLevelsEvent,
|
|
|
|
},
|
|
|
|
EventResult, FromRaw, TryFromRaw,
|
|
|
|
};
|
2020-04-06 11:12:02 +00:00
|
|
|
use crate::{AsyncClient, Session, SyncSettings};
|
|
|
|
|
2020-04-06 19:29:38 +00:00
|
|
|
use ansi_term::Colour;
|
2020-04-06 13:11:38 +00:00
|
|
|
use serde_json::Value;
|
2020-04-06 11:12:02 +00:00
|
|
|
use mockito::{mock, Matcher};
|
2020-04-06 13:11:38 +00:00
|
|
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
2020-04-06 11:12:02 +00:00
|
|
|
use url::Url;
|
|
|
|
|
2020-04-06 19:29:38 +00:00
|
|
|
use crate::models::Room;
|
2020-04-06 11:12:02 +00:00
|
|
|
|
2020-04-06 13:11:38 +00:00
|
|
|
#[derive(Default)]
|
2020-04-06 11:12:02 +00:00
|
|
|
pub struct ResponseBuilder {
|
2020-04-06 13:11:38 +00:00
|
|
|
events: Vec<RoomEvent>,
|
2020-04-06 11:12:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct TestRunner {
|
2020-04-06 19:29:38 +00:00
|
|
|
/// Used when testing the whole client
|
2020-04-06 11:12:02 +00:00
|
|
|
client: Option<AsyncClient>,
|
2020-04-06 19:29:38 +00:00
|
|
|
/// Used To test the models
|
|
|
|
room: Option<Room>,
|
|
|
|
/// When testing the models a vec of RoomEvents is needed.
|
|
|
|
events: Vec<RoomEvent>,
|
2020-04-06 11:12:02 +00:00
|
|
|
/// A `Vec` of callbacks that should assert something about the client.
|
|
|
|
///
|
|
|
|
/// The callback should panic if the state is unexpected (use `assert_*!` macro)
|
2020-04-06 19:29:38 +00:00
|
|
|
client_assertions: Vec<fn(&AsyncClient)>,
|
|
|
|
/// A `Vec` of callbacks that should assert something about the room.
|
|
|
|
///
|
|
|
|
/// The callback should panic if the state is unexpected (use `assert_*!` macro)
|
|
|
|
room_assertions: Vec<fn(&Room)>,
|
2020-04-06 11:12:02 +00:00
|
|
|
/// `mokito::Mock`
|
2020-04-06 19:29:38 +00:00
|
|
|
mock: Option<mockito::Mock>,
|
2020-04-06 11:12:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ResponseBuilder {
|
|
|
|
|
|
|
|
/// Creates an `IncomingResponse` to hold events for a sync.
|
2020-04-06 19:29:38 +00:00
|
|
|
pub fn create_sync_response(mut self) -> Self {
|
2020-04-06 11:12:02 +00:00
|
|
|
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Just throw events at the client, not part of a specific response.
|
2020-04-06 13:11:38 +00:00
|
|
|
pub fn create_event_stream(mut self) -> Self {
|
2020-04-06 11:12:02 +00:00
|
|
|
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2020-04-06 19:29:38 +00:00
|
|
|
/// Add an event to the events `Vec`.
|
2020-04-06 13:11:38 +00:00
|
|
|
pub fn add_event_from_file<Ev: TryFromRaw, P: AsRef<Path>>(mut self, path: P, variant: fn(Ev) -> RoomEvent) -> Self {
|
|
|
|
let val = fs::read_to_string(path.as_ref()).expect(&format!("file not found {:?}", path.as_ref()));
|
2020-04-06 19:29:38 +00:00
|
|
|
let event = serde_json::from_str::<ruma_events::EventResult<Ev>>(&val).unwrap().into_result().unwrap();
|
2020-04-06 13:11:38 +00:00
|
|
|
self.add_event(variant(event));
|
2020-04-06 11:12:02 +00:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2020-04-06 13:11:38 +00:00
|
|
|
fn add_event(&mut self, event: RoomEvent) {
|
|
|
|
self.events.push(event)
|
2020-04-06 11:12:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Consumes `ResponseBuilder and returns a `TestRunner`.
|
|
|
|
///
|
|
|
|
/// The `TestRunner` streams the events to the client and enables methods to set assertions
|
|
|
|
/// about the state of the client.
|
2020-04-06 19:29:38 +00:00
|
|
|
pub fn build_responses(mut self, method: &str, path: &str) -> TestRunner {
|
|
|
|
let body = serde_json::to_string(&self.events).unwrap();
|
|
|
|
let mock = Some(mock(method, path)
|
2020-04-06 11:12:02 +00:00
|
|
|
.with_status(200)
|
2020-04-06 19:29:38 +00:00
|
|
|
.with_body(body)
|
|
|
|
.create());
|
2020-04-06 11:12:02 +00:00
|
|
|
|
|
|
|
TestRunner {
|
|
|
|
client: None,
|
2020-04-06 19:29:38 +00:00
|
|
|
room: None,
|
|
|
|
events: Vec::new(),
|
|
|
|
client_assertions: Vec::new(),
|
|
|
|
room_assertions: Vec::new(),
|
2020-04-06 11:12:02 +00:00
|
|
|
mock,
|
|
|
|
}
|
|
|
|
}
|
2020-04-06 19:29:38 +00:00
|
|
|
|
|
|
|
/// Consumes `ResponseBuilder and returns a `TestRunner`.
|
|
|
|
///
|
|
|
|
/// The `TestRunner` streams the events to the client and enables methods to set assertions
|
|
|
|
/// about the state of the client.
|
|
|
|
pub fn build_room_events(mut self, room_id: &RoomId, user_id: &UserId) -> TestRunner {
|
|
|
|
TestRunner {
|
|
|
|
client: None,
|
|
|
|
room: Some(Room::new(room_id, user_id)),
|
|
|
|
events: self.events,
|
|
|
|
client_assertions: Vec::new(),
|
|
|
|
room_assertions: Vec::new(),
|
|
|
|
mock: None,
|
|
|
|
}
|
|
|
|
}
|
2020-04-06 11:12:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl TestRunner {
|
2020-04-06 19:29:38 +00:00
|
|
|
pub fn set_client(mut self, client: AsyncClient) -> Self {
|
2020-04-06 11:12:02 +00:00
|
|
|
self.client = Some(client);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2020-04-06 19:29:38 +00:00
|
|
|
pub fn add_client_assert(mut self, assert: fn(&AsyncClient)) -> Self {
|
|
|
|
self.client_assertions.push(assert);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add_room_assert(mut self, assert: fn(&Room)) -> Self {
|
|
|
|
self.room_assertions.push(assert);
|
|
|
|
self
|
|
|
|
}
|
2020-04-06 11:12:02 +00:00
|
|
|
|
2020-04-06 19:29:38 +00:00
|
|
|
fn run_client_tests(mut self) -> Result<(), Vec<String>> {
|
2020-04-06 11:12:02 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2020-04-06 19:29:38 +00:00
|
|
|
|
|
|
|
fn run_room_tests(mut self) -> Result<(), Vec<String>> {
|
|
|
|
let mut errs = Vec::new();
|
|
|
|
let mut room = self.room.unwrap();
|
|
|
|
for event in &self.events {
|
|
|
|
match event {
|
|
|
|
RoomEvent::RoomMember(m) => room.handle_membership(m),
|
|
|
|
RoomEvent::RoomName(n) => room.handle_room_name(n),
|
|
|
|
RoomEvent::RoomCanonicalAlias(ca) => room.handle_canonical(ca),
|
|
|
|
RoomEvent::RoomAliases(a) => room.handle_room_aliases(a),
|
|
|
|
RoomEvent::RoomPowerLevels(p) => room.handle_power_level(p),
|
|
|
|
// RoomEvent::RoomEncryption(e) => room.handle_encryption_event(e),
|
|
|
|
_ => todo!("implement more RoomEvent variants"),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
for assert in self.room_assertions {
|
|
|
|
if let Err(e) = panic::catch_unwind(|| assert(&room)) {
|
|
|
|
errs.push(stringify!(e).to_string());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if errs.is_empty() {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(errs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn run_test(mut self) {
|
|
|
|
let errs = if let Some(room) = &self.room {
|
|
|
|
self.run_room_tests()
|
|
|
|
} else if let Some(cli) = &self.client {
|
|
|
|
self.run_client_tests()
|
|
|
|
} else {
|
|
|
|
panic!("must have either AsyncClient or Room")
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Err(errs) = errs {
|
|
|
|
let err_str = errs.join(&format!("{}\n", Colour::Red.paint("Error: ")));
|
|
|
|
if !errs.is_empty() {
|
|
|
|
panic!("{}", Colour::Red.paint("some tests failed"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn test_room_users(room: &Room) {
|
|
|
|
assert_eq!(room.members.len(), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn test_room_power(room: &Room) {
|
|
|
|
assert!(room.power_levels.is_some());
|
|
|
|
assert_eq!(room.power_levels.as_ref().unwrap().kick, js_int::Int::new(50).unwrap());
|
|
|
|
let admin = room.members.get(&UserId::try_from("@example:localhost").unwrap()).unwrap();
|
|
|
|
assert_eq!(admin.power_level.unwrap(), js_int::Int::new(100).unwrap());
|
|
|
|
println!("{:#?}", room);
|
2020-04-06 11:12:02 +00:00
|
|
|
}
|
|
|
|
|
2020-04-06 13:11:38 +00:00
|
|
|
#[test]
|
2020-04-06 19:29:38 +00:00
|
|
|
fn room_events() {
|
|
|
|
let rid = RoomId::try_from("!roomid:room.com").unwrap();
|
|
|
|
let uid = UserId::try_from("@example:localhost").unwrap();
|
2020-04-06 13:11:38 +00:00
|
|
|
let mut bld = ResponseBuilder::default();
|
2020-04-06 19:29:38 +00:00
|
|
|
let runner = bld.add_event_from_file("./tests/data/events/member.json", RoomEvent::RoomMember)
|
|
|
|
.add_event_from_file("./tests/data/events/power_levels.json", RoomEvent::RoomPowerLevels)
|
|
|
|
.build_room_events(&rid, &uid)
|
|
|
|
.add_room_assert(test_room_power)
|
|
|
|
.add_room_assert(test_room_users);
|
|
|
|
|
|
|
|
runner.run_test();
|
2020-04-06 13:11:38 +00:00
|
|
|
}
|
|
|
|
|
2020-04-06 11:12:02 +00:00
|
|
|
}
|