@@ -28,6 +28,9 @@ use eyeball_im::VectorDiff;
28
28
use matrix_sdk:: {
29
29
assert_next_matches_with_timeout,
30
30
crypto:: { decrypt_room_key_export, types:: events:: UtdCause , OlmMachine } ,
31
+ deserialized_responses:: {
32
+ AlgorithmInfo , DecryptedRoomEvent , EncryptionInfo , VerificationLevel , VerificationState ,
33
+ } ,
31
34
test_utils:: test_client_builder,
32
35
} ;
33
36
use matrix_sdk_base:: deserialized_responses:: { TimelineEvent , UnableToDecryptReason } ;
@@ -38,18 +41,19 @@ use ruma::{
38
41
EncryptedEventScheme , MegolmV1AesSha2ContentInit , Relation , Replacement ,
39
42
RoomEncryptedEventContent ,
40
43
} ,
41
- room_id,
44
+ owned_device_id , room_id,
42
45
serde:: Raw ,
43
46
user_id,
44
47
} ;
45
48
use serde_json:: { json, value:: to_raw_value} ;
46
- use stream_assert:: assert_next_matches;
49
+ use stream_assert:: { assert_next_matches, assert_pending } ;
47
50
use tokio:: time:: sleep;
48
51
49
52
use super :: TestTimeline ;
50
53
use crate :: {
51
54
timeline:: {
52
- tests:: TestTimelineBuilder , EncryptedMessage , TimelineDetails , TimelineItemContent ,
55
+ tests:: { TestRoomDataProvider , TestTimelineBuilder } ,
56
+ EncryptedMessage , TimelineDetails , TimelineItemContent ,
53
57
} ,
54
58
unable_to_decrypt_hook:: { UnableToDecryptHook , UnableToDecryptInfo , UtdHookManager } ,
55
59
} ;
@@ -550,6 +554,94 @@ async fn test_retry_message_decryption_highlighted() {
550
554
assert ! ( event. is_highlighted( ) ) ;
551
555
}
552
556
557
+ #[ async_test]
558
+ async fn test_retry_fetching_encryption_info ( ) {
559
+ const SESSION_ID : & str = "C25PoE+4MlNidQD0YU5ibZqHawV0zZ/up7R8vYJBYTY" ;
560
+ let sender = user_id ! ( "@sender:s.co" ) ;
561
+ let room_id = room_id ! ( "!room:s.co" ) ;
562
+
563
+ // Given when I ask the room for new encryption info for any session, it will
564
+ // say "verified"
565
+ let verified_encryption_info = make_encryption_info ( SESSION_ID , VerificationState :: Verified ) ;
566
+ let provider = TestRoomDataProvider :: default ( ) . with_encryption_info ( verified_encryption_info) ;
567
+ let timeline = TestTimelineBuilder :: new ( ) . provider ( provider) . build ( ) ;
568
+ let f = & timeline. factory ;
569
+ let mut stream = timeline. subscribe ( ) . await ;
570
+
571
+ // But right now the timeline contains 2 events whose info says "unverified"
572
+ // One is linked to SESSION_ID, the other is linked to some other session.
573
+ let timeline_event_this_session: TimelineEvent = DecryptedRoomEvent {
574
+ event : f. text_msg ( "foo" ) . sender ( sender) . room ( room_id) . into_raw ( ) ,
575
+ encryption_info : make_encryption_info (
576
+ SESSION_ID ,
577
+ VerificationState :: Unverified ( VerificationLevel :: UnsignedDevice ) ,
578
+ ) ,
579
+ unsigned_encryption_info : None ,
580
+ }
581
+ . into ( ) ;
582
+ let timeline_event_other_session: TimelineEvent = DecryptedRoomEvent {
583
+ event : f. text_msg ( "foo" ) . sender ( sender) . room ( room_id) . into_raw ( ) ,
584
+ encryption_info : make_encryption_info (
585
+ "other_session_id" ,
586
+ VerificationState :: Unverified ( VerificationLevel :: UnsignedDevice ) ,
587
+ ) ,
588
+ unsigned_encryption_info : None ,
589
+ }
590
+ . into ( ) ;
591
+ timeline. handle_live_event ( timeline_event_this_session) . await ;
592
+ timeline. handle_live_event ( timeline_event_other_session) . await ;
593
+
594
+ // Sanity: the events come through as unverified
595
+ assert_eq ! ( timeline. controller. items( ) . await . len( ) , 3 ) ;
596
+ let item_1 = assert_next_matches ! ( stream, VectorDiff :: PushBack { value } => value) ;
597
+ let fetched_encryption_info_1 =
598
+ item_1. as_event ( ) . unwrap ( ) . as_remote ( ) . unwrap ( ) . encryption_info . as_ref ( ) . unwrap ( ) ;
599
+ assert_matches ! ( fetched_encryption_info_1. verification_state, VerificationState :: Unverified ( _) ) ;
600
+ // (Plus a date divider is emitted - not sure why it's in the middle...)
601
+ let date_divider = assert_next_matches ! ( stream, VectorDiff :: PushFront { value } => value) ;
602
+ assert ! ( date_divider. is_date_divider( ) ) ;
603
+ let item_2 = assert_next_matches ! ( stream, VectorDiff :: PushBack { value } => value) ;
604
+ let fetched_encryption_info_2 =
605
+ item_2. as_event ( ) . unwrap ( ) . as_remote ( ) . unwrap ( ) . encryption_info . as_ref ( ) . unwrap ( ) ;
606
+ assert_matches ! ( fetched_encryption_info_2. verification_state, VerificationState :: Unverified ( _) ) ;
607
+
608
+ // When we retry the session with ID SESSION_ID
609
+ let own_user_id = user_id ! ( "@me:s.co" ) ;
610
+ let olm_machine = OlmMachine :: new ( own_user_id, "SomeDeviceId" . into ( ) ) . await ;
611
+ timeline
612
+ . controller
613
+ . retry_event_decryption_test (
614
+ room_id,
615
+ olm_machine,
616
+ Some ( iter:: once ( SESSION_ID . to_owned ( ) ) . collect ( ) ) ,
617
+ )
618
+ . await ;
619
+
620
+ // Then the event in that session has been updated to be verified
621
+ assert_eq ! ( timeline. controller. items( ) . await . len( ) , 3 ) ;
622
+ let item = assert_next_matches ! ( stream, VectorDiff :: Set { index: 1 , value } => value) ;
623
+ let event = item. as_event ( ) . unwrap ( ) ;
624
+ let fetched_encryption_info = event. as_remote ( ) . unwrap ( ) . encryption_info . as_ref ( ) . unwrap ( ) ;
625
+ assert_matches ! ( fetched_encryption_info. verification_state, VerificationState :: Verified ) ;
626
+
627
+ // But the other one is unchanged because it was for a different session - no
628
+ // other updates are waiting
629
+ assert_pending ! ( stream) ;
630
+ }
631
+
632
+ fn make_encryption_info ( session_id : & str , verification_state : VerificationState ) -> EncryptionInfo {
633
+ EncryptionInfo {
634
+ sender : BOB . to_owned ( ) ,
635
+ sender_device : Some ( owned_device_id ! ( "BOBDEVICE" ) ) ,
636
+ algorithm_info : AlgorithmInfo :: MegolmV1AesSha2 {
637
+ curve25519_key : Default :: default ( ) ,
638
+ sender_claimed_keys : Default :: default ( ) ,
639
+ } ,
640
+ verification_state,
641
+ session_id : session_id. to_owned ( ) ,
642
+ }
643
+ }
644
+
553
645
#[ async_test]
554
646
async fn test_utd_cause_for_nonmember_event_is_found ( ) {
555
647
// Given a timline
0 commit comments