matrix_sdk/test_utils/
mod.rs1#![allow(dead_code)]
4
5use assert_matches2::assert_let;
6use matrix_sdk_base::{deserialized_responses::TimelineEvent, store::RoomLoadSettings};
7use ruma::{
8 api::MatrixVersion,
9 events::{AnySyncMessageLikeEvent, AnySyncTimelineEvent, room::message::MessageType},
10};
11use url::Url;
12
13pub mod client;
14#[cfg(not(target_family = "wasm"))]
15pub mod mocks;
16
17use self::client::mock_matrix_session;
18use crate::{Client, ClientBuilder, config::RequestConfig};
19
20#[track_caller]
22pub fn assert_event_matches_msg<E: Clone + Into<TimelineEvent>>(event: &E, expected: &str) {
23 let event: TimelineEvent = event.clone().into();
24 let event = event.raw().deserialize().unwrap();
25 assert_let!(
26 AnySyncTimelineEvent::MessageLike(AnySyncMessageLikeEvent::RoomMessage(message)) = event
27 );
28 let message = message.as_original().unwrap();
29 assert_let!(MessageType::Text(text) = &message.content.msgtype);
30 assert_eq!(text.body, expected);
31}
32
33pub fn test_client_builder(homeserver_url: Option<String>) -> ClientBuilder {
36 let homeserver = homeserver_url
37 .map(|url| Url::try_from(url.as_str()).unwrap())
38 .unwrap_or_else(|| Url::try_from("http://localhost:1234").unwrap());
39 Client::builder().homeserver_url(homeserver).server_versions([MatrixVersion::V1_0])
40}
41
42pub async fn no_retry_test_client(homeserver_url: Option<String>) -> Client {
45 test_client_builder(homeserver_url)
46 .request_config(RequestConfig::new().disable_retry())
47 .build()
48 .await
49 .unwrap()
50}
51
52pub async fn set_client_session(client: &Client) {
54 client
55 .matrix_auth()
56 .restore_session(mock_matrix_session(), RoomLoadSettings::default())
57 .await
58 .unwrap();
59}
60
61pub async fn logged_in_client(homeserver_url: Option<String>) -> Client {
65 let client = no_retry_test_client(homeserver_url).await;
66 set_client_session(&client).await;
67 client
68}
69
70#[cfg(not(target_family = "wasm"))]
72pub async fn test_client_builder_with_server() -> (ClientBuilder, wiremock::MockServer) {
73 let server = wiremock::MockServer::start().await;
74 let builder = test_client_builder(Some(server.uri()));
75 (builder, server)
76}
77
78#[cfg(not(target_family = "wasm"))]
80pub async fn no_retry_test_client_with_server() -> (Client, wiremock::MockServer) {
81 let server = wiremock::MockServer::start().await;
82 let client = no_retry_test_client(Some(server.uri().to_string())).await;
83 (client, server)
84}
85
86#[cfg(not(target_family = "wasm"))]
88pub async fn logged_in_client_with_server() -> (Client, wiremock::MockServer) {
89 let server = wiremock::MockServer::start().await;
90 let client = logged_in_client(Some(server.uri().to_string())).await;
91 (client, server)
92}
93
94#[macro_export]
122macro_rules! assert_next_with_timeout {
123 ($stream:expr) => {
124 $crate::assert_next_with_timeout!($stream, 500)
125 };
126 ($stream:expr, $timeout_ms:expr) => {{
127 #[allow(unused_imports)]
129 use futures_util::StreamExt as _;
130 tokio::time::timeout(std::time::Duration::from_millis($timeout_ms), $stream.next())
131 .await
132 .expect("Next event timed out")
133 .expect("No next event received")
134 }};
135}
136
137#[macro_export]
171macro_rules! assert_recv_with_timeout {
172 ($receiver:expr) => {
173 $crate::assert_recv_with_timeout!($receiver, 500)
174 };
175
176 ($receiver:expr, $timeout_ms:expr) => {{
177 tokio::time::timeout(std::time::Duration::from_millis($timeout_ms), $receiver.recv())
178 .await
179 .expect("Next event timed out")
180 .expect("No next event received")
181 }};
182}
183
184#[macro_export]
189macro_rules! assert_next_matches_with_timeout {
190 ($stream:expr, $pat:pat) => {
191 $crate::assert_next_matches_with_timeout!($stream, $pat => {})
192 };
193 ($stream:expr, $pat:pat => $arm:expr) => {
194 $crate::assert_next_matches_with_timeout!($stream, 100, $pat => $arm)
195 };
196 ($stream:expr, $timeout_ms:expr, $pat:pat) => {
197 $crate::assert_next_matches_with_timeout!($stream, $timeout_ms, $pat => {})
198 };
199 ($stream:expr, $timeout_ms:expr, $pat:pat => $arm:expr) => {
200 match $crate::assert_next_with_timeout!(&mut $stream, $timeout_ms) {
201 $pat => $arm,
202 val => {
203 ::core::panic!(
204 "assertion failed: `{:?}` does not match `{}`",
205 val, ::core::stringify!($pat)
206 );
207 }
208 }
209 };
210}
211
212#[macro_export]
248macro_rules! assert_next_eq_with_timeout {
249 ($stream:expr, $expected:expr) => {
250 $crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis(100));
251 };
252 ($stream:expr, $expected:expr, $timeout:literal ms) => {
253 $crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis($timeout));
254 };
255 ($stream:expr, $expected:expr, $timeout:literal ms, $($msg:tt)*) => {
256 $crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis($timeout), $($msg)*);
257 };
258 ($stream:expr, $expected:expr, $($msg:tt)*) => {
259 $crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis(100), $($msg)*);
260 };
261}
262
263#[macro_export]
288macro_rules! assert_decrypted_message_eq {
289 ($event:expr, $expected:expr, $($msg:tt)*) => {{
290 assert_matches2::assert_let!($crate::deserialized_responses::TimelineEventKind::Decrypted(decrypted_event) = $event.kind);
291
292 let deserialized_event = decrypted_event
293 .event
294 .deserialize()
295 .expect("We should be able to deserialize the decrypted event");
296
297 assert_matches2::assert_let!(
298 $crate::ruma::events::AnyTimelineEvent::MessageLike(deserialized_event) = deserialized_event
299 );
300
301 let content =
302 deserialized_event.original_content().expect("The event should not have been redacted");
303 assert_matches2::assert_let!($crate::ruma::events::AnyMessageLikeEventContent::RoomMessage(content) = content);
304 assert_eq!(content.body(), $expected, $($msg)*);
305 }};
306 ($event:expr, $expected:expr) => {{
307 assert_decrypted_message_eq!($event, $expected, "The decrypted content did not match to the expected value");
308 }};
309}
310
311#[macro_export]
340macro_rules! assert_let_decrypted_state_event_content {
341 ($pat:pat = $event:expr, $($msg:tt)*) => {
342 assert_matches2::assert_let!(
343 $crate::deserialized_responses::TimelineEventKind::Decrypted(decrypted_event) =
344 $event.kind,
345 "Event was not decrypted"
346 );
347
348 let deserialized_event = decrypted_event
349 .event
350 .deserialize_as_unchecked::<$crate::ruma::events::AnyStateEvent>()
351 .expect("We should be able to deserialize the decrypted event");
352
353 let content =
354 deserialized_event.original_content().expect("The event should not have been redacted");
355
356 assert_matches2::assert_let!($pat = content, $($msg)*);
357 };
358 ($pat:pat = $event:expr) => {
359 assert_let_decrypted_state_event_content!(
360 $pat = $event,
361 "The decrypted event did not match the expected value"
362 );
363 };
364}
365
366#[doc(hidden)]
367#[macro_export]
368macro_rules! assert_next_eq_with_timeout_impl {
369 ($stream:expr, $expected:expr, $timeout:expr) => {
370 let next_value = tokio::time::timeout(
371 $timeout,
372 $stream.next()
373 )
374 .await
375 .expect("We should be able to get the next value out of the stream by now")
376 .expect("The stream should have given us a new value instead of None");
377
378 assert_eq!(next_value, $expected);
379 };
380 ($stream:expr, $expected:expr, $timeout:expr, $($msg:tt)*) => {{
381 let next_value = tokio::time::timeout(
382 $timeout,
383 futures_util::StreamExt::next(&mut $stream)
384 )
385 .await
386 .expect("We should be able to get the next value out of the stream by now")
387 .expect("The stream should have given us a new value instead of None");
388
389 assert_eq!(next_value, $expected, $($msg)*);
390 }};
391}
392
393#[macro_export]
397macro_rules! assert_let_timeout {
398 ($timeout:expr, $pat:pat = $future:expr) => {
399 assert_matches2::assert_let!(Ok($pat) = tokio::time::timeout($timeout, $future).await);
400 };
401
402 ($pat:pat = $future:expr) => {
403 assert_let_timeout!(std::time::Duration::from_millis(100), $pat = $future);
404 };
405}