From 7ec331c842c5fc239c2a12a9fcdc398deb5fa4eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Commaille?= Date: Thu, 26 Feb 2026 09:57:39 +0100 Subject: [PATCH] testing: Create realistic modern event IDs in EventFactory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As a fallback when the ID is not provided when constructing the event. It allows to work with data that looks like what we would get in production, which is important for benchmarks. Signed-off-by: Kévin Commaille --- Cargo.lock | 1 + testing/matrix-sdk-test/Cargo.toml | 1 + testing/matrix-sdk-test/src/event_factory.rs | 37 ++++++++++---------- testing/matrix-sdk-test/src/lib.rs | 14 +++++++- 4 files changed, 34 insertions(+), 19 deletions(-) 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() +}