1#[allow(unused_macros)]
32#[macro_export]
33macro_rules! cryptostore_integration_tests {
34 () => {
35 mod cryptostore_integration_tests {
36 use std::collections::{BTreeMap, HashMap, HashSet};
37 use std::ops::Deref;
38 use std::time::Duration;
39
40 use assert_matches::assert_matches;
41 use matrix_sdk_test::async_test;
42 use ruma::{
43 device_id, events::secret::request::SecretName, room_id, serde::Raw, owned_room_id,
44 to_device::DeviceIdOrAllDevices, user_id, DeviceId, RoomId, TransactionId, UserId,
45 };
46 use serde_json::value::to_raw_value;
47 use serde_json::json;
48 use matrix_sdk_common::deserialized_responses::WithheldCode;
49 use $crate::{
50 olm::{
51 Account, Curve25519PublicKey, InboundGroupSession, OlmMessageHash,
52 PrivateCrossSigningIdentity, SenderData, SenderDataType, Session
53 },
54 store::{
55 types::{
56 BackupDecryptionKey, Changes, DehydratedDeviceKey, DeviceChanges,
57 IdentityChanges, PendingChanges, StoredRoomKeyBundleData, RoomKeyWithheldEntry,
58 RoomSettings
59 },
60 CryptoStore, GossipRequest,
61 },
62 testing::{get_device, get_other_identity, get_own_identity},
63 types::{
64 events::{
65 dummy::DummyEventContent,
66 olm_v1::{DecryptedSecretSendEvent, OlmV1Keys},
67 room_key_request::MegolmV1AesSha2Content,
68 room_key_withheld::{
69 CommonWithheldCodeContent, MegolmV1AesSha2WithheldContent,
70 RoomKeyWithheldContent,
71 },
72 room_key_bundle::RoomKeyBundleContent,
73 secret_send::SecretSendContent,
74 ToDeviceEvent,
75 },
76 requests::ToDeviceRequest,
77 DeviceKeys,
78 EventEncryptionAlgorithm,
79 },
80 vodozemac::megolm::{GroupSession, SessionConfig}, DeviceData, GossippedSecret, LocalTrust, SecretInfo,
81 TrackedUser,
82 };
83 #[cfg(feature = "experimental-push-secrets")]
84 use $crate::types::events::secret_push::SecretPushContent;
85
86 use super::get_store;
87
88 fn alice_id() -> &'static UserId {
89 user_id!("@alice:example.org")
90 }
91
92 fn alice_device_id() -> &'static DeviceId {
93 device_id!("ALICEDEVICE")
94 }
95
96 fn bob_id() -> &'static UserId {
97 user_id!("@bob:example.org")
98 }
99
100 fn bob_device_id() -> &'static DeviceId {
101 device_id!("BOBDEVICE")
102 }
103
104 pub async fn get_loaded_store(name: &str) -> (Account, impl CryptoStore + use<>) {
105 let store = get_store(name, None, true).await;
106 let account = get_account();
107
108 store.save_pending_changes(PendingChanges { account: Some(account.deep_clone()), }).await.expect("Can't save account");
109
110 (account, store)
111 }
112
113 fn get_account() -> Account {
114 Account::with_device_id(alice_id(), alice_device_id())
115 }
116
117 pub(crate) async fn get_account_and_session() -> (Account, Session) {
118 let alice = Account::with_device_id(alice_id(), alice_device_id());
119 let mut bob = Account::with_device_id(bob_id(), bob_device_id());
120
121 bob.generate_one_time_keys(1);
122 let one_time_key = *bob.one_time_keys().values().next().unwrap();
123 let sender_key = bob.identity_keys().curve25519;
124 let session = alice.create_outbound_session_helper(
125 Default::default(),
126 sender_key,
127 one_time_key,
128 false,
129 alice.device_keys(),
130 );
131
132 (alice, session)
133 }
134
135 #[async_test]
136 async fn test_save_account_via_generic_save() {
137 let store = get_store("save_account_via_generic", None, true).await;
138 assert!(store.get_static_account().is_none());
139 assert!(store.load_account().await.unwrap().is_none());
140 let account = get_account();
141
142 store
143 .save_pending_changes(PendingChanges { account: Some(account) })
144 .await
145 .expect("Can't save account");
146 assert!(store.get_static_account().is_some());
147 }
148
149 #[async_test]
150 async fn test_save_account() {
151 let store = get_store("save_account", None, true).await;
152 assert!(store.get_static_account().is_none());
153 assert!(store.load_account().await.unwrap().is_none());
154 let account = get_account();
155
156 store
157 .save_pending_changes(PendingChanges { account: Some(account) })
158 .await
159 .expect("Can't save account");
160 assert!(store.get_static_account().is_some());
161 }
162
163 #[async_test]
164 async fn test_load_account() {
165 let store = get_store("load_account", None, true).await;
166 let account = get_account();
167
168 store
169 .save_pending_changes(PendingChanges { account: Some(account.deep_clone()) })
170 .await
171 .expect("Can't save account");
172
173 let loaded_account = store.load_account().await.expect("Can't load account");
174 let loaded_account = loaded_account.unwrap();
175
176 assert_eq!(account, loaded_account);
177 }
178
179 #[async_test]
180 async fn test_load_account_with_passphrase() {
181 let passphrase = Some("secret_passphrase");
182 let store = get_store("load_account_with_passphrase", passphrase, true).await;
183 let account = get_account();
184
185 store
186 .save_pending_changes(PendingChanges { account: Some(account.deep_clone()) })
187 .await
188 .expect("Can't save account");
189
190 let loaded_account = store.load_account().await.expect("Can't load account");
191 let loaded_account = loaded_account.unwrap();
192
193 assert_eq!(account, loaded_account);
194 }
195
196 #[async_test]
197 async fn test_save_and_share_account() {
198 let store = get_store("save_and_share_account", None, true).await;
199 let mut account = get_account();
200
201 store
202 .save_pending_changes(PendingChanges { account: Some(account.deep_clone()) })
203 .await
204 .expect("Can't save account");
205
206 account.mark_as_shared();
207 account.update_uploaded_key_count(50);
208
209 store
210 .save_pending_changes(PendingChanges { account: Some(account.deep_clone()) })
211 .await
212 .expect("Can't save account");
213
214 let loaded_account = store.load_account().await.expect("Can't load account");
215 let loaded_account = loaded_account.unwrap();
216
217 assert_eq!(account, loaded_account);
218 assert_eq!(account.uploaded_key_count(), loaded_account.uploaded_key_count());
219 }
220
221 #[async_test]
222 async fn test_load_sessions() {
223 let store = get_store("load_sessions", None, true).await;
224 let (account, session) = get_account_and_session().await;
225 store
226 .save_pending_changes(PendingChanges { account: Some(account.deep_clone()) })
227 .await
228 .expect("Can't save account");
229
230 let changes = Changes {
231 sessions: vec![session.clone()],
232 devices: DeviceChanges { new: vec![DeviceData::from_account(&account)], ..Default::default() },
233 ..Default::default()
234 };
235
236 store.save_changes(changes).await.unwrap();
237
238 let sessions = store
239 .get_sessions(&session.sender_key.to_base64())
240 .await
241 .expect("Can't load sessions")
242 .unwrap();
243 let loaded_session = sessions.get(0).cloned().expect("We should find the session in the store.");
244
245 assert_eq!(&session, &loaded_session, "The loaded session should be the same one we put into the store.");
246 }
247
248 #[async_test]
249 async fn test_add_and_save_session() {
250 let store_name = "add_and_save_session";
251
252 let (session_id, account, sender_key) = {
254 let store = get_store(store_name, None, true).await;
255 let (account, session) = get_account_and_session().await;
256 let sender_key = session.sender_key.to_base64();
257 let session_id = session.session_id().to_owned();
258
259 store
260 .save_pending_changes(PendingChanges {
261 account: Some(account.deep_clone()),
262 })
263 .await
264 .expect("Can't save account");
265 store
266 .save_changes(Changes {
267 devices: DeviceChanges {
268 new: vec![DeviceData::from_account(&account)],
269 ..Default::default()
270 },
271 ..Default::default()
272 })
273 .await
274 .unwrap();
275
276 let changes = Changes { sessions: vec![session.clone()], ..Default::default() };
277 store.save_changes(changes).await.unwrap();
278
279 let sessions = store.get_sessions(&sender_key).await.unwrap().unwrap();
280 let session = &sessions[0];
281
282 assert_eq!(session_id, session.session_id());
283
284 (session_id, account, sender_key)
285 };
286
287 let store = get_store(store_name, None, false).await;
289
290 let loaded_account = store.load_account().await.unwrap().unwrap();
292 assert_eq!(account, loaded_account);
293
294 let sessions = store.get_sessions(&sender_key).await.unwrap().unwrap();
295 let session = &sessions[0];
296
297 assert_eq!(session_id, session.session_id());
298 }
299
300 #[async_test]
301 async fn test_load_outbound_group_session() {
302 let dir = "load_outbound_group_session";
303 let room_id = room_id!("!test:localhost");
304
305 {
307 let (account, store) = get_loaded_store(dir.clone()).await;
308 assert!(
309 store.get_outbound_group_session(&room_id).await.unwrap().is_none(),
310 "Initially there should be no outbound group session"
311 );
312
313 let (session, _) =
314 account.create_group_session_pair_with_defaults(&room_id).await;
315
316 let user_id = user_id!("@example:localhost");
317 let request = ToDeviceRequest::new(
318 user_id,
319 DeviceIdOrAllDevices::AllDevices,
320 "m.dummy",
321 Raw::from_json(to_raw_value(&DummyEventContent::new()).unwrap()),
322 );
323
324 session.add_request(TransactionId::new(), request.into(), Default::default());
325
326 let changes = Changes {
327 outbound_group_sessions: vec![session.clone()],
328 ..Default::default()
329 };
330
331 store.save_changes(changes).await.expect("Can't save group session");
332 assert!(
333 store.get_outbound_group_session(&room_id).await.unwrap().is_some(),
334 "Sanity: after we've saved one, there should be an outbound_group_session"
335 );
336 }
337
338 let store = get_store(dir, None, false).await;
340 store.load_account().await.unwrap();
341
342 assert!(
344 store.get_outbound_group_session(&room_id).await.unwrap().is_some(),
345 "The outbound_group_session should have been loaded"
346 );
347 }
348
349 #[async_test]
351 async fn test_save_changes_save_inbound_group_session() {
352 let (account, store) = get_loaded_store("save_inbound_group_session").await;
353
354 let room_id = &room_id!("!test:localhost");
355 let (_, session) = account.create_group_session_pair_with_defaults(room_id).await;
356
357 let changes =
358 Changes { inbound_group_sessions: vec![session], ..Default::default() };
359
360 store.save_changes(changes).await.expect("Can't save group session");
361 }
362
363 #[async_test]
366 async fn test_save_inbound_group_session_from_backup() {
367 let (account, store) =
368 get_loaded_store("save_inbound_group_session_from_backup").await;
369
370 let room_id = &room_id!("!test:localhost");
371 let (_, session) = account.create_group_session_pair_with_defaults(room_id).await;
372
373 session.mark_as_backed_up();
374 store
375 .save_inbound_group_sessions(vec![session.clone()], Some(&"bkpver1"))
376 .await
377 .expect("could not save sessions");
378
379 let loaded_session = store
380 .get_inbound_group_session(&session.room_id, session.session_id())
381 .await
382 .expect("error when loading session")
383 .expect("session not found in store");
384 assert_eq!(session, loaded_session);
385 assert_eq!(store.get_inbound_group_sessions().await.unwrap().len(), 1);
386 assert_eq!(store.inbound_group_session_counts(None).await.unwrap().total, 1);
387
388 let to_back_up = store.inbound_group_sessions_for_backup("bkpver1", 1).await.unwrap();
390 assert_eq!(to_back_up.len(), 0, "backup was returned by backup query");
391 assert_eq!(
392 store.inbound_group_session_counts(Some(&"bkpver1")).await.unwrap().backed_up, 1,
393 "backed_up count",
394 );
395 }
396
397 #[ignore]
402 #[async_test]
403 async fn test_save_inbound_group_session_from_old_backup() {
404 let (account, store) =
405 get_loaded_store("save_inbound_group_session_from_old_backup").await;
406
407 let room_id = &room_id!("!test:localhost");
408 let (_, session) = account.create_group_session_pair_with_defaults(room_id).await;
409
410 session.mark_as_backed_up();
411 store
412 .save_inbound_group_sessions(vec![session.clone()], Some(&"bkpver1"))
413 .await
414 .expect("could not save sessions");
415
416 let to_back_up = store.inbound_group_sessions_for_backup("bkpver2", 1).await.unwrap();
418 assert_eq!(to_back_up, vec![session]);
419 assert_eq!(
420 store.inbound_group_session_counts(Some(&"bkpver2")).await.unwrap().backed_up, 0,
421 "backed_up count for backup version 2",
422 );
423 }
424
425 #[async_test]
428 async fn test_save_inbound_group_session_from_import() {
429 let (account, store) =
430 get_loaded_store("save_inbound_group_session_from_import").await;
431
432 let room_id = &room_id!("!test:localhost");
433 let (_, session) = account.create_group_session_pair_with_defaults(room_id).await;
434
435 store
436 .save_inbound_group_sessions(vec![session.clone()], None)
437 .await
438 .expect("could not save sessions");
439
440 let loaded_session = store
441 .get_inbound_group_session(&session.room_id, session.session_id())
442 .await
443 .expect("error when loading session")
444 .expect("session not found in store");
445 assert_eq!(session, loaded_session);
446 assert_eq!(store.get_inbound_group_sessions().await.unwrap().len(), 1);
447 assert_eq!(store.inbound_group_session_counts(None).await.unwrap().total, 1);
448 assert_eq!(store.inbound_group_session_counts(None).await.unwrap().backed_up, 0);
449
450 let to_back_up = store.inbound_group_sessions_for_backup("bkpver1", 1).await.unwrap();
452 assert_eq!(to_back_up, vec![session]);
453 }
454
455 #[async_test]
456 async fn test_mark_inbound_group_sessions_as_backed_up() {
457 let (account, store) =
459 get_loaded_store("mark_inbound_group_sessions_as_backed_up").await;
460 let room_id = &room_id!("!test:localhost");
461 let mut sessions: Vec<InboundGroupSession> = Vec::with_capacity(10);
462 for _i in 0..10 {
463 sessions.push(account.create_group_session_pair_with_defaults(room_id).await.1);
464 }
465 let changes = Changes { inbound_group_sessions: sessions.clone(), ..Default::default() };
466 store.save_changes(changes).await.expect("Can't save group session");
467 assert_eq!(store.inbound_group_sessions_for_backup("bkpver", 100).await.unwrap().len(), 10);
468
469 store.mark_inbound_group_sessions_as_backed_up("bkpver", &[
471 session_info(&sessions[1]),
472 session_info(&sessions[3]),
473 session_info(&sessions[5]),
474 session_info(&sessions[7]),
475 session_info(&sessions[9]),
476 ]).await.expect("Failed to mark sessions as backed up");
477
478 let to_back_up = store.inbound_group_sessions_for_backup("bkpver", 10).await.unwrap();
480 let needs_backing_up = |i: usize| to_back_up.iter().any(|s| s.session_id() == sessions[i].session_id());
481
482 assert!(!needs_backing_up(1));
484 assert!(!needs_backing_up(3));
485 assert!(!needs_backing_up(5));
486 assert!(!needs_backing_up(7));
487 assert!(!needs_backing_up(9));
488
489 assert!(needs_backing_up(0));
491 assert!(needs_backing_up(2));
492 assert!(needs_backing_up(4));
493 assert!(needs_backing_up(6));
494 assert!(needs_backing_up(8));
495 assert_eq!(to_back_up.len(), 5);
496 }
497
498 #[async_test]
499 async fn test_reset_inbound_group_session_for_backup() {
500 let (account, store) =
502 get_loaded_store("reset_inbound_group_session_for_backup").await;
503 let room_id = &room_id!("!test:localhost");
504 let mut sessions: Vec<InboundGroupSession> = Vec::with_capacity(10);
505 for _ in 0..10 {
506 sessions.push(account.create_group_session_pair_with_defaults(room_id).await.1);
507 }
508 let changes = Changes { inbound_group_sessions: sessions.clone(), ..Default::default() };
509 store.save_changes(changes).await.expect("Can't save group session");
510 assert_eq!(store.inbound_group_sessions_for_backup("backup_1", 100).await.unwrap().len(), 10);
511 store.mark_inbound_group_sessions_as_backed_up(
512 "backup_1",
513 &(0..10).map(|i| session_info(&sessions[i])).collect::<Vec<_>>(),
514 ).await.expect("Failed to mark sessions as backed up");
515
516 {
518 let to_back_up_old = store.inbound_group_sessions_for_backup("backup_1", 10).await.unwrap();
519 assert_eq!(to_back_up_old.len(), 0);
520 }
521
522 store.reset_backup_state().await.expect("reset failed");
525
526 let to_back_up = store.inbound_group_sessions_for_backup("backup_02", 10).await.unwrap();
528
529 let needs_backing_up = |i: usize| to_back_up.iter().any(|s| s.session_id() == sessions[i].session_id());
531 assert!(needs_backing_up(0));
532 assert!(needs_backing_up(1));
533 assert!(needs_backing_up(8));
534 assert!(needs_backing_up(9));
535 assert_eq!(to_back_up.len(), 10);
536 }
537
538 #[async_test]
539 async fn test_load_inbound_group_session() {
540 let dir = "load_inbound_group_session";
541 let (account, store) = get_loaded_store(dir).await;
542 assert_eq!(store.get_inbound_group_sessions().await.unwrap().len(), 0);
543
544 let room_id = &room_id!("!test:localhost");
545 let (_, session) = account.create_group_session_pair_with_defaults(room_id).await;
546
547 let export = session.export().await;
548
549 let session = InboundGroupSession::from_export(&export).unwrap();
550
551 let changes =
552 Changes { inbound_group_sessions: vec![session.clone()], ..Default::default() };
553
554 store.save_changes(changes).await.expect("Can't save group session");
555
556 drop(store);
557
558 let store = get_store(dir, None, false).await;
559
560 store.load_account().await.unwrap();
561
562 let loaded_session = store
563 .get_inbound_group_session(&session.room_id, session.session_id())
564 .await
565 .unwrap()
566 .unwrap();
567 assert_eq!(session, loaded_session);
568 loaded_session.export().await;
569
570 assert_eq!(store.get_inbound_group_sessions().await.unwrap().len(), 1);
571 assert_eq!(store.inbound_group_session_counts(None).await.unwrap().total, 1);
572 }
573
574 #[async_test]
575 async fn test_get_inbound_group_sessions_by_room_id_empty() {
576 let dir = "get_inbound_group_session_by_room_id_empty";
577 let (_, store) = get_loaded_store(dir).await;
578 assert_eq!(store.get_inbound_group_sessions().await.unwrap().len(), 0);
579
580 let room_id = &room_id!("!testing:localhost");
581 assert_eq!(store.get_inbound_group_sessions_by_room_id(room_id).await.unwrap().len(), 0);
582 }
583
584 #[async_test]
585 async fn test_get_inbound_group_sessions_by_room_id() {
586 let dir = "get_inbound_group_session_by_room_id";
587 let (account, store) = get_loaded_store(dir).await;
588 assert_eq!(store.get_inbound_group_sessions().await.unwrap().len(), 0);
589
590 let room_id = &room_id!("!testing:localhost");
591 let (_, session_1) = account.create_group_session_pair_with_defaults(room_id).await;
592 let (_, session_2) = account.create_group_session_pair_with_defaults(room_id).await;
593
594 let second_room_id = &room_id!("!other_room_testing:localhost");
595 let (_, session_3) = account.create_group_session_pair_with_defaults(second_room_id).await;
596
597 let mut sessions = vec![
598 session_1,
599 session_2,
600 session_3
601 ];
602
603 let changes = Changes {
604 inbound_group_sessions: sessions.clone(),
605 ..Default::default()
606 };
607 store.save_changes(changes).await.expect("Can't save group session");
608
609 drop(store);
610
611 sessions.pop();
614
615 let store = get_store(dir, None, false).await;
616 assert_eq!(store.get_inbound_group_sessions().await.unwrap().len(), 3);
618
619 store.load_account().await.unwrap();
620
621 let loaded_sessions = store
622 .get_inbound_group_sessions_by_room_id(room_id)
623 .await
624 .unwrap();
625
626 assert_eq!(loaded_sessions.len(), 2);
627 assert_session_lists_eq(sessions, loaded_sessions, "room by id sessions");
628 }
629
630 #[async_test]
631 async fn test_fetch_inbound_group_sessions_for_device() {
632 let (account, store) =
634 get_loaded_store("fetch_inbound_group_sessions_for_device").await;
635
636 let dev1 = Curve25519PublicKey::from_base64(
637 "wjLpTLRqbqBzLs63aYaEv2Boi6cFEbbM/sSRQ2oAKk4"
638 ).unwrap();
639 let dev2 = Curve25519PublicKey::from_base64(
640 "LTpv2DGMhggPAXO02+7f68CNEp6A40F0Yl8B094Y8gc"
641 ).unwrap();
642
643 let dev_1_unknown_a = create_session(&account, &dev1, SenderDataType::UnknownDevice).await;
644 let dev_1_unknown_b = create_session(&account, &dev1, SenderDataType::UnknownDevice).await;
645
646 let dev_1_keys_a = create_session(&account, &dev1, SenderDataType::DeviceInfo).await;
647 let dev_1_keys_b = create_session(&account, &dev1, SenderDataType::DeviceInfo).await;
648 let dev_1_keys_c = create_session(&account, &dev1, SenderDataType::DeviceInfo).await;
649 let dev_1_keys_d = create_session(&account, &dev1, SenderDataType::DeviceInfo).await;
650
651 let dev_2_unknown = create_session(
652 &account, &dev2, SenderDataType::UnknownDevice).await;
653
654 let dev_2_keys = create_session(
655 &account, &dev2, SenderDataType::DeviceInfo).await;
656
657 let sessions = vec![
658 dev_1_unknown_a.clone(),
659 dev_1_unknown_b.clone(),
660 dev_1_keys_a.clone(),
661 dev_1_keys_b.clone(),
662 dev_1_keys_c.clone(),
663 dev_1_keys_d.clone(),
664 dev_2_unknown.clone(),
665 dev_2_keys.clone(),
666 ];
667
668 let changes = Changes {
669 inbound_group_sessions: sessions,
670 ..Default::default()
671 };
672 store.save_changes(changes).await.expect("Can't save group session");
673
674 let sessions_1_u = store.get_inbound_group_sessions_for_device_batch(
676 dev1,
677 SenderDataType::UnknownDevice,
678 None,
679 10
680 ).await.expect("Failed to get sessions for dev1");
681
682 assert_session_lists_eq(sessions_1_u, [dev_1_unknown_a, dev_1_unknown_b], "device 1 sessions");
684
685 let sessions_2_d = store
687 .get_inbound_group_sessions_for_device_batch(dev2, SenderDataType::DeviceInfo, None, 10)
688 .await
689 .expect("Failed to get sessions for dev2");
690
691 assert_eq!(sessions_2_d, vec![dev_2_keys], "device 2 sessions");
693
694 let mut sessions_1_k = Vec::new();
697 let mut previous_last_session_id: Option<String> = None;
698 loop {
699 let mut sessions_1_k_batch = store.get_inbound_group_sessions_for_device_batch(
700 dev1,
701 SenderDataType::DeviceInfo,
702 previous_last_session_id,
703 2
704 ).await.expect("Failed to get batch 1");
705
706 let Some(last_session) = sessions_1_k_batch.last() else {
708 break;
709 };
710
711 assert_eq!(sessions_1_k_batch.len(), 2);
713
714 previous_last_session_id = Some(last_session.session_id().to_owned());
715
716 let mut last_session = last_session.clone();
718 last_session.sender_data = SenderData::unknown();
719 store.save_inbound_group_sessions(vec![last_session], None).await.unwrap();
720
721 sessions_1_k.append(&mut sessions_1_k_batch);
722 }
723
724 assert_session_lists_eq(
725 sessions_1_k,
726 [dev_1_keys_a, dev_1_keys_b, dev_1_keys_c, dev_1_keys_d],
727 "device 1 batched results"
728 );
729 }
730
731 fn assert_session_lists_eq<I, J>(actual: I, expected: J, message: &str)
737 where I: IntoIterator<Item = InboundGroupSession>, J: IntoIterator<Item = InboundGroupSession>
738 {
739 let sorter = |a: &InboundGroupSession, b: &InboundGroupSession| Ord::cmp(a.session_id(), b.session_id());
740
741 let mut actual = Vec::from_iter(actual);
742 actual.sort_unstable_by(sorter);
743 let mut expected = Vec::from_iter(expected);
744 expected.sort_unstable_by(sorter);
745 assert_eq!(actual, expected, "{}", message);
746 }
747
748 #[async_test]
749 async fn test_tracked_users() {
750 let dir = "test_tracked_users";
751 let (_account, store) = get_loaded_store(dir.clone()).await;
752
753 let alice = user_id!("@alice:example.org");
754 let bob = user_id!("@bob:example.org");
755 let candy = user_id!("@candy:example.org");
756
757 let loaded = store.load_tracked_users().await.unwrap();
758 assert!(loaded.is_empty(), "Initially there are no tracked users");
759
760 let users = vec![(alice, true), (bob, false)];
761 store.save_tracked_users(&users).await.unwrap();
762
763 let check_loaded_users = |loaded: Vec<TrackedUser>| {
764 let loaded: HashMap<_, _> =
765 loaded.into_iter().map(|u| (u.user_id.to_owned(), u)).collect();
766
767 let loaded_alice =
768 loaded.get(alice).expect("Alice should be in the store as a tracked user");
769 let loaded_bob =
770 loaded.get(bob).expect("Bob should be in the store as as tracked user");
771
772 assert!(!loaded.contains_key(candy), "Candy shouldn't be part of the store");
773 assert_eq!(loaded.len(), 2, "Candy shouldn't be part of the store");
774
775 assert!(loaded_alice.dirty, "Alice should be considered to be dirty");
776 assert!(!loaded_bob.dirty, "Bob should not be considered to be dirty");
777 };
778
779 let loaded = store.load_tracked_users().await.unwrap();
780 check_loaded_users(loaded);
781
782 drop(store);
783
784 let name = dir.clone();let store = get_store(name, None, false).await;
785 let loaded = store.load_tracked_users().await.unwrap();
786 check_loaded_users(loaded);
787 }
788
789 #[async_test]
790 async fn test_device_saving() {
791 let dir = "device_saving";
792 let (_account, store) = get_loaded_store(dir.clone()).await;
793
794 let alice_device_1 = DeviceData::from_account(&Account::with_device_id(
795 "@alice:localhost".try_into().unwrap(),
796 "FIRSTDEVICE".into(),
797 ));
798
799 let alice_device_2 = DeviceData::from_account(&Account::with_device_id(
800 "@alice:localhost".try_into().unwrap(),
801 "SECONDDEVICE".into(),
802 ));
803
804 let json = json!({
805 "algorithms": ["m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"],
806 "user_id": "@bob:localhost",
807 "device_id": "BOBDEVICE",
808 "extra_property": "somevalue",
809 "keys": {
810 "curve25519:BOBDEVICE": "n0zs7qnaPLLf/OTL+dDLcI5kaPexbUeQ8jLQ2q6sO0E",
811 "ed25519:BOBDEVICE": "RrKiu4+5EHRBWY6Qj6OtQGC0txpmEeanOz2irEZ/IN4",
812 },
813 "signatures": {
814 "@bob:localhost": {
815 "ed25519:BOBDEVICE": "9NjPewVHfB7Ah32mJ+CBx64mVoiQ8gbh+/2pc9WfAgut/H0Kqd/bbpgJq9Pn518szaXcGqEq0DxDP6CABBX8CQ",
816 },
817 },
818 });
819
820 let bob_device_1_keys: DeviceKeys = serde_json::from_value(json).unwrap();
821 let bob_device_1 = DeviceData::new(bob_device_1_keys, LocalTrust::Unset);
822
823 let changes = Changes {
824 devices: DeviceChanges {
825 new: vec![alice_device_1.clone(), alice_device_2.clone(), bob_device_1.clone()],
826 ..Default::default()
827 },
828 ..Default::default()
829 };
830
831 store.save_changes(changes).await.unwrap();
832
833 drop(store);
834
835 let store = get_store(dir, None, false).await;
836
837 store.load_account().await.unwrap();
838
839 let loaded_device = store
840 .get_device(alice_device_1.user_id(), alice_device_1.device_id())
841 .await
842 .unwrap()
843 .unwrap();
844
845 assert_eq!(alice_device_1, loaded_device);
846
847 for algorithm in loaded_device.algorithms() {
848 assert!(alice_device_1.algorithms().contains(algorithm));
849 }
850 assert_eq!(alice_device_1.algorithms().len(), loaded_device.algorithms().len());
851 assert_eq!(alice_device_1.keys(), loaded_device.keys());
852
853 let user_devices = store.get_user_devices(alice_device_1.user_id()).await.unwrap();
854 assert_eq!(user_devices.len(), 2);
855
856 let bob_device = store
857 .get_device(bob_device_1.user_id(), bob_device_1.device_id())
858 .await
859 .unwrap();
860
861 let bob_device_json = serde_json::to_value(bob_device).unwrap();
862 assert_eq!(bob_device_json["device_keys"]["extra_property"], json!("somevalue"));
863 }
864
865 #[async_test]
866 async fn test_device_deleting() {
867 let dir = "device_deleting";
868 let (_account, store) = get_loaded_store(dir.clone()).await;
869 let device = get_device();
870
871 let changes = Changes {
872 devices: DeviceChanges { changed: vec![device.clone()], ..Default::default() },
873 ..Default::default()
874 };
875
876 store.save_changes(changes).await.unwrap();
877
878 let changes = Changes {
879 devices: DeviceChanges { deleted: vec![device.clone()], ..Default::default() },
880 ..Default::default()
881 };
882
883 store.save_changes(changes).await.unwrap();
884 drop(store);
885
886 let store = get_store(dir, None, false).await;
887
888 store.load_account().await.unwrap();
889
890 let loaded_device =
891 store.get_device(device.user_id(), device.device_id()).await.unwrap();
892
893 assert!(loaded_device.is_none());
894 }
895
896 #[async_test]
897 async fn test_user_saving() {
898 let dir = "user_saving";
899
900 let user_id = user_id!("@example:localhost");
901 let device_id: &DeviceId = "WSKKLTJZCL".into();
902
903 let store = get_store(dir, None, true).await;
904
905 let account = Account::with_device_id(&user_id, device_id);
906
907 store.save_pending_changes(PendingChanges { account: Some(account), })
908 .await
909 .expect("Can't save account");
910
911 let own_identity = get_own_identity();
912
913 let changes = Changes {
914 identities: IdentityChanges {
915 changed: vec![own_identity.clone().into()],
916 ..Default::default()
917 },
918 ..Default::default()
919 };
920
921 store.save_changes(changes).await.expect("Can't save identity");
922
923 drop(store);
924
925 let store = get_store(dir, None, false).await;
926
927 store.load_account().await.unwrap();
928
929 let loaded_user =
930 store.get_user_identity(own_identity.user_id()).await.unwrap().unwrap();
931
932 assert_eq!(loaded_user.master_key(), own_identity.master_key());
933 assert_eq!(loaded_user.self_signing_key(), own_identity.self_signing_key());
934 assert_eq!(loaded_user.own().unwrap().clone(), own_identity.clone());
935
936 let other_identity = get_other_identity();
937
938 let changes = Changes {
939 identities: IdentityChanges {
940 changed: vec![other_identity.clone().into()],
941 ..Default::default()
942 },
943 ..Default::default()
944 };
945
946 store.save_changes(changes).await.unwrap();
947
948 let loaded_user =
949 store.get_user_identity(other_identity.user_id()).await.unwrap().unwrap();
950
951 assert_eq!(loaded_user.master_key(), other_identity.master_key());
952 assert_eq!(loaded_user.self_signing_key(), other_identity.self_signing_key());
953 assert_eq!(loaded_user.user_id(), other_identity.user_id());
954 assert_eq!(loaded_user.other().unwrap().clone(), other_identity);
955
956 own_identity.mark_as_verified();
957
958 let changes = Changes {
959 identities: IdentityChanges {
960 changed: vec![own_identity.into()],
961 ..Default::default()
962 },
963 ..Default::default()
964 };
965
966 store.save_changes(changes).await.unwrap();
967 let loaded_user = store.get_user_identity(&user_id).await.unwrap().unwrap();
968 assert!(loaded_user.own().unwrap().is_verified())
969 }
970
971 #[async_test]
972 async fn test_private_identity_saving() {
973 let (_, store) = get_loaded_store("private_identity_saving").await;
974 assert!(store.load_identity().await.unwrap().is_none());
975 let identity = PrivateCrossSigningIdentity::new(alice_id().to_owned());
976
977 let changes =
978 Changes { private_identity: Some(identity.clone()), ..Default::default() };
979
980 store.save_changes(changes).await.unwrap();
981 let loaded_identity = store.load_identity().await.unwrap().unwrap();
982 assert_eq!(identity.user_id(), loaded_identity.user_id());
983 }
984
985 #[async_test]
986 async fn test_olm_hash_saving() {
987 let (_, store) = get_loaded_store("olm_hash_saving").await;
988
989 let hash = OlmMessageHash {
990 sender_key: "test_sender".to_owned(),
991 hash: "test_hash".to_owned(),
992 };
993
994 let mut changes = Changes::default();
995 changes.message_hashes.push(hash.clone());
996
997 assert!(!store.is_message_known(&hash).await.unwrap());
998 store.save_changes(changes).await.unwrap();
999 assert!(store.is_message_known(&hash).await.unwrap());
1000 }
1001
1002 #[async_test]
1003 async fn test_key_request_saving() {
1004 let (account, store) = get_loaded_store("key_request_saving").await;
1005 let sender_key =
1006 Curve25519PublicKey::from_base64("Nn0L2hkcCMFKqynTjyGsJbth7QrVmX3lbrksMkrGOAw")
1007 .unwrap();
1008
1009 let id = TransactionId::new();
1010 let info: SecretInfo = MegolmV1AesSha2Content {
1011 room_id: owned_room_id!("!test:localhost"),
1012 sender_key: Some(sender_key),
1013 session_id: "test_session_id".to_owned(),
1014 }
1015 .into();
1016
1017 let request = GossipRequest {
1018 request_recipient: account.user_id().to_owned(),
1019 request_id: id.clone(),
1020 info: info.clone(),
1021 sent_out: false,
1022 };
1023
1024 assert!(store.get_outgoing_secret_requests(&id).await.unwrap().is_none());
1025
1026 let mut changes = Changes::default();
1027 changes.key_requests.push(request.clone());
1028 store.save_changes(changes).await.unwrap();
1029
1030 let request = Some(request);
1031
1032 let stored_request = store.get_outgoing_secret_requests(&id).await.unwrap();
1033 assert_eq!(request, stored_request);
1034
1035 let stored_request = store.get_secret_request_by_info(&info).await.unwrap();
1036 assert_eq!(request, stored_request);
1037 assert!(!store.get_unsent_secret_requests().await.unwrap().is_empty());
1038
1039 let request = GossipRequest {
1040 request_recipient: account.user_id().to_owned(),
1041 request_id: id.clone(),
1042 info: info.clone(),
1043 sent_out: true,
1044 };
1045
1046 let mut changes = Changes::default();
1047 changes.key_requests.push(request.clone());
1048 store.save_changes(changes).await.unwrap();
1049
1050 assert!(store.get_unsent_secret_requests().await.unwrap().is_empty());
1051 let stored_request = store.get_outgoing_secret_requests(&id).await.unwrap();
1052 assert_eq!(Some(request), stored_request);
1053
1054 store.delete_outgoing_secret_requests(&id).await.unwrap();
1055
1056 let stored_request = store.get_outgoing_secret_requests(&id).await.unwrap();
1057 assert_eq!(None, stored_request);
1058
1059 let stored_request = store.get_secret_request_by_info(&info).await.unwrap();
1060 assert_eq!(None, stored_request);
1061 assert!(store.get_unsent_secret_requests().await.unwrap().is_empty());
1062 }
1063
1064 #[async_test]
1065 async fn test_gossipped_secret_saving() {
1066 let (account, store) = get_loaded_store("gossipped_secret_saving").await;
1067
1068 let secret = "It is a secret to everybody";
1069
1070 let id = TransactionId::new();
1071 let info: SecretInfo = MegolmV1AesSha2Content {
1072 room_id: owned_room_id!("!test:localhost"),
1073 sender_key: Some(account.identity_keys().curve25519),
1074 session_id: "test_session_id".to_owned(),
1075 }
1076 .into();
1077
1078 let gossip_request = GossipRequest {
1079 request_recipient: account.user_id().to_owned(),
1080 request_id: id.clone(),
1081 info: info.clone(),
1082 sent_out: true,
1083 };
1084
1085 let mut event = DecryptedSecretSendEvent {
1086 sender: account.user_id().to_owned(),
1087 recipient: account.user_id().to_owned(),
1088 keys: OlmV1Keys {
1089 ed25519: account.identity_keys().ed25519,
1090 },
1091 recipient_keys: OlmV1Keys {
1092 ed25519: account.identity_keys().ed25519,
1093 },
1094 sender_device_keys: None,
1095 content: SecretSendContent::new(id.to_owned(), secret.to_owned()),
1096 };
1097
1098 let value = GossippedSecret {
1099 secret_name: SecretName::RecoveryKey,
1100 gossip_request: gossip_request.to_owned(),
1101 event: event.to_owned(),
1102 };
1103
1104 assert!(
1105 store.get_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap().is_empty(),
1106 "No secret should initially be found in the store"
1107 );
1108
1109 let mut changes = Changes::default();
1110 changes.secrets.push(value.into());
1111 store.save_changes(changes).await.unwrap();
1112
1113 let restored = store.get_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap();
1114 let first_secret = restored.first().expect("We should have restored a secret now");
1115 assert_eq!(first_secret.deref(), secret);
1116 assert_eq!(restored.len(), 1, "We should only have one secret stored for now");
1117
1118 let secret2 = "It is another secret to everybody";
1119 event.content.request_id = TransactionId::new();
1120 event.content.secret = secret2.to_string();
1121 let another_secret = GossippedSecret {
1122 secret_name: SecretName::RecoveryKey,
1123 gossip_request,
1124 event,
1125 };
1126
1127 let mut changes = Changes::default();
1128 changes.secrets.push(another_secret.clone().into());
1129 store.save_changes(changes).await.unwrap();
1130
1131 let restored = store.get_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap();
1132 assert_eq!(restored.len(), 2, "We should only have two secrets stored");
1133
1134 let restored = store.get_secrets_from_inbox(&SecretName::CrossSigningMasterKey).await.unwrap();
1135 assert!(restored.is_empty(), "We should not have secrets of a different type stored");
1136
1137 let mut changes = Changes::default();
1140 changes.secrets.push(another_secret.into());
1141 store.save_changes(changes).await.unwrap();
1142
1143 let restored = store.get_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap();
1144 assert!(restored.len() == 2 || restored.len() == 3, "We should only have two or three secrets stored");
1147
1148 store.delete_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap();
1149
1150 let restored = store.get_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap();
1151 assert!(restored.is_empty(), "We should not have any secrets after we have deleted them");
1152 }
1153
1154 #[async_test]
1155 #[cfg(feature = "experimental-push-secrets")]
1156 async fn test_pushed_secret_saving() {
1157 let (_account, store) = get_loaded_store("pushed_secret_saving").await;
1158
1159 let secret = "It is a secret to everybody";
1160
1161 let value = SecretPushContent::new(
1162 SecretName::RecoveryKey,
1163 secret.to_owned(),
1164 );
1165
1166 assert!(
1167 store.get_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap().is_empty(),
1168 "No secret should initially be found in the store"
1169 );
1170
1171 let mut changes = Changes::default();
1172 changes.secrets.push(value.clone().into());
1173 store.save_changes(changes).await.unwrap();
1174
1175 let restored = store.get_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap();
1176 let first_secret = restored.first().expect("We should have restored a secret now");
1177 assert_eq!(first_secret.deref(), secret);
1178 assert_eq!(restored.len(), 1, "We should only have one secret stored for now");
1179
1180 let secret2 = "It is another secret to everybody";
1181 let another_secret = SecretPushContent::new(
1182 SecretName::RecoveryKey,
1183 secret2.to_owned(),
1184 );
1185
1186 let mut changes = Changes::default();
1187 changes.secrets.push(another_secret.into());
1188 store.save_changes(changes).await.unwrap();
1189
1190 let restored = store.get_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap();
1191 assert_eq!(restored.len(), 2, "We should only have two secrets stored");
1192
1193 let restored = store.get_secrets_from_inbox(&SecretName::CrossSigningMasterKey).await.unwrap();
1194 assert!(restored.is_empty(), "We should not have secrets of a different type stored");
1195
1196 store.delete_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap();
1197
1198 let restored = store.get_secrets_from_inbox(&SecretName::RecoveryKey).await.unwrap();
1199 assert!(restored.is_empty(), "We should not have any secrets after we have deleted them");
1200 }
1201
1202 #[async_test]
1203 async fn test_withheld_info_storage() {
1204 let (account, store) = get_loaded_store("withheld_info_storage").await;
1205
1206 let user_id = account.user_id().to_owned();
1207 let room_id = room_id!("!DwLygpkclUAfQNnfva:example.com");
1208 let session_id_1 = "GBnDxGP9i3IkPsz3/ihNr6P7qjIXxSRVWZ1MYmSn09w";
1209 let session_id_2 = "IDLtnNCH2kIr3xIf1B7JFkGpQmTjyMca2jww+X6zeOE";
1210
1211 {
1212 let mut info_list: BTreeMap<_, BTreeMap<_, RoomKeyWithheldEntry>> = BTreeMap::new();
1213
1214 let content = RoomKeyWithheldContent::MegolmV1AesSha2(
1215 MegolmV1AesSha2WithheldContent::Unverified(
1216 CommonWithheldCodeContent::new(
1217 room_id.to_owned(),
1218 session_id_1.into(),
1219 Curve25519PublicKey::from_base64(
1220 "9n7mdWKOjr9c4NTlG6zV8dbFtNK79q9vZADoh7nMUwA",
1221 )
1222 .unwrap(),
1223 "DEVICEID".into(),
1224 )
1225 .into(),
1226 ),
1227 );
1228 let event = ToDeviceEvent::new(user_id.to_owned(), content);
1229 info_list
1230 .entry(room_id.to_owned())
1231 .or_default()
1232 .insert(session_id_1.to_owned(), event.into());
1233
1234 let content = RoomKeyWithheldContent::MegolmV1AesSha2(
1235 MegolmV1AesSha2WithheldContent::BlackListed(
1236 CommonWithheldCodeContent::new(
1237 room_id.to_owned(),
1238 session_id_2.into(),
1239 Curve25519PublicKey::from_base64(
1240 "9n7mdWKOjr9c4NTlG6zV8dbFtNK79q9vZADoh7nMUwA",
1241 )
1242 .unwrap(),
1243 "DEVICEID".into(),
1244 )
1245 .into(),
1246 ),
1247 );
1248 let event = ToDeviceEvent::new(user_id.to_owned(), content);
1249 info_list
1250 .entry(room_id.to_owned())
1251 .or_default()
1252 .insert(session_id_2.to_owned(), event.into());
1253
1254 let changes = Changes { withheld_session_info: info_list, ..Default::default() };
1255 store.save_changes(changes).await.unwrap();
1256 }
1257
1258 let is_withheld = store.get_withheld_info(room_id, session_id_1).await.unwrap();
1261
1262 assert_matches!(
1263 is_withheld, Some(event)
1264 if event.content.algorithm() == EventEncryptionAlgorithm::MegolmV1AesSha2 &&
1265 event.content.withheld_code() == WithheldCode::Unverified
1266 );
1267
1268 let is_withheld = store.get_withheld_info(room_id, session_id_2).await.unwrap();
1269
1270 assert_matches!(
1271 is_withheld, Some(event)
1272 if event.content.algorithm() == EventEncryptionAlgorithm::MegolmV1AesSha2 &&
1273 event.content.withheld_code() == WithheldCode::Blacklisted
1274 );
1275
1276 let other_room_id = room_id!("!nQRyiRFuyUhXeaQfiR:example.com");
1277
1278 let is_withheld =
1279 store.get_withheld_info(other_room_id, session_id_2).await.unwrap();
1280
1281 assert!(is_withheld.is_none());
1282
1283 let withhelds = store.get_withheld_sessions_by_room_id(room_id).await.expect("Error getting withheld sessions by room ID");
1285 assert_eq!(withhelds.len(), 2);
1286 let withheld1 = withhelds.iter().find(|entry| entry.content.megolm_session_id() == Some(session_id_1)).expect("Did not find session 1 in withhelds list");
1287 assert_eq!(withheld1.content.withheld_code(), WithheldCode::Unverified)
1288 }
1289
1290 #[async_test]
1291 async fn test_room_settings_saving() {
1292 let (_, store) = get_loaded_store("room_settings_saving").await;
1293
1294 let room_1 = room_id!("!test_1:localhost");
1295 let settings_1 = RoomSettings {
1296 algorithm: EventEncryptionAlgorithm::MegolmV1AesSha2,
1297 #[cfg(feature = "experimental-encrypted-state-events")]
1298 encrypt_state_events: false,
1299 only_allow_trusted_devices: true,
1300 session_rotation_period: Some(Duration::from_secs(10)),
1301 session_rotation_period_messages: Some(123),
1302 };
1303
1304 let room_2 = room_id!("!test_2:localhost");
1305 let settings_2 = RoomSettings {
1306 algorithm: EventEncryptionAlgorithm::OlmV1Curve25519AesSha2,
1307 only_allow_trusted_devices: false,
1308 ..Default::default()
1309 };
1310
1311 let room_3 = room_id!("!test_3:localhost");
1312
1313 let changes = Changes {
1314 room_settings: HashMap::from([
1315 (room_1.into(), settings_1.clone()),
1316 (room_2.into(), settings_2.clone()),
1317 ]),
1318 ..Default::default()
1319 };
1320
1321 store.save_changes(changes).await.unwrap();
1322
1323 let loaded_settings_1 = store.get_room_settings(room_1).await.unwrap();
1324 assert_eq!(Some(settings_1), loaded_settings_1);
1325
1326 let loaded_settings_2 = store.get_room_settings(room_2).await.unwrap();
1327 assert_eq!(Some(settings_2), loaded_settings_2);
1328
1329 let loaded_settings_3 = store.get_room_settings(room_3).await.unwrap();
1330 assert_eq!(None, loaded_settings_3);
1331 }
1332
1333 #[async_test]
1334 async fn test_backup_keys_saving() {
1335 let (_account, store) = get_loaded_store("backup_keys_saving").await;
1336
1337 let restored = store.load_backup_keys().await.unwrap();
1338 assert!(restored.decryption_key.is_none(), "Initially no backup decryption key should be present");
1339
1340 let backup_decryption_key = Some(BackupDecryptionKey::new());
1341
1342 let changes = Changes { backup_decryption_key, ..Default::default() };
1343 store.save_changes(changes).await.unwrap();
1344
1345 let restored = store.load_backup_keys().await.unwrap();
1346 assert!(restored.decryption_key.is_some(), "We should be able to restore a backup decryption key");
1347 assert!(restored.backup_version.is_none(), "The backup version should still be None");
1348
1349 let changes = Changes { backup_version: Some("some_version".to_owned()), ..Default::default() };
1350 store.save_changes(changes).await.unwrap();
1351
1352 let restored = store.load_backup_keys().await.unwrap();
1353 assert!(restored.decryption_key.is_some(), "The backup decryption key should still be known");
1354 assert!(restored.backup_version.is_some(), "The backup version should now be Some as well");
1355 }
1356
1357 #[async_test]
1358 async fn test_dehydration_pickle_key_saving() {
1359 let (_account, store) = get_loaded_store("dehydration_pickle_key_saving").await;
1360
1361 let restored = store.load_dehydrated_device_pickle_key().await.unwrap();
1362 assert!(restored.is_none(), "Initially no pickle key should be present");
1363
1364 let dehydrated_device_pickle_key = Some(DehydratedDeviceKey::new());
1365 let exported_base64 = dehydrated_device_pickle_key.clone().unwrap().to_base64();
1366
1367 let changes = Changes { dehydrated_device_pickle_key, ..Default::default() };
1368 store.save_changes(changes).await.unwrap();
1369
1370 let restored = store.load_dehydrated_device_pickle_key().await.unwrap();
1371 assert!(restored.is_some(), "We should be able to restore a pickle key");
1372 assert_eq!(restored.unwrap().to_base64(), exported_base64);
1373
1374 let changes = Changes { dehydrated_device_pickle_key: None, ..Default::default() };
1376 store.save_changes(changes).await.unwrap();
1377
1378 let restored = store.load_dehydrated_device_pickle_key().await.unwrap();
1379 assert!(restored.is_some(), "We should be able to restore a pickle key");
1380 assert_eq!(restored.unwrap().to_base64(), exported_base64);
1381
1382 }
1383
1384 #[async_test]
1385 async fn test_delete_dehydration_pickle_key() {
1386 let (_account, store) = get_loaded_store("delete_dehydration_pickle_key").await;
1387
1388 let dehydrated_device_pickle_key = DehydratedDeviceKey::new();
1389
1390 let changes = Changes { dehydrated_device_pickle_key: Some(dehydrated_device_pickle_key), ..Default::default() };
1391 store.save_changes(changes).await.unwrap();
1392
1393 let restored = store.load_dehydrated_device_pickle_key().await.unwrap();
1394 assert!(restored.is_some(), "We should be able to restore a pickle key");
1395
1396 store.delete_dehydrated_device_pickle_key().await.unwrap();
1397
1398 let restored = store.load_dehydrated_device_pickle_key().await.unwrap();
1399 assert!(restored.is_none(), "The previously saved key should be deleted");
1400
1401 }
1402
1403
1404 #[async_test]
1405 async fn test_custom_value_saving() {
1406 let (_, store) = get_loaded_store("custom_value_saving").await;
1407 store.set_custom_value("A", "Hello".as_bytes().to_vec()).await.unwrap();
1408
1409 let loaded_1 = store.get_custom_value("A").await.unwrap();
1410 assert_eq!(Some("Hello".as_bytes().to_vec()), loaded_1);
1411
1412 let loaded_2 = store.get_custom_value("B").await.unwrap();
1413 assert_eq!(None, loaded_2);
1414 }
1415
1416 #[async_test]
1417 async fn test_received_room_key_bundle() {
1418 let store = get_store("received_room_key_bundle", None, true).await;
1419 let test_room = room_id!("!room:example.org");
1420
1421 fn make_bundle_data(sender_user: &UserId, bundle_uri: &str) -> StoredRoomKeyBundleData {
1422 let info = ruma::events::room::V2EncryptedFileInfo::encode([0; 32], [0;16]).into();
1423
1424 let file = ruma::events::room::EncryptedFile::new(
1425 ruma::OwnedMxcUri::from(bundle_uri),
1426 info,
1427 Default::default()
1428 );
1429
1430 StoredRoomKeyBundleData {
1431 sender_user: sender_user.to_owned(),
1432 sender_key: Curve25519PublicKey::from_bytes([0u8; 32]),
1433 sender_data: SenderData::unknown(),
1434 bundle_data: RoomKeyBundleContent {
1435 room_id: owned_room_id!("!room:example.org"),
1436 file,
1437 },
1438 }
1439 }
1440
1441 let changes = Changes {
1443 received_room_key_bundles: vec![
1444 make_bundle_data(user_id!("@alice:example.com"), "alice1"),
1445 make_bundle_data(user_id!("@bob:example.com"), "bob1"),
1446 make_bundle_data(user_id!("@alice:example.com"), "alice2"),
1447 ],
1448 ..Default::default()
1449 };
1450 store.save_changes(changes).await.unwrap();
1451
1452 let bundle = store.get_received_room_key_bundle_data(
1454 test_room, user_id!("@alice:example.com")
1455 ).await.unwrap().expect("Did not get any bundle data");
1456 assert_eq!(bundle.bundle_data.file.url.to_string(), "alice2");
1457 }
1458
1459 #[async_test]
1460 async fn test_room_pending_key_bundle() {
1461 use $crate::store::types::RoomPendingKeyBundleDetails;
1462 let store = get_store("room_pending_key_bundle", None, true).await;
1463 let test_room = room_id!("!room:example.org");
1464 let test_user = user_id!("@user:example.com");
1465 let timestamp = ruma::MilliSecondsSinceUnixEpoch::now();
1466
1467 assert!(store.get_pending_key_bundle_details_for_room(test_room).await.unwrap().is_none());
1469
1470 store.save_changes(Changes {
1472 rooms_pending_key_bundle: HashMap::from([(
1473 test_room.to_owned(),
1474 Some(RoomPendingKeyBundleDetails {
1475 room_id: test_room.to_owned(),
1476 invite_accepted_at: timestamp,
1477 inviter: test_user.to_owned(),
1478 }),
1479 )]),
1480 ..Default::default()
1481 }).await.unwrap();
1482
1483 let details = store.get_pending_key_bundle_details_for_room(test_room).await.unwrap();
1484 assert_matches!(details, Some(details) => {
1485 assert_eq!(details.room_id, test_room);
1486 assert_eq!(details.inviter, test_user);
1487 assert_eq!(details.invite_accepted_at, timestamp);
1488 });
1489
1490 let all_rooms = store.get_all_rooms_pending_key_bundles().await.unwrap();
1491 assert_eq!(all_rooms.len(), 1);
1492 assert_eq!(all_rooms[0].room_id, test_room);
1493 assert_eq!(all_rooms[0].inviter, test_user);
1494 assert_eq!(all_rooms[0].invite_accepted_at, timestamp);
1495
1496 store.save_changes(Changes {
1498 rooms_pending_key_bundle: HashMap::from([(test_room.to_owned(), None)]),
1499 ..Default::default()
1500 }).await.unwrap();
1501 assert!(
1502 store.get_pending_key_bundle_details_for_room(test_room).await.unwrap().is_none(),
1503 "Pending key bundle details were present after being cleared"
1504 );
1505 }
1506
1507 #[async_test]
1508 async fn test_set_has_downloaded_all_room_keys() {
1509 let store = get_store("room_key_backups_fully_downloaded", None, true).await;
1510 let test_room = room_id!("!room:example.org");
1511
1512 let changes = Changes {
1513 room_key_backups_fully_downloaded: HashSet::from_iter([test_room.to_owned()]),
1514 ..Default::default()
1515 };
1516 store
1517 .save_changes(changes)
1518 .await
1519 .expect("We should be able to save the changes to the store");
1520
1521 assert!(
1522 store
1523 .has_downloaded_all_room_keys(test_room)
1524 .await
1525 .expect("We should be able to check if we have downloaded room keys")
1526 );
1527 }
1528
1529 fn session_info(session: &InboundGroupSession) -> (&RoomId, &str) {
1530 (&session.room_id(), &session.session_id())
1531 }
1532
1533 async fn create_session(
1534 account: &Account,
1535 device_curve_key: &Curve25519PublicKey,
1536 sender_data_type: SenderDataType,
1537 ) -> InboundGroupSession {
1538 let sender_data = match sender_data_type {
1539 SenderDataType::UnknownDevice => {
1540 SenderData::UnknownDevice { legacy_session: false, owner_check_failed: false }
1541 }
1542 SenderDataType::DeviceInfo => SenderData::DeviceInfo {
1543 device_keys: account.device_keys().clone(),
1544 legacy_session: false,
1545 },
1546 SenderDataType::VerificationViolation => panic!("VerificationViolation not supported"),
1547 SenderDataType::SenderUnverified=> panic!("SenderUnverified not supported"),
1548 SenderDataType::SenderVerified => panic!("SenderVerified not supported"),
1549 };
1550
1551 let session_key = GroupSession::new(SessionConfig::default()).session_key();
1552
1553 InboundGroupSession::new(
1554 device_curve_key.clone(),
1555 account.device_keys().ed25519_key().unwrap(),
1556 room_id!("!r:s.co"),
1557 &session_key,
1558 sender_data,
1559 None,
1560 EventEncryptionAlgorithm::MegolmV1AesSha2,
1561 None,
1562 false,
1563 )
1564 .unwrap()
1565 }
1566 }
1567 };
1568}
1569
1570#[allow(unused_macros)]
1571#[macro_export]
1572macro_rules! cryptostore_integration_tests_time {
1573 () => {
1574 mod cryptostore_integration_tests_time {
1575 use std::time::Duration;
1576
1577 use matrix_sdk_test::async_test;
1578 use $crate::store::CryptoStore as _;
1579
1580 use super::cryptostore_integration_tests::*;
1581
1582 #[async_test]
1583 async fn test_lease_locks() {
1584 let (_account, store) = get_loaded_store("lease_locks").await;
1585
1586 let acquired0 = store.try_take_leased_lock(0, "key", "alice").await.unwrap();
1587 assert_eq!(acquired0, Some(1)); let acquired2 = store.try_take_leased_lock(300, "key", "alice").await.unwrap();
1591 assert_eq!(acquired2, Some(1)); let acquired3 = store.try_take_leased_lock(300, "key", "alice").await.unwrap();
1595 assert_eq!(acquired3, Some(1)); let acquired4 = store.try_take_leased_lock(300, "key", "bob").await.unwrap();
1599 assert!(acquired4.is_none()); let acquired5 = store.try_take_leased_lock(300, "key", "bob").await.unwrap();
1603 assert!(acquired5.is_none());
1604
1605 tokio::time::sleep(Duration::from_millis(50)).await;
1607
1608 let acquired55 = store.try_take_leased_lock(300, "key", "bob").await.unwrap();
1610 assert!(acquired55.is_none()); tokio::time::sleep(Duration::from_millis(250)).await;
1614
1615 let acquired6 = store.try_take_leased_lock(0, "key", "bob").await.unwrap();
1617 assert_eq!(acquired6, Some(2)); tokio::time::sleep(Duration::from_millis(1)).await;
1620
1621 let acquired7 = store.try_take_leased_lock(0, "key", "alice").await.unwrap();
1623 assert_eq!(acquired7, Some(3)); tokio::time::sleep(Duration::from_millis(1)).await;
1626
1627 let acquired8 = store.try_take_leased_lock(300, "key", "bob").await.unwrap();
1629 assert_eq!(acquired8, Some(4)); let acquired9 = store.try_take_leased_lock(300, "key", "alice").await.unwrap();
1633 assert!(acquired9.is_none()); let acquired10 = store.try_take_leased_lock(300, "key", "bob").await.unwrap();
1637 assert_eq!(acquired10, Some(4)); }
1639 }
1640 };
1641}