@@ -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,87 @@ 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
+ #[ cfg( feature = "sqlite" ) ]
1089
+ #[ async_test]
1090
+ async fn test_generation_counter_invalidates_olm_machine ( ) {
1091
+ // Create two clients using the same sqlite database.
1092
+ let sqlite_path = std:: env:: temp_dir ( ) . join ( "generation_counter_sqlite.db" ) ;
1093
+ let session = Session {
1094
+ meta : SessionMeta {
1095
+ user_id : user_id ! ( "@example:localhost" ) . to_owned ( ) ,
1096
+ device_id : device_id ! ( "DEVICEID" ) . to_owned ( ) ,
1097
+ } ,
1098
+ tokens : SessionTokens { access_token : "1234" . to_owned ( ) , refresh_token : None } ,
1099
+ } ;
1100
+
1101
+ let client1 = Client :: builder ( )
1102
+ . homeserver_url ( "http://localhost:1234" )
1103
+ . request_config ( RequestConfig :: new ( ) . disable_retry ( ) )
1104
+ . sqlite_store ( & sqlite_path, None )
1105
+ . build ( )
1106
+ . await
1107
+ . unwrap ( ) ;
1108
+ client1. matrix_auth ( ) . restore_session ( session. clone ( ) ) . await . unwrap ( ) ;
1109
+
1110
+ let client2 = Client :: builder ( )
1111
+ . homeserver_url ( "http://localhost:1234" )
1112
+ . request_config ( RequestConfig :: new ( ) . disable_retry ( ) )
1113
+ . sqlite_store ( sqlite_path, None )
1114
+ . build ( )
1115
+ . await
1116
+ . unwrap ( ) ;
1117
+ client2. matrix_auth ( ) . restore_session ( session) . await . unwrap ( ) ;
1118
+
1119
+ // When the lock isn't enabled, any attempt at locking won't return a guard.
1120
+ let guard = client1. encryption ( ) . try_lock_store_once ( ) . await . unwrap ( ) ;
1121
+ assert ! ( guard. is_none( ) ) ;
1122
+
1123
+ client1. encryption ( ) . enable_cross_process_store_lock ( "client1" . to_owned ( ) ) . await . unwrap ( ) ;
1124
+ client2. encryption ( ) . enable_cross_process_store_lock ( "client2" . to_owned ( ) ) . await . unwrap ( ) ;
1125
+
1126
+ // One client can take the lock.
1127
+ let acquired1 = client1. encryption ( ) . try_lock_store_once ( ) . await . unwrap ( ) ;
1128
+ assert ! ( acquired1. is_some( ) ) ;
1129
+
1130
+ // Keep the olm machine, so we can see if it's changed later, by comparing Arcs.
1131
+ let initial_olm_machine =
1132
+ client1. olm_machine ( ) . await . clone ( ) . expect ( "must have an olm machine" ) ;
1133
+
1134
+ // The other client can't take the lock too.
1135
+ let acquired2 = client2. encryption ( ) . try_lock_store_once ( ) . await . unwrap ( ) ;
1136
+ assert ! ( acquired2. is_none( ) ) ;
1137
+
1138
+ // Now have the first client release the lock,
1139
+ drop ( acquired1) ;
1140
+ tokio:: time:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
1141
+
1142
+ // And re-take it.
1143
+ let acquired1 = client1. encryption ( ) . try_lock_store_once ( ) . await . unwrap ( ) ;
1144
+ assert ! ( acquired1. is_some( ) ) ;
1145
+
1146
+ // In that case, the Olm Machine shouldn't change.
1147
+ let olm_machine = client1. olm_machine ( ) . await . clone ( ) . expect ( "must have an olm machine" ) ;
1148
+ assert ! ( initial_olm_machine. same_as( & olm_machine) ) ;
1149
+
1150
+ // Ok, release again.
1151
+ drop ( acquired1) ;
1152
+ tokio:: time:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
1153
+
1154
+ // Client2 can acquire the lock.
1155
+ let acquired2 = client2. encryption ( ) . try_lock_store_once ( ) . await . unwrap ( ) ;
1156
+ assert ! ( acquired2. is_some( ) ) ;
1157
+
1158
+ // And then release it.
1159
+ drop ( acquired2) ;
1160
+ tokio:: time:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
1161
+
1162
+ // Client1 can acquire it again,
1163
+ let acquired1 = client1. encryption ( ) . try_lock_store_once ( ) . await . unwrap ( ) ;
1164
+ assert ! ( acquired1. is_some( ) ) ;
1165
+
1166
+ // But now its olm machine has been invalidated and thus regenerated!
1167
+ let olm_machine = client1. olm_machine ( ) . await . clone ( ) . expect ( "must have an olm machine" ) ;
1168
+ assert ! ( !initial_olm_machine. same_as( & olm_machine) ) ;
1169
+ }
1079
1170
}
0 commit comments