@@ -941,12 +941,15 @@ impl Encryption {
941
941
942
942
#[ cfg( all( test, not( target_arch = "wasm32" ) ) ) ]
943
943
mod tests {
944
+ use std:: time:: Duration ;
945
+
946
+ use matrix_sdk_base:: SessionMeta ;
944
947
use matrix_sdk_test:: {
945
948
async_test, test_json, EventBuilder , GlobalAccountDataTestEvent , JoinedRoomBuilder ,
946
949
StateTestEvent ,
947
950
} ;
948
951
use ruma:: {
949
- event_id,
952
+ device_id , event_id,
950
953
events:: { reaction:: ReactionEventContent , relation:: Annotation } ,
951
954
user_id,
952
955
} ;
@@ -956,7 +959,12 @@ mod tests {
956
959
Mock , MockServer , ResponseTemplate ,
957
960
} ;
958
961
959
- use crate :: test_utils:: logged_in_client;
962
+ use crate :: {
963
+ config:: RequestConfig ,
964
+ matrix_auth:: { Session , SessionTokens } ,
965
+ test_utils:: logged_in_client,
966
+ Client ,
967
+ } ;
960
968
961
969
#[ async_test]
962
970
async fn test_reaction_sending ( ) {
@@ -1076,4 +1084,86 @@ mod tests {
1076
1084
let found_room = client. get_dm_room ( user_id) . expect ( "DM not found!" ) ;
1077
1085
assert ! ( found_room. get_member_no_sync( user_id) . await . unwrap( ) . is_some( ) ) ;
1078
1086
}
1087
+
1088
+ #[ async_test]
1089
+ async fn test_generation_counter_invalidates_olm_machine ( ) {
1090
+ // Create two clients using the same sqlite database.
1091
+ let sqlite_path = std:: env:: temp_dir ( ) . join ( "generation_counter_sqlite.db" ) ;
1092
+ let session = Session {
1093
+ meta : SessionMeta {
1094
+ user_id : user_id ! ( "@example:localhost" ) . to_owned ( ) ,
1095
+ device_id : device_id ! ( "DEVICEID" ) . to_owned ( ) ,
1096
+ } ,
1097
+ tokens : SessionTokens { access_token : "1234" . to_owned ( ) , refresh_token : None } ,
1098
+ } ;
1099
+
1100
+ let client1 = Client :: builder ( )
1101
+ . homeserver_url ( "http://localhost:1234" )
1102
+ . request_config ( RequestConfig :: new ( ) . disable_retry ( ) )
1103
+ . sqlite_store ( & sqlite_path, None )
1104
+ . build ( )
1105
+ . await
1106
+ . unwrap ( ) ;
1107
+ client1. matrix_auth ( ) . restore_session ( session. clone ( ) ) . await . unwrap ( ) ;
1108
+
1109
+ let client2 = Client :: builder ( )
1110
+ . homeserver_url ( "http://localhost:1234" )
1111
+ . request_config ( RequestConfig :: new ( ) . disable_retry ( ) )
1112
+ . sqlite_store ( sqlite_path, None )
1113
+ . build ( )
1114
+ . await
1115
+ . unwrap ( ) ;
1116
+ client2. matrix_auth ( ) . restore_session ( session) . await . unwrap ( ) ;
1117
+
1118
+ // When the lock isn't enabled, any attempt at locking won't return a guard.
1119
+ let guard = client1. encryption ( ) . try_lock_store_once ( ) . await . unwrap ( ) ;
1120
+ assert ! ( guard. is_none( ) ) ;
1121
+
1122
+ client1. encryption ( ) . enable_cross_process_store_lock ( "client1" . to_owned ( ) ) . await . unwrap ( ) ;
1123
+ client2. encryption ( ) . enable_cross_process_store_lock ( "client2" . to_owned ( ) ) . await . unwrap ( ) ;
1124
+
1125
+ // One client can take the lock.
1126
+ let acquired1 = client1. encryption ( ) . try_lock_store_once ( ) . await . unwrap ( ) ;
1127
+ assert ! ( acquired1. is_some( ) ) ;
1128
+
1129
+ // Keep the olm machine, so we can see if it's changed later, by comparing Arcs.
1130
+ let initial_olm_machine =
1131
+ client1. olm_machine ( ) . await . clone ( ) . expect ( "must have an olm machine" ) ;
1132
+
1133
+ // The other client can't take the lock too.
1134
+ let acquired2 = client2. encryption ( ) . try_lock_store_once ( ) . await . unwrap ( ) ;
1135
+ assert ! ( acquired2. is_none( ) ) ;
1136
+
1137
+ // Now have the first client release the lock,
1138
+ drop ( acquired1) ;
1139
+ tokio:: time:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
1140
+
1141
+ // And re-take it.
1142
+ let acquired1 = client1. encryption ( ) . try_lock_store_once ( ) . await . unwrap ( ) ;
1143
+ assert ! ( acquired1. is_some( ) ) ;
1144
+
1145
+ // In that case, the Olm Machine shouldn't change.
1146
+ let olm_machine = client1. olm_machine ( ) . await . clone ( ) . expect ( "must have an olm machine" ) ;
1147
+ assert ! ( initial_olm_machine. same_as( & olm_machine) ) ;
1148
+
1149
+ // Ok, release again.
1150
+ drop ( acquired1) ;
1151
+ tokio:: time:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
1152
+
1153
+ // Client2 can acquire the lock.
1154
+ let acquired2 = client2. encryption ( ) . try_lock_store_once ( ) . await . unwrap ( ) ;
1155
+ assert ! ( acquired2. is_some( ) ) ;
1156
+
1157
+ // And then release it.
1158
+ drop ( acquired2) ;
1159
+ tokio:: time:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
1160
+
1161
+ // Client1 can acquire it again,
1162
+ let acquired1 = client1. encryption ( ) . try_lock_store_once ( ) . await . unwrap ( ) ;
1163
+ assert ! ( acquired1. is_some( ) ) ;
1164
+
1165
+ // But now its olm machine has been invalidated and thus regenerated!
1166
+ let olm_machine = client1. olm_machine ( ) . await . clone ( ) . expect ( "must have an olm machine" ) ;
1167
+ assert ! ( !initial_olm_machine. same_as( & olm_machine) ) ;
1168
+ }
1079
1169
}
0 commit comments