Skip to content

Commit d146ba8

Browse files
authored
sdk: Refactor key-backup integration tests (#3560)
* sdk: Integ tests: factor out some helper methods A few common methods for logic shared between the tests. This serves two purposes: * It reduces duplication, this making it easier to maintain the tests by reducing the number of places that we have to change things. * It makes the tests easier to read. By factoring out discrete steps, it's much easier to get an overview of what a test is doing than when it's all in one big function. * sdk: Integ tests: timeout if nothing happens If the test is going to fail, let's have it do so properly rather than mysteriously getting stuck.
1 parent 3ffeef5 commit d146ba8

File tree

1 file changed

+112
-164
lines changed
  • crates/matrix-sdk/tests/integration/encryption

1 file changed

+112
-164
lines changed

crates/matrix-sdk/tests/integration/encryption/backups.rs

Lines changed: 112 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,23 @@ use matrix_sdk::{
2121
config::RequestConfig,
2222
encryption::{
2323
backups::{futures::SteadyStateError, BackupState, UploadState},
24+
secret_storage::SecretStore,
2425
BackupDownloadStrategy, EncryptionSettings,
2526
},
2627
matrix_auth::{MatrixSession, MatrixSessionTokens},
2728
test_utils::{no_retry_test_client_with_server, test_client_builder_with_server},
2829
Client,
2930
};
3031
use matrix_sdk_base::SessionMeta;
32+
use matrix_sdk_common::timeout::timeout;
3133
use matrix_sdk_test::{async_test, JoinedRoomBuilder, SyncResponseBuilder};
3234
use ruma::{
3335
api::client::room::create_room::v3::Request as CreateRoomRequest,
3436
assign, device_id, event_id,
3537
events::room::message::{RoomMessageEvent, RoomMessageEventContent},
36-
room_id, user_id, TransactionId,
38+
room_id, user_id, EventId, RoomId, TransactionId,
3739
};
38-
use serde_json::json;
40+
use serde_json::{json, Value};
3941
use tempfile::tempdir;
4042
use tokio::spawn;
4143
use wiremock::{
@@ -896,32 +898,18 @@ async fn enable_from_secret_storage() {
896898

897899
client.sync_once(Default::default()).await.expect("We should be able to sync with the server");
898900

899-
Mock::given(method("GET"))
900-
.and(path("_matrix/client/r0/rooms/!DovneieKSTkdHKpIXy:morpheus.localhost/event/$JbFHtZpEJiH8uaajZjPLz0QUZc1xtBR9rPGBOjF6WFM"))
901-
.and(header("authorization", "Bearer 1234"))
902-
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
903-
"content": {
904-
"algorithm": "m.megolm.v1.aes-sha2",
905-
"ciphertext": "AwgAEpABhetEzzZzyYrxtEVUtlJnZtJcURBlQUQJ9irVeklCTs06LwgTMQj61PMUS4Vy\
906-
YOX+PD67+hhU40/8olOww+Ud0m2afjMjC3wFX+4fFfSkoWPVHEmRVucfcdSF1RSB4EmK\
907-
PIP4eo1X6x8kCIMewBvxl2sI9j4VNvDvAN7M3zkLJfFLOFHbBviI4FN7hSFHFeM739Zg\
908-
iwxEs3hIkUXEiAfrobzaMEM/zY7SDrTdyffZndgJo7CZOVhoV6vuaOhmAy4X2t4UnbuV\
909-
JGJjKfV57NAhp8W+9oT7ugwO",
910-
"device_id": "KIUVQQSDTM",
911-
"sender_key": "LvryVyoCjdONdBCi2vvoSbI34yTOx7YrCFACUEKoXnc",
912-
"session_id": "64H7XKokIx0ASkYDHZKlT5zd/Zccz/cQspPNdvnNULA"
913-
},
914-
"event_id": "$JbFHtZpEJiH8uaajZjPLz0QUZc1xtBR9rPGBOjF6WFM",
915-
"origin_server_ts": 1698579035927u64,
916-
"sender": "@example2:morpheus.localhost",
917-
"type": "m.room.encrypted",
918-
"unsigned": {
919-
"age": 14393491
920-
}
921-
})))
922-
.expect(2)
923-
.mount(&server)
924-
.await;
901+
let event_content = json!({
902+
"algorithm": "m.megolm.v1.aes-sha2",
903+
"ciphertext": "AwgAEpABhetEzzZzyYrxtEVUtlJnZtJcURBlQUQJ9irVeklCTs06LwgTMQj61PMUS4Vy\
904+
YOX+PD67+hhU40/8olOww+Ud0m2afjMjC3wFX+4fFfSkoWPVHEmRVucfcdSF1RSB4EmK\
905+
PIP4eo1X6x8kCIMewBvxl2sI9j4VNvDvAN7M3zkLJfFLOFHbBviI4FN7hSFHFeM739Zg\
906+
iwxEs3hIkUXEiAfrobzaMEM/zY7SDrTdyffZndgJo7CZOVhoV6vuaOhmAy4X2t4UnbuV\
907+
JGJjKfV57NAhp8W+9oT7ugwO",
908+
"device_id": "KIUVQQSDTM",
909+
"sender_key": "LvryVyoCjdONdBCi2vvoSbI34yTOx7YrCFACUEKoXnc",
910+
"session_id": "64H7XKokIx0ASkYDHZKlT5zd/Zccz/cQspPNdvnNULA"
911+
});
912+
mock_get_event(room_id, event_id, event_content, &server).await;
925913

926914
let room = client.get_room(room_id).expect("We should have access to the room after the sync");
927915
let event = room.event(event_id).await.expect("We should be able to fetch our encrypted event");
@@ -940,22 +928,7 @@ async fn enable_from_secret_storage() {
940928
.await
941929
.expect("We should be able to open our secret store");
942930

943-
Mock::given(method("GET"))
944-
.and(path("_matrix/client/r0/room_keys/version"))
945-
.and(header("authorization", "Bearer 1234"))
946-
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
947-
"algorithm": "m.megolm_backup.v1.curve25519-aes-sha2",
948-
"auth_data": {
949-
"public_key": "hdx5rSn94rBuvJI5cwnhKAVmFyZgfJjk7vwEBD6mIHc",
950-
"signatures": {}
951-
},
952-
"count": 1,
953-
"etag": "1",
954-
"version": "6"
955-
})))
956-
.expect(2)
957-
.mount(&server)
958-
.await;
931+
mock_query_key_backup(&server).await;
959932

960933
Mock::given(method("GET"))
961934
.and(path("_matrix/client/r0/room_keys/keys"))
@@ -1032,8 +1005,6 @@ async fn enable_from_secret_storage() {
10321005

10331006
#[async_test]
10341007
async fn enable_from_secret_storage_no_existing_backup() {
1035-
const SECRET_STORE_KEY: &str = "mypassphrase";
1036-
const KEY_ID: &str = "yJWwBm2Ts8jHygTBslKpABFyykavhhfA";
10371008
let user_id = user_id!("@example2:morpheus.localhost");
10381009

10391010
let session = MatrixSession {
@@ -1054,15 +1025,7 @@ async fn enable_from_secret_storage_no_existing_backup() {
10541025

10551026
client.restore_session(session).await.unwrap();
10561027

1057-
mock_secret_store_with_backup_key(user_id, KEY_ID, &server).await;
1058-
1059-
let secret_storage = client.encryption().secret_storage();
1060-
1061-
let store = secret_storage
1062-
.open_secret_store(SECRET_STORE_KEY)
1063-
.await
1064-
.expect("We should be able to open our secret store");
1065-
1028+
let store = init_secret_store(&client, &server).await;
10661029
store.import_secrets().await.expect_err(
10671030
"We should return an error if we couldn't fetch the backup version from the server",
10681031
);
@@ -1085,8 +1048,6 @@ async fn enable_from_secret_storage_no_existing_backup() {
10851048

10861049
#[async_test]
10871050
async fn enable_from_secret_storage_mismatched_key() {
1088-
const SECRET_STORE_KEY: &str = "mypassphrase";
1089-
const KEY_ID: &str = "yJWwBm2Ts8jHygTBslKpABFyykavhhfA";
10901051
let user_id = user_id!("@example2:morpheus.localhost");
10911052

10921053
let session = MatrixSession {
@@ -1107,14 +1068,7 @@ async fn enable_from_secret_storage_mismatched_key() {
11071068

11081069
client.restore_session(session).await.unwrap();
11091070

1110-
mock_secret_store_with_backup_key(user_id, KEY_ID, &server).await;
1111-
1112-
let secret_storage = client.encryption().secret_storage();
1113-
1114-
let store = secret_storage
1115-
.open_secret_store(SECRET_STORE_KEY)
1116-
.await
1117-
.expect("We should be able to open our secret store");
1071+
let store = init_secret_store(&client, &server).await;
11181072

11191073
Mock::given(method("GET"))
11201074
.and(path("_matrix/client/r0/room_keys/version"))
@@ -1146,8 +1100,6 @@ async fn enable_from_secret_storage_mismatched_key() {
11461100

11471101
#[async_test]
11481102
async fn enable_from_secret_storage_manual_download() {
1149-
const SECRET_STORE_KEY: &str = "mypassphrase";
1150-
const KEY_ID: &str = "yJWwBm2Ts8jHygTBslKpABFyykavhhfA";
11511103
let user_id = user_id!("@example2:morpheus.localhost");
11521104

11531105
let session = MatrixSession {
@@ -1160,14 +1112,7 @@ async fn enable_from_secret_storage_manual_download() {
11601112

11611113
client.restore_session(session).await.unwrap();
11621114

1163-
mock_secret_store_with_backup_key(user_id, KEY_ID, &server).await;
1164-
1165-
let secret_storage = client.encryption().secret_storage();
1166-
1167-
let store = secret_storage
1168-
.open_secret_store(SECRET_STORE_KEY)
1169-
.await
1170-
.expect("We should be able to open our secret store");
1115+
let store = init_secret_store(&client, &server).await;
11711116

11721117
Mock::given(method("GET"))
11731118
.and(path("_matrix/client/r0/room_keys/version"))
@@ -1186,9 +1131,6 @@ async fn enable_from_secret_storage_manual_download() {
11861131

11871132
#[async_test]
11881133
async fn enable_from_secret_storage_and_manual_download() {
1189-
const SECRET_STORE_KEY: &str = "mypassphrase";
1190-
const KEY_ID: &str = "yJWwBm2Ts8jHygTBslKpABFyykavhhfA";
1191-
11921134
let user_id = user_id!("@example2:morpheus.localhost");
11931135
let room_id = room_id!("!DovneieKSTkdHKpIXy:morpheus.localhost");
11941136

@@ -1210,33 +1152,7 @@ async fn enable_from_secret_storage_and_manual_download() {
12101152

12111153
client.restore_session(session).await.unwrap();
12121154

1213-
mock_secret_store_with_backup_key(user_id, KEY_ID, &server).await;
1214-
1215-
let secret_storage = client.encryption().secret_storage();
1216-
1217-
let store = secret_storage
1218-
.open_secret_store(SECRET_STORE_KEY)
1219-
.await
1220-
.expect("We should be able to open our secret store");
1221-
1222-
Mock::given(method("GET"))
1223-
.and(path("_matrix/client/r0/room_keys/version"))
1224-
.and(header("authorization", "Bearer 1234"))
1225-
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
1226-
"algorithm": "m.megolm_backup.v1.curve25519-aes-sha2",
1227-
"auth_data": {
1228-
"public_key": "hdx5rSn94rBuvJI5cwnhKAVmFyZgfJjk7vwEBD6mIHc",
1229-
"signatures": {}
1230-
},
1231-
"count": 1,
1232-
"etag": "1",
1233-
"version": "6"
1234-
})))
1235-
.expect(1)
1236-
.mount(&server)
1237-
.await;
1238-
1239-
store.import_secrets().await.unwrap();
1155+
init_client_secret_storage_and_backup(&client, &server).await;
12401156

12411157
Mock::given(method("GET"))
12421158
.and(path("/_matrix/client/r0/room_keys/keys/!DovneieKSTkdHKpIXy:morpheus.localhost"))
@@ -1336,9 +1252,6 @@ async fn enable_from_secret_storage_and_manual_download() {
13361252

13371253
#[async_test]
13381254
async fn enable_from_secret_storage_and_download_after_utd() {
1339-
const SECRET_STORE_KEY: &str = "mypassphrase";
1340-
const KEY_ID: &str = "yJWwBm2Ts8jHygTBslKpABFyykavhhfA";
1341-
13421255
let user_id = user_id!("@example2:morpheus.localhost");
13431256
let room_id = room_id!("!DovneieKSTkdHKpIXy:morpheus.localhost");
13441257
let event_id = event_id!("$JbFHtZpEJiH8uaajZjPLz0QUZc1xtBR9rPGBOjF6WFM");
@@ -1368,60 +1281,21 @@ async fn enable_from_secret_storage_and_download_after_utd() {
13681281

13691282
client.sync_once(Default::default()).await.expect("We should be able to sync with the server");
13701283

1371-
mock_secret_store_with_backup_key(user_id, KEY_ID, &server).await;
1372-
1373-
let secret_storage = client.encryption().secret_storage();
1374-
1375-
let store = secret_storage
1376-
.open_secret_store(SECRET_STORE_KEY)
1377-
.await
1378-
.expect("We should be able to open our secret store");
1379-
1380-
Mock::given(method("GET"))
1381-
.and(path("_matrix/client/r0/room_keys/version"))
1382-
.and(header("authorization", "Bearer 1234"))
1383-
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
1384-
"algorithm": "m.megolm_backup.v1.curve25519-aes-sha2",
1385-
"auth_data": {
1386-
"public_key": "hdx5rSn94rBuvJI5cwnhKAVmFyZgfJjk7vwEBD6mIHc",
1387-
"signatures": {}
1388-
},
1389-
"count": 1,
1390-
"etag": "1",
1391-
"version": "6"
1392-
})))
1393-
.expect(1)
1394-
.mount(&server)
1395-
.await;
1284+
init_client_secret_storage_and_backup(&client, &server).await;
1285+
1286+
let event_content = json!({
1287+
"algorithm": "m.megolm.v1.aes-sha2",
1288+
"ciphertext": "AwgAEpABhetEzzZzyYrxtEVUtlJnZtJcURBlQUQJ9irVeklCTs06LwgTMQj61PMUS4Vy\
1289+
YOX+PD67+hhU40/8olOww+Ud0m2afjMjC3wFX+4fFfSkoWPVHEmRVucfcdSF1RSB4EmK\
1290+
PIP4eo1X6x8kCIMewBvxl2sI9j4VNvDvAN7M3zkLJfFLOFHbBviI4FN7hSFHFeM739Zg\
1291+
iwxEs3hIkUXEiAfrobzaMEM/zY7SDrTdyffZndgJo7CZOVhoV6vuaOhmAy4X2t4UnbuV\
1292+
JGJjKfV57NAhp8W+9oT7ugwO",
1293+
"device_id": "KIUVQQSDTM",
1294+
"sender_key": "LvryVyoCjdONdBCi2vvoSbI34yTOx7YrCFACUEKoXnc",
1295+
"session_id": "64H7XKokIx0ASkYDHZKlT5zd/Zccz/cQspPNdvnNULA"
1296+
});
13961297

1397-
store.import_secrets().await.unwrap();
1398-
1399-
Mock::given(method("GET"))
1400-
.and(path("_matrix/client/r0/rooms/!DovneieKSTkdHKpIXy:morpheus.localhost/event/$JbFHtZpEJiH8uaajZjPLz0QUZc1xtBR9rPGBOjF6WFM"))
1401-
.and(header("authorization", "Bearer 1234"))
1402-
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
1403-
"content": {
1404-
"algorithm": "m.megolm.v1.aes-sha2",
1405-
"ciphertext": "AwgAEpABhetEzzZzyYrxtEVUtlJnZtJcURBlQUQJ9irVeklCTs06LwgTMQj61PMUS4Vy\
1406-
YOX+PD67+hhU40/8olOww+Ud0m2afjMjC3wFX+4fFfSkoWPVHEmRVucfcdSF1RSB4EmK\
1407-
PIP4eo1X6x8kCIMewBvxl2sI9j4VNvDvAN7M3zkLJfFLOFHbBviI4FN7hSFHFeM739Zg\
1408-
iwxEs3hIkUXEiAfrobzaMEM/zY7SDrTdyffZndgJo7CZOVhoV6vuaOhmAy4X2t4UnbuV\
1409-
JGJjKfV57NAhp8W+9oT7ugwO",
1410-
"device_id": "KIUVQQSDTM",
1411-
"sender_key": "LvryVyoCjdONdBCi2vvoSbI34yTOx7YrCFACUEKoXnc",
1412-
"session_id": "64H7XKokIx0ASkYDHZKlT5zd/Zccz/cQspPNdvnNULA"
1413-
},
1414-
"event_id": "$JbFHtZpEJiH8uaajZjPLz0QUZc1xtBR9rPGBOjF6WFM",
1415-
"origin_server_ts": 1698579035927u64,
1416-
"sender": "@example2:morpheus.localhost",
1417-
"type": "m.room.encrypted",
1418-
"unsigned": {
1419-
"age": 14393491
1420-
}
1421-
})))
1422-
.expect(2)
1423-
.mount(&server)
1424-
.await;
1298+
mock_get_event(room_id, event_id, event_content, &server).await;
14251299

14261300
Mock::given(method("GET"))
14271301
.and(path("/_matrix/client/r0/room_keys/keys/!DovneieKSTkdHKpIXy:morpheus.localhost/64H7XKokIx0ASkYDHZKlT5zd%2FZccz%2FcQspPNdvnNULA"))
@@ -1464,11 +1338,16 @@ async fn enable_from_secret_storage_and_download_after_utd() {
14641338
"We should not be able to decrypt the event right away"
14651339
);
14661340

1467-
if let Some(Ok(room_keys)) = room_key_stream.next().await {
1341+
// Wait for the key to be downloaded from backup.
1342+
{
1343+
let room_keys = timeout(room_key_stream.next(), std::time::Duration::from_secs(5))
1344+
.await
1345+
.expect("did not get a room key stream update within 5 seconds")
1346+
.expect("room_key_stream.next() returned None")
1347+
.expect("room_key_stream.next() returned an error");
1348+
14681349
let (_, room_key_set) = room_keys.first_key_value().unwrap();
14691350
assert!(room_key_set.contains("64H7XKokIx0ASkYDHZKlT5zd/Zccz/cQspPNdvnNULA"));
1470-
} else {
1471-
panic!("Failed to get an update about room keys being imported from the backup")
14721351
}
14731352

14741353
let event = room.event(event_id).await.expect("We should be able to fetch our encrypted event");
@@ -1481,3 +1360,72 @@ async fn enable_from_secret_storage_and_download_after_utd() {
14811360

14821361
server.verify().await;
14831362
}
1363+
1364+
/// Set up secret storage, and allow the client to import the backup
1365+
/// decryption key from 4S.
1366+
async fn init_client_secret_storage_and_backup(client: &Client, server: &wiremock::MockServer) {
1367+
let store = init_secret_store(client, server).await;
1368+
mock_query_key_backup(server).await;
1369+
store.import_secrets().await.unwrap();
1370+
}
1371+
1372+
/// Mock the data for secret storage, and use it to set up a `SecretStore`.
1373+
async fn init_secret_store(client: &Client, server: &wiremock::MockServer) -> SecretStore {
1374+
const SECRET_STORE_KEY: &str = "mypassphrase";
1375+
const KEY_ID: &str = "yJWwBm2Ts8jHygTBslKpABFyykavhhfA";
1376+
1377+
mock_secret_store_with_backup_key(client.user_id().unwrap(), KEY_ID, server).await;
1378+
client
1379+
.encryption()
1380+
.secret_storage()
1381+
.open_secret_store(SECRET_STORE_KEY)
1382+
.await
1383+
.expect("We should be able to open our secret store")
1384+
}
1385+
1386+
/// Add a mock for a `GET /_matrix/client/r0/rooms/{}/event/{}` for the given
1387+
/// room/event ID.
1388+
async fn mock_get_event(
1389+
room_id: &RoomId,
1390+
event_id: &EventId,
1391+
event_content_json: Value,
1392+
server: &wiremock::MockServer,
1393+
) {
1394+
let event_json = json!({
1395+
"content": event_content_json,
1396+
"event_id": event_id,
1397+
"origin_server_ts": 1698579035927u64,
1398+
"sender": "@example2:morpheus.localhost",
1399+
"type": "m.room.encrypted",
1400+
"unsigned": {
1401+
"age": 14393491
1402+
}
1403+
});
1404+
Mock::given(method("GET"))
1405+
.and(path(format!("_matrix/client/r0/rooms/{}/event/{}", room_id, event_id)))
1406+
.and(header("authorization", "Bearer 1234"))
1407+
.respond_with(ResponseTemplate::new(200).set_body_json(event_json))
1408+
.expect(2)
1409+
.mount(server)
1410+
.await;
1411+
}
1412+
1413+
/// Add a mock for a `GET /_matrix/client/r0/room_keys/version` request; return
1414+
/// some suitable backup data.
1415+
async fn mock_query_key_backup(server: &wiremock::MockServer) {
1416+
Mock::given(method("GET"))
1417+
.and(path("_matrix/client/r0/room_keys/version"))
1418+
.and(header("authorization", "Bearer 1234"))
1419+
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
1420+
"algorithm": "m.megolm_backup.v1.curve25519-aes-sha2",
1421+
"auth_data": {
1422+
"public_key": "hdx5rSn94rBuvJI5cwnhKAVmFyZgfJjk7vwEBD6mIHc",
1423+
"signatures": {}
1424+
},
1425+
"count": 1,
1426+
"etag": "1",
1427+
"version": "6"
1428+
})))
1429+
.mount(server)
1430+
.await;
1431+
}

0 commit comments

Comments
 (0)