From 5957232e5414138756f6e0bc80dff45cfcdf9fc0 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Thu, 7 Nov 2024 16:31:46 +0100 Subject: [PATCH] task(tests): add a `MockClientBuilder` to help with creating `Client`s connected to a `MatrixMockServer` --- crates/matrix-sdk/src/client/mod.rs | 8 +- crates/matrix-sdk/src/test_utils/mocks.rs | 74 +++++++++++++++-- .../tests/integration/room/attachment/mod.rs | 10 +-- .../tests/integration/room/joined.rs | 4 +- .../tests/integration/send_queue.rs | 81 ++++++++----------- crates/matrix-sdk/tests/integration/widget.rs | 2 +- 6 files changed, 113 insertions(+), 66 deletions(-) diff --git a/crates/matrix-sdk/src/client/mod.rs b/crates/matrix-sdk/src/client/mod.rs index e8a6f98fb79..ca0e34c3b42 100644 --- a/crates/matrix-sdk/src/client/mod.rs +++ b/crates/matrix-sdk/src/client/mod.rs @@ -2989,7 +2989,7 @@ pub(crate) mod tests { #[async_test] async fn test_is_room_alias_available_if_alias_is_not_resolved() { let server = MatrixMockServer::new().await; - let client = logged_in_client(Some(server.server().uri())).await; + let client = server.client_builder().build().await; server.mock_room_directory_resolve_alias().not_found().expect(1).mount().await; @@ -3000,7 +3000,7 @@ pub(crate) mod tests { #[async_test] async fn test_is_room_alias_available_if_alias_is_resolved() { let server = MatrixMockServer::new().await; - let client = logged_in_client(Some(server.server().uri())).await; + let client = server.client_builder().build().await; server .mock_room_directory_resolve_alias() @@ -3016,7 +3016,7 @@ pub(crate) mod tests { #[async_test] async fn test_is_room_alias_available_if_error_found() { let server = MatrixMockServer::new().await; - let client = logged_in_client(Some(server.server().uri())).await; + let client = server.client_builder().build().await; server.mock_room_directory_resolve_alias().error500().expect(1).mount().await; @@ -3027,7 +3027,7 @@ pub(crate) mod tests { #[async_test] async fn test_create_room_alias() { let server = MatrixMockServer::new().await; - let client = logged_in_client(Some(server.server().uri())).await; + let client = server.client_builder().build().await; server.mock_create_room_alias().ok().expect(1).mount().await; diff --git a/crates/matrix-sdk/src/test_utils/mocks.rs b/crates/matrix-sdk/src/test_utils/mocks.rs index 3cd2af0123f..7e5d3820678 100644 --- a/crates/matrix-sdk/src/test_utils/mocks.rs +++ b/crates/matrix-sdk/src/test_utils/mocks.rs @@ -19,20 +19,23 @@ use std::sync::{Arc, Mutex}; -use matrix_sdk_base::deserialized_responses::TimelineEvent; +use matrix_sdk_base::{deserialized_responses::TimelineEvent, store::StoreConfig, SessionMeta}; use matrix_sdk_test::{ test_json, InvitedRoomBuilder, JoinedRoomBuilder, KnockedRoomBuilder, LeftRoomBuilder, SyncResponseBuilder, }; -use ruma::{MxcUri, OwnedEventId, OwnedRoomId, RoomId}; +use ruma::{api::MatrixVersion, device_id, user_id, MxcUri, OwnedEventId, OwnedRoomId, RoomId}; use serde_json::json; use wiremock::{ matchers::{body_partial_json, header, method, path, path_regex}, Mock, MockBuilder, MockGuard, MockServer, Respond, ResponseTemplate, Times, }; -use super::logged_in_client; -use crate::{Client, Room}; +use crate::{ + config::RequestConfig, + matrix_auth::{MatrixSession, MatrixSessionTokens}, + Client, ClientBuilder, Room, +}; /// A `wiremock` [`MockServer`] along with useful methods to help mocking Matrix /// client-server API endpoints easily. @@ -80,10 +83,10 @@ impl MatrixMockServer { Self { server, sync_response_builder: Default::default() } } - /// Creates a new [`Client`] configured to use this server, preconfigured - /// with a session expected by the server endpoints. - pub async fn make_client(&self) -> Client { - logged_in_client(Some(self.server.uri().to_string())).await + /// Creates a new [`MockClientBuilder`] configured to use this server, + /// preconfigured with a session expected by the server endpoints. + pub fn client_builder(&self) -> MockClientBuilder { + MockClientBuilder::new(self.server.uri()) } /// Return the underlying server. @@ -550,3 +553,58 @@ impl<'a> MockEndpoint<'a, CreateRoomAliasEndpoint> { MatrixMock { server: self.server, mock } } } + +/// An augmented [`ClientBuilder`] that also allows for handling session login. +pub struct MockClientBuilder { + builder: ClientBuilder, + logged_in: bool, +} + +impl MockClientBuilder { + fn new(homeserver: String) -> Self { + let default_builder = Client::builder() + .homeserver_url(homeserver) + .server_versions([MatrixVersion::V1_0]) + .request_config(RequestConfig::new().disable_retry()); + + Self { builder: default_builder, logged_in: true } + } + + /// Doesn't log-in a user. + /// + /// Authenticated requests will fail if this is called. + pub fn unlogged(mut self) -> Self { + self.logged_in = false; + self + } + + /// Provides another [`StoreConfig`] for the underlying [`ClientBuilder`]. + pub fn store_config(mut self, store_config: StoreConfig) -> Self { + self.builder = self.builder.store_config(store_config); + self + } + + /// Finish building the client into the final [`Client`] instance. + pub async fn build(self) -> Client { + let client = self.builder.build().await.expect("building client failed"); + + if self.logged_in { + client + .matrix_auth() + .restore_session(MatrixSession { + meta: SessionMeta { + user_id: user_id!("@example:localhost").to_owned(), + device_id: device_id!("DEVICEID").to_owned(), + }, + tokens: MatrixSessionTokens { + access_token: "1234".to_owned(), + refresh_token: None, + }, + }) + .await + .unwrap(); + } + + client + } +} diff --git a/crates/matrix-sdk/tests/integration/room/attachment/mod.rs b/crates/matrix-sdk/tests/integration/room/attachment/mod.rs index 22c8a356a4f..f81a6f09c67 100644 --- a/crates/matrix-sdk/tests/integration/room/attachment/mod.rs +++ b/crates/matrix-sdk/tests/integration/room/attachment/mod.rs @@ -40,7 +40,7 @@ async fn test_room_attachment_send() { .mount() .await; - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, &DEFAULT_TEST_ROOM_ID).await; mock.mock_room_state_encryption().plain().mount().await; @@ -82,7 +82,7 @@ async fn test_room_attachment_send_info() { .mount() .await; - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, &DEFAULT_TEST_ROOM_ID).await; mock.mock_room_state_encryption().plain().mount().await; @@ -132,7 +132,7 @@ async fn test_room_attachment_send_wrong_info() { .mount() .await; - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, &DEFAULT_TEST_ROOM_ID).await; mock.mock_room_state_encryption().plain().mount().await; @@ -191,7 +191,7 @@ async fn test_room_attachment_send_info_thumbnail() { // Second request: return the media MXC. mock.mock_upload().expect_mime_type("image/jpeg").ok(&media_mxc).mock_once().mount().await; - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, &DEFAULT_TEST_ROOM_ID).await; mock.mock_room_state_encryption().plain().mount().await; @@ -286,7 +286,7 @@ async fn test_room_attachment_send_mentions() { .mount() .await; - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, &DEFAULT_TEST_ROOM_ID).await; mock.mock_room_state_encryption().plain().mount().await; diff --git a/crates/matrix-sdk/tests/integration/room/joined.rs b/crates/matrix-sdk/tests/integration/room/joined.rs index d8b247685fc..2c81f1caaca 100644 --- a/crates/matrix-sdk/tests/integration/room/joined.rs +++ b/crates/matrix-sdk/tests/integration/room/joined.rs @@ -721,7 +721,7 @@ async fn test_make_reply_event_doesnt_require_event_cache() { // /event query to get details on an event. let mock = MatrixMockServer::new().await; - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let user_id = client.user_id().unwrap().to_owned(); let room_id = room_id!("!galette:saucisse.bzh"); @@ -745,7 +745,7 @@ async fn test_make_reply_event_doesnt_require_event_cache() { #[async_test] async fn test_enable_encryption_doesnt_stay_unencrypted() { let mock = MatrixMockServer::new().await; - let client = mock.make_client().await; + let client = mock.client_builder().build().await; mock.mock_room_state_encryption().plain().mount().await; mock.mock_set_room_state_encryption().ok(event_id!("$1")).mount().await; diff --git a/crates/matrix-sdk/tests/integration/send_queue.rs b/crates/matrix-sdk/tests/integration/send_queue.rs index 6cb96670d2a..51529c9b122 100644 --- a/crates/matrix-sdk/tests/integration/send_queue.rs +++ b/crates/matrix-sdk/tests/integration/send_queue.rs @@ -3,7 +3,7 @@ use std::{ops::Not as _, sync::Arc, time::Duration}; use assert_matches2::{assert_let, assert_matches}; use matrix_sdk::{ attachment::{AttachmentConfig, AttachmentInfo, BaseImageInfo, BaseThumbnailInfo, Thumbnail}, - config::{RequestConfig, StoreConfig}, + config::StoreConfig, media::{MediaFormat, MediaRequestParameters, MediaThumbnailSettings}, send_queue::{ LocalEcho, LocalEchoContent, RoomSendQueueError, RoomSendQueueStorageError, @@ -11,15 +11,12 @@ use matrix_sdk::{ }, test_utils::{ events::EventFactory, - logged_in_client, mocks::{MatrixMock, MatrixMockServer}, - set_client_session, }, - Client, MemoryStore, + MemoryStore, }; use matrix_sdk_test::{async_test, InvitedRoomBuilder, KnockedRoomBuilder, LeftRoomBuilder}; use ruma::{ - api::MatrixVersion, event_id, events::{ poll::unstable_start::{ @@ -210,7 +207,7 @@ async fn test_cant_send_invited_room() { // When I'm invited to a room, let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_room(&client, room_id, InvitedRoomBuilder::new(room_id)).await; // I can't send message to it with the send queue. @@ -226,7 +223,7 @@ async fn test_cant_send_left_room() { // When I've left a room, let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_room(&client, room_id, LeftRoomBuilder::new(room_id)).await; // I can't send message to it with the send queue. @@ -244,7 +241,7 @@ async fn test_cant_send_knocked_room() { // When I've knocked into a room, let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_room(&client, room_id, KnockedRoomBuilder::new(room_id)).await; // I can't send message to it with the send queue. @@ -262,7 +259,7 @@ async fn test_nothing_sent_when_disabled() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; // When I disable the send queue, @@ -294,7 +291,7 @@ async fn test_smoke() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let q = room.send_queue(); @@ -359,7 +356,7 @@ async fn test_smoke_raw() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let q = room.send_queue(); @@ -402,7 +399,7 @@ async fn test_smoke_raw() { async fn test_error_then_locally_reenabling() { let mock = MatrixMockServer::new().await; - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let mut errors = client.send_queue().subscribe_errors(); // Starting with a globally enabled queue. @@ -504,7 +501,7 @@ async fn test_error_then_locally_reenabling() { async fn test_error_then_globally_reenabling() { let mock = MatrixMockServer::new().await; - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let mut errors = client.send_queue().subscribe_errors(); // Starting with a globally enabled queue. @@ -571,7 +568,7 @@ async fn test_reenabling_queue() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let errors = client.send_queue().subscribe_errors(); @@ -644,7 +641,7 @@ async fn test_disjoint_enabled_status() { let room_id1 = room_id!("!a:b.c"); let room_id2 = room_id!("!b:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room1 = mock.sync_joined_room(&client, room_id1).await; let room2 = mock.sync_joined_room(&client, room_id2).await; @@ -679,7 +676,7 @@ async fn test_cancellation() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let q = room.send_queue(); @@ -796,7 +793,7 @@ async fn test_edit() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let q = room.send_queue(); @@ -900,7 +897,7 @@ async fn test_edit_with_poll_start() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let q = room.send_queue(); @@ -1028,7 +1025,7 @@ async fn test_edit_while_being_sent_and_fails() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let q = room.send_queue(); @@ -1109,7 +1106,7 @@ async fn test_edit_wakes_the_sending_task() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let q = room.send_queue(); @@ -1159,7 +1156,7 @@ async fn test_abort_after_disable() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let mut errors = client.send_queue().subscribe_errors(); @@ -1217,7 +1214,7 @@ async fn test_abort_or_edit_after_send() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; // Start with an enabled sending queue. @@ -1260,7 +1257,7 @@ async fn test_abort_while_being_sent_and_fails() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let q = room.send_queue(); @@ -1329,7 +1326,7 @@ async fn test_unrecoverable_errors() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let mut errors = client.send_queue().subscribe_errors(); @@ -1391,7 +1388,7 @@ async fn test_unwedge_unrecoverable_errors() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let mut errors = client.send_queue().subscribe_errors(); @@ -1457,8 +1454,8 @@ async fn test_no_network_access_error_is_recoverable() { // server in a static. Using the line below will create a "bare" server, // which is effectively dropped upon `drop()`. let server = wiremock::MockServer::builder().start().await; - let client = logged_in_client(Some(server.uri().to_string())).await; let mock = MatrixMockServer::from_server(server); + let client = mock.client_builder().build().await; // Mark the room as joined. let room_id = room_id!("!a:b.c"); @@ -1512,20 +1509,16 @@ async fn test_reloading_rooms_with_unsent_events() { let room_id2 = room_id!("!d:e.f"); let server = wiremock::MockServer::start().await; - let client = Client::builder() - .homeserver_url(server.uri()) - .server_versions([MatrixVersion::V1_0]) + let mock = MatrixMockServer::from_server(server); + + let client = mock + .client_builder() .store_config( StoreConfig::new("cross-process-store-locks-holder-name".to_owned()) .state_store(store.clone()), ) - .request_config(RequestConfig::new().disable_retry()) .build() - .await - .unwrap(); - set_client_session(&client).await; - - let mock = MatrixMockServer::from_server(server); + .await; // Mark two rooms as joined. let room = mock.sync_joined_room(&client, room_id).await; @@ -1570,19 +1563,15 @@ async fn test_reloading_rooms_with_unsent_events() { mock.mock_room_send().ok(event_id!("$1")).mock_once().mount().await; mock.mock_room_send().ok(event_id!("$2")).mock_once().mount().await; - let client = Client::builder() - .homeserver_url(mock.server().uri()) - .server_versions([MatrixVersion::V1_0]) + let new_client = mock + .client_builder() .store_config( StoreConfig::new("cross-process-store-locks-holder-name".to_owned()).state_store(store), ) - .request_config(RequestConfig::new().disable_retry()) .build() - .await - .unwrap(); - set_client_session(&client).await; + .await; - client.send_queue().respawn_tasks_for_rooms_with_unsent_requests().await; + new_client.send_queue().respawn_tasks_for_rooms_with_unsent_requests().await; // Let the sending queues process events. sleep(Duration::from_secs(1)).await; @@ -1597,7 +1586,7 @@ async fn test_reactions() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let q = room.send_queue(); @@ -1720,7 +1709,7 @@ async fn test_media_uploads() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let q = room.send_queue(); @@ -1940,7 +1929,7 @@ async fn test_media_upload_retry() { // Mark the room as joined. let room_id = room_id!("!a:b.c"); - let client = mock.make_client().await; + let client = mock.client_builder().build().await; let room = mock.sync_joined_room(&client, room_id).await; let q = room.send_queue(); diff --git a/crates/matrix-sdk/tests/integration/widget.rs b/crates/matrix-sdk/tests/integration/widget.rs index 909880dcd40..e03b73a9a62 100644 --- a/crates/matrix-sdk/tests/integration/widget.rs +++ b/crates/matrix-sdk/tests/integration/widget.rs @@ -74,7 +74,7 @@ async fn run_test_driver( } } let mock_server = MatrixMockServer::new().await; - let client = mock_server.make_client().await; + let client = mock_server.client_builder().build().await; let room = mock_server.sync_joined_room(&client, &ROOM_ID).await; mock_server.mock_room_state_encryption().plain().mount().await;