matrix_sdk: Fix most of the tests now that we have the big split.

master
Damir Jelić 2020-05-07 16:22:18 +02:00
parent 30f8ccd2de
commit 14580bc383
10 changed files with 309 additions and 537 deletions

View File

@ -1198,12 +1198,10 @@ mod test {
ban_user, create_receipt, create_typing_event, forget_room, invite_user, kick_user, ban_user, create_receipt, create_typing_event, forget_room, invite_user, kick_user,
leave_room, leave_room,
}; };
use super::{AsyncClient, Session, SyncSettings, Url}; use super::{AsyncClient, AsyncClientConfig, Session, SyncSettings, Url};
use crate::events::collections::all::RoomEvent;
use crate::events::room::member::MembershipState; use crate::events::room::member::MembershipState;
use crate::identifiers::{EventId, RoomId, UserId}; use crate::identifiers::{EventId, RoomId, UserId};
use matrix_sdk_base::JsonStore;
use crate::test_builder::EventBuilder;
use mockito::{mock, Matcher}; use mockito::{mock, Matcher};
use std::convert::TryFrom; use std::convert::TryFrom;
@ -1234,71 +1232,71 @@ mod test {
let _response = client.sync(sync_settings).await.unwrap(); let _response = client.sync(sync_settings).await.unwrap();
let bc = &client.base_client; // let bc = &client.base_client;
let ignored_users = bc.ignored_users.read().await; // let ignored_users = bc.ignored_users.read().await;
assert_eq!(1, ignored_users.len()) // assert_eq!(1, ignored_users.len())
} }
#[tokio::test] // #[tokio::test]
async fn client_runner() { // async fn client_runner() {
let session = crate::Session { // let session = crate::Session {
access_token: "12345".to_owned(), // access_token: "12345".to_owned(),
user_id: UserId::try_from("@example:localhost").unwrap(), // user_id: UserId::try_from("@example:localhost").unwrap(),
device_id: "DEVICEID".to_owned(), // device_id: "DEVICEID".to_owned(),
}; // };
let homeserver = url::Url::parse(&mockito::server_url()).unwrap(); // let homeserver = url::Url::parse(&mockito::server_url()).unwrap();
let client = AsyncClient::new(homeserver, Some(session)).unwrap(); // let client = AsyncClient::new(homeserver, Some(session)).unwrap();
let rid = RoomId::try_from("!roomid:room.com").unwrap(); // let rid = RoomId::try_from("!roomid:room.com").unwrap();
let uid = UserId::try_from("@example:localhost").unwrap(); // let uid = UserId::try_from("@example:localhost").unwrap();
let mut bld = EventBuilder::default() // let mut bld = EventBuilder::default()
.add_room_event_from_file("../test_data/events/member.json", RoomEvent::RoomMember) // .add_room_event_from_file("../test_data/events/member.json", RoomEvent::RoomMember)
.add_room_event_from_file( // .add_room_event_from_file(
"../test_data/events/power_levels.json", // "../test_data/events/power_levels.json",
RoomEvent::RoomPowerLevels, // RoomEvent::RoomPowerLevels,
) // )
.build_client_runner(rid, uid); // .build_client_runner(rid, uid);
let cli = bld.set_client(client).to_client().await; // let cli = bld.set_client(client).to_client().await;
assert_eq!( // assert_eq!(
cli.homeserver(), // cli.homeserver(),
&Url::parse(&mockito::server_url()).unwrap() // &Url::parse(&mockito::server_url()).unwrap()
); // );
} // }
#[tokio::test] // #[tokio::test]
async fn mock_runner() { // async fn mock_runner() {
use std::convert::TryFrom; // use std::convert::TryFrom;
let session = crate::Session { // let session = crate::Session {
access_token: "12345".to_owned(), // access_token: "12345".to_owned(),
user_id: UserId::try_from("@example:localhost").unwrap(), // user_id: UserId::try_from("@example:localhost").unwrap(),
device_id: "DEVICEID".to_owned(), // device_id: "DEVICEID".to_owned(),
}; // };
let homeserver = url::Url::parse(&mockito::server_url()).unwrap(); // let homeserver = url::Url::parse(&mockito::server_url()).unwrap();
let client = AsyncClient::new(homeserver, Some(session)).unwrap(); // let client = AsyncClient::new(homeserver, Some(session)).unwrap();
let mut bld = EventBuilder::default() // let mut bld = EventBuilder::default()
.add_room_event_from_file("../test_data/events/member.json", RoomEvent::RoomMember) // .add_room_event_from_file("../test_data/events/member.json", RoomEvent::RoomMember)
.add_room_event_from_file( // .add_room_event_from_file(
"../test_data/events/power_levels.json", // "../test_data/events/power_levels.json",
RoomEvent::RoomPowerLevels, // RoomEvent::RoomPowerLevels,
) // )
.build_mock_runner( // .build_mock_runner(
"GET", // "GET",
mockito::Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()), // mockito::Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()),
); // );
let cli = bld.set_client(client).to_client().await.unwrap(); // let cli = bld.set_client(client).to_client().await.unwrap();
assert_eq!( // assert_eq!(
cli.homeserver(), // cli.homeserver(),
&Url::parse(&mockito::server_url()).unwrap() // &Url::parse(&mockito::server_url()).unwrap()
); // );
} // }
#[tokio::test] #[tokio::test]
async fn login_error() { async fn login_error() {
@ -1646,33 +1644,89 @@ mod test {
assert!(room.power_levels.is_some()) assert!(room.power_levels.is_some())
} }
#[tokio::test] // #[tokio::test]
async fn calculate_room_names_from_summary() { // async fn calculate_room_names_from_summary() {
let homeserver = Url::from_str(&mockito::server_url()).unwrap(); // let homeserver = Url::from_str(&mockito::server_url()).unwrap();
let mut bld = EventBuilder::default().build_with_response( // let mut bld = EventBuilder::default().build_with_response(
// this sync has no room.name or room.alias events so only relies on summary // // this sync has no room.name or room.alias events so only relies on summary
"../test_data/sync_with_summary.json", // "../test_data/sync_with_summary.json",
"GET", // "GET",
Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()), // Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()),
); // );
// let session = Session {
// access_token: "1234".to_owned(),
// user_id: UserId::try_from("@example:localhost").unwrap(),
// device_id: "DEVICEID".to_owned(),
// };
// let client = AsyncClient::new(homeserver, Some(session)).unwrap();
// let client = bld.set_client(client).to_client().await.unwrap();
// let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000));
// let _response = client.sync(sync_settings).await.unwrap();
// let mut room_names = vec![];
// for room in client.joined_rooms().read().await.values() {
// room_names.push(room.read().await.display_name())
// }
// assert_eq!(vec!["example, example2"], room_names);
// }
#[tokio::test]
async fn test_client_sync_store() {
let homeserver = url::Url::from_str(&mockito::server_url()).unwrap();
let session = Session { let session = Session {
access_token: "1234".to_owned(), access_token: "1234".to_owned(),
user_id: UserId::try_from("@example:localhost").unwrap(), user_id: UserId::try_from("@cheeky_monkey:matrix.org").unwrap(),
device_id: "DEVICEID".to_owned(), device_id: "DEVICEID".to_owned(),
}; };
let client = AsyncClient::new(homeserver, Some(session)).unwrap();
let client = bld.set_client(client).to_client().await.unwrap();
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); let _m = mock(
let _response = client.sync(sync_settings).await.unwrap(); "GET",
Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()),
)
.with_status(200)
.with_body_from_file("../test_data/sync.json")
.create();
let mut room_names = vec![]; let _m = mock("POST", "/_matrix/client/r0/login")
for room in client.joined_rooms().read().await.values() { .with_status(200)
room_names.push(room.read().await.display_name()) .with_body_from_file("../test_data/login_response.json")
} .create();
assert_eq!(vec!["example, example2"], room_names); let dir = tempfile::tempdir().unwrap();
// a sync response to populate our JSON store
let config = AsyncClientConfig::default()
.state_store(Box::new(JsonStore::open(dir.path()).unwrap()));
let client =
AsyncClient::new_with_config(homeserver.clone(), Some(session.clone()), config)
.unwrap();
let sync_settings = SyncSettings::new().timeout(std::time::Duration::from_millis(3000));
// gather state to save to the db, the first time through loading will be skipped
let _ = client.sync(sync_settings.clone()).await.unwrap();
// now syncing the client will update from the state store
let config = AsyncClientConfig::default()
.state_store(Box::new(JsonStore::open(dir.path()).unwrap()));
let client =
AsyncClient::new_with_config(homeserver, Some(session.clone()), config).unwrap();
client.sync(sync_settings).await.unwrap();
let base_client = &client.base_client;
// assert the synced client and the logged in client are equal
assert_eq!(*base_client.session().read().await, Some(session));
assert_eq!(
base_client.sync_token().await,
Some("s526_47314_0_7_1_1_1_11444_1".to_string())
);
// assert_eq!(
// *base_client.ignored_users.read().await,
// vec![UserId::try_from("@someone:example.org").unwrap()]
// );
} }
} }

View File

@ -27,7 +27,7 @@
#![deny(missing_docs)] #![deny(missing_docs)]
pub use matrix_sdk_base::{Error, EventEmitter, Result, Room, Session}; pub use matrix_sdk_base::{Error, EventEmitter, Result, Room, Session};
pub use matrix_sdk_base::{JsonStore, StateStore}; pub use matrix_sdk_base::{JsonStore, RoomState, StateStore};
pub use matrix_sdk_common::*; pub use matrix_sdk_common::*;
pub use reqwest::header::InvalidHeaderValue; pub use reqwest::header::InvalidHeaderValue;
@ -35,6 +35,8 @@ pub use reqwest::header::InvalidHeaderValue;
pub use matrix_sdk_base::{Device, TrustState}; pub use matrix_sdk_base::{Device, TrustState};
mod async_client; mod async_client;
mod request_builder;
pub use async_client::{AsyncClient, AsyncClientConfig, SyncSettings}; pub use async_client::{AsyncClient, AsyncClientConfig, SyncSettings};
pub use request_builder::{MessagesRequestBuilder, RoomBuilder};
pub(crate) const VERSION: &str = env!("CARGO_PKG_VERSION"); pub(crate) const VERSION: &str = env!("CARGO_PKG_VERSION");

View File

@ -46,13 +46,13 @@ use crate::RoomState;
/// # use std::sync::Arc; /// # use std::sync::Arc;
/// # use std::{env, process::exit}; /// # use std::{env, process::exit};
/// # use url::Url; /// # use url::Url;
/// use matrix_sdk::{ /// # use matrix_sdk_base::{
/// self, /// # self,
/// events::{ /// # events::{
/// room::message::{MessageEvent, MessageEventContent, TextMessageEventContent}, /// # room::message::{MessageEvent, MessageEventContent, TextMessageEventContent},
/// }, /// # },
/// AsyncClient, AsyncClientConfig, EventEmitter, RoomState, SyncSettings, /// # EventEmitter, RoomState
/// }; /// # };
/// use tokio::sync::RwLock; /// use tokio::sync::RwLock;
/// ///
/// struct EventCallback; /// struct EventCallback;
@ -276,42 +276,43 @@ mod test {
} }
} }
use crate::api::r0::sync::sync_events::Response as SyncResponse;
use crate::identifiers::UserId; use crate::identifiers::UserId;
use crate::{AsyncClient, Session, SyncSettings}; use crate::{Client, Session};
use mockito::{mock, Matcher};
use url::Url;
use http::Response;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::str::FromStr; use std::fs::File;
use std::time::Duration; use std::io::Read;
#[tokio::test] fn sync_response(file: &str) -> SyncResponse {
async fn event_emitter_joined() { let mut file = File::open(file).unwrap();
let homeserver = Url::from_str(&mockito::server_url()).unwrap(); let mut data = vec![];
file.read_to_end(&mut data).unwrap();
let response = Response::builder().body(data).unwrap();
SyncResponse::try_from(response).unwrap()
}
fn get_client() -> Client {
let session = Session { let session = Session {
access_token: "1234".to_owned(), access_token: "1234".to_owned(),
user_id: UserId::try_from("@example:example.com").unwrap(), user_id: UserId::try_from("@example:example.com").unwrap(),
device_id: "DEVICEID".to_owned(), device_id: "DEVICEID".to_owned(),
}; };
Client::new(Some(session)).unwrap()
}
let _m = mock( #[tokio::test]
"GET", async fn event_emitter_joined() {
Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()),
)
.with_status(200)
.with_body_from_file("../test_data/sync.json")
.create();
let vec = Arc::new(Mutex::new(Vec::new())); let vec = Arc::new(Mutex::new(Vec::new()));
let test_vec = Arc::clone(&vec); let test_vec = Arc::clone(&vec);
let emitter = Box::new(EvEmitterTest(vec)); let emitter = Box::new(EvEmitterTest(vec));
let mut client = AsyncClient::new(homeserver, Some(session)).unwrap();
let client = get_client();
client.add_event_emitter(emitter).await; client.add_event_emitter(emitter).await;
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); let mut response = sync_response("../test_data/sync.json");
let _response = client.sync(sync_settings).await.unwrap(); client.receive_sync_response(&mut response).await.unwrap();
let v = test_vec.lock().await; let v = test_vec.lock().await;
assert_eq!( assert_eq!(
@ -334,30 +335,15 @@ mod test {
#[tokio::test] #[tokio::test]
async fn event_emitter_invite() { async fn event_emitter_invite() {
let homeserver = Url::from_str(&mockito::server_url()).unwrap();
let session = Session {
access_token: "1234".to_owned(),
user_id: UserId::try_from("@example:example.com").unwrap(),
device_id: "DEVICEID".to_owned(),
};
let _m = mock(
"GET",
Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()),
)
.with_status(200)
.with_body_from_file("../test_data/invite_sync.json")
.create();
let vec = Arc::new(Mutex::new(Vec::new())); let vec = Arc::new(Mutex::new(Vec::new()));
let test_vec = Arc::clone(&vec); let test_vec = Arc::clone(&vec);
let emitter = Box::new(EvEmitterTest(vec)); let emitter = Box::new(EvEmitterTest(vec));
let mut client = AsyncClient::new(homeserver, Some(session)).unwrap();
let client = get_client();
client.add_event_emitter(emitter).await; client.add_event_emitter(emitter).await;
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); let mut response = sync_response("../test_data/invite_sync.json");
let _response = client.sync(sync_settings).await.unwrap(); client.receive_sync_response(&mut response).await.unwrap();
let v = test_vec.lock().await; let v = test_vec.lock().await;
assert_eq!( assert_eq!(
@ -368,30 +354,15 @@ mod test {
#[tokio::test] #[tokio::test]
async fn event_emitter_leave() { async fn event_emitter_leave() {
let homeserver = Url::from_str(&mockito::server_url()).unwrap();
let session = Session {
access_token: "1234".to_owned(),
user_id: UserId::try_from("@example:example.com").unwrap(),
device_id: "DEVICEID".to_owned(),
};
let _m = mock(
"GET",
Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()),
)
.with_status(200)
.with_body_from_file("../test_data/leave_sync.json")
.create();
let vec = Arc::new(Mutex::new(Vec::new())); let vec = Arc::new(Mutex::new(Vec::new()));
let test_vec = Arc::clone(&vec); let test_vec = Arc::clone(&vec);
let emitter = Box::new(EvEmitterTest(vec)); let emitter = Box::new(EvEmitterTest(vec));
let mut client = AsyncClient::new(homeserver, Some(session)).unwrap();
let client = get_client();
client.add_event_emitter(emitter).await; client.add_event_emitter(emitter).await;
let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); let mut response = sync_response("../test_data/leave_sync.json");
let _response = client.sync(sync_settings).await.unwrap(); client.receive_sync_response(&mut response).await.unwrap();
let v = test_vec.lock().await; let v = test_vec.lock().await;
assert_eq!( assert_eq!(

View File

@ -34,7 +34,6 @@ mod base_client;
mod error; mod error;
mod event_emitter; mod event_emitter;
mod models; mod models;
mod request_builder;
mod session; mod session;
mod state; mod state;
@ -46,5 +45,4 @@ pub use event_emitter::EventEmitter;
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
pub use matrix_sdk_crypto::{Device, TrustState}; pub use matrix_sdk_crypto::{Device, TrustState};
pub use models::Room; pub use models::Room;
pub use request_builder::{MessagesRequestBuilder, RoomBuilder};
pub use state::{JsonStore, StateStore}; pub use state::{JsonStore, StateStore};

View File

@ -537,18 +537,25 @@ mod test {
SyncResponse::try_from(response).unwrap() SyncResponse::try_from(response).unwrap()
} }
#[tokio::test] fn get_client() -> Client {
async fn user_presence() {
let session = Session { let session = Session {
access_token: "1234".to_owned(), access_token: "1234".to_owned(),
user_id: UserId::try_from("@example:localhost").unwrap(), user_id: UserId::try_from("@example:localhost").unwrap(),
device_id: "DEVICEID".to_owned(), device_id: "DEVICEID".to_owned(),
}; };
Client::new(Some(session)).unwrap()
}
fn get_room_id() -> RoomId {
RoomId::try_from("!SVkFJHzfwvuaIEawgC:localhost").unwrap()
}
#[tokio::test]
async fn user_presence() {
let client = get_client();
let mut response = sync_response("../test_data/sync.json"); let mut response = sync_response("../test_data/sync.json");
let client = Client::new(Some(session)).unwrap();
client.receive_sync_response(&mut response).await.unwrap(); client.receive_sync_response(&mut response).await.unwrap();
let rooms_lock = &client.joined_rooms(); let rooms_lock = &client.joined_rooms();
@ -567,20 +574,24 @@ mod test {
assert!(room.deref().power_levels.is_some()) assert!(room.deref().power_levels.is_some())
} }
#[test] #[tokio::test]
fn room_events() { async fn room_events() {
let rid = RoomId::try_from("!roomid:room.com").unwrap(); let client = get_client();
let uid = UserId::try_from("@example:localhost").unwrap(); let room_id = get_room_id();
let user_id = UserId::try_from("@example:localhost").unwrap();
let mut bld = EventBuilder::default() let mut response = EventBuilder::default()
.add_room_event_from_file("../test_data/events/member.json", RoomEvent::RoomMember) .add_room_event_from_file("../test_data/events/member.json", RoomEvent::RoomMember)
.add_room_event_from_file( .add_room_event_from_file(
"../test_data/events/power_levels.json", "../test_data/events/power_levels.json",
RoomEvent::RoomPowerLevels, RoomEvent::RoomPowerLevels,
) )
.build_room_runner(&rid, &uid); .build_sync_response();
let room = bld.to_room(); client.receive_sync_response(&mut response).await.unwrap();
let room = client.get_joined_room(&room_id).await.unwrap();
let room = room.read().await;
assert_eq!(room.members.len(), 1); assert_eq!(room.members.len(), 1);
assert!(room.power_levels.is_some()); assert!(room.power_levels.is_some());
@ -588,57 +599,66 @@ mod test {
room.power_levels.as_ref().unwrap().kick, room.power_levels.as_ref().unwrap().kick,
crate::js_int::Int::new(50).unwrap() crate::js_int::Int::new(50).unwrap()
); );
let admin = room let admin = room.members.get(&user_id).unwrap();
.members
.get(&UserId::try_from("@example:localhost").unwrap())
.unwrap();
assert_eq!( assert_eq!(
admin.power_level.unwrap(), admin.power_level.unwrap(),
crate::js_int::Int::new(100).unwrap() crate::js_int::Int::new(100).unwrap()
); );
} }
#[test] #[tokio::test]
fn calculate_aliases() { async fn calculate_aliases() {
let rid = RoomId::try_from("!roomid:room.com").unwrap(); let client = get_client();
let uid = UserId::try_from("@example:localhost").unwrap();
let mut bld = EventBuilder::default() let room_id = get_room_id();
let mut response = EventBuilder::default()
.add_state_event_from_file("../test_data/events/aliases.json", StateEvent::RoomAliases) .add_state_event_from_file("../test_data/events/aliases.json", StateEvent::RoomAliases)
.build_room_runner(&rid, &uid); .build_sync_response();
let room = bld.to_room(); client.receive_sync_response(&mut response).await.unwrap();
let room = client.get_joined_room(&room_id).await.unwrap();
let room = room.read().await;
assert_eq!("tutorial", room.display_name()); assert_eq!("tutorial", room.display_name());
} }
#[test] #[tokio::test]
fn calculate_alias() { async fn calculate_alias() {
let rid = RoomId::try_from("!roomid:room.com").unwrap(); let client = get_client();
let uid = UserId::try_from("@example:localhost").unwrap();
let mut bld = EventBuilder::default() let room_id = get_room_id();
let mut response = EventBuilder::default()
.add_state_event_from_file( .add_state_event_from_file(
"../test_data/events/alias.json", "../test_data/events/alias.json",
StateEvent::RoomCanonicalAlias, StateEvent::RoomCanonicalAlias,
) )
.build_room_runner(&rid, &uid); .build_sync_response();
let room = bld.to_room(); client.receive_sync_response(&mut response).await.unwrap();
let room = client.get_joined_room(&room_id).await.unwrap();
let room = room.read().await;
assert_eq!("tutorial", room.display_name()); assert_eq!("tutorial", room.display_name());
} }
#[test] #[tokio::test]
fn calculate_name() { async fn calculate_name() {
let rid = RoomId::try_from("!roomid:room.com").unwrap(); let client = get_client();
let uid = UserId::try_from("@example:localhost").unwrap();
let mut bld = EventBuilder::default() let room_id = get_room_id();
let mut response = EventBuilder::default()
.add_state_event_from_file("../test_data/events/name.json", StateEvent::RoomName) .add_state_event_from_file("../test_data/events/name.json", StateEvent::RoomName)
.build_room_runner(&rid, &uid); .build_sync_response();
let room = bld.to_room(); client.receive_sync_response(&mut response).await.unwrap();
let room = client.get_joined_room(&room_id).await.unwrap();
let room = room.read().await;
assert_eq!("room name", room.display_name()); assert_eq!("room name", room.display_name());
} }

View File

@ -200,27 +200,46 @@ impl RoomMember {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::events::collections::all::RoomEvent; use crate::events::collections::all::RoomEvent;
use crate::events::presence::PresenceState;
use crate::events::room::member::MembershipState; use crate::events::room::member::MembershipState;
use crate::identifiers::{RoomId, UserId}; use crate::identifiers::{RoomId, UserId};
use crate::test_builder::EventBuilder; use crate::test_builder::EventBuilder;
use crate::{Client, Session};
use crate::js_int::{Int, UInt}; use crate::js_int::Int;
use std::convert::TryFrom; use std::convert::TryFrom;
#[test] fn get_client() -> Client {
fn room_member_events() { let session = Session {
let rid = RoomId::try_from("!roomid:room.com").unwrap(); access_token: "1234".to_owned(),
let uid = UserId::try_from("@example:localhost").unwrap(); user_id: UserId::try_from("@example:localhost").unwrap(),
let mut bld = EventBuilder::default() device_id: "DEVICEID".to_owned(),
};
Client::new(Some(session)).unwrap()
}
fn get_room_id() -> RoomId {
RoomId::try_from("!SVkFJHzfwvuaIEawgC:localhost").unwrap()
}
#[tokio::test]
async fn room_member_events() {
let client = get_client();
let room_id = get_room_id();
let mut response = EventBuilder::default()
.add_room_event_from_file("../test_data/events/member.json", RoomEvent::RoomMember) .add_room_event_from_file("../test_data/events/member.json", RoomEvent::RoomMember)
.add_room_event_from_file( .add_room_event_from_file(
"../test_data/events/power_levels.json", "../test_data/events/power_levels.json",
RoomEvent::RoomPowerLevels, RoomEvent::RoomPowerLevels,
) )
.build_room_runner(&rid, &uid); .build_sync_response();
let room = bld.to_room();
client.receive_sync_response(&mut response).await.unwrap();
let room = client.get_joined_room(&room_id).await.unwrap();
let room = room.read().await;
let member = room let member = room
.members .members
@ -230,20 +249,25 @@ mod test {
assert_eq!(member.power_level, Int::new(100)); assert_eq!(member.power_level, Int::new(100));
} }
#[test] #[tokio::test]
fn member_presence_events() { async fn member_presence_events() {
let rid = RoomId::try_from("!roomid:room.com").unwrap(); let client = get_client();
let uid = UserId::try_from("@example:localhost").unwrap();
let mut bld = EventBuilder::default() let room_id = get_room_id();
let mut response = EventBuilder::default()
.add_room_event_from_file("../test_data/events/member.json", RoomEvent::RoomMember) .add_room_event_from_file("../test_data/events/member.json", RoomEvent::RoomMember)
.add_room_event_from_file( .add_room_event_from_file(
"../test_data/events/power_levels.json", "../test_data/events/power_levels.json",
RoomEvent::RoomPowerLevels, RoomEvent::RoomPowerLevels,
) )
.add_presence_event_from_file("../test_data/events/presence.json") .add_presence_event_from_file("../test_data/events/presence.json")
.build_room_runner(&rid, &uid); .build_sync_response();
let room = bld.to_room(); client.receive_sync_response(&mut response).await.unwrap();
let room = client.get_joined_room(&room_id).await.unwrap();
let room = room.read().await;
let member = room let member = room
.members .members
@ -253,8 +277,8 @@ mod test {
assert_eq!(member.membership, MembershipState::Join); assert_eq!(member.membership, MembershipState::Join);
assert_eq!(member.power_level, Int::new(100)); assert_eq!(member.power_level, Int::new(100));
assert!(member.avatar_url.is_some()); assert!(member.avatar_url.is_none());
assert_eq!(member.last_active_ago, UInt::new(1)); assert_eq!(member.last_active_ago, None);
assert_eq!(member.presence, Some(PresenceState::Online)); assert_eq!(member.presence, None);
} }
} }

View File

@ -135,49 +135,30 @@ impl StateStore for JsonStore {
mod test { mod test {
use super::*; use super::*;
use http::Response;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fs; use std::fs::File;
use std::future::Future; use std::io::Read;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr;
use lazy_static::lazy_static; use tempfile::tempdir;
use mockito::{mock, Matcher};
use tokio::sync::Mutex;
use crate::api::r0::sync::sync_events::Response as SyncResponse;
use crate::identifiers::{RoomId, UserId}; use crate::identifiers::{RoomId, UserId};
use crate::{AsyncClient, AsyncClientConfig, Session, SyncSettings}; use crate::{Client, Session};
lazy_static! { fn sync_response(file: &str) -> SyncResponse {
/// Limit io tests to one thread at a time. let mut file = File::open(file).unwrap();
pub static ref MTX: Mutex<()> = Mutex::new(()); let mut data = vec![];
} file.read_to_end(&mut data).unwrap();
let response = Response::builder().body(data).unwrap();
lazy_static! { SyncResponse::try_from(response).unwrap()
/// Limit io tests to one thread at a time.
pub static ref PATH: PathBuf = {
let mut path = dirs::home_dir().unwrap();
path.push(".matrix_store");
path
};
}
async fn run_and_cleanup<Fut>(test: fn() -> Fut)
where
Fut: Future<Output = ()>,
{
let _lock = MTX.lock().await;
test().await;
if PATH.exists() {
let path: &Path = &PATH;
fs::remove_dir_all(path).unwrap();
}
} }
#[tokio::test]
async fn test_store_client_state() { async fn test_store_client_state() {
let path: &Path = &PATH; let dir = tempdir().unwrap();
let path: &Path = dir.path();
let user = UserId::try_from("@example:example.com").unwrap(); let user = UserId::try_from("@example:example.com").unwrap();
@ -206,12 +187,9 @@ mod test {
} }
#[tokio::test] #[tokio::test]
async fn store_client_state() {
run_and_cleanup(test_store_client_state).await;
}
async fn test_store_room_state() { async fn test_store_room_state() {
let path: &Path = &PATH; let dir = tempdir().unwrap();
let path: &Path = dir.path();
let store = JsonStore::open(path).unwrap(); let store = JsonStore::open(path).unwrap();
let id = RoomId::try_from("!roomid:example.com").unwrap(); let id = RoomId::try_from("!roomid:example.com").unwrap();
@ -224,12 +202,9 @@ mod test {
} }
#[tokio::test] #[tokio::test]
async fn store_room_state() {
run_and_cleanup(test_store_room_state).await;
}
async fn test_load_rooms() { async fn test_load_rooms() {
let path: &Path = &PATH; let dir = tempdir().unwrap();
let path: &Path = dir.path();
let store = JsonStore::open(path).unwrap(); let store = JsonStore::open(path).unwrap();
let id = RoomId::try_from("!roomid:example.com").unwrap(); let id = RoomId::try_from("!roomid:example.com").unwrap();
@ -242,12 +217,9 @@ mod test {
} }
#[tokio::test] #[tokio::test]
async fn load_rooms() {
run_and_cleanup(test_load_rooms).await;
}
async fn test_client_sync_store() { async fn test_client_sync_store() {
let homeserver = url::Url::from_str(&mockito::server_url()).unwrap(); let dir = tempdir().unwrap();
let path: &Path = dir.path();
let session = Session { let session = Session {
access_token: "1234".to_owned(), access_token: "1234".to_owned(),
@ -255,54 +227,29 @@ mod test {
device_id: "DEVICEID".to_owned(), device_id: "DEVICEID".to_owned(),
}; };
let _m = mock(
"GET",
Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()),
)
.with_status(200)
.with_body_from_file("../test_data/sync.json")
.create();
let _m = mock("POST", "/_matrix/client/r0/login")
.with_status(200)
.with_body_from_file("../test_data/login_response.json")
.create();
let path: &Path = &PATH;
// a sync response to populate our JSON store // a sync response to populate our JSON store
let config = let store = Box::new(JsonStore::open(path).unwrap());
AsyncClientConfig::default().state_store(Box::new(JsonStore::open(path).unwrap())); let client = Client::new_with_state_store(Some(session.clone()), store).unwrap();
let client =
AsyncClient::new_with_config(homeserver.clone(), Some(session.clone()), config) let mut response = sync_response("../test_data/sync.json");
.unwrap();
let sync_settings = SyncSettings::new().timeout(std::time::Duration::from_millis(3000));
// gather state to save to the db, the first time through loading will be skipped // gather state to save to the db, the first time through loading will be skipped
let _ = client.sync(sync_settings.clone()).await.unwrap(); client.receive_sync_response(&mut response).await.unwrap();
// now syncing the client will update from the state store // now syncing the client will update from the state store
let config = let store = Box::new(JsonStore::open(path).unwrap());
AsyncClientConfig::default().state_store(Box::new(JsonStore::open(path).unwrap())); let client = Client::new_with_state_store(Some(session.clone()), store).unwrap();
let client = client.sync_with_state_store().await.unwrap();
AsyncClient::new_with_config(homeserver, Some(session.clone()), config).unwrap();
client.sync(sync_settings).await.unwrap();
let base_client = &client.base_client;
// assert the synced client and the logged in client are equal // assert the synced client and the logged in client are equal
assert_eq!(*base_client.session().read().await, Some(session)); assert_eq!(*client.session().read().await, Some(session));
assert_eq!( assert_eq!(
base_client.sync_token().await, client.sync_token().await,
Some("s526_47314_0_7_1_1_1_11444_1".to_string()) Some("s526_47314_0_7_1_1_1_11444_1".to_string())
); );
assert_eq!( assert_eq!(
*base_client.ignored_users.read().await, *client.ignored_users.read().await,
vec![UserId::try_from("@someone:example.org").unwrap()] vec![UserId::try_from("@someone:example.org").unwrap()]
); );
} }
#[tokio::test]
async fn client_sync_store() {
run_and_cleanup(test_client_sync_store).await;
}
} }

View File

@ -4,6 +4,7 @@ use std::fs;
use std::panic; use std::panic;
use std::path::Path; use std::path::Path;
use crate::api::r0::sync::sync_events::Response as SyncResponse;
use crate::events::{ use crate::events::{
collections::{ collections::{
all::{RoomEvent, StateEvent}, all::{RoomEvent, StateEvent},
@ -12,12 +13,8 @@ use crate::events::{
presence::PresenceEvent, presence::PresenceEvent,
EventJson, TryFromRaw, EventJson, TryFromRaw,
}; };
use crate::identifiers::{RoomId, UserId}; use http::Response;
use crate::{AsyncClient, Error, SyncSettings}; use std::convert::TryFrom;
use mockito::{self, mock, Matcher, Mock};
use crate::models::Room;
/// Easily create events to stream into either a Client or a `Room` for testing. /// Easily create events to stream into either a Client or a `Room` for testing.
#[derive(Default)] #[derive(Default)]
@ -34,60 +31,6 @@ pub struct EventBuilder {
account_data: Vec<Event>, account_data: Vec<Event>,
} }
pub struct RoomTestRunner {
/// Used To test the models
room: Option<Room>,
/// The ephemeral room events that determine the state of a `Room`.
ephemeral: Vec<Event>,
/// The account data events that determine the state of a `Room`.
account_data: Vec<Event>,
/// The events that determine the state of a `Room`.
room_events: Vec<RoomEvent>,
/// The presence events that determine the presence state of a `RoomMember`.
presence_events: Vec<PresenceEvent>,
/// The state events that determine the state of a `Room`.
state_events: Vec<StateEvent>,
}
pub struct ClientTestRunner {
/// Used when testing the whole client
client: Option<AsyncClient>,
/// RoomId and UserId to use for the events.
///
/// The RoomId must match the RoomId of the events to track.
room_user_id: (RoomId, UserId),
/// The ephemeral room events that determine the state of a `Room`.
ephemeral: Vec<Event>,
/// The account data events that determine the state of a `Room`.
account_data: Vec<Event>,
/// The events that determine the state of a `Room`.
room_events: Vec<RoomEvent>,
/// The presence events that determine the presence state of a `RoomMember`.
presence_events: Vec<PresenceEvent>,
/// The state events that determine the state of a `Room`.
state_events: Vec<StateEvent>,
}
#[allow(dead_code)]
pub struct MockTestRunner {
/// Used when testing the whole client
client: Option<AsyncClient>,
/// The ephemeral room events that determine the state of a `Room`.
ephemeral: Vec<Event>,
/// The account data events that determine the state of a `Room`.
account_data: Vec<Event>,
/// The events that determine the state of a `Room`.
room_events: Vec<RoomEvent>,
/// The presence events that determine the presence state of a `RoomMember`.
presence_events: Vec<PresenceEvent>,
/// The state events that determine the state of a `Room`.
state_events: Vec<StateEvent>,
/// `mokito::Mock`
mock: Option<mockito::Mock>,
}
#[allow(dead_code)]
#[allow(unused_mut)]
impl EventBuilder { impl EventBuilder {
/// Add an event to the room events `Vec`. /// Add an event to the room events `Vec`.
pub fn add_ephemeral_from_file<Ev: TryFromRaw, P: AsRef<Path>>( pub fn add_ephemeral_from_file<Ev: TryFromRaw, P: AsRef<Path>>(
@ -165,38 +108,8 @@ impl EventBuilder {
self self
} }
/// Consumes `ResponseBuilder and returns a `TestRunner`. /// Consumes `ResponseBuilder and returns SyncResponse.
/// pub fn build_sync_response(self) -> SyncResponse {
/// The `TestRunner` responds to requests made by the `AsyncClient`.
pub fn build_with_response<M, P>(mut self, path: P, method: &str, matcher: M) -> MockTestRunner
where
M: Into<mockito::Matcher>,
P: AsRef<Path>,
{
let body = fs::read_to_string(path.as_ref())
.unwrap_or_else(|_| panic!("file not found {:?}", path.as_ref()));
let mock = Some(
mock(method, matcher)
.with_status(200)
.with_body(body)
.create(),
);
MockTestRunner {
client: None,
ephemeral: Vec::new(),
account_data: Vec::new(),
room_events: Vec::new(),
presence_events: Vec::new(),
state_events: Vec::new(),
mock,
}
}
/// Consumes `ResponseBuilder and returns a `TestRunner`.
///
/// The `TestRunner` streams the events to the client and holds methods to make assertions
/// about the state of the client.
pub fn build_mock_runner<P: Into<Matcher>>(mut self, method: &str, path: P) -> MockTestRunner {
let body = serde_json::json! { let body = serde_json::json! {
{ {
"device_one_time_keys_count": {}, "device_one_time_keys_count": {},
@ -240,166 +153,9 @@ impl EventBuilder {
} }
} }
}; };
let mock = Some( let response = Response::builder()
mock(method, path) .body(serde_json::to_vec(&body).unwrap())
.with_status(200) .unwrap();
.with_body(body.to_string()) SyncResponse::try_from(response).unwrap()
.create(),
);
MockTestRunner {
client: None,
ephemeral: Vec::new(),
account_data: Vec::new(),
room_events: Vec::new(),
presence_events: Vec::new(),
state_events: Vec::new(),
mock,
}
}
/// Consumes `ResponseBuilder and returns a `TestRunner`.
///
/// The `TestRunner` streams the events to the `AsyncClient` and holds methods to make assertions
/// about the state of the `AsyncClient`.
pub fn build_client_runner(self, room_id: RoomId, user_id: UserId) -> ClientTestRunner {
ClientTestRunner {
client: None,
room_user_id: (room_id, user_id),
ephemeral: self.ephemeral,
account_data: self.account_data,
room_events: self.room_events,
presence_events: self.presence_events,
state_events: self.state_events,
}
}
/// Consumes `ResponseBuilder and returns a `TestRunner`.
///
/// The `TestRunner` streams the events to the `Room` and holds methods to make assertions
/// about the state of the `Room`.
pub fn build_room_runner(self, room_id: &RoomId, user_id: &UserId) -> RoomTestRunner {
RoomTestRunner {
room: Some(Room::new(room_id, user_id)),
ephemeral: self.ephemeral,
account_data: self.account_data,
room_events: self.room_events,
presence_events: self.presence_events,
state_events: self.state_events,
}
}
}
impl RoomTestRunner {
/// Set `Room`
pub fn set_room(&mut self, room: Room) -> &mut Self {
self.room = Some(room);
self
}
fn stream_room_events(&mut self) {
let room = self
.room
.as_mut()
.expect("`Room` must be set use `RoomTestRunner::set_room`");
for event in &self.account_data {
match event {
// Event::IgnoredUserList(iu) => room.handle_ignored_users(iu),
Event::Presence(p) => room.receive_presence_event(p),
// Event::PushRules(pr) => room.handle_push_rules(pr),
_ => todo!("implement more account data events"),
};
}
for event in &self.ephemeral {
match event {
// Event::IgnoredUserList(iu) => room.handle_ignored_users(iu),
Event::Presence(p) => room.receive_presence_event(p),
// Event::PushRules(pr) => room.handle_push_rules(pr),
_ => todo!("implement more account data events"),
};
}
for event in &self.room_events {
room.receive_timeline_event(event);
}
for event in &self.presence_events {
room.receive_presence_event(event);
}
for event in &self.state_events {
room.receive_state_event(event);
}
}
pub fn to_room(&mut self) -> &mut Room {
self.stream_room_events();
self.room.as_mut().unwrap()
}
}
impl ClientTestRunner {
pub fn set_client(&mut self, client: AsyncClient) -> &mut Self {
self.client = Some(client);
self
}
async fn stream_client_events(&mut self) {
let cli = &self
.client
.as_ref()
.expect("`AsyncClient` must be set use `ClientTestRunner::set_client`")
.base_client;
let room_id = &self.room_user_id.0;
for event in &self.account_data {
match event {
// Event::IgnoredUserList(iu) => room.handle_ignored_users(iu),
Event::Presence(p) => cli.receive_presence_event(room_id, p).await,
// Event::PushRules(pr) => room.handle_push_rules(pr),
_ => todo!("implement more account data events"),
};
}
for event in &self.ephemeral {
cli.receive_ephemeral_event(room_id, event).await;
}
for event in &self.room_events {
cli.receive_joined_timeline_event(room_id, &mut EventJson::from(event))
.await;
}
for event in &self.presence_events {
cli.receive_presence_event(room_id, event).await;
}
for event in &self.state_events {
cli.receive_joined_state_event(room_id, event).await;
}
}
pub async fn to_client(&mut self) -> &mut AsyncClient {
self.stream_client_events().await;
self.client.as_mut().unwrap()
}
}
impl MockTestRunner {
pub fn set_client(&mut self, client: AsyncClient) -> &mut Self {
self.client = Some(client);
self
}
pub fn set_mock(mut self, mock: Mock) -> Self {
self.mock = Some(mock);
self
}
pub async fn to_client(&mut self) -> Result<&mut AsyncClient, Error> {
self.client
.as_mut()
.unwrap()
.sync(SyncSettings::default())
.await?;
Ok(self.client.as_mut().unwrap())
} }
} }