testing: Create realistic modern event IDs in EventFactory

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 <zecakeh@tedomum.fr>
This commit is contained in:
Kévin Commaille
2026-02-26 09:57:39 +01:00
committed by Ivan Enderlin
parent 8472b5504e
commit 7ec331c842
4 changed files with 34 additions and 19 deletions

1
Cargo.lock generated
View File

@@ -3540,6 +3540,7 @@ dependencies = [
"ruma",
"serde",
"serde_json",
"sha2",
"tokio",
"tracing-subscriber",
"vodozemac",

View File

@@ -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]

View File

@@ -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
}

View File

@@ -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<AnyMessageLikeEventContent>` from arbitrary JSON.
///
@@ -124,3 +127,12 @@ impl<T: fmt::Display + fmt::Debug> From<T> 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::<UrlSafe, _>::new(Sha256::digest(bytes)).encode()
}