Skip to content

Commit cbdfb27

Browse files
committed
test: Test that room keys received by notification clients trigger redecryptions
1 parent 090c9ee commit cbdfb27

File tree

1 file changed

+159
-4
lines changed
  • testing/matrix-sdk-integration-testing/src/tests

1 file changed

+159
-4
lines changed

testing/matrix-sdk-integration-testing/src/tests/timeline.rs

Lines changed: 159 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,20 @@ use matrix_sdk::{
2525
encryption::{backups::BackupState, EncryptionSettings},
2626
room::edit::EditedContent,
2727
ruma::{
28-
api::client::room::create_room::v3::Request as CreateRoomRequest,
28+
api::client::room::create_room::v3::{Request as CreateRoomRequest, RoomPreset},
2929
events::{
3030
room::{encryption::RoomEncryptionEventContent, message::RoomMessageEventContent},
3131
InitialStateEvent,
3232
},
3333
MilliSecondsSinceUnixEpoch,
3434
},
35+
RoomState,
3536
};
36-
use matrix_sdk_ui::timeline::{
37-
EventSendState, ReactionStatus, RoomExt, TimelineItem, TimelineItemContent,
37+
use matrix_sdk_ui::{
38+
notification_client::NotificationClient,
39+
room_list_service::RoomListLoadingState,
40+
sync_service::SyncService,
41+
timeline::{EventSendState, ReactionStatus, RoomExt, TimelineItem, TimelineItemContent},
3842
};
3943
use similar_asserts::assert_eq;
4044
use tokio::{
@@ -357,7 +361,7 @@ async fn test_enabling_backups_retries_decryption() {
357361
.create_room(assign!(CreateRoomRequest::new(), {
358362
is_direct: true,
359363
initial_state,
360-
preset: Some(matrix_sdk::ruma::api::client::room::create_room::v3::RoomPreset::PrivateChat)
364+
preset: Some(RoomPreset::PrivateChat)
361365
}))
362366
.await
363367
.unwrap();
@@ -462,3 +466,154 @@ async fn test_enabling_backups_retries_decryption() {
462466

463467
bob_sync.abort();
464468
}
469+
470+
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
471+
async fn test_foobar() {
472+
let alice = TestClientBuilder::new("alice").use_sqlite().build().await.unwrap();
473+
alice.encryption().wait_for_e2ee_initialization_tasks().await;
474+
475+
// Set up sync for user Alice, and create a room.
476+
let alice_sync = spawn({
477+
let alice = alice.clone();
478+
async move {
479+
alice.sync(Default::default()).await.expect("sync failed!");
480+
}
481+
});
482+
483+
debug!("Creating the room…");
484+
485+
// The room needs to be encrypted.
486+
let initial_state =
487+
vec![InitialStateEvent::new(RoomEncryptionEventContent::with_recommended_defaults())
488+
.to_raw_any()];
489+
490+
let alice_room = alice
491+
.create_room(assign!(CreateRoomRequest::new(), {
492+
is_direct: true,
493+
initial_state,
494+
preset: Some(RoomPreset::PrivateChat)
495+
}))
496+
.await
497+
.unwrap();
498+
499+
assert!(alice_room
500+
.is_encrypted()
501+
.await
502+
.expect("We should be able to check that the room is encrypted"));
503+
504+
// Now here comes bob.
505+
let bob = TestClientBuilder::new("bob").use_sqlite().build().await.unwrap();
506+
bob.encryption().wait_for_e2ee_initialization_tasks().await;
507+
508+
debug!("Inviting Bob.");
509+
510+
alice_room
511+
.invite_user_by_id(bob.user_id().expect("We should have access to bob's user ID"))
512+
.await
513+
.expect("We should be able to invite Bob to the room");
514+
515+
// Sync once to get access to the room.
516+
let sync_service = SyncService::builder(bob.clone()).build().await.expect("Wat");
517+
sync_service.start().await;
518+
519+
let bob_rooms = sync_service
520+
.room_list_service()
521+
.all_rooms()
522+
.await
523+
.expect("We should be able to get the room");
524+
525+
debug!("Waiting for the room list to load");
526+
let wait_for_room_list_load = async {
527+
while let Some(state) = bob_rooms.loading_state().next().await {
528+
match state {
529+
RoomListLoadingState::Loaded { .. } => break,
530+
_ => (),
531+
}
532+
}
533+
};
534+
535+
timeout(Duration::from_secs(5), wait_for_room_list_load)
536+
.await
537+
.expect("We should be able to load the room list");
538+
539+
// Bob joins the room.
540+
let bob_room =
541+
bob.get_room(alice_room.room_id()).expect("We should have access to the room now");
542+
bob_room.join().await.expect("Bob should be able to join the room");
543+
544+
debug!("Bob joined the room");
545+
assert_eq!(bob_room.state(), RoomState::Joined);
546+
assert!(bob_room.is_encrypted().await.unwrap());
547+
548+
// Let's stop the sync so we don't receive the room key using the usual channel.
549+
sync_service.stop().await.expect("We should be able to stop the sync service");
550+
551+
debug!("Alice sends the message");
552+
let event_id = alice_room
553+
.send(RoomMessageEventContent::text_plain("It's a secret to everybody!"))
554+
.await
555+
.expect("We should be able to send a message to our new room")
556+
.event_id;
557+
558+
// We don't need Alice anymore.
559+
alice_sync.abort();
560+
561+
// Let's get the timeline and backpaginate to load the event.
562+
let timeline =
563+
bob_room.timeline().await.expect("We should be able to get a timeline for our room");
564+
565+
timeline
566+
.paginate_backwards(50)
567+
.await
568+
.expect("We should be able to paginate the timeline to fetch the history");
569+
let item =
570+
timeline.item_by_event_id(&event_id).await.expect("The event should be in the timeline");
571+
572+
// The event is not decrypted yet.
573+
assert_matches!(item.content(), TimelineItemContent::UnableToDecrypt(_));
574+
575+
// Let's subscribe to our timeline so we don't miss the transition from UTD to
576+
// decrypted event.
577+
let (_, mut stream) = timeline
578+
.subscribe_filter_map(|item| {
579+
item.as_event().cloned().filter(|item| item.event_id() == Some(&event_id))
580+
})
581+
.await;
582+
583+
// Now we create a notification client.
584+
let notification_client = bob
585+
.notification_client("BOB_NOTIFICATION_CLIENT".to_owned())
586+
.await
587+
.expect("We should be able to build a notification client");
588+
589+
// This syncs and fetches the room key.
590+
debug!("The notification client syncs");
591+
let notification_client = NotificationClient::new(
592+
notification_client,
593+
matrix_sdk_ui::notification_client::NotificationProcessSetup::SingleProcess {
594+
sync_service: sync_service.into(),
595+
},
596+
)
597+
.await
598+
.expect("We should be able to build a notification client");
599+
600+
let _ = notification_client
601+
.get_notification(bob_room.room_id(), &event_id)
602+
.await
603+
.expect("We should be able toe get a notification item for the given event");
604+
605+
// Alright, we should now receive an update that the event had been decrypted.
606+
let _vector_diff = timeout(Duration::from_secs(5), stream.next()).await.unwrap().unwrap();
607+
608+
// Let's fetch the event again.
609+
let item =
610+
timeline.item_by_event_id(&event_id).await.expect("The event should be in the timeline");
611+
612+
// Yup it's decrypted great.
613+
assert_let!(
614+
TimelineItemContent::Message(message) = item.content(),
615+
"The event should have been decrypted now"
616+
);
617+
618+
assert_eq!(message.body(), "It's a secret to everybody!");
619+
}

0 commit comments

Comments
 (0)