1use std::{
4 collections::{BTreeMap, BTreeSet, HashMap},
5 str::FromStr,
6};
7
8use assert_matches::assert_matches;
9use growable_bloom_filter::GrowableBloomBuilder;
10use matrix_sdk_common::ttl::TtlValue;
11use matrix_sdk_test::{TestResult, event_factory::EventFactory};
12use ruma::{
13 EventId, MilliSecondsSinceUnixEpoch, OwnedUserId, RoomId, TransactionId, UserId,
14 api::{
15 FeatureFlag, MatrixVersion,
16 client::{
17 discovery::discover_homeserver::HomeserverInfo,
18 rtc::{LiveKitRtcTransport, RtcTransport},
19 },
20 },
21 event_id,
22 events::{
23 AnyGlobalAccountDataEvent, AnyMessageLikeEventContent, AnyRoomAccountDataEvent,
24 AnyStrippedStateEvent, AnySyncStateEvent, GlobalAccountDataEventType,
25 RoomAccountDataEventType, StateEventType, SyncStateEvent,
26 presence::PresenceEvent,
27 receipt::{ReceiptThread, ReceiptType},
28 room::{
29 member::{
30 MembershipState, RoomMemberEventContent, StrippedRoomMemberEvent,
31 SyncRoomMemberEvent,
32 },
33 message::RoomMessageEventContent,
34 power_levels::RoomPowerLevelsEventContent,
35 redaction::SyncRoomRedactionEvent,
36 topic::RoomTopicEventContent,
37 },
38 tag::{TagInfo, TagName, Tags, UserTagName},
39 },
40 mxc_uri, owned_event_id, owned_mxc_uri,
41 presence::PresenceState,
42 profile::{ProfileFieldName, UserProfileChanges, UserProfileUpdate},
43 push::Ruleset,
44 room_id,
45 room_version_rules::AuthorizationRules,
46 serde::Raw,
47 uint, user_id,
48};
49use serde_json::json;
50use strass::assert_let;
51
52#[cfg(feature = "unstable-msc4354")]
53use super::QueuedRequestKind;
54use super::{
55 DependentQueuedRequestKind, DisplayName, DynStateStore, RoomLoadSettings,
56 SupportedVersionsResponse, WellKnownResponse, send_queue::SentRequestKey,
57};
58use crate::{
59 RoomInfo, RoomMemberships, RoomState, StateChanges, StateStoreDataKey, StateStoreDataValue,
60 deserialized_responses::MemberEvent,
61 store::{
62 ChildTransactionId, QueueWedgeError, SerializableEventContent, StateStoreExt,
63 StoredThreadSubscription, ThreadSubscriptionStatus,
64 },
65 utils::RawStateEventWithKeys,
66};
67
68#[allow(async_fn_in_trait)]
73pub trait StateStoreIntegrationTests {
74 async fn populate(&self) -> TestResult;
76 async fn test_topic_redaction(&self) -> TestResult;
78 async fn test_populate_store(&self) -> TestResult;
80 async fn test_member_saving(&self) -> TestResult;
82 async fn test_filter_saving(&self) -> TestResult;
84 async fn test_user_avatar_url_saving(&self) -> TestResult;
86 async fn test_sync_token_saving(&self) -> TestResult;
88 async fn test_utd_hook_manager_data_saving(&self) -> TestResult;
90 async fn test_one_time_key_already_uploaded_data_saving(&self) -> TestResult;
92 async fn test_stripped_member_saving(&self) -> TestResult;
94 async fn test_power_level_saving(&self) -> TestResult;
96 async fn test_receipts_saving(&self) -> TestResult;
98 async fn test_custom_storage(&self) -> TestResult;
100 async fn test_stripped_non_stripped(&self) -> TestResult;
102 async fn test_stripped_state_is_kept_across_saves(&self) -> TestResult;
104 async fn test_room_info_only_save_keeps_room_data(&self) -> TestResult;
106 async fn test_room_removal(&self) -> TestResult;
108 async fn test_profile_removal(&self) -> TestResult;
110 async fn test_presence_saving(&self) -> TestResult;
112 async fn test_display_names_saving(&self) -> TestResult;
114 async fn test_send_queue(&self) -> TestResult;
116 async fn test_send_queue_priority(&self) -> TestResult;
118 async fn test_send_queue_dependents(&self) -> TestResult;
120 async fn test_send_queue_sticky_events(&self) -> TestResult;
122 async fn test_update_send_queue_dependent(&self) -> TestResult;
124 async fn test_supported_versions_saving(&self) -> TestResult;
126 async fn test_well_known_saving(&self) -> TestResult;
128 async fn test_get_room_infos(&self) -> TestResult;
130 async fn test_thread_subscriptions(&self) -> TestResult;
132 async fn test_thread_subscriptions_bulk_upsert(&self) -> TestResult;
134 async fn test_global_profiles_saving(&self) -> TestResult;
136 async fn test_global_profiles_bulk_loading(&self) -> TestResult;
138 async fn test_missing_global_profiles(&self) -> TestResult;
140}
141
142impl StateStoreIntegrationTests for DynStateStore {
143 async fn populate(&self) -> TestResult {
144 let mut changes = StateChanges::default();
145
146 let user_id = user_id();
147 let invited_user_id = invited_user_id();
148 let room_id = room_id();
149 let stripped_room_id = stripped_room_id();
150
151 changes.sync_token = Some("t392-516_47314_0_7_1_1_1_11444_1".to_owned());
152
153 let f = EventFactory::new().sender(user_id);
154 let presence_raw: Raw<PresenceEvent> = f
155 .presence(PresenceState::Online)
156 .avatar_url(mxc_uri!("mxc://localhost/wefuiwegh8742w"))
157 .currently_active(false)
158 .last_active_ago(1)
159 .status_msg("Making cupcakes")
160 .into();
161 let presence_event = presence_raw.deserialize()?;
162 changes.add_presence_event(presence_event, presence_raw);
163
164 let f = EventFactory::new().sender(user_id);
165 let pushrules_raw: Raw<AnyGlobalAccountDataEvent> =
166 f.push_rules(Ruleset::server_default(user_id)).into();
167 let pushrules_event = pushrules_raw.deserialize()?;
168 changes.account_data.insert(pushrules_event.event_type(), pushrules_raw);
169
170 let mut room = RoomInfo::new(room_id, RoomState::Joined);
171 room.mark_as_left();
172
173 let f = EventFactory::new().sender(user_id).room(room_id);
174 let mut tags = Tags::new();
175 tags.insert(TagName::Favorite, TagInfo::new());
176 tags.insert(TagName::User(UserTagName::from_str("u.work").unwrap()), TagInfo::new());
177 let tag_raw: Raw<AnyRoomAccountDataEvent> = f.tag(tags).into();
178 let tag_event = tag_raw.deserialize()?;
179 changes.add_room_account_data(room_id, tag_event, tag_raw);
180
181 let f = EventFactory::new().sender(user_id).room(room_id);
182 let name_raw: Raw<AnySyncStateEvent> = f.room_name("room name").into();
183 let name_event = name_raw.deserialize()?;
184 room.handle_state_event(
185 &mut RawStateEventWithKeys::try_from_raw_state_event(name_raw.clone())
186 .expect("generated state event should be valid"),
187 );
188 changes.add_state_event(room_id, name_event, name_raw);
189
190 let f = EventFactory::new().sender(user_id);
191 let receipt_content = f
192 .room(room_id)
193 .read_receipts()
194 .add(event_id!("$example"), user_id, ReceiptType::Read, ReceiptThread::Unthreaded)
195 .into_content();
196 changes.add_receipts(room_id, receipt_content);
197
198 let topic_event_id = topic_event_id();
199 let topic_raw: Raw<AnySyncStateEvent> = EventFactory::new()
200 .room(room_id)
201 .sender(user_id)
202 .room_topic("😀")
203 .event_id(topic_event_id)
204 .prev_content(RoomTopicEventContent::new("test".to_owned()))
205 .into_raw_sync_state();
206 let topic_event = topic_raw.deserialize()?;
207 room.handle_state_event(
208 &mut RawStateEventWithKeys::try_from_raw_state_event(topic_raw.clone())
209 .expect("generated state event should be valid"),
210 );
211 changes.add_state_event(room_id, topic_event, topic_raw);
212
213 let mut room_ambiguity_map = HashMap::new();
214 let mut room_profiles = BTreeMap::new();
215
216 let f = EventFactory::new().sender(user_id).room(room_id);
217 let member_raw: Raw<SyncRoomMemberEvent> =
218 f.member(user_id).display_name("example").previous(MembershipState::Invite).into();
219 let member_event: SyncRoomMemberEvent = member_raw.deserialize()?;
220 let displayname = DisplayName::new(
221 member_event.as_original().unwrap().content.displayname.as_ref().unwrap(),
222 );
223 room_ambiguity_map.insert(displayname.clone(), BTreeSet::from([user_id.to_owned()]));
224 room_profiles.insert(user_id.to_owned(), (&member_event).into());
225
226 let member_raw: Raw<AnySyncStateEvent> = member_raw.cast_unchecked();
227 let member_state_event = member_raw.deserialize()?;
228 changes.add_state_event(room_id, member_state_event, member_raw);
229
230 let f = EventFactory::new().sender(user_id).room(room_id);
231 let invited_member_raw: Raw<SyncRoomMemberEvent> = f
232 .member(invited_user_id)
233 .invited(invited_user_id)
234 .display_name("example")
235 .avatar_url(mxc_uri!("mxc://localhost/SEsfnsuifSDFSSEF"))
236 .reason("Looking for support")
237 .into();
238 let invited_member_event: SyncRoomMemberEvent = invited_member_raw.deserialize()?;
240 room_ambiguity_map.entry(displayname).or_default().insert(invited_user_id.to_owned());
241 room_profiles.insert(invited_user_id.to_owned(), (&invited_member_event).into());
242
243 let invited_member_raw: Raw<AnySyncStateEvent> = invited_member_raw.cast_unchecked();
244 let invited_member_state_event = invited_member_raw.deserialize()?;
245 changes.add_state_event(room_id, invited_member_state_event, invited_member_raw);
246
247 changes.ambiguity_maps.insert(room_id.to_owned(), room_ambiguity_map);
248 changes.profiles.insert(room_id.to_owned(), room_profiles);
249 changes.add_room(room);
250
251 let mut stripped_room = RoomInfo::new(stripped_room_id, RoomState::Invited);
252
253 let f = EventFactory::new().sender(user_id).room(stripped_room_id);
254 let stripped_name_raw: Raw<AnyStrippedStateEvent> = f.room_name("room name").into();
255 let mut stripped_name_event =
256 RawStateEventWithKeys::try_from_raw_state_event(stripped_name_raw).unwrap();
257 stripped_room.handle_stripped_state_event(&mut stripped_name_event);
258 changes.stripped_state.insert(
259 stripped_room_id.to_owned(),
260 BTreeMap::from([(
261 stripped_name_event.event_type,
262 BTreeMap::from([(stripped_name_event.state_key, stripped_name_event.raw)]),
263 )]),
264 );
265
266 changes.add_room(stripped_room);
267
268 let f = EventFactory::new().sender(user_id).room(stripped_room_id);
269 let stripped_member_raw: Raw<StrippedRoomMemberEvent> =
270 f.member(user_id).display_name("example").into();
271 changes.add_stripped_member(stripped_room_id, user_id, stripped_member_raw);
272
273 self.save_changes(&changes).await?;
274
275 Ok(())
276 }
277
278 async fn test_topic_redaction(&self) -> TestResult {
279 let room_id = room_id();
280 let f = EventFactory::new();
281 self.populate().await?;
282
283 assert!(self.get_kv_data(StateStoreDataKey::SyncToken).await?.is_some());
284 assert_eq!(
285 self.get_state_event_static::<RoomTopicEventContent>(room_id)
286 .await?
287 .expect("room topic found before redaction")
288 .deserialize()
289 .expect("can deserialize room topic before redaction")
290 .as_sync()
291 .expect("room topic is a sync state event")
292 .as_original()
293 .expect("room topic is not redacted yet")
294 .content
295 .topic,
296 "😀"
297 );
298
299 let mut changes = StateChanges::default();
300
301 let topic_event_id = topic_event_id();
302 let redaction_evt: Raw<SyncRoomRedactionEvent> =
303 f.room(room_id).sender(user_id()).redaction(topic_event_id).into_raw();
304
305 changes.add_redaction(room_id, topic_event_id, redaction_evt);
306 self.save_changes(&changes).await?;
307
308 let redacted_event = self
309 .get_state_event_static::<RoomTopicEventContent>(room_id)
310 .await?
311 .expect("room topic found after redaction")
312 .deserialize()
313 .expect("can deserialize room topic after redaction");
314
315 assert_matches!(redacted_event.as_sync(), Some(SyncStateEvent::Redacted(_)));
316
317 Ok(())
318 }
319
320 async fn test_populate_store(&self) -> TestResult {
321 let room_id = room_id();
322 let user_id = user_id();
323 let display_name = DisplayName::new("example");
324
325 self.populate().await?;
326
327 assert!(self.get_kv_data(StateStoreDataKey::SyncToken).await?.is_some());
328 assert!(self.get_presence_event(user_id).await?.is_some());
329 assert_eq!(
330 self.get_room_infos(&RoomLoadSettings::default()).await?.len(),
331 2,
332 "Expected to find 2 room infos"
333 );
334 assert!(
335 self.get_account_data_event(GlobalAccountDataEventType::PushRules).await?.is_some()
336 );
337
338 assert!(self.get_state_event(room_id, StateEventType::RoomName, "").await?.is_some());
339 assert_eq!(
340 self.get_state_events(room_id, StateEventType::RoomTopic).await?.len(),
341 1,
342 "Expected to find 1 room topic"
343 );
344 assert!(self.get_profile(room_id, user_id).await?.is_some());
345 assert!(self.get_member_event(room_id, user_id).await?.is_some());
346 assert_eq!(
347 self.get_user_ids(room_id, RoomMemberships::empty()).await?.len(),
348 2,
349 "Expected to find 2 members for room"
350 );
351 assert_eq!(
352 self.get_user_ids(room_id, RoomMemberships::INVITE).await?.len(),
353 1,
354 "Expected to find 1 invited user ids"
355 );
356 assert_eq!(
357 self.get_user_ids(room_id, RoomMemberships::JOIN).await?.len(),
358 1,
359 "Expected to find 1 joined user ids"
360 );
361 assert_eq!(
362 self.get_users_with_display_name(room_id, &display_name).await?.len(),
363 2,
364 "Expected to find 2 display names for room"
365 );
366 assert!(
367 self.get_room_account_data_event(room_id, RoomAccountDataEventType::Tag)
368 .await?
369 .is_some()
370 );
371 assert!(
372 self.get_user_room_receipt_event(
373 room_id,
374 ReceiptType::Read,
375 &ReceiptThread::Unthreaded,
376 user_id
377 )
378 .await?
379 .is_some()
380 );
381 assert_eq!(
382 self.get_event_room_receipt_events(
383 room_id,
384 ReceiptType::Read,
385 &ReceiptThread::Unthreaded,
386 first_receipt_event_id()
387 )
388 .await?
389 .len(),
390 1,
391 "Expected to find 1 read receipt"
392 );
393 Ok(())
394 }
395
396 async fn test_member_saving(&self) -> TestResult {
397 let room_id = room_id!("!test_member_saving:localhost");
398 let user_id = user_id();
399 let second_user_id = user_id!("@second:localhost");
400 let third_user_id = user_id!("@third:localhost");
401 let unknown_user_id = user_id!("@unknown:localhost");
402
403 let mut user_ids = vec![user_id.to_owned()];
405 assert!(self.get_member_event(room_id, user_id).await?.is_none());
406 let member_events = self
407 .get_state_events_for_keys_static::<RoomMemberEventContent, _, _>(room_id, &user_ids)
408 .await;
409 assert!(member_events?.is_empty());
410 assert!(self.get_profile(room_id, user_id).await?.is_none());
411 let profiles = self.get_profiles(room_id, &user_ids).await;
412 assert!(profiles?.is_empty());
413
414 let mut changes = StateChanges::default();
416 let raw_member_event = membership_event();
417 let profile = raw_member_event.deserialize()?.into();
418 changes
419 .state
420 .entry(room_id.to_owned())
421 .or_default()
422 .entry(StateEventType::RoomMember)
423 .or_default()
424 .insert(user_id.into(), raw_member_event.cast());
425 changes.profiles.entry(room_id.to_owned()).or_default().insert(user_id.to_owned(), profile);
426 self.save_changes(&changes).await?;
427
428 assert!(self.get_member_event(room_id, user_id).await?.is_some());
429 let member_events = self
430 .get_state_events_for_keys_static::<RoomMemberEventContent, _, _>(room_id, &user_ids)
431 .await;
432 assert_eq!(member_events?.len(), 1);
433 let members = self.get_user_ids(room_id, RoomMemberships::empty()).await?;
434 assert_eq!(members.len(), 1, "We expected to find members for the room");
435 assert!(self.get_profile(room_id, user_id).await?.is_some());
436 let profiles = self.get_profiles(room_id, &user_ids).await;
437 assert_eq!(profiles?.len(), 1);
438
439 let mut changes = StateChanges::default();
441 let changes_members = changes
442 .state
443 .entry(room_id.to_owned())
444 .or_default()
445 .entry(StateEventType::RoomMember)
446 .or_default();
447 let changes_profiles = changes.profiles.entry(room_id.to_owned()).or_default();
448 let raw_second_member_event =
449 custom_membership_event(second_user_id, event_id!("$second_member_event"));
450 let second_profile = raw_second_member_event.deserialize()?.into();
451 changes_members.insert(second_user_id.into(), raw_second_member_event.cast());
452 changes_profiles.insert(second_user_id.to_owned(), second_profile);
453 let raw_third_member_event =
454 custom_membership_event(third_user_id, event_id!("$third_member_event"));
455 let third_profile = raw_third_member_event.deserialize()?.into();
456 changes_members.insert(third_user_id.into(), raw_third_member_event.cast());
457 changes_profiles.insert(third_user_id.to_owned(), third_profile);
458 self.save_changes(&changes).await?;
459
460 user_ids.extend([second_user_id.to_owned(), third_user_id.to_owned()]);
461 assert!(self.get_member_event(room_id, second_user_id).await?.is_some());
462 assert!(self.get_member_event(room_id, third_user_id).await?.is_some());
463 let member_events = self
464 .get_state_events_for_keys_static::<RoomMemberEventContent, _, _>(room_id, &user_ids)
465 .await;
466 assert_eq!(member_events?.len(), 3);
467 let members = self.get_user_ids(room_id, RoomMemberships::empty()).await?;
468 assert_eq!(members.len(), 3, "We expected to find members for the room");
469 assert!(self.get_profile(room_id, second_user_id).await?.is_some());
470 assert!(self.get_profile(room_id, third_user_id).await?.is_some());
471 let profiles = self.get_profiles(room_id, &user_ids).await;
472 assert_eq!(profiles?.len(), 3);
473
474 user_ids.push(unknown_user_id.to_owned());
476 let member_events = self
477 .get_state_events_for_keys_static::<RoomMemberEventContent, _, _>(room_id, &user_ids)
478 .await;
479 assert_eq!(member_events?.len(), 3);
480 let profiles = self.get_profiles(room_id, &user_ids).await;
481 assert_eq!(profiles?.len(), 3);
482
483 let member_events = self
485 .get_state_events_for_keys_static::<RoomMemberEventContent, OwnedUserId, _>(
486 room_id,
487 &[],
488 )
489 .await;
490 assert!(member_events?.is_empty());
491 let profiles = self.get_profiles(room_id, &[]).await;
492 assert!(profiles?.is_empty());
493
494 Ok(())
495 }
496
497 async fn test_filter_saving(&self) -> TestResult {
498 let filter_name = "filter_name";
499 let filter_id = "filter_id_1234";
500
501 self.set_kv_data(
502 StateStoreDataKey::Filter(filter_name),
503 StateStoreDataValue::Filter(filter_id.to_owned()),
504 )
505 .await?;
506 assert_let!(
507 Ok(Some(StateStoreDataValue::Filter(stored_filter_id))) =
508 self.get_kv_data(StateStoreDataKey::Filter(filter_name)).await
509 );
510 assert_eq!(stored_filter_id, filter_id);
511
512 self.remove_kv_data(StateStoreDataKey::Filter(filter_name)).await?;
513 assert_matches!(self.get_kv_data(StateStoreDataKey::Filter(filter_name)).await, Ok(None));
514
515 Ok(())
516 }
517
518 async fn test_user_avatar_url_saving(&self) -> TestResult {
519 let user_id = user_id!("@alice:example.org");
520 let url = owned_mxc_uri!("mxc://example.org/poiuyt098");
521
522 self.set_kv_data(
523 StateStoreDataKey::UserAvatarUrl(user_id),
524 StateStoreDataValue::UserAvatarUrl(url.clone()),
525 )
526 .await?;
527
528 assert_let!(
529 Ok(Some(StateStoreDataValue::UserAvatarUrl(stored_url))) =
530 self.get_kv_data(StateStoreDataKey::UserAvatarUrl(user_id)).await
531 );
532 assert_eq!(stored_url, url);
533
534 self.remove_kv_data(StateStoreDataKey::UserAvatarUrl(user_id)).await?;
535 assert_matches!(
536 self.get_kv_data(StateStoreDataKey::UserAvatarUrl(user_id)).await,
537 Ok(None)
538 );
539
540 Ok(())
541 }
542
543 async fn test_supported_versions_saving(&self) -> TestResult {
544 let versions =
545 BTreeSet::from([MatrixVersion::V1_1, MatrixVersion::V1_2, MatrixVersion::V1_11]);
546 let supported_versions = SupportedVersionsResponse {
547 versions: versions.iter().map(|version| version.as_str().unwrap().to_owned()).collect(),
548 unstable_features: [("org.matrix.experimental".to_owned(), true)].into(),
549 };
550
551 self.set_kv_data(
552 StateStoreDataKey::SupportedVersions,
553 StateStoreDataValue::SupportedVersions(TtlValue::new(supported_versions.clone())),
554 )
555 .await?;
556
557 assert_let!(
558 Ok(Some(StateStoreDataValue::SupportedVersions(stored_supported_versions))) =
559 self.get_kv_data(StateStoreDataKey::SupportedVersions).await
560 );
561 let stored_supported_versions = stored_supported_versions.into_data();
562 assert_eq!(supported_versions, stored_supported_versions);
563
564 let stored_supported = stored_supported_versions.supported_versions();
565 assert_eq!(stored_supported.versions, versions);
566 assert_eq!(stored_supported.features.len(), 1);
567 assert!(stored_supported.features.contains(&FeatureFlag::from("org.matrix.experimental")));
568
569 self.remove_kv_data(StateStoreDataKey::SupportedVersions).await?;
570 assert_matches!(self.get_kv_data(StateStoreDataKey::SupportedVersions).await, Ok(None));
571
572 Ok(())
573 }
574
575 async fn test_well_known_saving(&self) -> TestResult {
576 let well_known = WellKnownResponse {
577 homeserver: HomeserverInfo::new("matrix.example.com".to_owned()),
578 identity_server: None,
579 tile_server: None,
580 rtc_foci: vec![RtcTransport::LiveKit(LiveKitRtcTransport::new(
581 "wss://livekit.example.com".to_owned(),
582 ))],
583 };
584
585 self.set_kv_data(
586 StateStoreDataKey::WellKnown,
587 StateStoreDataValue::WellKnown(TtlValue::new(Some(well_known.clone()))),
588 )
589 .await?;
590
591 assert_let!(
592 Ok(Some(StateStoreDataValue::WellKnown(stored_well_known))) =
593 self.get_kv_data(StateStoreDataKey::WellKnown).await
594 );
595 let stored_well_known = stored_well_known.into_data();
596 assert_eq!(stored_well_known, Some(well_known));
597
598 self.remove_kv_data(StateStoreDataKey::WellKnown).await?;
599 assert_matches!(self.get_kv_data(StateStoreDataKey::WellKnown).await, Ok(None));
600
601 self.set_kv_data(
602 StateStoreDataKey::WellKnown,
603 StateStoreDataValue::WellKnown(TtlValue::new(None)),
604 )
605 .await?;
606
607 assert_let!(
608 Ok(Some(StateStoreDataValue::WellKnown(stored_well_known))) =
609 self.get_kv_data(StateStoreDataKey::WellKnown).await
610 );
611 let stored_well_known = stored_well_known.into_data();
612 assert_eq!(stored_well_known, None);
613
614 Ok(())
615 }
616
617 async fn test_sync_token_saving(&self) -> TestResult {
618 let sync_token_1 = "t392-516_47314_0_7_1";
619 let sync_token_2 = "t392-516_47314_0_7_2";
620
621 assert_matches!(self.get_kv_data(StateStoreDataKey::SyncToken).await, Ok(None));
622
623 let changes =
624 StateChanges { sync_token: Some(sync_token_1.to_owned()), ..Default::default() };
625 self.save_changes(&changes).await?;
626 assert_let!(
627 Ok(Some(StateStoreDataValue::SyncToken(stored_sync_token))) =
628 self.get_kv_data(StateStoreDataKey::SyncToken).await
629 );
630 assert_eq!(stored_sync_token, sync_token_1);
631
632 self.set_kv_data(
633 StateStoreDataKey::SyncToken,
634 StateStoreDataValue::SyncToken(sync_token_2.to_owned()),
635 )
636 .await?;
637 assert_let!(
638 Ok(Some(StateStoreDataValue::SyncToken(stored_sync_token))) =
639 self.get_kv_data(StateStoreDataKey::SyncToken).await
640 );
641 assert_eq!(stored_sync_token, sync_token_2);
642
643 self.remove_kv_data(StateStoreDataKey::SyncToken).await?;
644 assert_matches!(self.get_kv_data(StateStoreDataKey::SyncToken).await, Ok(None));
645
646 Ok(())
647 }
648
649 async fn test_utd_hook_manager_data_saving(&self) -> TestResult {
650 assert!(
652 self.get_kv_data(StateStoreDataKey::UtdHookManagerData)
653 .await
654 .expect("Could not read data")
655 .is_none(),
656 "Store was not empty at start"
657 );
658
659 let data = GrowableBloomBuilder::new().build();
661 self.set_kv_data(
662 StateStoreDataKey::UtdHookManagerData,
663 StateStoreDataValue::UtdHookManagerData(data.clone()),
664 )
665 .await
666 .expect("Could not save data");
667
668 let read_data = self
670 .get_kv_data(StateStoreDataKey::UtdHookManagerData)
671 .await
672 .expect("Could not read data")
673 .expect("no data found")
674 .into_utd_hook_manager_data()
675 .expect("not UtdHookManagerData");
676
677 assert_eq!(read_data, data);
678
679 Ok(())
680 }
681
682 async fn test_one_time_key_already_uploaded_data_saving(&self) -> TestResult {
683 assert!(
685 self.get_kv_data(StateStoreDataKey::OneTimeKeyAlreadyUploaded).await?.is_none(),
686 "Store was not empty at start"
687 );
688
689 self.set_kv_data(
690 StateStoreDataKey::OneTimeKeyAlreadyUploaded,
691 StateStoreDataValue::OneTimeKeyAlreadyUploaded,
692 )
693 .await?;
694
695 let data = self.get_kv_data(StateStoreDataKey::OneTimeKeyAlreadyUploaded).await?;
696 data.expect("The loaded data should be Some");
697
698 Ok(())
699 }
700
701 async fn test_stripped_member_saving(&self) -> TestResult {
702 let room_id = room_id!("!test_stripped_member_saving:localhost");
703 let user_id = user_id();
704 let second_user_id = user_id!("@second:localhost");
705 let third_user_id = user_id!("@third:localhost");
706 let unknown_user_id = user_id!("@unknown:localhost");
707
708 assert!(self.get_member_event(room_id, user_id).await?.is_none());
710 let member_events = self
711 .get_state_events_for_keys_static::<RoomMemberEventContent, _, _>(
712 room_id,
713 &[user_id.to_owned()],
714 )
715 .await;
716 assert!(member_events?.is_empty());
717
718 let mut changes = StateChanges::default();
720 changes
721 .stripped_state
722 .entry(room_id.to_owned())
723 .or_default()
724 .entry(StateEventType::RoomMember)
725 .or_default()
726 .insert(user_id.into(), stripped_membership_event().cast());
727 self.save_changes(&changes).await?;
728
729 assert!(self.get_member_event(room_id, user_id).await?.is_some());
730 let member_events = self
731 .get_state_events_for_keys_static::<RoomMemberEventContent, _, _>(
732 room_id,
733 &[user_id.to_owned()],
734 )
735 .await;
736 assert_eq!(member_events?.len(), 1);
737 let members = self.get_user_ids(room_id, RoomMemberships::empty()).await?;
738 assert_eq!(members.len(), 1, "We expected to find members for the room");
739
740 let mut changes = StateChanges::default();
742 let changes_members = changes
743 .stripped_state
744 .entry(room_id.to_owned())
745 .or_default()
746 .entry(StateEventType::RoomMember)
747 .or_default();
748 changes_members
749 .insert(second_user_id.into(), custom_stripped_membership_event(second_user_id).cast());
750 changes_members
751 .insert(third_user_id.into(), custom_stripped_membership_event(third_user_id).cast());
752 self.save_changes(&changes).await?;
753
754 assert!(self.get_member_event(room_id, second_user_id).await?.is_some());
755 assert!(self.get_member_event(room_id, third_user_id).await?.is_some());
756 let member_events = self
757 .get_state_events_for_keys_static::<RoomMemberEventContent, _, _>(
758 room_id,
759 &[user_id.to_owned(), second_user_id.to_owned(), third_user_id.to_owned()],
760 )
761 .await;
762 assert_eq!(member_events?.len(), 3);
763 let members = self.get_user_ids(room_id, RoomMemberships::empty()).await?;
764 assert_eq!(members.len(), 3, "We expected to find members for the room");
765
766 let member_events = self
768 .get_state_events_for_keys_static::<RoomMemberEventContent, _, _>(
769 room_id,
770 &[
771 user_id.to_owned(),
772 second_user_id.to_owned(),
773 third_user_id.to_owned(),
774 unknown_user_id.to_owned(),
775 ],
776 )
777 .await;
778 assert_eq!(member_events?.len(), 3);
779
780 let member_events = self
782 .get_state_events_for_keys_static::<RoomMemberEventContent, OwnedUserId, _>(
783 room_id,
784 &[],
785 )
786 .await;
787 assert!(member_events?.is_empty());
788
789 Ok(())
790 }
791
792 async fn test_power_level_saving(&self) -> TestResult {
793 let room_id = room_id!("!test_power_level_saving:localhost");
794
795 let raw_event = power_level_event();
796 let event = raw_event.deserialize()?;
797
798 assert!(
799 self.get_state_event(room_id, StateEventType::RoomPowerLevels, "").await?.is_none()
800 );
801 let mut changes = StateChanges::default();
802 changes.add_state_event(room_id, event, raw_event);
803
804 self.save_changes(&changes).await?;
805 assert!(
806 self.get_state_event(room_id, StateEventType::RoomPowerLevels, "").await?.is_some()
807 );
808
809 Ok(())
810 }
811
812 async fn test_receipts_saving(&self) -> TestResult {
813 let room_id = room_id!("!test_receipts_saving:localhost");
814
815 let first_event_id = event_id!("$1435641916114394fHBLK:matrix.org");
816 let second_event_id = event_id!("$fHBLK1435641916114394:matrix.org");
817
818 let first_receipt_ts = uint!(1436451550);
819 let second_receipt_ts = uint!(1436451653);
820 let third_receipt_ts = uint!(1436474532);
821
822 let first_receipt_event = serde_json::from_value(json!({
823 first_event_id: {
824 "m.read": {
825 user_id(): {
826 "ts": first_receipt_ts,
827 }
828 }
829 }
830 }))?;
831
832 let second_receipt_event = serde_json::from_value(json!({
833 second_event_id: {
834 "m.read": {
835 user_id(): {
836 "ts": second_receipt_ts,
837 }
838 }
839 }
840 }))?;
841
842 let third_receipt_event = serde_json::from_value(json!({
843 second_event_id: {
844 "m.read": {
845 user_id(): {
846 "ts": third_receipt_ts,
847 "thread_id": "main",
848 }
849 }
850 }
851 }))?;
852
853 assert!(
854 self.get_user_room_receipt_event(
855 room_id,
856 ReceiptType::Read,
857 &ReceiptThread::Unthreaded,
858 user_id()
859 )
860 .await
861 .expect("failed to read unthreaded user room receipt")
862 .is_none()
863 );
864 assert!(
865 self.get_event_room_receipt_events(
866 room_id,
867 ReceiptType::Read,
868 &ReceiptThread::Unthreaded,
869 first_event_id
870 )
871 .await
872 .expect("failed to read unthreaded event room receipt for 1")
873 .is_empty()
874 );
875 assert!(
876 self.get_event_room_receipt_events(
877 room_id,
878 ReceiptType::Read,
879 &ReceiptThread::Unthreaded,
880 second_event_id
881 )
882 .await
883 .expect("failed to read unthreaded event room receipt for 2")
884 .is_empty()
885 );
886
887 let mut changes = StateChanges::default();
888 changes.add_receipts(room_id, first_receipt_event);
889
890 self.save_changes(&changes).await?;
891 let (unthreaded_user_receipt_event_id, unthreaded_user_receipt) = self
892 .get_user_room_receipt_event(
893 room_id,
894 ReceiptType::Read,
895 &ReceiptThread::Unthreaded,
896 user_id(),
897 )
898 .await
899 .expect("failed to read unthreaded user room receipt after save")
900 .unwrap();
901 assert_eq!(unthreaded_user_receipt_event_id, first_event_id);
902 assert_eq!(unthreaded_user_receipt.ts.unwrap().0, first_receipt_ts);
903 let first_event_unthreaded_receipts = self
904 .get_event_room_receipt_events(
905 room_id,
906 ReceiptType::Read,
907 &ReceiptThread::Unthreaded,
908 first_event_id,
909 )
910 .await
911 .expect("failed to read unthreaded event room receipt for 1 after save");
912 assert_eq!(
913 first_event_unthreaded_receipts.len(),
914 1,
915 "Found a wrong number of unthreaded receipts for 1 after save"
916 );
917 assert_eq!(first_event_unthreaded_receipts[0].0, user_id());
918 assert_eq!(first_event_unthreaded_receipts[0].1.ts.unwrap().0, first_receipt_ts);
919 assert!(
920 self.get_event_room_receipt_events(
921 room_id,
922 ReceiptType::Read,
923 &ReceiptThread::Unthreaded,
924 second_event_id
925 )
926 .await
927 .expect("failed to read unthreaded event room receipt for 2 after save")
928 .is_empty()
929 );
930
931 let mut changes = StateChanges::default();
932 changes.add_receipts(room_id, second_receipt_event);
933
934 self.save_changes(&changes).await.expect("Saving works");
935 let (unthreaded_user_receipt_event_id, unthreaded_user_receipt) = self
936 .get_user_room_receipt_event(
937 room_id,
938 ReceiptType::Read,
939 &ReceiptThread::Unthreaded,
940 user_id(),
941 )
942 .await
943 .expect("Getting unthreaded user room receipt after save failed")
944 .unwrap();
945 assert_eq!(unthreaded_user_receipt_event_id, second_event_id);
946 assert_eq!(unthreaded_user_receipt.ts.unwrap().0, second_receipt_ts);
947 assert!(
948 self.get_event_room_receipt_events(
949 room_id,
950 ReceiptType::Read,
951 &ReceiptThread::Unthreaded,
952 first_event_id
953 )
954 .await
955 .expect("Getting unthreaded event room receipt events for first event failed")
956 .is_empty()
957 );
958 let second_event_unthreaded_receipts = self
959 .get_event_room_receipt_events(
960 room_id,
961 ReceiptType::Read,
962 &ReceiptThread::Unthreaded,
963 second_event_id,
964 )
965 .await
966 .expect("Getting unthreaded event room receipt events for second event failed");
967 assert_eq!(
968 second_event_unthreaded_receipts.len(),
969 1,
970 "Found a wrong number of unthreaded receipts for second event after save"
971 );
972 assert_eq!(second_event_unthreaded_receipts[0].0, user_id());
973 assert_eq!(second_event_unthreaded_receipts[0].1.ts.unwrap().0, second_receipt_ts);
974
975 assert!(
976 self.get_user_room_receipt_event(
977 room_id,
978 ReceiptType::Read,
979 &ReceiptThread::Main,
980 user_id()
981 )
982 .await
983 .expect("failed to read threaded user room receipt")
984 .is_none()
985 );
986 assert!(
987 self.get_event_room_receipt_events(
988 room_id,
989 ReceiptType::Read,
990 &ReceiptThread::Main,
991 second_event_id
992 )
993 .await
994 .expect("Getting threaded event room receipts for 2 failed")
995 .is_empty()
996 );
997
998 let mut changes = StateChanges::default();
999 changes.add_receipts(room_id, third_receipt_event);
1000
1001 self.save_changes(&changes).await.expect("Saving works");
1002 let (unthreaded_user_receipt_event_id, unthreaded_user_receipt) = self
1004 .get_user_room_receipt_event(
1005 room_id,
1006 ReceiptType::Read,
1007 &ReceiptThread::Unthreaded,
1008 user_id(),
1009 )
1010 .await
1011 .expect("Getting unthreaded user room receipt after save failed")
1012 .unwrap();
1013 assert_eq!(unthreaded_user_receipt_event_id, second_event_id);
1014 assert_eq!(unthreaded_user_receipt.ts.unwrap().0, second_receipt_ts);
1015 let second_event_unthreaded_receipts = self
1016 .get_event_room_receipt_events(
1017 room_id,
1018 ReceiptType::Read,
1019 &ReceiptThread::Unthreaded,
1020 second_event_id,
1021 )
1022 .await
1023 .expect("Getting unthreaded event room receipt events for second event failed");
1024 assert_eq!(
1025 second_event_unthreaded_receipts.len(),
1026 1,
1027 "Found a wrong number of unthreaded receipts for second event after save"
1028 );
1029 assert_eq!(second_event_unthreaded_receipts[0].0, user_id());
1030 assert_eq!(second_event_unthreaded_receipts[0].1.ts.unwrap().0, second_receipt_ts);
1031 let (threaded_user_receipt_event_id, threaded_user_receipt) = self
1033 .get_user_room_receipt_event(
1034 room_id,
1035 ReceiptType::Read,
1036 &ReceiptThread::Main,
1037 user_id(),
1038 )
1039 .await
1040 .expect("Getting threaded user room receipt after save failed")
1041 .unwrap();
1042 assert_eq!(threaded_user_receipt_event_id, second_event_id);
1043 assert_eq!(threaded_user_receipt.ts.unwrap().0, third_receipt_ts);
1044 let second_event_threaded_receipts = self
1045 .get_event_room_receipt_events(
1046 room_id,
1047 ReceiptType::Read,
1048 &ReceiptThread::Main,
1049 second_event_id,
1050 )
1051 .await
1052 .expect("Getting threaded event room receipt events for second event failed");
1053 assert_eq!(
1054 second_event_threaded_receipts.len(),
1055 1,
1056 "Found a wrong number of threaded receipts for second event after save"
1057 );
1058 assert_eq!(second_event_threaded_receipts[0].0, user_id());
1059 assert_eq!(second_event_threaded_receipts[0].1.ts.unwrap().0, third_receipt_ts);
1060
1061 Ok(())
1062 }
1063
1064 async fn test_custom_storage(&self) -> TestResult {
1065 let key = "my_key";
1066 let value = &[0, 1, 2, 3];
1067
1068 self.set_custom_value(key.as_bytes(), value.to_vec()).await?;
1069
1070 let read = self.get_custom_value(key.as_bytes()).await?;
1071
1072 assert_eq!(Some(value.as_ref()), read.as_deref());
1073
1074 Ok(())
1075 }
1076
1077 async fn test_stripped_non_stripped(&self) -> TestResult {
1078 let room_id = room_id!("!test_stripped_non_stripped:localhost");
1079 let user_id = user_id();
1080
1081 assert!(self.get_member_event(room_id, user_id).await?.is_none());
1082 assert_eq!(self.get_room_infos(&RoomLoadSettings::default()).await?.len(), 0);
1083
1084 let mut changes = StateChanges::default();
1085 changes
1086 .state
1087 .entry(room_id.to_owned())
1088 .or_default()
1089 .entry(StateEventType::RoomMember)
1090 .or_default()
1091 .insert(user_id.into(), membership_event().cast());
1092 changes.add_room(RoomInfo::new(room_id, RoomState::Left));
1093 self.save_changes(&changes).await?;
1094
1095 let member_event = self.get_member_event(room_id, user_id).await?.unwrap().deserialize()?;
1096 assert!(matches!(member_event, MemberEvent::Sync(_)));
1097 assert_eq!(self.get_room_infos(&RoomLoadSettings::default()).await?.len(), 1);
1098
1099 let members = self.get_user_ids(room_id, RoomMemberships::empty()).await?;
1100 assert_eq!(members, vec![user_id.to_owned()]);
1101
1102 let mut changes = StateChanges::default();
1103 changes.add_stripped_member(room_id, user_id, custom_stripped_membership_event(user_id));
1104 changes.add_room(RoomInfo::new(room_id, RoomState::Invited));
1105 self.save_changes(&changes).await?;
1106
1107 let member_event = self.get_member_event(room_id, user_id).await?.unwrap().deserialize()?;
1108 assert!(matches!(member_event, MemberEvent::Stripped(_)));
1109 assert_eq!(self.get_room_infos(&RoomLoadSettings::default()).await?.len(), 1);
1110
1111 let members = self.get_user_ids(room_id, RoomMemberships::empty()).await?;
1112 assert_eq!(members, vec![user_id.to_owned()]);
1113
1114 Ok(())
1115 }
1116
1117 async fn test_stripped_state_is_kept_across_saves(&self) -> TestResult {
1118 for (room_id, room_state) in [
1121 (room_id!("!test_stripped_state_invited:localhost"), RoomState::Invited),
1122 (room_id!("!test_stripped_state_knocked:localhost"), RoomState::Knocked),
1123 ] {
1124 let user_id = user_id();
1125
1126 let mut changes = StateChanges::default();
1127 changes.add_stripped_member(
1128 room_id,
1129 user_id,
1130 custom_stripped_membership_event(user_id),
1131 );
1132
1133 let f = EventFactory::new().sender(user_id).room(room_id);
1134 let stripped_name_raw: Raw<AnyStrippedStateEvent> = f.room_name("room name").into();
1135 let stripped_name_event =
1136 RawStateEventWithKeys::try_from_raw_state_event(stripped_name_raw).unwrap();
1137 changes
1138 .stripped_state
1139 .entry(room_id.to_owned())
1140 .or_default()
1141 .entry(stripped_name_event.event_type)
1142 .or_default()
1143 .insert(stripped_name_event.state_key, stripped_name_event.raw);
1144
1145 changes.add_room(RoomInfo::new(room_id, room_state));
1146 self.save_changes(&changes).await?;
1147
1148 assert!(
1149 self.get_state_event(room_id, StateEventType::RoomName, "").await?.is_some(),
1150 "{room_state:?}: the stripped room name must be saved"
1151 );
1152 let member_event =
1153 self.get_member_event(room_id, user_id).await?.unwrap().deserialize()?;
1154 assert_matches!(member_event, MemberEvent::Stripped(_));
1155
1156 let mut changes = StateChanges::default();
1158 changes.add_room(RoomInfo::new(room_id, room_state));
1159 self.save_changes(&changes).await?;
1160
1161 assert!(
1162 self.get_state_event(room_id, StateEventType::RoomName, "").await?.is_some(),
1163 "{room_state:?}: the stripped room name must survive a room info save"
1164 );
1165 assert!(
1166 self.get_member_event(room_id, user_id).await?.is_some(),
1167 "{room_state:?}: the stripped member must survive a room info save"
1168 );
1169 assert_eq!(
1170 self.get_user_ids(room_id, RoomMemberships::empty()).await?,
1171 vec![user_id.to_owned()],
1172 "{room_state:?}: the stripped member must still be listed"
1173 );
1174 }
1175
1176 Ok(())
1177 }
1178
1179 async fn test_room_info_only_save_keeps_room_data(&self) -> TestResult {
1180 for (room_id, new_state) in [
1184 (room_id!("!test_room_info_only_save_knocked:localhost"), RoomState::Knocked),
1185 (room_id!("!test_room_info_only_save_invited:localhost"), RoomState::Invited),
1186 ] {
1187 let user_id = user_id();
1188
1189 let mut changes = StateChanges::default();
1190 changes
1191 .state
1192 .entry(room_id.to_owned())
1193 .or_default()
1194 .entry(StateEventType::RoomMember)
1195 .or_default()
1196 .insert(user_id.into(), membership_event().cast());
1197
1198 let f = EventFactory::new().sender(user_id).room(room_id);
1199 let name_raw: Raw<AnySyncStateEvent> = f.room_name("room name").into();
1200 let name_event = name_raw.deserialize()?;
1201 changes.add_state_event(room_id, name_event, name_raw);
1202
1203 changes.add_room(RoomInfo::new(room_id, RoomState::Left));
1204 self.save_changes(&changes).await?;
1205
1206 let member_event =
1207 self.get_member_event(room_id, user_id).await?.unwrap().deserialize()?;
1208 assert_matches!(member_event, MemberEvent::Sync(_));
1209 assert!(self.get_state_event(room_id, StateEventType::RoomName, "").await?.is_some());
1210
1211 let mut changes = StateChanges::default();
1213 changes.add_room(RoomInfo::new(room_id, new_state));
1214 self.save_changes(&changes).await?;
1215
1216 let member_event = self
1217 .get_member_event(room_id, user_id)
1218 .await?
1219 .unwrap_or_else(|| {
1220 panic!("{new_state:?}: the member event must survive a room info only save")
1221 })
1222 .deserialize()?;
1223 assert_matches!(member_event, MemberEvent::Sync(_));
1224 assert!(
1225 self.get_state_event(room_id, StateEventType::RoomName, "").await?.is_some(),
1226 "{new_state:?}: the room name must survive a room info only save"
1227 );
1228 assert_eq!(
1229 self.get_user_ids(room_id, RoomMemberships::empty()).await?,
1230 vec![user_id.to_owned()],
1231 "{new_state:?}: the member must still be listed"
1232 );
1233 }
1234
1235 Ok(())
1236 }
1237
1238 async fn test_room_removal(&self) -> TestResult {
1239 let room_id = room_id();
1240 let user_id = user_id();
1241 let display_name = DisplayName::new("example");
1242 let stripped_room_id = stripped_room_id();
1243
1244 self.populate().await?;
1245
1246 {
1247 let txn = TransactionId::new();
1249 let ev =
1250 SerializableEventContent::new(&RoomMessageEventContent::text_plain("sup").into())?;
1251 self.save_send_queue_request(
1252 room_id,
1253 txn.clone(),
1254 MilliSecondsSinceUnixEpoch::now(),
1255 ev.into(),
1256 0,
1257 )
1258 .await?;
1259
1260 self.save_dependent_queued_request(
1262 room_id,
1263 &txn,
1264 ChildTransactionId::new(),
1265 MilliSecondsSinceUnixEpoch::now(),
1266 DependentQueuedRequestKind::RedactEvent,
1267 )
1268 .await?;
1269 }
1270
1271 self.remove_room(room_id).await?;
1272
1273 assert_eq!(
1274 self.get_room_infos(&RoomLoadSettings::default()).await?.len(),
1275 1,
1276 "room is still there"
1277 );
1278
1279 assert!(self.get_state_event(room_id, StateEventType::RoomName, "").await?.is_none());
1280 assert!(
1281 self.get_state_events(room_id, StateEventType::RoomTopic).await?.is_empty(),
1282 "still state events found"
1283 );
1284 assert!(self.get_profile(room_id, user_id).await?.is_none());
1285 assert!(self.get_member_event(room_id, user_id).await?.is_none());
1286 assert!(
1287 self.get_user_ids(room_id, RoomMemberships::empty()).await?.is_empty(),
1288 "still user ids found"
1289 );
1290 assert!(
1291 self.get_user_ids(room_id, RoomMemberships::INVITE).await?.is_empty(),
1292 "still invited user ids found"
1293 );
1294 assert!(
1295 self.get_user_ids(room_id, RoomMemberships::JOIN).await?.is_empty(),
1296 "still joined users found"
1297 );
1298 assert!(
1299 self.get_users_with_display_name(room_id, &display_name).await?.is_empty(),
1300 "still display names found"
1301 );
1302 assert!(
1303 self.get_room_account_data_event(room_id, RoomAccountDataEventType::Tag)
1304 .await?
1305 .is_none()
1306 );
1307 assert!(
1308 self.get_user_room_receipt_event(
1309 room_id,
1310 ReceiptType::Read,
1311 &ReceiptThread::Unthreaded,
1312 user_id
1313 )
1314 .await?
1315 .is_none()
1316 );
1317 assert!(
1318 self.get_event_room_receipt_events(
1319 room_id,
1320 ReceiptType::Read,
1321 &ReceiptThread::Unthreaded,
1322 first_receipt_event_id()
1323 )
1324 .await?
1325 .is_empty(),
1326 "still event receipts in the store"
1327 );
1328 assert!(self.load_send_queue_requests(room_id).await?.is_empty());
1329 assert!(self.load_dependent_queued_requests(room_id).await?.is_empty());
1330
1331 self.remove_room(stripped_room_id).await?;
1332
1333 assert!(
1334 self.get_room_infos(&RoomLoadSettings::default()).await?.is_empty(),
1335 "still room info found"
1336 );
1337 Ok(())
1338 }
1339
1340 async fn test_profile_removal(&self) -> TestResult {
1341 let room_id = room_id();
1342
1343 let user_id = user_id();
1345 let invited_user_id = invited_user_id();
1346
1347 self.populate().await?;
1348
1349 let new_invite_member_json = json!({
1350 "content": {
1351 "avatar_url": "mxc://localhost/SEsfnsuifSDFSSEG",
1352 "displayname": "example after update",
1353 "membership": "invite",
1354 "reason": "Looking for support"
1355 },
1356 "event_id": "$143273582443PhrSm:localhost",
1357 "origin_server_ts": 1432735824,
1358 "room_id": room_id,
1359 "sender": user_id,
1360 "state_key": invited_user_id,
1361 "type": "m.room.member",
1362 });
1363 let new_invite_member_event: SyncRoomMemberEvent =
1364 serde_json::from_value(new_invite_member_json.clone())?;
1365
1366 let mut changes = StateChanges {
1367 profiles_to_delete: [(
1369 room_id.to_owned(),
1370 vec![user_id.to_owned(), invited_user_id.to_owned()],
1371 )]
1372 .into(),
1373
1374 profiles: {
1376 let mut map = BTreeMap::default();
1377 map.insert(
1378 room_id.to_owned(),
1379 [(invited_user_id.to_owned(), new_invite_member_event.into())]
1380 .into_iter()
1381 .collect(),
1382 );
1383 map
1384 },
1385
1386 ..StateChanges::default()
1387 };
1388
1389 let raw = serde_json::from_value::<Raw<AnySyncStateEvent>>(new_invite_member_json)
1390 .expect("can create sync-state-event for topic");
1391 let event = raw.deserialize()?;
1392 changes.add_state_event(room_id, event, raw);
1393
1394 self.save_changes(&changes).await?;
1395
1396 assert!(self.get_profile(room_id, user_id).await?.is_none());
1398 assert!(self.get_member_event(room_id, user_id).await?.is_some());
1399
1400 let invited_member_event = self.get_profile(room_id, invited_user_id).await?.unwrap();
1402 assert_eq!(
1403 invited_member_event.content.displayname.as_deref(),
1404 Some("example after update")
1405 );
1406 assert!(self.get_member_event(room_id, invited_user_id).await?.is_some());
1407
1408 Ok(())
1409 }
1410
1411 async fn test_presence_saving(&self) -> TestResult {
1412 let user_id = user_id();
1413 let second_user_id = user_id!("@second:localhost");
1414 let third_user_id = user_id!("@third:localhost");
1415 let unknown_user_id = user_id!("@unknown:localhost");
1416
1417 let mut user_ids = vec![user_id.to_owned()];
1419 let presence_event = self.get_presence_event(user_id).await;
1420 assert!(presence_event?.is_none());
1421 let presence_events = self.get_presence_events(&user_ids).await;
1422 assert!(presence_events?.is_empty());
1423
1424 let mut changes = StateChanges::default();
1426 changes.presence.insert(user_id.to_owned(), custom_presence_event(user_id));
1427 self.save_changes(&changes).await?;
1428
1429 let presence_event = self.get_presence_event(user_id).await;
1430 assert!(presence_event?.is_some());
1431 let presence_events = self.get_presence_events(&user_ids).await;
1432 assert_eq!(presence_events?.len(), 1);
1433
1434 let mut changes = StateChanges::default();
1436 changes.presence.insert(second_user_id.to_owned(), custom_presence_event(second_user_id));
1437 changes.presence.insert(third_user_id.to_owned(), custom_presence_event(third_user_id));
1438 self.save_changes(&changes).await?;
1439
1440 user_ids.extend([second_user_id.to_owned(), third_user_id.to_owned()]);
1441 let presence_event = self.get_presence_event(second_user_id).await;
1442 assert!(presence_event?.is_some());
1443 let presence_event = self.get_presence_event(third_user_id).await;
1444 assert!(presence_event?.is_some());
1445 let presence_events = self.get_presence_events(&user_ids).await;
1446 assert_eq!(presence_events?.len(), 3);
1447
1448 user_ids.push(unknown_user_id.to_owned());
1450 let member_events = self.get_presence_events(&user_ids).await;
1451 assert_eq!(member_events?.len(), 3);
1452
1453 let presence_events = self.get_presence_events(&[]).await;
1455 assert!(presence_events?.is_empty());
1456
1457 Ok(())
1458 }
1459
1460 async fn test_display_names_saving(&self) -> TestResult {
1461 let room_id = room_id!("!test_display_names_saving:localhost");
1462 let user_id = user_id();
1463 let user_display_name = DisplayName::new("User");
1464 let second_user_id = user_id!("@second:localhost");
1465 let third_user_id = user_id!("@third:localhost");
1466 let other_display_name = DisplayName::new("Raoul");
1467 let unknown_display_name = DisplayName::new("Unknown");
1468
1469 let mut display_names = vec![user_display_name.to_owned()];
1471 let users = self.get_users_with_display_name(room_id, &user_display_name).await?;
1472 assert!(users.is_empty());
1473 let names = self.get_users_with_display_names(room_id, &display_names).await?;
1474 assert!(names.is_empty());
1475
1476 let mut changes = StateChanges::default();
1478 changes
1479 .ambiguity_maps
1480 .entry(room_id.to_owned())
1481 .or_default()
1482 .insert(user_display_name.to_owned(), [user_id.to_owned()].into());
1483 self.save_changes(&changes).await?;
1484
1485 let users = self.get_users_with_display_name(room_id, &user_display_name).await?;
1486 assert_eq!(users.len(), 1);
1487 let names = self.get_users_with_display_names(room_id, &display_names).await?;
1488 assert_eq!(names.len(), 1);
1489 assert_eq!(names.get(&user_display_name).unwrap().len(), 1);
1490
1491 let mut changes = StateChanges::default();
1493 changes.ambiguity_maps.entry(room_id.to_owned()).or_default().insert(
1494 other_display_name.to_owned(),
1495 [second_user_id.to_owned(), third_user_id.to_owned()].into(),
1496 );
1497 self.save_changes(&changes).await?;
1498
1499 display_names.push(other_display_name.to_owned());
1500 let users = self.get_users_with_display_name(room_id, &user_display_name).await?;
1501 assert_eq!(users.len(), 1);
1502 let users = self.get_users_with_display_name(room_id, &other_display_name).await?;
1503 assert_eq!(users.len(), 2);
1504 let names = self.get_users_with_display_names(room_id, &display_names).await?;
1505 assert_eq!(names.len(), 2);
1506 assert_eq!(names.get(&user_display_name).unwrap().len(), 1);
1507 assert_eq!(names.get(&other_display_name).unwrap().len(), 2);
1508
1509 display_names.push(unknown_display_name.to_owned());
1511 let names = self.get_users_with_display_names(room_id, &display_names).await?;
1512 assert_eq!(names.len(), 2);
1513
1514 let names = self.get_users_with_display_names(room_id, &[]).await?;
1516 assert!(names.is_empty());
1517
1518 Ok(())
1519 }
1520
1521 #[allow(clippy::needless_range_loop)]
1522 async fn test_send_queue(&self) -> TestResult {
1523 let room_id = room_id!("!test_send_queue:localhost");
1524
1525 let events = self.load_send_queue_requests(room_id).await?;
1527 assert!(events.is_empty());
1528
1529 let txn0 = TransactionId::new();
1531 let event0 =
1532 SerializableEventContent::new(&RoomMessageEventContent::text_plain("msg0").into())?;
1533 self.save_send_queue_request(
1534 room_id,
1535 txn0.clone(),
1536 MilliSecondsSinceUnixEpoch::now(),
1537 event0.into(),
1538 0,
1539 )
1540 .await?;
1541
1542 let pending = self.load_send_queue_requests(room_id).await?;
1544
1545 assert_eq!(pending.len(), 1);
1546 {
1547 assert_eq!(pending[0].transaction_id, txn0);
1548
1549 let deserialized = pending[0].as_event().unwrap().deserialize()?;
1550 assert_let!(AnyMessageLikeEventContent::RoomMessage(content) = deserialized);
1551 assert_eq!(content.body(), "msg0");
1552
1553 assert!(!pending[0].is_wedged());
1554 }
1555
1556 for i in 1..=3 {
1558 let txn = TransactionId::new();
1559 let event = SerializableEventContent::new(
1560 &RoomMessageEventContent::text_plain(format!("msg{i}")).into(),
1561 )?;
1562
1563 self.save_send_queue_request(
1564 room_id,
1565 txn,
1566 MilliSecondsSinceUnixEpoch::now(),
1567 event.into(),
1568 0,
1569 )
1570 .await?;
1571 }
1572
1573 let pending = self.load_send_queue_requests(room_id).await?;
1575
1576 assert_eq!(pending.len(), 4);
1578
1579 assert_eq!(pending[0].transaction_id, txn0);
1580
1581 for i in 0..4 {
1582 let deserialized = pending[i].as_event().unwrap().deserialize()?;
1583 assert_let!(AnyMessageLikeEventContent::RoomMessage(content) = deserialized);
1584 assert_eq!(content.body(), format!("msg{i}"));
1585 assert!(!pending[i].is_wedged());
1586 }
1587
1588 let txn2 = &pending[2].transaction_id;
1590 self.update_send_queue_request_status(
1591 room_id,
1592 txn2,
1593 Some(QueueWedgeError::GenericApiError { msg: "Oops".to_owned() }),
1594 )
1595 .await?;
1596
1597 let pending = self.load_send_queue_requests(room_id).await?;
1599
1600 assert_eq!(pending.len(), 4);
1602 assert_eq!(pending[0].transaction_id, txn0);
1603 assert_eq!(pending[2].transaction_id, *txn2);
1604 assert!(pending[2].is_wedged());
1605 let error = pending[2].clone().error.unwrap();
1606 let generic_error = assert_matches!(error, QueueWedgeError::GenericApiError { msg } => msg);
1607 assert_eq!(generic_error, "Oops");
1608 for i in 0..4 {
1609 if i != 2 {
1610 assert!(!pending[i].is_wedged());
1611 }
1612 }
1613
1614 let event0 = SerializableEventContent::new(
1616 &RoomMessageEventContent::text_plain("wow that's a cool test").into(),
1617 )?;
1618 self.update_send_queue_request(room_id, txn2, event0.into()).await?;
1619
1620 let pending = self.load_send_queue_requests(room_id).await?;
1622
1623 assert_eq!(pending.len(), 4);
1624 {
1625 assert_eq!(pending[2].transaction_id, *txn2);
1626
1627 let deserialized = pending[2].as_event().unwrap().deserialize()?;
1628 assert_let!(AnyMessageLikeEventContent::RoomMessage(content) = deserialized);
1629 assert_eq!(content.body(), "wow that's a cool test");
1630
1631 assert!(!pending[2].is_wedged());
1632
1633 for i in 0..4 {
1634 if i != 2 {
1635 let deserialized = pending[i].as_event().unwrap().deserialize()?;
1636 assert_let!(AnyMessageLikeEventContent::RoomMessage(content) = deserialized);
1637 assert_eq!(content.body(), format!("msg{i}"));
1638
1639 assert!(!pending[i].is_wedged());
1640 }
1641 }
1642 }
1643
1644 self.remove_send_queue_request(room_id, &txn0).await?;
1646
1647 let pending = self.load_send_queue_requests(room_id).await?;
1649
1650 assert_eq!(pending.len(), 3);
1651 assert_eq!(pending[1].transaction_id, *txn2);
1652 for i in 0..3 {
1653 assert_ne!(pending[i].transaction_id, txn0);
1654 }
1655
1656 let room_id2 = room_id!("!test_send_queue_two:localhost");
1661 {
1662 let txn = TransactionId::new();
1663 let event = SerializableEventContent::new(
1664 &RoomMessageEventContent::text_plain("room2").into(),
1665 )?;
1666 self.save_send_queue_request(
1667 room_id2,
1668 txn.clone(),
1669 MilliSecondsSinceUnixEpoch::now(),
1670 event.into(),
1671 0,
1672 )
1673 .await?;
1674 }
1675
1676 {
1678 let room_id3 = room_id!("!test_send_queue_three:localhost");
1679 let txn = TransactionId::new();
1680 let event = SerializableEventContent::new(
1681 &RoomMessageEventContent::text_plain("room3").into(),
1682 )?;
1683 self.save_send_queue_request(
1684 room_id3,
1685 txn.clone(),
1686 MilliSecondsSinceUnixEpoch::now(),
1687 event.into(),
1688 0,
1689 )
1690 .await?;
1691
1692 self.remove_send_queue_request(room_id3, &txn).await?;
1693 }
1694
1695 let outstanding_rooms = self.load_rooms_with_unsent_requests().await?;
1698 assert_eq!(outstanding_rooms.len(), 2);
1699 assert!(outstanding_rooms.iter().any(|room| room == room_id));
1700 assert!(outstanding_rooms.iter().any(|room| room == room_id2));
1701
1702 Ok(())
1703 }
1704
1705 async fn test_send_queue_priority(&self) -> TestResult {
1706 let room_id = room_id!("!test_send_queue:localhost");
1707
1708 let events = self.load_send_queue_requests(room_id).await?;
1710 assert!(events.is_empty());
1711
1712 let low0_txn = TransactionId::new();
1714 let ev0 =
1715 SerializableEventContent::new(&RoomMessageEventContent::text_plain("low0").into())?;
1716 self.save_send_queue_request(
1717 room_id,
1718 low0_txn.clone(),
1719 MilliSecondsSinceUnixEpoch::now(),
1720 ev0.into(),
1721 2,
1722 )
1723 .await?;
1724
1725 let high_txn = TransactionId::new();
1727 let ev1 =
1728 SerializableEventContent::new(&RoomMessageEventContent::text_plain("high").into())?;
1729 self.save_send_queue_request(
1730 room_id,
1731 high_txn.clone(),
1732 MilliSecondsSinceUnixEpoch::now(),
1733 ev1.into(),
1734 10,
1735 )
1736 .await?;
1737
1738 let low1_txn = TransactionId::new();
1740 let ev2 =
1741 SerializableEventContent::new(&RoomMessageEventContent::text_plain("low1").into())?;
1742 self.save_send_queue_request(
1743 room_id,
1744 low1_txn.clone(),
1745 MilliSecondsSinceUnixEpoch::now(),
1746 ev2.into(),
1747 2,
1748 )
1749 .await?;
1750
1751 let pending = self.load_send_queue_requests(room_id).await?;
1754
1755 assert_eq!(pending.len(), 3);
1756 {
1757 assert_eq!(pending[0].transaction_id, high_txn);
1758
1759 let deserialized = pending[0].as_event().unwrap().deserialize()?;
1760 assert_let!(AnyMessageLikeEventContent::RoomMessage(content) = deserialized);
1761 assert_eq!(content.body(), "high");
1762 }
1763
1764 {
1765 assert_eq!(pending[1].transaction_id, low0_txn);
1766
1767 let deserialized = pending[1].as_event().unwrap().deserialize()?;
1768 assert_let!(AnyMessageLikeEventContent::RoomMessage(content) = deserialized);
1769 assert_eq!(content.body(), "low0");
1770 }
1771
1772 {
1773 assert_eq!(pending[2].transaction_id, low1_txn);
1774
1775 let deserialized = pending[2].as_event().unwrap().deserialize()?;
1776 assert_let!(AnyMessageLikeEventContent::RoomMessage(content) = deserialized);
1777 assert_eq!(content.body(), "low1");
1778 }
1779
1780 Ok(())
1781 }
1782
1783 #[cfg(not(feature = "unstable-msc4354"))]
1784 async fn test_send_queue_sticky_events(&self) -> TestResult {
1785 Ok(()) }
1787
1788 #[cfg(feature = "unstable-msc4354")]
1789 async fn test_send_queue_sticky_events(&self) -> TestResult {
1790 use ruma::events::sticky::StickyDurationMs;
1791
1792 let room_id = room_id!("!test_send_queue_sticky_events:localhost");
1793
1794 let content =
1796 SerializableEventContent::new(&RoomMessageEventContent::text_plain("regular").into())?;
1797 let regular_txn = TransactionId::new();
1798 self.save_send_queue_request(
1799 room_id,
1800 regular_txn.clone(),
1801 MilliSecondsSinceUnixEpoch::now(),
1802 content.into(),
1803 0,
1804 )
1805 .await?;
1806
1807 let content =
1809 SerializableEventContent::new(&RoomMessageEventContent::text_plain("sticky").into())?;
1810 let sticky_txn = TransactionId::new();
1811 self.save_send_queue_request(
1812 room_id,
1813 sticky_txn.clone(),
1814 MilliSecondsSinceUnixEpoch::now(),
1815 QueuedRequestKind::Event {
1816 content,
1817 sticky_duration: Some(StickyDurationMs::new_clamped(300_000u32)),
1818 },
1819 0,
1820 )
1821 .await?;
1822
1823 let pending = self.load_send_queue_requests(room_id).await?;
1824 assert_eq!(pending.len(), 2);
1825
1826 assert_eq!(pending[0].transaction_id, regular_txn);
1827 assert_matches!(&pending[0].kind, QueuedRequestKind::Event { sticky_duration: None, .. });
1828
1829 assert_eq!(pending[1].transaction_id, sticky_txn);
1830 assert_matches!(
1831 &pending[1].kind,
1832 QueuedRequestKind::Event { sticky_duration: Some(duration), .. } => {
1833 assert_eq!(duration.get(), 300_000);
1834 }
1835 );
1836
1837 Ok(())
1838 }
1839
1840 async fn test_send_queue_dependents(&self) -> TestResult {
1841 let room_id = room_id!("!test_send_queue_dependents:localhost");
1842
1843 let txn0 = TransactionId::new();
1845 let event0 =
1846 SerializableEventContent::new(&RoomMessageEventContent::text_plain("hey").into())?;
1847 self.save_send_queue_request(
1848 room_id,
1849 txn0.clone(),
1850 MilliSecondsSinceUnixEpoch::now(),
1851 event0.clone().into(),
1852 0,
1853 )
1854 .await?;
1855
1856 assert!(self.load_dependent_queued_requests(room_id).await?.is_empty());
1858
1859 let child_txn = ChildTransactionId::new();
1861 self.save_dependent_queued_request(
1862 room_id,
1863 &txn0,
1864 child_txn.clone(),
1865 MilliSecondsSinceUnixEpoch::now(),
1866 DependentQueuedRequestKind::RedactEvent,
1867 )
1868 .await?;
1869
1870 let dependents = self.load_dependent_queued_requests(room_id).await?;
1872 assert_eq!(dependents.len(), 1);
1873 assert_eq!(dependents[0].parent_transaction_id, txn0);
1874 assert_eq!(dependents[0].own_transaction_id, child_txn);
1875 assert!(dependents[0].parent_key.is_none());
1876 assert_matches!(dependents[0].kind, DependentQueuedRequestKind::RedactEvent);
1877
1878 let (event, event_type) = event0.raw();
1880 let event_id = owned_event_id!("$1");
1881 let num_updated = self
1882 .mark_dependent_queued_requests_as_ready(
1883 room_id,
1884 &txn0,
1885 SentRequestKey::Event {
1886 event_id: event_id.clone(),
1887 event: event.clone(),
1888 event_type: event_type.to_owned(),
1889 },
1890 )
1891 .await?;
1892 assert_eq!(num_updated, 1);
1893
1894 let dependents = self.load_dependent_queued_requests(room_id).await?;
1896 assert_eq!(dependents.len(), 1);
1897 assert_eq!(dependents[0].parent_transaction_id, txn0);
1898 assert_eq!(dependents[0].own_transaction_id, child_txn);
1899 assert_matches!(
1900 dependents[0].parent_key.as_ref(),
1901 Some(SentRequestKey::Event {
1902 event_id: received_event_id,
1903 event: received_event,
1904 event_type: received_event_type
1905 }) => {
1906 assert_eq!(received_event_id, &event_id);
1907 assert_eq!(received_event.json().to_string(), event.json().to_string());
1908 assert_eq!(received_event_type.as_str(), event_type);
1909 }
1910 );
1911 assert_matches!(dependents[0].kind, DependentQueuedRequestKind::RedactEvent);
1912
1913 let removed = self
1915 .remove_dependent_queued_request(room_id, &dependents[0].own_transaction_id)
1916 .await?;
1917 assert!(removed);
1918
1919 assert!(self.load_dependent_queued_requests(room_id).await?.is_empty());
1921
1922 let txn1 = TransactionId::new();
1925 let event1 =
1926 SerializableEventContent::new(&RoomMessageEventContent::text_plain("hey2").into())?;
1927 self.save_send_queue_request(
1928 room_id,
1929 txn1.clone(),
1930 MilliSecondsSinceUnixEpoch::now(),
1931 event1.into(),
1932 0,
1933 )
1934 .await?;
1935
1936 self.save_dependent_queued_request(
1937 room_id,
1938 &txn0,
1939 ChildTransactionId::new(),
1940 MilliSecondsSinceUnixEpoch::now(),
1941 DependentQueuedRequestKind::RedactEvent,
1942 )
1943 .await?;
1944 assert_eq!(self.load_dependent_queued_requests(room_id).await?.len(), 1);
1945
1946 self.save_dependent_queued_request(
1947 room_id,
1948 &txn1,
1949 ChildTransactionId::new(),
1950 MilliSecondsSinceUnixEpoch::now(),
1951 DependentQueuedRequestKind::EditEvent {
1952 new_content: SerializableEventContent::new(
1953 &RoomMessageEventContent::text_plain("edit").into(),
1954 )?,
1955 },
1956 )
1957 .await?;
1958 assert_eq!(self.load_dependent_queued_requests(room_id).await?.len(), 2);
1959
1960 let removed = self.remove_send_queue_request(room_id, &txn0).await?;
1962 assert!(removed);
1963
1964 let dependents = self.load_dependent_queued_requests(room_id).await?;
1966 assert_eq!(dependents.len(), 2);
1967
1968 Ok(())
1969 }
1970
1971 async fn test_update_send_queue_dependent(&self) -> TestResult {
1972 let room_id = room_id!("!test_send_queue_dependents:localhost");
1973
1974 let txn = TransactionId::new();
1975
1976 let child_txn = ChildTransactionId::new();
1978
1979 self.save_dependent_queued_request(
1980 room_id,
1981 &txn,
1982 child_txn.clone(),
1983 MilliSecondsSinceUnixEpoch::now(),
1984 DependentQueuedRequestKind::RedactEvent,
1985 )
1986 .await?;
1987
1988 let dependents = self.load_dependent_queued_requests(room_id).await?;
1990 assert_eq!(dependents.len(), 1);
1991 assert_eq!(dependents[0].parent_transaction_id, txn);
1992 assert_eq!(dependents[0].own_transaction_id, child_txn);
1993 assert!(dependents[0].parent_key.is_none());
1994 assert_matches!(dependents[0].kind, DependentQueuedRequestKind::RedactEvent);
1995
1996 self.update_dependent_queued_request(
1998 room_id,
1999 &child_txn,
2000 DependentQueuedRequestKind::ReactEvent { key: "👍".to_owned() },
2001 )
2002 .await?;
2003
2004 let dependents = self.load_dependent_queued_requests(room_id).await?;
2006 assert_eq!(dependents.len(), 1);
2007 assert_eq!(dependents[0].parent_transaction_id, txn);
2008 assert_eq!(dependents[0].own_transaction_id, child_txn);
2009 assert!(dependents[0].parent_key.is_none());
2010 assert_matches!(
2011 &dependents[0].kind,
2012 DependentQueuedRequestKind::ReactEvent { key } => {
2013 assert_eq!(key, "👍");
2014 }
2015 );
2016
2017 Ok(())
2018 }
2019
2020 async fn test_get_room_infos(&self) -> TestResult {
2021 let room_id_0 = room_id!("!r0");
2022 let room_id_1 = room_id!("!r1");
2023 let room_id_2 = room_id!("!r2");
2024
2025 {
2027 assert_eq!(self.get_room_infos(&RoomLoadSettings::default()).await?.len(), 0);
2028 }
2029
2030 let mut changes = StateChanges::default();
2032 changes.add_room(RoomInfo::new(room_id_0, RoomState::Joined));
2033 changes.add_room(RoomInfo::new(room_id_1, RoomState::Joined));
2034 self.save_changes(&changes).await?;
2035
2036 {
2038 let mut all_rooms = self.get_room_infos(&RoomLoadSettings::All).await?;
2039
2040 all_rooms.sort_by(|a, b| a.room_id.cmp(&b.room_id));
2043
2044 assert_eq!(all_rooms.len(), 2);
2045 assert_eq!(all_rooms[0].room_id, room_id_0);
2046 assert_eq!(all_rooms[1].room_id, room_id_1);
2047 }
2048
2049 {
2051 let all_rooms =
2052 self.get_room_infos(&RoomLoadSettings::One(room_id_1.to_owned())).await?;
2053
2054 assert_eq!(all_rooms.len(), 1);
2055 assert_eq!(all_rooms[0].room_id, room_id_1);
2056 }
2057
2058 {
2061 let all_rooms =
2062 self.get_room_infos(&RoomLoadSettings::One(room_id_2.to_owned())).await?;
2063
2064 assert_eq!(all_rooms.len(), 0);
2065 }
2066
2067 Ok(())
2068 }
2069
2070 async fn test_thread_subscriptions(&self) -> TestResult {
2071 let first_thread = event_id!("$t1");
2072 let second_thread = event_id!("$t2");
2073
2074 let maybe_sub = self.load_thread_subscription(room_id(), first_thread).await?;
2076 assert!(maybe_sub.is_none());
2077
2078 let maybe_sub = self.load_thread_subscription(room_id(), second_thread).await?;
2079 assert!(maybe_sub.is_none());
2080
2081 self.upsert_thread_subscriptions(vec![(
2083 room_id(),
2084 first_thread,
2085 StoredThreadSubscription {
2086 status: ThreadSubscriptionStatus::Subscribed { automatic: true },
2087 bump_stamp: None,
2088 },
2089 )])
2090 .await?;
2091
2092 self.upsert_thread_subscriptions(vec![(
2093 room_id(),
2094 second_thread,
2095 StoredThreadSubscription {
2096 status: ThreadSubscriptionStatus::Subscribed { automatic: false },
2097 bump_stamp: None,
2098 },
2099 )])
2100 .await?;
2101
2102 let maybe_sub = self.load_thread_subscription(room_id(), first_thread).await?;
2104 assert_eq!(
2105 maybe_sub,
2106 Some(StoredThreadSubscription {
2107 status: ThreadSubscriptionStatus::Subscribed { automatic: true },
2108 bump_stamp: None,
2109 })
2110 );
2111
2112 let maybe_sub = self.load_thread_subscription(room_id(), second_thread).await?;
2113 assert_eq!(
2114 maybe_sub,
2115 Some(StoredThreadSubscription {
2116 status: ThreadSubscriptionStatus::Subscribed { automatic: false },
2117 bump_stamp: None,
2118 })
2119 );
2120
2121 self.upsert_thread_subscriptions(vec![(
2123 room_id(),
2124 first_thread,
2125 StoredThreadSubscription {
2126 status: ThreadSubscriptionStatus::Unsubscribed,
2127 bump_stamp: None,
2128 },
2129 )])
2130 .await?;
2131
2132 let maybe_sub = self.load_thread_subscription(room_id(), first_thread).await?;
2134 assert_eq!(
2135 maybe_sub,
2136 Some(StoredThreadSubscription {
2137 status: ThreadSubscriptionStatus::Unsubscribed,
2138 bump_stamp: None,
2139 })
2140 );
2141
2142 let maybe_sub = self.load_thread_subscription(room_id(), second_thread).await?;
2144 assert_eq!(
2145 maybe_sub,
2146 Some(StoredThreadSubscription {
2147 status: ThreadSubscriptionStatus::Subscribed { automatic: false },
2148 bump_stamp: None,
2149 })
2150 );
2151
2152 self.remove_thread_subscription(room_id(), second_thread).await?;
2154
2155 let maybe_sub = self.load_thread_subscription(room_id(), second_thread).await?;
2157 assert_eq!(maybe_sub, None);
2158
2159 let maybe_sub = self.load_thread_subscription(room_id(), first_thread).await?;
2161 assert_eq!(
2162 maybe_sub,
2163 Some(StoredThreadSubscription {
2164 status: ThreadSubscriptionStatus::Unsubscribed,
2165 bump_stamp: None,
2166 })
2167 );
2168
2169 self.remove_thread_subscription(room_id(), second_thread).await?;
2171
2172 Ok(())
2173 }
2174
2175 async fn test_thread_subscriptions_bulk_upsert(&self) -> TestResult {
2176 let threads = [
2177 event_id!("$t1"),
2178 event_id!("$t2"),
2179 event_id!("$t3"),
2180 event_id!("$t4"),
2181 event_id!("$t5"),
2182 event_id!("$t6"),
2183 ];
2184 let build_subscription_updates = |subs: &[StoredThreadSubscription]| {
2188 threads
2189 .iter()
2190 .zip(subs)
2191 .map(|(&event_id, &sub)| (room_id(), event_id, sub))
2192 .collect::<Vec<_>>()
2193 };
2194
2195 let initial_subscriptions = build_subscription_updates(&[
2197 StoredThreadSubscription {
2198 status: ThreadSubscriptionStatus::Unsubscribed,
2199 bump_stamp: None,
2200 },
2201 StoredThreadSubscription {
2202 status: ThreadSubscriptionStatus::Unsubscribed,
2203 bump_stamp: Some(14),
2204 },
2205 StoredThreadSubscription {
2206 status: ThreadSubscriptionStatus::Unsubscribed,
2207 bump_stamp: None,
2208 },
2209 StoredThreadSubscription {
2210 status: ThreadSubscriptionStatus::Unsubscribed,
2211 bump_stamp: Some(210),
2212 },
2213 StoredThreadSubscription {
2214 status: ThreadSubscriptionStatus::Unsubscribed,
2215 bump_stamp: Some(5),
2216 },
2217 StoredThreadSubscription {
2218 status: ThreadSubscriptionStatus::Unsubscribed,
2219 bump_stamp: Some(100),
2220 },
2221 ]);
2222
2223 let update_subscriptions = build_subscription_updates(&[
2224 StoredThreadSubscription {
2225 status: ThreadSubscriptionStatus::Subscribed { automatic: true },
2226 bump_stamp: None,
2227 },
2228 StoredThreadSubscription {
2229 status: ThreadSubscriptionStatus::Subscribed { automatic: true },
2230 bump_stamp: None,
2231 },
2232 StoredThreadSubscription {
2233 status: ThreadSubscriptionStatus::Subscribed { automatic: true },
2234 bump_stamp: Some(1101),
2235 },
2236 StoredThreadSubscription {
2237 status: ThreadSubscriptionStatus::Subscribed { automatic: true },
2238 bump_stamp: Some(222),
2239 },
2240 StoredThreadSubscription {
2241 status: ThreadSubscriptionStatus::Subscribed { automatic: true },
2242 bump_stamp: Some(1),
2243 },
2244 StoredThreadSubscription {
2245 status: ThreadSubscriptionStatus::Subscribed { automatic: true },
2246 bump_stamp: Some(100),
2247 },
2248 ]);
2249
2250 let expected_subscriptions = build_subscription_updates(&[
2251 StoredThreadSubscription {
2253 status: ThreadSubscriptionStatus::Subscribed { automatic: true },
2254 bump_stamp: None,
2255 },
2256 StoredThreadSubscription {
2258 status: ThreadSubscriptionStatus::Subscribed { automatic: true },
2259 bump_stamp: Some(14),
2260 },
2261 StoredThreadSubscription {
2263 status: ThreadSubscriptionStatus::Subscribed { automatic: true },
2264 bump_stamp: Some(1101),
2265 },
2266 StoredThreadSubscription {
2268 status: ThreadSubscriptionStatus::Subscribed { automatic: true },
2269 bump_stamp: Some(222),
2270 },
2271 StoredThreadSubscription {
2273 status: ThreadSubscriptionStatus::Unsubscribed,
2274 bump_stamp: Some(5),
2275 },
2276 StoredThreadSubscription {
2278 status: ThreadSubscriptionStatus::Unsubscribed,
2279 bump_stamp: Some(100),
2280 },
2281 ]);
2282
2283 self.upsert_thread_subscriptions(initial_subscriptions.clone()).await?;
2285
2286 for (room_id, thread_id, expected_sub) in &initial_subscriptions {
2288 let stored_subscription = self.load_thread_subscription(room_id, thread_id).await?;
2289 assert_eq!(stored_subscription, Some(*expected_sub));
2290 }
2291
2292 self.upsert_thread_subscriptions(update_subscriptions).await?;
2294
2295 for (room_id, thread_id, expected_sub) in &expected_subscriptions {
2297 let stored_subscription = self.load_thread_subscription(room_id, thread_id).await?;
2298 assert_eq!(stored_subscription, Some(*expected_sub));
2299 }
2300
2301 for (room_id, thread_id, _) in &expected_subscriptions {
2303 self.remove_thread_subscription(room_id, thread_id).await?;
2304 }
2305
2306 let initial_subscriptions = build_subscription_updates(&[
2307 StoredThreadSubscription {
2308 status: ThreadSubscriptionStatus::Unsubscribed,
2309 bump_stamp: Some(1),
2310 },
2311 StoredThreadSubscription {
2312 status: ThreadSubscriptionStatus::Subscribed { automatic: false },
2313 bump_stamp: Some(1),
2314 },
2315 StoredThreadSubscription {
2316 status: ThreadSubscriptionStatus::Subscribed { automatic: true },
2317 bump_stamp: Some(1),
2318 },
2319 ]);
2320
2321 self.upsert_thread_subscriptions(initial_subscriptions.clone()).await?;
2322
2323 for (room_id, thread_id, expected_sub) in &initial_subscriptions {
2324 let stored_subscription = self.load_thread_subscription(room_id, thread_id).await?;
2325 assert_eq!(stored_subscription, Some(*expected_sub));
2326 }
2327
2328 let update_subscriptions = build_subscription_updates(&[
2329 StoredThreadSubscription {
2330 status: ThreadSubscriptionStatus::Subscribed { automatic: true },
2331 bump_stamp: Some(2),
2332 },
2333 StoredThreadSubscription {
2334 status: ThreadSubscriptionStatus::Unsubscribed,
2335 bump_stamp: Some(2),
2336 },
2337 StoredThreadSubscription {
2338 status: ThreadSubscriptionStatus::Subscribed { automatic: false },
2339 bump_stamp: Some(2),
2340 },
2341 ]);
2342
2343 self.upsert_thread_subscriptions(update_subscriptions.clone()).await?;
2344
2345 for (room_id, thread_id, expected_sub) in &update_subscriptions {
2346 let stored_subscription = self.load_thread_subscription(room_id, thread_id).await?;
2347 assert_eq!(stored_subscription, Some(*expected_sub));
2348 }
2349
2350 Ok(())
2351 }
2352
2353 async fn test_global_profiles_saving(&self) -> TestResult {
2354 let user_id = user_id();
2355
2356 assert_matches!(self.get_global_profile(user_id).await, Ok(None));
2357
2358 let mut changes = UserProfileChanges::new();
2359 changes.updated.insert(ProfileFieldName::DisplayName, json!("Alice"));
2360 changes.removed.push(ProfileFieldName::AvatarUrl);
2361 let update = UserProfileUpdate::Updated(changes);
2362
2363 let mut changes = StateChanges::default();
2364 changes.global_profiles.insert(user_id.to_owned(), update);
2365 self.save_changes(&changes).await?;
2366
2367 let loaded = self.get_global_profile(user_id).await?.expect("Profile should be saved");
2368 let loaded_map: BTreeMap<String, serde_json::Value> = loaded.into_iter().collect();
2369 assert_eq!(loaded_map.get("displayname"), Some(&json!("Alice")));
2370 assert!(!loaded_map.contains_key("avatar_url"));
2371
2372 let mut changes = UserProfileChanges::new();
2373 changes.removed.push(ProfileFieldName::DisplayName);
2374 changes.updated.insert(ProfileFieldName::AvatarUrl, json!("mxc://example.com/avatar"));
2375 let update2 = UserProfileUpdate::Updated(changes);
2376
2377 let mut changes = StateChanges::default();
2378 changes.global_profiles.insert(user_id.to_owned(), update2);
2379 self.save_changes(&changes).await?;
2380
2381 let loaded2 = self.get_global_profile(user_id).await?.expect("Profile should exist");
2382 let loaded_map2: BTreeMap<String, serde_json::Value> = loaded2.into_iter().collect();
2383 assert!(!loaded_map2.contains_key("displayname"));
2384 assert_eq!(loaded_map2.get("avatar_url"), Some(&json!("mxc://example.com/avatar")));
2385
2386 Ok(())
2387 }
2388
2389 async fn test_global_profiles_bulk_loading(&self) -> TestResult {
2390 let alice = user_id!("@alice:localhost");
2391 let bob = user_id!("@bob:localhost");
2392 let unknown = user_id!("@unknown:localhost");
2393
2394 let mut changes = StateChanges::default();
2395 changes.global_profiles.insert(alice.to_owned(), {
2396 let mut profile_changes = UserProfileChanges::new();
2397 profile_changes.updated.insert(ProfileFieldName::DisplayName, json!("Alice"));
2398 UserProfileUpdate::Updated(profile_changes)
2399 });
2400 changes.global_profiles.insert(bob.to_owned(), {
2401 let mut profile_changes = UserProfileChanges::new();
2402 profile_changes.updated.insert(ProfileFieldName::DisplayName, json!("Bob"));
2403 UserProfileUpdate::Updated(profile_changes)
2404 });
2405 self.save_changes(&changes).await?;
2406
2407 let requested = [alice.to_owned(), bob.to_owned(), unknown.to_owned()];
2409 let profiles = self.get_global_profiles(&requested).await?;
2410
2411 assert_eq!(profiles.len(), 2);
2412 assert!(!profiles.contains_key(unknown));
2413
2414 let alice_map: BTreeMap<String, serde_json::Value> = profiles
2415 .get(alice)
2416 .expect("Alice's profile should be loaded")
2417 .clone()
2418 .into_iter()
2419 .collect();
2420 assert_eq!(alice_map.get("displayname"), Some(&json!("Alice")));
2421
2422 let bob_map: BTreeMap<String, serde_json::Value> = profiles
2423 .get(bob)
2424 .expect("Bob's profile should be loaded")
2425 .clone()
2426 .into_iter()
2427 .collect();
2428 assert_eq!(bob_map.get("displayname"), Some(&json!("Bob")));
2429
2430 Ok(())
2431 }
2432
2433 async fn test_missing_global_profiles(&self) -> TestResult {
2434 let alice = user_id!("@alice:localhost");
2436 let bob = user_id!("@bob:localhost");
2437 let carol = user_id!("@carol:localhost");
2438 let dan = user_id!("@dan:localhost");
2439 let requested = [dan, carol, bob, alice].map(ToOwned::to_owned);
2440 assert_eq!(
2441 self.get_missing_global_profiles(&requested).await?,
2442 vec![dan, carol, bob, alice]
2443 );
2444
2445 let mut changes = StateChanges::default();
2448 changes.global_profiles.insert(alice.to_owned(), {
2449 let mut profile_changes = UserProfileChanges::new();
2450 profile_changes.updated.insert(ProfileFieldName::DisplayName, json!("Alice"));
2451 UserProfileUpdate::Updated(profile_changes)
2452 });
2453 changes
2454 .unavailable_global_profiles
2455 .insert(bob.to_owned(), MilliSecondsSinceUnixEpoch(uint!(1000)));
2456 self.save_changes(&changes).await?;
2457
2458 let mut changes = StateChanges::default();
2459 changes
2460 .unavailable_global_profiles
2461 .insert(carol.to_owned(), MilliSecondsSinceUnixEpoch(uint!(2000)));
2462 self.save_changes(&changes).await?;
2463
2464 assert_eq!(self.get_missing_global_profiles(&requested).await?, vec![dan]);
2466
2467 let mut changes = StateChanges::default();
2469 changes.global_profiles.insert(bob.to_owned(), {
2470 let mut profile_changes = UserProfileChanges::new();
2471 profile_changes.updated.insert(ProfileFieldName::DisplayName, json!("Bob"));
2472 UserProfileUpdate::Updated(profile_changes)
2473 });
2474 self.save_changes(&changes).await?;
2475
2476 let mut changes = StateChanges::default();
2477 changes.global_profiles.insert(bob.to_owned(), UserProfileUpdate::Dropped);
2478 self.save_changes(&changes).await?;
2479
2480 assert_eq!(self.get_missing_global_profiles(&requested).await?, vec![dan, bob]);
2483
2484 Ok(())
2485 }
2486}
2487
2488#[allow(unused_macros, unused_extern_crates)]
2515#[macro_export]
2516macro_rules! statestore_integration_tests {
2517 () => {
2518 mod statestore_integration_tests {
2519 use matrix_sdk_test::{TestResult, async_test};
2520 use $crate::store::{IntoStateStore, StateStoreIntegrationTests};
2521
2522 use super::get_store;
2523
2524 #[async_test]
2525 async fn test_topic_redaction() -> TestResult {
2526 let store = get_store().await?.into_state_store();
2527 store.test_topic_redaction().await
2528 }
2529
2530 #[async_test]
2531 async fn test_populate_store() -> TestResult {
2532 let store = get_store().await?.into_state_store();
2533 store.test_populate_store().await
2534 }
2535
2536 #[async_test]
2537 async fn test_member_saving() -> TestResult {
2538 let store = get_store().await?.into_state_store();
2539 store.test_member_saving().await
2540 }
2541
2542 #[async_test]
2543 async fn test_filter_saving() -> TestResult {
2544 let store = get_store().await?.into_state_store();
2545 store.test_filter_saving().await
2546 }
2547
2548 #[async_test]
2549 async fn test_user_avatar_url_saving() -> TestResult {
2550 let store = get_store().await?.into_state_store();
2551 store.test_user_avatar_url_saving().await
2552 }
2553
2554 #[async_test]
2555 async fn test_supported_versions_saving() -> TestResult {
2556 let store = get_store().await?.into_state_store();
2557 store.test_supported_versions_saving().await
2558 }
2559
2560 #[async_test]
2561 async fn test_well_known_saving() -> TestResult {
2562 let store = get_store().await?.into_state_store();
2563 store.test_well_known_saving().await
2564 }
2565
2566 #[async_test]
2567 async fn test_sync_token_saving() -> TestResult {
2568 let store = get_store().await?.into_state_store();
2569 store.test_sync_token_saving().await
2570 }
2571
2572 #[async_test]
2573 async fn test_utd_hook_manager_data_saving() -> TestResult {
2574 let store = get_store().await?.into_state_store();
2575 store.test_utd_hook_manager_data_saving().await
2576 }
2577
2578 #[async_test]
2579 async fn test_one_time_key_already_uploaded_data_saving() -> TestResult {
2580 let store = get_store().await?.into_state_store();
2581 store.test_one_time_key_already_uploaded_data_saving().await
2582 }
2583
2584 #[async_test]
2585 async fn test_stripped_member_saving() -> TestResult {
2586 let store = get_store().await?.into_state_store();
2587 store.test_stripped_member_saving().await
2588 }
2589
2590 #[async_test]
2591 async fn test_power_level_saving() -> TestResult {
2592 let store = get_store().await?.into_state_store();
2593 store.test_power_level_saving().await
2594 }
2595
2596 #[async_test]
2597 async fn test_receipts_saving() -> TestResult {
2598 let store = get_store().await?.into_state_store();
2599 store.test_receipts_saving().await
2600 }
2601
2602 #[async_test]
2603 async fn test_custom_storage() -> TestResult {
2604 let store = get_store().await?.into_state_store();
2605 store.test_custom_storage().await
2606 }
2607
2608 #[async_test]
2609 async fn test_stripped_non_stripped() -> TestResult {
2610 let store = get_store().await?.into_state_store();
2611 store.test_stripped_non_stripped().await
2612 }
2613
2614 #[async_test]
2615 async fn test_stripped_state_is_kept_across_saves() -> TestResult {
2616 let store = get_store().await?.into_state_store();
2617 store.test_stripped_state_is_kept_across_saves().await
2618 }
2619
2620 #[async_test]
2621 async fn test_room_info_only_save_keeps_room_data() -> TestResult {
2622 let store = get_store().await?.into_state_store();
2623 store.test_room_info_only_save_keeps_room_data().await
2624 }
2625
2626 #[async_test]
2627 async fn test_room_removal() -> TestResult {
2628 let store = get_store().await?.into_state_store();
2629 store.test_room_removal().await
2630 }
2631
2632 #[async_test]
2633 async fn test_profile_removal() -> TestResult {
2634 let store = get_store().await?.into_state_store();
2635 store.test_profile_removal().await
2636 }
2637
2638 #[async_test]
2639 async fn test_presence_saving() -> TestResult {
2640 let store = get_store().await?.into_state_store();
2641 store.test_presence_saving().await
2642 }
2643
2644 #[async_test]
2645 async fn test_display_names_saving() -> TestResult {
2646 let store = get_store().await?.into_state_store();
2647 store.test_display_names_saving().await
2648 }
2649
2650 #[async_test]
2651 async fn test_send_queue() -> TestResult {
2652 let store = get_store().await?.into_state_store();
2653 store.test_send_queue().await
2654 }
2655
2656 #[async_test]
2657 async fn test_send_queue_priority() -> TestResult {
2658 let store = get_store().await?.into_state_store();
2659 store.test_send_queue_priority().await
2660 }
2661
2662 #[async_test]
2663 async fn test_send_queue_dependents() -> TestResult {
2664 let store = get_store().await?.into_state_store();
2665 store.test_send_queue_dependents().await
2666 }
2667
2668 #[async_test]
2669 async fn test_send_queue_sticky_events() -> TestResult {
2670 let store = get_store().await?.into_state_store();
2671 store.test_send_queue_sticky_events().await
2672 }
2673
2674 #[async_test]
2675 async fn test_update_send_queue_dependent() -> TestResult {
2676 let store = get_store().await?.into_state_store();
2677 store.test_update_send_queue_dependent().await
2678 }
2679
2680 #[async_test]
2681 async fn test_get_room_infos() -> TestResult {
2682 let store = get_store().await?.into_state_store();
2683 store.test_get_room_infos().await
2684 }
2685
2686 #[async_test]
2687 async fn test_thread_subscriptions() -> TestResult {
2688 let store = get_store().await?.into_state_store();
2689 store.test_thread_subscriptions().await
2690 }
2691
2692 #[async_test]
2693 async fn test_thread_subscriptions_bulk_upsert() -> TestResult {
2694 let store = get_store().await?.into_state_store();
2695 store.test_thread_subscriptions_bulk_upsert().await
2696 }
2697
2698 #[async_test]
2699 async fn test_global_profiles_saving() -> TestResult {
2700 let store = get_store().await?.into_state_store();
2701 store.test_global_profiles_saving().await
2702 }
2703
2704 #[async_test]
2705 async fn test_global_profiles_bulk_loading() -> TestResult {
2706 let store = get_store().await?.into_state_store();
2707 store.test_global_profiles_bulk_loading().await
2708 }
2709
2710 #[async_test]
2711 async fn test_missing_global_profiles() -> TestResult {
2712 let store = get_store().await?.into_state_store();
2713 store.test_missing_global_profiles().await
2714 }
2715 }
2716 };
2717}
2718
2719fn user_id() -> &'static UserId {
2720 user_id!("@example:localhost")
2721}
2722
2723fn invited_user_id() -> &'static UserId {
2724 user_id!("@invited:localhost")
2725}
2726
2727fn room_id() -> &'static RoomId {
2728 room_id!("!test:localhost")
2729}
2730
2731fn stripped_room_id() -> &'static RoomId {
2732 room_id!("!stripped:localhost")
2733}
2734
2735fn first_receipt_event_id() -> &'static EventId {
2736 event_id!("$example")
2737}
2738
2739fn topic_event_id() -> &'static EventId {
2740 event_id!("$topic_event")
2741}
2742
2743fn power_level_event() -> Raw<AnySyncStateEvent> {
2744 let content = RoomPowerLevelsEventContent::new(&AuthorizationRules::V1);
2745
2746 let event = json!({
2747 "event_id": "$h29iv0s8:example.com",
2748 "content": content,
2749 "sender": user_id(),
2750 "type": "m.room.power_levels",
2751 "origin_server_ts": 0u64,
2752 "state_key": "",
2753 });
2754
2755 serde_json::from_value(event).unwrap()
2756}
2757
2758fn stripped_membership_event() -> Raw<StrippedRoomMemberEvent> {
2759 custom_stripped_membership_event(user_id())
2760}
2761
2762fn custom_stripped_membership_event(user_id: &UserId) -> Raw<StrippedRoomMemberEvent> {
2763 let ev_json = json!({
2764 "type": "m.room.member",
2765 "content": RoomMemberEventContent::new(MembershipState::Join),
2766 "sender": user_id,
2767 "state_key": user_id,
2768 });
2769
2770 Raw::new(&ev_json).unwrap().cast_unchecked()
2771}
2772
2773fn membership_event() -> Raw<SyncRoomMemberEvent> {
2774 custom_membership_event(user_id(), event_id!("$h29iv0s8:example.com"))
2775}
2776
2777fn custom_membership_event(user_id: &UserId, event_id: &EventId) -> Raw<SyncRoomMemberEvent> {
2778 let ev_json = json!({
2779 "type": "m.room.member",
2780 "content": RoomMemberEventContent::new(MembershipState::Join),
2781 "event_id": event_id,
2782 "origin_server_ts": 198,
2783 "sender": user_id,
2784 "state_key": user_id,
2785 });
2786
2787 Raw::new(&ev_json).unwrap().cast_unchecked()
2788}
2789
2790fn custom_presence_event(user_id: &UserId) -> Raw<PresenceEvent> {
2791 let ev_json = json!({
2792 "content": {
2793 "presence": "online"
2794 },
2795 "sender": user_id,
2796 });
2797
2798 Raw::new(&ev_json).unwrap().cast_unchecked()
2799}