#![allow(dead_code)]
use assert_matches2::assert_let;
use matrix_sdk_base::{deserialized_responses::TimelineEvent, store::RoomLoadSettings};
use ruma::{
api::MatrixVersion,
events::{AnySyncMessageLikeEvent, AnySyncTimelineEvent, room::message::MessageType},
};
use url::Url;
pub mod client;
#[cfg(not(target_family = "wasm"))]
pub mod mocks;
use self::client::mock_matrix_session;
use crate::{Client, ClientBuilder, config::RequestConfig};
#[track_caller]
pub fn assert_event_matches_msg<E: Clone + Into<TimelineEvent>>(event: &E, expected: &str) {
let event: TimelineEvent = event.clone().into();
let event = event.raw().deserialize().unwrap();
assert_let!(
AnySyncTimelineEvent::MessageLike(AnySyncMessageLikeEvent::RoomMessage(message)) = event
);
let message = message.as_original().unwrap();
assert_let!(MessageType::Text(text) = &message.content.msgtype);
assert_eq!(text.body, expected);
}
pub fn test_client_builder(homeserver_url: Option<String>) -> ClientBuilder {
let homeserver = homeserver_url
.map(|url| Url::try_from(url.as_str()).unwrap())
.unwrap_or_else(|| Url::try_from("http://localhost:1234").unwrap());
Client::builder().homeserver_url(homeserver).server_versions([MatrixVersion::V1_0])
}
pub async fn no_retry_test_client(homeserver_url: Option<String>) -> Client {
test_client_builder(homeserver_url)
.request_config(RequestConfig::new().disable_retry())
.build()
.await
.unwrap()
}
pub async fn set_client_session(client: &Client) {
client
.matrix_auth()
.restore_session(mock_matrix_session(), RoomLoadSettings::default())
.await
.unwrap();
}
pub async fn logged_in_client(homeserver_url: Option<String>) -> Client {
let client = no_retry_test_client(homeserver_url).await;
set_client_session(&client).await;
client
}
#[cfg(not(target_family = "wasm"))]
pub async fn test_client_builder_with_server() -> (ClientBuilder, wiremock::MockServer) {
let server = wiremock::MockServer::start().await;
let builder = test_client_builder(Some(server.uri()));
(builder, server)
}
#[cfg(not(target_family = "wasm"))]
pub async fn no_retry_test_client_with_server() -> (Client, wiremock::MockServer) {
let server = wiremock::MockServer::start().await;
let client = no_retry_test_client(Some(server.uri().to_string())).await;
(client, server)
}
#[cfg(not(target_family = "wasm"))]
pub async fn logged_in_client_with_server() -> (Client, wiremock::MockServer) {
let server = wiremock::MockServer::start().await;
let client = logged_in_client(Some(server.uri().to_string())).await;
(client, server)
}
#[macro_export]
macro_rules! assert_next_with_timeout {
($stream:expr) => {
$crate::assert_next_with_timeout!($stream, 500)
};
($stream:expr, $timeout_ms:expr) => {{
#[allow(unused_imports)]
use futures_util::StreamExt as _;
tokio::time::timeout(std::time::Duration::from_millis($timeout_ms), $stream.next())
.await
.expect("Next event timed out")
.expect("No next event received")
}};
}
#[macro_export]
macro_rules! assert_recv_with_timeout {
($receiver:expr) => {
$crate::assert_recv_with_timeout!($receiver, 500)
};
($receiver:expr, $timeout_ms:expr) => {{
tokio::time::timeout(std::time::Duration::from_millis($timeout_ms), $receiver.recv())
.await
.expect("Next event timed out")
.expect("No next event received")
}};
}
#[macro_export]
macro_rules! assert_next_matches_with_timeout {
($stream:expr, $pat:pat) => {
$crate::assert_next_matches_with_timeout!($stream, $pat => {})
};
($stream:expr, $pat:pat => $arm:expr) => {
$crate::assert_next_matches_with_timeout!($stream, 100, $pat => $arm)
};
($stream:expr, $timeout_ms:expr, $pat:pat) => {
$crate::assert_next_matches_with_timeout!($stream, $timeout_ms, $pat => {})
};
($stream:expr, $timeout_ms:expr, $pat:pat => $arm:expr) => {
match $crate::assert_next_with_timeout!(&mut $stream, $timeout_ms) {
$pat => $arm,
val => {
::core::panic!(
"assertion failed: `{:?}` does not match `{}`",
val, ::core::stringify!($pat)
);
}
}
};
}
#[macro_export]
macro_rules! assert_next_eq_with_timeout {
($stream:expr, $expected:expr) => {
$crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis(100));
};
($stream:expr, $expected:expr, $timeout:literal ms) => {
$crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis($timeout));
};
($stream:expr, $expected:expr, $timeout:literal ms, $($msg:tt)*) => {
$crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis($timeout), $($msg)*);
};
($stream:expr, $expected:expr, $($msg:tt)*) => {
$crate::assert_next_eq_with_timeout_impl!($stream, $expected, std::time::Duration::from_millis(100), $($msg)*);
};
}
#[macro_export]
macro_rules! assert_decrypted_message_eq {
($event:expr, $expected:expr, $($msg:tt)*) => {{
assert_matches2::assert_let!($crate::deserialized_responses::TimelineEventKind::Decrypted(decrypted_event) = $event.kind);
let deserialized_event = decrypted_event
.event
.deserialize()
.expect("We should be able to deserialize the decrypted event");
assert_matches2::assert_let!(
$crate::ruma::events::AnyTimelineEvent::MessageLike(deserialized_event) = deserialized_event
);
let content =
deserialized_event.original_content().expect("The event should not have been redacted");
assert_matches2::assert_let!($crate::ruma::events::AnyMessageLikeEventContent::RoomMessage(content) = content);
assert_eq!(content.body(), $expected, $($msg)*);
}};
($event:expr, $expected:expr) => {{
assert_decrypted_message_eq!($event, $expected, "The decrypted content did not match to the expected value");
}};
}
#[macro_export]
macro_rules! assert_let_decrypted_state_event_content {
($pat:pat = $event:expr, $($msg:tt)*) => {
assert_matches2::assert_let!(
$crate::deserialized_responses::TimelineEventKind::Decrypted(decrypted_event) =
$event.kind,
"Event was not decrypted"
);
let deserialized_event = decrypted_event
.event
.deserialize_as_unchecked::<$crate::ruma::events::AnyStateEvent>()
.expect("We should be able to deserialize the decrypted event");
let content =
deserialized_event.original_content().expect("The event should not have been redacted");
assert_matches2::assert_let!($pat = content, $($msg)*);
};
($pat:pat = $event:expr) => {
assert_let_decrypted_state_event_content!(
$pat = $event,
"The decrypted event did not match the expected value"
);
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! assert_next_eq_with_timeout_impl {
($stream:expr, $expected:expr, $timeout:expr) => {
let next_value = tokio::time::timeout(
$timeout,
$stream.next()
)
.await
.expect("We should be able to get the next value out of the stream by now")
.expect("The stream should have given us a new value instead of None");
assert_eq!(next_value, $expected);
};
($stream:expr, $expected:expr, $timeout:expr, $($msg:tt)*) => {{
let next_value = tokio::time::timeout(
$timeout,
futures_util::StreamExt::next(&mut $stream)
)
.await
.expect("We should be able to get the next value out of the stream by now")
.expect("The stream should have given us a new value instead of None");
assert_eq!(next_value, $expected, $($msg)*);
}};
}
#[macro_export]
macro_rules! assert_let_timeout {
($timeout:expr, $pat:pat = $future:expr) => {
assert_matches2::assert_let!(Ok($pat) = tokio::time::timeout($timeout, $future).await);
};
($pat:pat = $future:expr) => {
assert_let_timeout!(std::time::Duration::from_millis(100), $pat = $future);
};
}