Skip to content

Commit 9ef1a04

Browse files
committed
test: add the start of an integration test for room history sharing
This is only a partial test, since we haven't yet implemented the receiver side of the history-sharing messages.
1 parent f11158a commit 9ef1a04

File tree

2 files changed

+140
-8
lines changed

2 files changed

+140
-8
lines changed

testing/matrix-sdk-integration-testing/src/helpers.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use matrix_sdk::{
1616
RoomId,
1717
},
1818
sliding_sync::VersionBuilder,
19+
sync::SyncResponse,
1920
Client, ClientBuilder, Room,
2021
};
2122
use once_cell::sync::Lazy;
@@ -185,7 +186,7 @@ impl SyncTokenAwareClient {
185186
Self { client, token: Arc::new(None.into()) }
186187
}
187188

188-
pub async fn sync_once(&self) -> Result<()> {
189+
pub async fn sync_once(&self) -> Result<SyncResponse> {
189190
let mut settings = SyncSettings::default().timeout(Duration::from_secs(1));
190191

191192
let token = { self.token.lock().unwrap().clone() };
@@ -197,9 +198,9 @@ impl SyncTokenAwareClient {
197198

198199
let mut prev_token = self.token.lock().unwrap();
199200
if prev_token.as_ref() != Some(&response.next_batch) {
200-
*prev_token = Some(response.next_batch);
201+
*prev_token = Some(response.next_batch.clone());
201202
}
202-
Ok(())
203+
Ok(response)
203204
}
204205
}
205206

testing/matrix-sdk-integration-testing/src/tests/e2ee.rs

Lines changed: 136 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::{
2+
future::IntoFuture,
23
sync::{Arc, Mutex},
34
time::Duration,
45
};
@@ -9,7 +10,7 @@ use assert_matches2::assert_let;
910
use assign::assign;
1011
use matrix_sdk::{
1112
assert_next_eq_with_timeout,
12-
crypto::{format_emojis, SasState},
13+
crypto::{format_emojis, SasState, UserDevices},
1314
encryption::{
1415
backups::BackupState,
1516
recovery::{Recovery, RecoveryState},
@@ -19,17 +20,21 @@ use matrix_sdk::{
1920
BackupDownloadStrategy, EncryptionSettings, LocalTrust,
2021
},
2122
ruma::{
22-
api::client::room::create_room::v3::Request as CreateRoomRequest,
23+
api::client::{
24+
message::send_message_event,
25+
room::create_room::v3::{Request as CreateRoomRequest, RoomPreset},
26+
},
2327
events::{
2428
key::verification::{request::ToDeviceKeyVerificationRequestEvent, VerificationMethod},
2529
room::message::{
2630
MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent,
2731
SyncRoomMessageEvent,
2832
},
2933
secret_storage::secret::SecretEventContent,
30-
GlobalAccountDataEventType, OriginalSyncMessageLikeEvent,
34+
GlobalAccountDataEventType, MessageLikeEventType, OriginalSyncMessageLikeEvent,
3135
},
32-
OwnedEventId,
36+
serde::Raw,
37+
OwnedEventId, TransactionId, UserId,
3338
},
3439
timeout::timeout,
3540
Client,
@@ -39,7 +44,7 @@ use matrix_sdk_ui::{
3944
sync_service::SyncService,
4045
};
4146
use similar_asserts::assert_eq;
42-
use tracing::{debug, warn};
47+
use tracing::{debug, info, warn, Instrument};
4348

4449
use crate::helpers::{SyncTokenAwareClient, TestClientBuilder};
4550

@@ -1175,3 +1180,129 @@ async fn test_recovery_disabling_deletes_secret_storage_secrets() -> Result<()>
11751180

11761181
Ok(())
11771182
}
1183+
1184+
/// When we invite another user to a room with "joined" history visibility, we
1185+
/// share the encryption history.
1186+
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
1187+
async fn test_history_share_on_invite() -> Result<()> {
1188+
let alice_span = tracing::info_span!("alice");
1189+
let bob_span = tracing::info_span!("bob");
1190+
1191+
let encryption_settings =
1192+
EncryptionSettings { auto_enable_cross_signing: true, ..Default::default() };
1193+
1194+
let alice = TestClientBuilder::new("alice")
1195+
.use_sqlite()
1196+
.encryption_settings(encryption_settings)
1197+
.build()
1198+
.await?;
1199+
1200+
let sync_service_span = tracing::info_span!(parent: &alice_span, "sync_service");
1201+
let alice_sync_service = Arc::new(
1202+
SyncService::builder(alice.clone())
1203+
.with_parent_span(sync_service_span)
1204+
.build()
1205+
.await
1206+
.expect("Could not build alice sync service"),
1207+
);
1208+
1209+
alice.encryption().wait_for_e2ee_initialization_tasks().await;
1210+
alice_sync_service.start().await;
1211+
1212+
let bob = SyncTokenAwareClient::new(
1213+
TestClientBuilder::new("bob").encryption_settings(encryption_settings).build().await?,
1214+
);
1215+
1216+
{
1217+
// Alice and Bob share an encrypted room
1218+
// TODO: get rid of all of this: history sharing should work even if Bob and
1219+
// Alice do not share a room
1220+
let alice_shared_room = alice
1221+
.create_room(assign!(CreateRoomRequest::new(), {preset: Some(RoomPreset::PublicChat)}))
1222+
.await?;
1223+
let shared_room_id = alice_shared_room.room_id();
1224+
alice_shared_room.enable_encryption().await?;
1225+
bob.join_room_by_id(shared_room_id)
1226+
.instrument(bob_span.clone())
1227+
.await
1228+
.expect("Bob should have joined the room");
1229+
1230+
// Bob sends a message to trigger another sync from Alice, which causes her to
1231+
// send out the outgoing requests
1232+
//
1233+
// FIXME: this appears to be needed due to a bug in the sliding sync client,
1234+
// which means it does not send out outgoing requests caused by a
1235+
// /sync response
1236+
let request = send_message_event::v3::Request::new_raw(
1237+
shared_room_id.to_owned(),
1238+
TransactionId::new(),
1239+
MessageLikeEventType::Message,
1240+
Raw::new(&RoomMessageEventContent::text_plain("")).unwrap().cast(),
1241+
);
1242+
bob.send(request).into_future().instrument(bob_span.clone()).await?;
1243+
1244+
// Sanity check: Both users see the others' device
1245+
async fn devices_seen(client: &Client, other: &UserId) -> UserDevices {
1246+
client
1247+
.olm_machine_for_testing()
1248+
.await
1249+
.as_ref()
1250+
.unwrap()
1251+
.get_user_devices(other, Some(Duration::from_secs(1)))
1252+
.await
1253+
.unwrap()
1254+
}
1255+
1256+
timeout(
1257+
async {
1258+
loop {
1259+
let bob_devices = devices_seen(&alice, bob.user_id().unwrap()).await;
1260+
if bob_devices.devices().count() >= 1 {
1261+
return;
1262+
}
1263+
}
1264+
},
1265+
Duration::from_secs(30), // This can take quite a while to happen on the CI runners.
1266+
)
1267+
.await
1268+
.expect("Alice did not see bob's device");
1269+
1270+
bob.sync_once().instrument(bob_span.clone()).await?;
1271+
let alice_devices = devices_seen(&bob, alice.user_id().unwrap()).await;
1272+
assert_eq!(alice_devices.devices().count(), 1, "Bob did not see Alice's device");
1273+
}
1274+
1275+
// Alice creates a room ...
1276+
let alice_room = alice
1277+
.create_room(assign!(CreateRoomRequest::new(), {
1278+
preset: Some(RoomPreset::PublicChat),
1279+
}))
1280+
.await?;
1281+
alice_room.enable_encryption().await?;
1282+
1283+
info!(room_id = ?alice_room.room_id(), "Alice has created and enabled encryption in the room");
1284+
1285+
// ... and sends a message
1286+
alice_room
1287+
.send(RoomMessageEventContent::text_plain("Hello Bob"))
1288+
.await
1289+
.expect("We should be able to send a message to the room");
1290+
1291+
// Alice invites Bob to the room
1292+
// TODO: invite Bob rather than just call `share_history`
1293+
alice_room.share_history(bob.user_id().unwrap()).await?;
1294+
1295+
let bob_response = bob.sync_once().instrument(bob_span.clone()).await?;
1296+
1297+
// Bob should have received a to-device event with the payload
1298+
assert_eq!(bob_response.to_device.len(), 1);
1299+
let to_device_event = &bob_response.to_device[0];
1300+
assert_eq!(
1301+
to_device_event.get_field::<String>("type").unwrap().unwrap(),
1302+
"io.element.msc4268.room_key_bundle"
1303+
);
1304+
1305+
// TODO: ensure Bob can decrypt the content
1306+
1307+
Ok(())
1308+
}

0 commit comments

Comments
 (0)