Skip to main content

matrix_sdk_base/store/
integration_tests.rs

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