diff --git a/Cargo.lock b/Cargo.lock index 3a1b80f41..6dafff5a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3540,6 +3540,7 @@ dependencies = [ "ruma", "serde", "serde_json", + "sha2", "tokio", "tracing-subscriber", "vodozemac", diff --git a/testing/matrix-sdk-test/Cargo.toml b/testing/matrix-sdk-test/Cargo.toml index 910f2806c..dfa803d91 100644 --- a/testing/matrix-sdk-test/Cargo.toml +++ b/testing/matrix-sdk-test/Cargo.toml @@ -32,6 +32,7 @@ matrix-sdk-test-macros = { version = "0.16.0", path = "../matrix-sdk-test-macros ruma = { workspace = true, features = ["client-api-s", "rand", "unstable-msc3381", "unstable-msc4274"] } serde.workspace = true serde_json.workspace = true +sha2.workspace = true vodozemac.workspace = true [target.'cfg(not(target_family = "wasm"))'.dependencies] diff --git a/testing/matrix-sdk-test/src/event_factory.rs b/testing/matrix-sdk-test/src/event_factory.rs index dc2087ab9..81c728122 100644 --- a/testing/matrix-sdk-test/src/event_factory.rs +++ b/testing/matrix-sdk-test/src/event_factory.rs @@ -105,6 +105,8 @@ use ruma::{ use serde::Serialize; use serde_json::json; +use crate::base64_sha256_hash; + pub trait TimestampArg { fn to_milliseconds_since_unix_epoch(self) -> MilliSecondsSinceUnixEpoch; } @@ -342,20 +344,6 @@ where map.insert("sender".to_owned(), json!(sender)); } - if self.format.has_event_id() && !self.no_event_id { - let event_id = self.event_id.unwrap_or_else(|| { - let server_name = self - .room - .as_ref() - .and_then(|room_id| room_id.server_name()) - .unwrap_or(server_name!("dummy.org")); - - EventId::new_v1(server_name) - }); - - map.insert("event_id".to_owned(), json!(event_id)); - } - if self.format.has_room_id() { let room_id = self.room.expect("TimelineEvent requires a room id"); map.insert("room_id".to_owned(), json!(room_id)); @@ -365,14 +353,27 @@ where map.insert("redacts".to_owned(), json!(redacts)); } - if let Some(unsigned) = self.unsigned { - map.insert("unsigned".to_owned(), json!(unsigned)); - } - if let Some(state_key) = self.state_key { map.insert("state_key".to_owned(), json!(state_key)); } + if self.format.has_event_id() && !self.no_event_id { + let event_id = self.event_id.unwrap_or_else(|| { + // Compute a hash of the event to use it as the event ID, similar to how a + // server would. This is a little bit different since a server would redact the + // event before hashing, but at least the event ID construction will be + // deterministic and have the same format as in recent room versions. + let bytes = serde_json::to_vec(&map).unwrap(); + EventId::new_v2_or_v3(&base64_sha256_hash(&bytes)).unwrap() + }); + + map.insert("event_id".to_owned(), json!(event_id)); + } + + if let Some(unsigned) = self.unsigned { + map.insert("unsigned".to_owned(), json!(unsigned)); + } + json } diff --git a/testing/matrix-sdk-test/src/lib.rs b/testing/matrix-sdk-test/src/lib.rs index 0554c68c4..a7ea6fefd 100644 --- a/testing/matrix-sdk-test/src/lib.rs +++ b/testing/matrix-sdk-test/src/lib.rs @@ -5,8 +5,11 @@ pub use matrix_sdk_test_macros::async_test; use ruma::{ RoomId, UserId, api::{IncomingResponse, OutgoingResponse}, - room_id, user_id, + room_id, + serde::{Base64, base64::UrlSafe}, + user_id, }; +use sha2::{Digest, Sha256}; /// Create a `Raw` from arbitrary JSON. /// @@ -124,3 +127,12 @@ impl From for TestError { } pub type TestResult = Result<(), TestError>; + +/// Compute the sha256 hash of the given bytes and convert it to unpadded +/// URL-safe base64. +/// +/// This matches the format of event IDs since room version 4, and of room IDs +/// since room version 12. +pub fn base64_sha256_hash(bytes: &[u8]) -> String { + Base64::::new(Sha256::digest(bytes)).encode() +}