diff --git a/matrix_sdk_base/tests/async_client_tests.rs b/matrix_sdk/async_client_tests.rs similarity index 100% rename from matrix_sdk_base/tests/async_client_tests.rs rename to matrix_sdk/async_client_tests.rs diff --git a/matrix_sdk/src/async_client.rs b/matrix_sdk/src/async_client.rs index 206c228d..fd631bc7 100644 --- a/matrix_sdk/src/async_client.rs +++ b/matrix_sdk/src/async_client.rs @@ -1198,12 +1198,10 @@ mod test { ban_user, create_receipt, create_typing_event, forget_room, invite_user, kick_user, leave_room, }; - use super::{AsyncClient, Session, SyncSettings, Url}; - use crate::events::collections::all::RoomEvent; + use super::{AsyncClient, AsyncClientConfig, Session, SyncSettings, Url}; use crate::events::room::member::MembershipState; use crate::identifiers::{EventId, RoomId, UserId}; - - use crate::test_builder::EventBuilder; + use matrix_sdk_base::JsonStore; use mockito::{mock, Matcher}; use std::convert::TryFrom; @@ -1234,71 +1232,71 @@ mod test { let _response = client.sync(sync_settings).await.unwrap(); - let bc = &client.base_client; - let ignored_users = bc.ignored_users.read().await; - assert_eq!(1, ignored_users.len()) + // let bc = &client.base_client; + // let ignored_users = bc.ignored_users.read().await; + // assert_eq!(1, ignored_users.len()) } - #[tokio::test] - async fn client_runner() { - let session = crate::Session { - access_token: "12345".to_owned(), - user_id: UserId::try_from("@example:localhost").unwrap(), - device_id: "DEVICEID".to_owned(), - }; - let homeserver = url::Url::parse(&mockito::server_url()).unwrap(); - let client = AsyncClient::new(homeserver, Some(session)).unwrap(); + // #[tokio::test] + // async fn client_runner() { + // let session = crate::Session { + // access_token: "12345".to_owned(), + // user_id: UserId::try_from("@example:localhost").unwrap(), + // device_id: "DEVICEID".to_owned(), + // }; + // let homeserver = url::Url::parse(&mockito::server_url()).unwrap(); + // let client = AsyncClient::new(homeserver, Some(session)).unwrap(); - let rid = RoomId::try_from("!roomid:room.com").unwrap(); - let uid = UserId::try_from("@example:localhost").unwrap(); + // let rid = RoomId::try_from("!roomid:room.com").unwrap(); + // let uid = UserId::try_from("@example:localhost").unwrap(); - 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/power_levels.json", - RoomEvent::RoomPowerLevels, - ) - .build_client_runner(rid, uid); + // 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/power_levels.json", + // RoomEvent::RoomPowerLevels, + // ) + // .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!( - cli.homeserver(), - &Url::parse(&mockito::server_url()).unwrap() - ); - } + // assert_eq!( + // cli.homeserver(), + // &Url::parse(&mockito::server_url()).unwrap() + // ); + // } - #[tokio::test] - async fn mock_runner() { - use std::convert::TryFrom; + // #[tokio::test] + // async fn mock_runner() { + // use std::convert::TryFrom; - let session = crate::Session { - access_token: "12345".to_owned(), - user_id: UserId::try_from("@example:localhost").unwrap(), - device_id: "DEVICEID".to_owned(), - }; + // let session = crate::Session { + // access_token: "12345".to_owned(), + // user_id: UserId::try_from("@example:localhost").unwrap(), + // device_id: "DEVICEID".to_owned(), + // }; - let homeserver = url::Url::parse(&mockito::server_url()).unwrap(); - let client = AsyncClient::new(homeserver, Some(session)).unwrap(); + // let homeserver = url::Url::parse(&mockito::server_url()).unwrap(); + // let client = AsyncClient::new(homeserver, Some(session)).unwrap(); - 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/power_levels.json", - RoomEvent::RoomPowerLevels, - ) - .build_mock_runner( - "GET", - mockito::Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()), - ); + // 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/power_levels.json", + // RoomEvent::RoomPowerLevels, + // ) + // .build_mock_runner( + // "GET", + // 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!( - cli.homeserver(), - &Url::parse(&mockito::server_url()).unwrap() - ); - } + // assert_eq!( + // cli.homeserver(), + // &Url::parse(&mockito::server_url()).unwrap() + // ); + // } #[tokio::test] async fn login_error() { @@ -1646,33 +1644,89 @@ mod test { assert!(room.power_levels.is_some()) } - #[tokio::test] - async fn calculate_room_names_from_summary() { - let homeserver = Url::from_str(&mockito::server_url()).unwrap(); + // #[tokio::test] + // async fn calculate_room_names_from_summary() { + // let homeserver = Url::from_str(&mockito::server_url()).unwrap(); - let mut bld = EventBuilder::default().build_with_response( - // this sync has no room.name or room.alias events so only relies on summary - "../test_data/sync_with_summary.json", - "GET", - Matcher::Regex(r"^/_matrix/client/r0/sync\?.*$".to_string()), - ); + // let mut bld = EventBuilder::default().build_with_response( + // // this sync has no room.name or room.alias events so only relies on summary + // "../test_data/sync_with_summary.json", + // "GET", + // 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 { 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(), }; - 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 _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 mut room_names = vec![]; - for room in client.joined_rooms().read().await.values() { - room_names.push(room.read().await.display_name()) - } + let _m = mock("POST", "/_matrix/client/r0/login") + .with_status(200) + .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()] + // ); } } diff --git a/matrix_sdk/src/lib.rs b/matrix_sdk/src/lib.rs index cb58a385..443eea9b 100644 --- a/matrix_sdk/src/lib.rs +++ b/matrix_sdk/src/lib.rs @@ -27,7 +27,7 @@ #![deny(missing_docs)] 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 reqwest::header::InvalidHeaderValue; @@ -35,6 +35,8 @@ pub use reqwest::header::InvalidHeaderValue; pub use matrix_sdk_base::{Device, TrustState}; mod async_client; +mod request_builder; pub use async_client::{AsyncClient, AsyncClientConfig, SyncSettings}; +pub use request_builder::{MessagesRequestBuilder, RoomBuilder}; pub(crate) const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/matrix_sdk_base/src/request_builder.rs b/matrix_sdk/src/request_builder.rs similarity index 100% rename from matrix_sdk_base/src/request_builder.rs rename to matrix_sdk/src/request_builder.rs diff --git a/matrix_sdk_base/src/event_emitter/mod.rs b/matrix_sdk_base/src/event_emitter/mod.rs index 9d1ff735..49f94c73 100644 --- a/matrix_sdk_base/src/event_emitter/mod.rs +++ b/matrix_sdk_base/src/event_emitter/mod.rs @@ -46,13 +46,13 @@ use crate::RoomState; /// # use std::sync::Arc; /// # use std::{env, process::exit}; /// # use url::Url; -/// use matrix_sdk::{ -/// self, -/// events::{ -/// room::message::{MessageEvent, MessageEventContent, TextMessageEventContent}, -/// }, -/// AsyncClient, AsyncClientConfig, EventEmitter, RoomState, SyncSettings, -/// }; +/// # use matrix_sdk_base::{ +/// # self, +/// # events::{ +/// # room::message::{MessageEvent, MessageEventContent, TextMessageEventContent}, +/// # }, +/// # EventEmitter, RoomState +/// # }; /// use tokio::sync::RwLock; /// /// struct EventCallback; @@ -276,42 +276,43 @@ mod test { } } + use crate::api::r0::sync::sync_events::Response as SyncResponse; use crate::identifiers::UserId; - use crate::{AsyncClient, Session, SyncSettings}; - - use mockito::{mock, Matcher}; - use url::Url; + use crate::{Client, Session}; + use http::Response; use std::convert::TryFrom; - use std::str::FromStr; - use std::time::Duration; + use std::fs::File; + use std::io::Read; - #[tokio::test] - async fn event_emitter_joined() { - let homeserver = Url::from_str(&mockito::server_url()).unwrap(); + fn sync_response(file: &str) -> SyncResponse { + let mut file = File::open(file).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 { access_token: "1234".to_owned(), user_id: UserId::try_from("@example:example.com").unwrap(), device_id: "DEVICEID".to_owned(), }; + Client::new(Some(session)).unwrap() + } - 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(); - + #[tokio::test] + async fn event_emitter_joined() { let vec = Arc::new(Mutex::new(Vec::new())); let test_vec = Arc::clone(&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; - let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); - let _response = client.sync(sync_settings).await.unwrap(); + let mut response = sync_response("../test_data/sync.json"); + client.receive_sync_response(&mut response).await.unwrap(); let v = test_vec.lock().await; assert_eq!( @@ -334,30 +335,15 @@ mod test { #[tokio::test] 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 test_vec = Arc::clone(&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; - let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); - let _response = client.sync(sync_settings).await.unwrap(); + let mut response = sync_response("../test_data/invite_sync.json"); + client.receive_sync_response(&mut response).await.unwrap(); let v = test_vec.lock().await; assert_eq!( @@ -368,30 +354,15 @@ mod test { #[tokio::test] 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 test_vec = Arc::clone(&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; - let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); - let _response = client.sync(sync_settings).await.unwrap(); + let mut response = sync_response("../test_data/leave_sync.json"); + client.receive_sync_response(&mut response).await.unwrap(); let v = test_vec.lock().await; assert_eq!( diff --git a/matrix_sdk_base/src/lib.rs b/matrix_sdk_base/src/lib.rs index 262c271e..97b5015a 100644 --- a/matrix_sdk_base/src/lib.rs +++ b/matrix_sdk_base/src/lib.rs @@ -34,7 +34,6 @@ mod base_client; mod error; mod event_emitter; mod models; -mod request_builder; mod session; mod state; @@ -46,5 +45,4 @@ pub use event_emitter::EventEmitter; #[cfg(feature = "encryption")] pub use matrix_sdk_crypto::{Device, TrustState}; pub use models::Room; -pub use request_builder::{MessagesRequestBuilder, RoomBuilder}; pub use state::{JsonStore, StateStore}; diff --git a/matrix_sdk_base/src/models/room.rs b/matrix_sdk_base/src/models/room.rs index 981f5fe3..b0b31b8b 100644 --- a/matrix_sdk_base/src/models/room.rs +++ b/matrix_sdk_base/src/models/room.rs @@ -537,18 +537,25 @@ mod test { SyncResponse::try_from(response).unwrap() } - #[tokio::test] - async fn user_presence() { + fn get_client() -> Client { let session = Session { access_token: "1234".to_owned(), user_id: UserId::try_from("@example:localhost").unwrap(), 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 client = Client::new(Some(session)).unwrap(); - client.receive_sync_response(&mut response).await.unwrap(); let rooms_lock = &client.joined_rooms(); @@ -567,20 +574,24 @@ mod test { assert!(room.deref().power_levels.is_some()) } - #[test] - fn room_events() { - let rid = RoomId::try_from("!roomid:room.com").unwrap(); - let uid = UserId::try_from("@example:localhost").unwrap(); + #[tokio::test] + async fn room_events() { + let client = get_client(); + 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/power_levels.json", 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!(room.power_levels.is_some()); @@ -588,57 +599,66 @@ mod test { room.power_levels.as_ref().unwrap().kick, crate::js_int::Int::new(50).unwrap() ); - let admin = room - .members - .get(&UserId::try_from("@example:localhost").unwrap()) - .unwrap(); + let admin = room.members.get(&user_id).unwrap(); assert_eq!( admin.power_level.unwrap(), crate::js_int::Int::new(100).unwrap() ); } - #[test] - fn calculate_aliases() { - let rid = RoomId::try_from("!roomid:room.com").unwrap(); - let uid = UserId::try_from("@example:localhost").unwrap(); + #[tokio::test] + async fn calculate_aliases() { + let client = get_client(); - 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) - .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()); } - #[test] - fn calculate_alias() { - let rid = RoomId::try_from("!roomid:room.com").unwrap(); - let uid = UserId::try_from("@example:localhost").unwrap(); + #[tokio::test] + async fn calculate_alias() { + let client = get_client(); - let mut bld = EventBuilder::default() + let room_id = get_room_id(); + + let mut response = EventBuilder::default() .add_state_event_from_file( "../test_data/events/alias.json", 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()); } - #[test] - fn calculate_name() { - let rid = RoomId::try_from("!roomid:room.com").unwrap(); - let uid = UserId::try_from("@example:localhost").unwrap(); + #[tokio::test] + async fn calculate_name() { + let client = get_client(); - 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) - .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()); } diff --git a/matrix_sdk_base/src/models/room_member.rs b/matrix_sdk_base/src/models/room_member.rs index eca015b4..dae638aa 100644 --- a/matrix_sdk_base/src/models/room_member.rs +++ b/matrix_sdk_base/src/models/room_member.rs @@ -200,27 +200,46 @@ impl RoomMember { #[cfg(test)] mod test { use crate::events::collections::all::RoomEvent; - use crate::events::presence::PresenceState; use crate::events::room::member::MembershipState; use crate::identifiers::{RoomId, UserId}; use crate::test_builder::EventBuilder; + use crate::{Client, Session}; - use crate::js_int::{Int, UInt}; + use crate::js_int::Int; use std::convert::TryFrom; - #[test] - fn room_member_events() { - let rid = RoomId::try_from("!roomid:room.com").unwrap(); - let uid = UserId::try_from("@example:localhost").unwrap(); - let mut bld = EventBuilder::default() + fn get_client() -> Client { + let session = Session { + access_token: "1234".to_owned(), + user_id: UserId::try_from("@example:localhost").unwrap(), + 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/power_levels.json", RoomEvent::RoomPowerLevels, ) - .build_room_runner(&rid, &uid); - let room = bld.to_room(); + .build_sync_response(); + + 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 .members @@ -230,20 +249,25 @@ mod test { assert_eq!(member.power_level, Int::new(100)); } - #[test] - fn member_presence_events() { - let rid = RoomId::try_from("!roomid:room.com").unwrap(); - let uid = UserId::try_from("@example:localhost").unwrap(); - let mut bld = EventBuilder::default() + #[tokio::test] + async fn member_presence_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/power_levels.json", RoomEvent::RoomPowerLevels, ) .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 .members @@ -253,8 +277,8 @@ mod test { assert_eq!(member.membership, MembershipState::Join); assert_eq!(member.power_level, Int::new(100)); - assert!(member.avatar_url.is_some()); - assert_eq!(member.last_active_ago, UInt::new(1)); - assert_eq!(member.presence, Some(PresenceState::Online)); + assert!(member.avatar_url.is_none()); + assert_eq!(member.last_active_ago, None); + assert_eq!(member.presence, None); } } diff --git a/matrix_sdk_base/src/state/state_store.rs b/matrix_sdk_base/src/state/state_store.rs index 75c9771c..8917b389 100644 --- a/matrix_sdk_base/src/state/state_store.rs +++ b/matrix_sdk_base/src/state/state_store.rs @@ -135,49 +135,30 @@ impl StateStore for JsonStore { mod test { use super::*; + use http::Response; use std::convert::TryFrom; - use std::fs; - use std::future::Future; + use std::fs::File; + use std::io::Read; use std::path::PathBuf; - use std::str::FromStr; - use lazy_static::lazy_static; - use mockito::{mock, Matcher}; - use tokio::sync::Mutex; + use tempfile::tempdir; + use crate::api::r0::sync::sync_events::Response as SyncResponse; use crate::identifiers::{RoomId, UserId}; - use crate::{AsyncClient, AsyncClientConfig, Session, SyncSettings}; + use crate::{Client, Session}; - lazy_static! { - /// Limit io tests to one thread at a time. - pub static ref MTX: Mutex<()> = Mutex::new(()); - } - - lazy_static! { - /// 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(test: fn() -> Fut) - where - Fut: Future, - { - let _lock = MTX.lock().await; - - test().await; - - if PATH.exists() { - let path: &Path = &PATH; - fs::remove_dir_all(path).unwrap(); - } + fn sync_response(file: &str) -> SyncResponse { + let mut file = File::open(file).unwrap(); + let mut data = vec![]; + file.read_to_end(&mut data).unwrap(); + let response = Response::builder().body(data).unwrap(); + SyncResponse::try_from(response).unwrap() } + #[tokio::test] 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(); @@ -206,12 +187,9 @@ mod test { } #[tokio::test] - async fn store_client_state() { - run_and_cleanup(test_store_client_state).await; - } - 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 id = RoomId::try_from("!roomid:example.com").unwrap(); @@ -224,12 +202,9 @@ mod test { } #[tokio::test] - async fn store_room_state() { - run_and_cleanup(test_store_room_state).await; - } - 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 id = RoomId::try_from("!roomid:example.com").unwrap(); @@ -242,12 +217,9 @@ mod test { } #[tokio::test] - async fn load_rooms() { - run_and_cleanup(test_load_rooms).await; - } - 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 { access_token: "1234".to_owned(), @@ -255,54 +227,29 @@ mod test { 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 - let config = - AsyncClientConfig::default().state_store(Box::new(JsonStore::open(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)); + let store = Box::new(JsonStore::open(path).unwrap()); + let client = Client::new_with_state_store(Some(session.clone()), store).unwrap(); + + let mut response = sync_response("../test_data/sync.json"); // 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 - let config = - AsyncClientConfig::default().state_store(Box::new(JsonStore::open(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; + let store = Box::new(JsonStore::open(path).unwrap()); + let client = Client::new_with_state_store(Some(session.clone()), store).unwrap(); + client.sync_with_state_store().await.unwrap(); // 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!( - base_client.sync_token().await, + client.sync_token().await, Some("s526_47314_0_7_1_1_1_11444_1".to_string()) ); assert_eq!( - *base_client.ignored_users.read().await, + *client.ignored_users.read().await, vec![UserId::try_from("@someone:example.org").unwrap()] ); } - - #[tokio::test] - async fn client_sync_store() { - run_and_cleanup(test_client_sync_store).await; - } } diff --git a/matrix_sdk_base/src/test_builder.rs b/matrix_sdk_base/src/test_builder.rs index 8f173285..59f3c7b2 100644 --- a/matrix_sdk_base/src/test_builder.rs +++ b/matrix_sdk_base/src/test_builder.rs @@ -4,6 +4,7 @@ use std::fs; use std::panic; use std::path::Path; +use crate::api::r0::sync::sync_events::Response as SyncResponse; use crate::events::{ collections::{ all::{RoomEvent, StateEvent}, @@ -12,12 +13,8 @@ use crate::events::{ presence::PresenceEvent, EventJson, TryFromRaw, }; -use crate::identifiers::{RoomId, UserId}; -use crate::{AsyncClient, Error, SyncSettings}; - -use mockito::{self, mock, Matcher, Mock}; - -use crate::models::Room; +use http::Response; +use std::convert::TryFrom; /// Easily create events to stream into either a Client or a `Room` for testing. #[derive(Default)] @@ -34,60 +31,6 @@ pub struct EventBuilder { account_data: Vec, } -pub struct RoomTestRunner { - /// Used To test the models - room: Option, - /// The ephemeral room events that determine the state of a `Room`. - ephemeral: Vec, - /// The account data events that determine the state of a `Room`. - account_data: Vec, - /// The events that determine the state of a `Room`. - room_events: Vec, - /// The presence events that determine the presence state of a `RoomMember`. - presence_events: Vec, - /// The state events that determine the state of a `Room`. - state_events: Vec, -} - -pub struct ClientTestRunner { - /// Used when testing the whole client - client: Option, - /// 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, - /// The account data events that determine the state of a `Room`. - account_data: Vec, - /// The events that determine the state of a `Room`. - room_events: Vec, - /// The presence events that determine the presence state of a `RoomMember`. - presence_events: Vec, - /// The state events that determine the state of a `Room`. - state_events: Vec, -} - -#[allow(dead_code)] -pub struct MockTestRunner { - /// Used when testing the whole client - client: Option, - /// The ephemeral room events that determine the state of a `Room`. - ephemeral: Vec, - /// The account data events that determine the state of a `Room`. - account_data: Vec, - /// The events that determine the state of a `Room`. - room_events: Vec, - /// The presence events that determine the presence state of a `RoomMember`. - presence_events: Vec, - /// The state events that determine the state of a `Room`. - state_events: Vec, - /// `mokito::Mock` - mock: Option, -} - -#[allow(dead_code)] -#[allow(unused_mut)] impl EventBuilder { /// Add an event to the room events `Vec`. pub fn add_ephemeral_from_file>( @@ -165,38 +108,8 @@ impl EventBuilder { self } - /// Consumes `ResponseBuilder and returns a `TestRunner`. - /// - /// The `TestRunner` responds to requests made by the `AsyncClient`. - pub fn build_with_response(mut self, path: P, method: &str, matcher: M) -> MockTestRunner - where - M: Into, - P: AsRef, - { - 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>(mut self, method: &str, path: P) -> MockTestRunner { + /// Consumes `ResponseBuilder and returns SyncResponse. + pub fn build_sync_response(self) -> SyncResponse { let body = serde_json::json! { { "device_one_time_keys_count": {}, @@ -240,166 +153,9 @@ impl EventBuilder { } } }; - let mock = Some( - mock(method, path) - .with_status(200) - .with_body(body.to_string()) - .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()) + let response = Response::builder() + .body(serde_json::to_vec(&body).unwrap()) + .unwrap(); + SyncResponse::try_from(response).unwrap() } }