17
17
//! tests.
18
18
use std:: {
19
19
collections:: BTreeMap ,
20
- sync:: {
21
- atomic:: { AtomicU32 , Ordering } ,
22
- Arc , Mutex ,
23
- } ,
20
+ sync:: { atomic:: Ordering , Arc , Mutex } ,
24
21
} ;
25
22
26
- use matrix_sdk_base:: SessionMeta ;
27
- use matrix_sdk_test:: SyncResponseBuilder ;
28
23
use ruma:: {
29
- api:: { client:: keys:: upload_signatures:: v3:: SignedKeys , MatrixVersion } ,
24
+ api:: client:: keys:: upload_signatures:: v3:: SignedKeys ,
30
25
encryption:: { CrossSigningKey , DeviceKeys , OneTimeKey } ,
31
26
owned_device_id, owned_user_id,
32
27
serde:: Raw ,
33
28
CrossSigningKeyId , DeviceId , OneTimeKeyAlgorithm , OwnedDeviceId , OwnedOneTimeKeyId ,
34
29
OwnedUserId , UserId ,
35
30
} ;
36
- use serde:: Serialize ;
37
31
use serde_json:: json;
38
32
use wiremock:: {
39
- matchers:: { method, path , query_param , query_param_is_missing } ,
40
- Mock , MockGuard , MockServer , Request , ResponseTemplate ,
33
+ matchers:: { method, path_regex } ,
34
+ Mock , Request , ResponseTemplate ,
41
35
} ;
42
36
43
- use crate :: { authentication:: matrix:: MatrixSession , config:: RequestConfig , Client , SessionTokens } ;
44
-
45
- #[ derive( Debug , Default ) ]
46
- struct Keys {
47
- device : BTreeMap < OwnedUserId , BTreeMap < String , Raw < DeviceKeys > > > ,
48
- master : BTreeMap < OwnedUserId , Raw < CrossSigningKey > > ,
49
- self_signing : BTreeMap < OwnedUserId , Raw < CrossSigningKey > > ,
50
- user_signing : BTreeMap < OwnedUserId , Raw < CrossSigningKey > > ,
51
- one_time_keys : BTreeMap <
52
- OwnedUserId ,
53
- BTreeMap < OwnedDeviceId , BTreeMap < OwnedOneTimeKeyId , Raw < OneTimeKey > > > ,
54
- > ,
55
- }
37
+ use crate :: {
38
+ test_utils:: {
39
+ client:: MockClientBuilder ,
40
+ mocks:: { Keys , MatrixMockServer } ,
41
+ } ,
42
+ Client ,
43
+ } ;
56
44
57
- /// A [`wiremock`] [`MockServer`] along with useful methods to help mocking
45
+ /// Extends the `MatrixMockServer` with useful methods to help mocking
58
46
/// matrix crypto API and perform integration test with encryption.
59
47
///
60
48
/// It implements mock endpoints for the `keys/upload`, will store the uploaded
@@ -65,66 +53,26 @@ struct Keys {
65
53
/// client running out of otks. More can be added if needed later.
66
54
///
67
55
/// It works like this:
68
- /// * Start by creating the mock server like this [`MatrixKeysMockServer::new`].
69
- /// It will setup the mocks
70
- /// * Create your test client using [`MatrixKeysMockServer::create_client`],
71
- /// this is important as it will set up an access token that will allow to
72
- /// know what client is doing what request.
73
- ///
74
- /// # Examples
75
- ///
76
- /// ```
77
- /// # tokio_test::block_on(async {
78
- /// use matrix_sdk::{
79
- /// ruma::{device_id, user_id},
80
- /// test_utils::mocks::encryption::MatrixKeysMockServer,
81
- /// };
82
- /// let mock_server = MatrixKeysMockServer::new().await;
83
- ///
84
- /// let (alice, bob) = mock_server.set_up_alice_and_bob_for_encryption().await;
56
+ /// * Start by creating the mock server like this [`MatrixMockServer::new`].
57
+ /// * Then mock the crypto API endpoints
58
+ /// [`MatrixMockServer::mock_crypto_endpoints_preset`].
59
+ /// * Create your test client using
60
+ /// [`MatrixMockServer::client_builder_for_crypto_end_to_end`], this is
61
+ /// important as it will set up an access token that will allow to know what
62
+ /// client is doing what request.
85
63
///
86
- /// let alice_bob_device = alice
87
- /// .encryption()
88
- /// .get_device(bob.user_id().unwrap(), bob.device_id().unwrap())
89
- /// .await
90
- /// .unwrap()
91
- /// .expect("alice sees bob's device");
92
- ///
93
- /// # anyhow::Ok(()) });
94
- /// ```
95
- pub struct MatrixKeysMockServer {
96
- /// The underlying [`wiremock`] [`MockServer`]
97
- pub server : MockServer ,
98
- keys : Arc < Mutex < Keys > > ,
99
- token_to_user_id_map : Arc < Mutex < BTreeMap < String , OwnedUserId > > > ,
100
- token_counter : AtomicU32 ,
101
- }
102
-
103
- impl MatrixKeysMockServer {
104
- /// Creates a new `MatrixKeysMockServer` and mocks the crypto API end-points
105
- pub async fn new ( ) -> Self {
106
- let server = MockServer :: start ( ) . await ;
107
- let keys: Arc < Mutex < Keys > > = Default :: default ( ) ;
108
- let mock_keys_server = Self {
109
- server,
110
- keys,
111
- token_to_user_id_map : Default :: default ( ) ,
112
- token_counter : Default :: default ( ) ,
113
- } ;
114
- mock_keys_server. mock_endpoints ( ) . await ;
115
- mock_keys_server
116
- }
117
-
118
- /// Creates a `Client` that will use this mock server.
119
- pub async fn create_client ( & self , user_id : & UserId , device_id : & DeviceId ) -> Client {
120
- let client = Client :: builder ( )
121
- . homeserver_url ( self . server . uri ( ) )
122
- . server_versions ( [ MatrixVersion :: V1_0 ] )
123
- . request_config ( RequestConfig :: new ( ) . disable_retry ( ) )
124
- . build ( )
125
- . await
126
- . unwrap ( ) ;
127
-
64
+ /// The [`MatrixMockServer::set_up_alice_and_bob_for_encryption`] will set up
65
+ /// two olm machines aware of each other and ready to communicate.
66
+ impl MatrixMockServer {
67
+ /// Creates a new [`MockClientBuilder`] configured to use this server and
68
+ /// suitable for usage of the crypto API end points.
69
+ /// Will create a specific access token and some mapping to the associated
70
+ /// user_id.
71
+ pub fn client_builder_for_crypto_end_to_end (
72
+ & self ,
73
+ user_id : & UserId ,
74
+ device_id : & DeviceId ,
75
+ ) -> MockClientBuilder {
128
76
// Create an access token and store the token to user_id mapping
129
77
let next = self . token_counter . fetch_add ( 1 , Ordering :: Relaxed ) ;
130
78
let access_token = format ! ( "TOKEN_{}" , next) ;
@@ -135,15 +83,11 @@ impl MatrixKeysMockServer {
135
83
mappings. insert ( auth_string, user_id. to_owned ( ) ) ;
136
84
}
137
85
138
- client
139
- . restore_session ( MatrixSession {
140
- meta : SessionMeta { user_id : user_id. to_owned ( ) , device_id : device_id. to_owned ( ) } ,
141
- tokens : SessionTokens { access_token, refresh_token : None } ,
142
- } )
143
- . await
144
- . unwrap ( ) ;
145
-
146
- client
86
+ MockClientBuilder :: new ( self . server . uri ( ) ) . logged_in_with_token (
87
+ access_token,
88
+ user_id. to_owned ( ) ,
89
+ device_id. to_owned ( ) ,
90
+ )
147
91
}
148
92
149
93
/// Makes the server forget about all the one-time-keys for that device.
@@ -159,11 +103,15 @@ impl MatrixKeysMockServer {
159
103
let alice_user_id = owned_user_id ! ( "@alice:example.org" ) ;
160
104
let alice_device_id = owned_device_id ! ( "4L1C3" ) ;
161
105
162
- let alice = self . create_client ( & alice_user_id, & alice_device_id) . await ;
106
+ let alice = self
107
+ . client_builder_for_crypto_end_to_end ( & alice_user_id, & alice_device_id)
108
+ . build ( )
109
+ . await ;
163
110
164
111
let bob_user_id = owned_user_id ! ( "@bob:example.org" ) ;
165
112
let bob_device_id = owned_device_id ! ( "B0B0B0B0B" ) ;
166
- let bob = self . create_client ( & bob_user_id, & bob_device_id) . await ;
113
+ let bob =
114
+ self . client_builder_for_crypto_end_to_end ( & bob_user_id, & bob_device_id) . build ( ) . await ;
167
115
168
116
// Have Alice track Bob, so she queries his keys later.
169
117
{
@@ -174,67 +122,49 @@ impl MatrixKeysMockServer {
174
122
175
123
// Have Alice and Bob upload their signed device keys.
176
124
{
177
- let mut sync_response_builder = SyncResponseBuilder :: new ( ) ;
178
- let response_body = sync_response_builder. build_json_sync_response ( ) ;
179
- let _scope = mock_sync_scoped ( & self . server , response_body, None ) . await ;
180
-
181
- alice
182
- . sync_once ( Default :: default ( ) )
183
- . await
184
- . expect ( "We should be able to sync with Alice so we upload the device keys" ) ;
185
- bob. sync_once ( Default :: default ( ) ) . await . unwrap ( ) ;
125
+ self . mock_sync ( ) . ok_and_run ( & alice, |_x| { } ) . await ;
126
+ self . mock_sync ( ) . ok_and_run ( & bob, |_x| { } ) . await ;
186
127
}
187
128
188
129
// Run a sync so we do send outgoing requests, including the /keys/query for
189
130
// getting bob's identity.
190
- let mut sync_response_builder = SyncResponseBuilder :: new ( ) ;
191
-
192
- {
193
- let _scope = mock_sync_scoped (
194
- & self . server ,
195
- sync_response_builder. build_json_sync_response ( ) ,
196
- None ,
197
- )
198
- . await ;
199
- alice
200
- . sync_once ( Default :: default ( ) )
201
- . await
202
- . expect ( "We should be able to sync so we get theinitial set of devices" ) ;
203
- }
131
+ self . mock_sync ( ) . ok_and_run ( & alice, |_x| { } ) . await ;
204
132
205
133
( alice, bob)
206
134
}
207
135
208
- async fn mock_endpoints ( & self ) {
136
+ /// Mock up the various crypto API so that it can serve back keys when
137
+ /// needed
138
+ pub async fn mock_crypto_endpoints_preset ( & self ) {
209
139
let keys = & self . keys ;
210
140
let token_map = & self . token_to_user_id_map ;
211
141
212
142
Mock :: given ( method ( "POST" ) )
213
- . and ( path ( " /_matrix/client/r0 /keys/query") )
143
+ . and ( path_regex ( r"^ /_matrix/client/.* /keys/query") )
214
144
. respond_with ( mock_keys_query ( keys. clone ( ) ) )
215
145
. mount ( & self . server )
216
146
. await ;
217
147
218
148
Mock :: given ( method ( "POST" ) )
219
- . and ( path ( " /_matrix/client/r0 /keys/upload") )
149
+ . and ( path_regex ( r"^ /_matrix/client/.* /keys/upload") )
220
150
. respond_with ( mock_keys_upload ( keys. clone ( ) , token_map. clone ( ) ) )
221
151
. mount ( & self . server )
222
152
. await ;
223
153
224
154
Mock :: given ( method ( "POST" ) )
225
- . and ( path ( " /_matrix/client/unstable /keys/device_signing/upload") )
155
+ . and ( path_regex ( r"^ /_matrix/client/.* /keys/device_signing/upload") )
226
156
. respond_with ( mock_keys_device_signing_upload ( keys. clone ( ) ) )
227
157
. mount ( & self . server )
228
158
. await ;
229
159
230
160
Mock :: given ( method ( "POST" ) )
231
- . and ( path ( " /_matrix/client/unstable /keys/signatures/upload") )
161
+ . and ( path_regex ( r"^ /_matrix/client/.* /keys/signatures/upload") )
232
162
. respond_with ( mock_keys_signature_upload ( keys. clone ( ) ) )
233
163
. mount ( & self . server )
234
164
. await ;
235
165
236
166
Mock :: given ( method ( "POST" ) )
237
- . and ( path ( " /_matrix/client/r0 /keys/claim") )
167
+ . and ( path_regex ( r"^ /_matrix/client/.* /keys/claim") )
238
168
. respond_with ( mock_keys_claimed_request ( keys. clone ( ) ) )
239
169
. mount ( & self . server )
240
170
. await ;
@@ -310,7 +240,7 @@ fn mock_keys_upload(
310
240
let tokens = token_to_user_id_map. lock ( ) . unwrap ( ) ;
311
241
// Get the user
312
242
let user_id = tokens. get ( bearer_token)
313
- . expect ( "Expect this token to be known, ensure you use `MatrixKeysMockServer::createClient `" )
243
+ . expect ( "Expect this token to be known, ensure you use `MatrixKeysServer::client_builder_for_crypto_end_to_end `" )
314
244
. to_owned ( ) ;
315
245
316
246
if let Some ( new_device_keys) = params. device_keys {
@@ -556,25 +486,3 @@ fn mock_keys_claimed_request(keys: Arc<Mutex<Keys>>) -> impl Fn(&Request) -> Res
556
486
} ) )
557
487
}
558
488
}
559
-
560
- /// Mount a Mock on the given server to handle the `GET /sync` endpoint with
561
- /// an optional `since` param that returns a 200 status code with the given
562
- /// response body.
563
- async fn mock_sync_scoped (
564
- server : & MockServer ,
565
- response_body : impl Serialize ,
566
- since : Option < String > ,
567
- ) -> MockGuard {
568
- let mut builder = Mock :: given ( method ( "GET" ) ) . and ( path ( "/_matrix/client/r0/sync" ) ) ;
569
-
570
- if let Some ( since) = since {
571
- builder = builder. and ( query_param ( "since" , since) ) ;
572
- } else {
573
- builder = builder. and ( query_param_is_missing ( "since" ) ) ;
574
- }
575
-
576
- builder
577
- . respond_with ( ResponseTemplate :: new ( 200 ) . set_body_json ( response_body) )
578
- . mount_as_scoped ( server)
579
- . await
580
- }
0 commit comments