events: Make all pub structs non_exhaustive

This commit is contained in:
Devin Ragotzy 2021-06-18 08:21:01 -04:00 committed by Jonas Platte
parent 4312085b4a
commit e05aad184e
31 changed files with 137 additions and 30 deletions

View File

@ -204,6 +204,20 @@ pub fn expand_event_content(
quote! { true }
};
let initializer = if kept_redacted_fields.is_empty() {
let doc = format!("Creates an empty {}.", redacted_ident);
quote! {
impl #redacted_ident {
#[doc = #doc]
pub fn new() -> Self {
Self
}
}
}
} else {
TokenStream::new()
};
let redacted_event_content =
generate_event_content_impl(&redacted_ident, event_type, ruma_events);
@ -237,8 +251,11 @@ pub fn expand_event_content(
#[doc = #doc]
#[derive(Clone, Debug, #serde::Deserialize, #serde::Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct #redacted_ident #redacted_fields
#initializer
#redacted_event_content
#[automatically_derived]

View File

@ -638,9 +638,7 @@ fn generate_redacted_fields(
if name == "unsigned" {
quote! {
unsigned: #ruma_events::RedactedUnsigned {
redacted_because: Some(::std::boxed::Box::new(redaction)),
},
unsigned: #ruma_events::RedactedUnsigned::new_because(::std::boxed::Box::new(redaction)),
}
} else {
quote! {

View File

@ -15,6 +15,7 @@ use crate::{
/// A custom event's type and `content` JSON object.
#[derive(Clone, Debug, Serialize)]
#[allow(clippy::exhaustive_structs)]
pub struct CustomEventContent {
/// The event type string.
#[serde(skip)]
@ -60,6 +61,7 @@ impl StateEventContent for CustomEventContent {}
/// A custom event that has been redacted.
#[derive(Clone, Debug, Serialize)]
#[allow(clippy::exhaustive_structs)]
pub struct RedactedCustomEventContent {
// This field is marked skipped but will be present because deserialization
// passes the `type` field of the JSON event to the events `EventContent::from_parts` method.

View File

@ -17,6 +17,7 @@ pub type DirectEvent = crate::GlobalAccountDataEvent<DirectEventContent>;
/// A mapping of `UserId`s to a list of `RoomId`s which are considered *direct* for that
/// particular user.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[allow(clippy::exhaustive_structs)]
#[ruma_event(type = "m.direct", kind = GlobalAccountData)]
pub struct DirectEventContent(pub BTreeMap<UserId, Vec<RoomId>>);

View File

@ -19,10 +19,18 @@ use serde::{
/// this *m.dummy* event as the most recent event and using the keyshare request to set up the
/// session. The keyshare request and *m.dummy* combination should result in the original sending
/// client receiving keys over the newly established session.
#[derive(Clone, Debug, EventContent)]
#[derive(Clone, Debug, Default, EventContent)]
#[allow(clippy::exhaustive_structs)]
#[ruma_event(type = "m.dummy", kind = ToDevice)]
pub struct DummyToDeviceEventContent;
impl DummyToDeviceEventContent {
/// Create a new `DummyToDeviceEventContent`.
pub fn new() -> Self {
Self
}
}
impl<'de> Deserialize<'de> for DummyToDeviceEventContent {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where

View File

@ -17,6 +17,7 @@ impl Error for InvalidInput {}
/// An error when attempting to create a value from a string via the `FromStr` trait.
#[derive(Clone, Eq, Debug, Hash, PartialEq)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct FromStrError;
impl fmt::Display for FromStrError {

View File

@ -1,3 +1,5 @@
#![allow(clippy::exhaustive_structs)]
use ruma_common::MilliSecondsSinceUnixEpoch;
use ruma_events_macros::Event;
use ruma_identifiers::{EventId, RoomId, UserId};

View File

@ -48,6 +48,7 @@ pub struct ForwardedRoomKeyToDeviceEventContent {
/// This struct will not be updated even if additional fields are added to `ConditionalPushRule` in
/// a new (non-breaking) release of the Matrix specification.
#[derive(Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct ForwardedRoomKeyToDeviceEventContentInit {
/// The encryption algorithm the key in this event is to be used with.
pub algorithm: EventEncryptionAlgorithm,

View File

@ -83,6 +83,7 @@ pub enum AcceptMethod {
/// Method specific content of a unknown key verification method.
#[doc(hidden)]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(clippy::exhaustive_structs)]
pub struct _CustomContent {
/// The name of the method.
pub method: String,
@ -124,6 +125,7 @@ pub struct SasV1Content {
/// Mandatory initial set of fields for creating an accept `SasV1Content`.
#[derive(Clone, Debug, Deserialize)]
#[allow(clippy::exhaustive_structs)]
pub struct SasV1ContentInit {
/// The key agreement protocol the device is choosing to use, out of the
/// options in the *m.key.verification.start* message.

View File

@ -15,6 +15,7 @@ pub type KeyEvent = MessageEvent<KeyEventContent>;
/// The payload for a to-device `KeyEvent`.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.key.verification.key", kind = ToDevice)]
pub struct KeyToDeviceEventContent {
/// An opaque identifier for the verification process.

View File

@ -45,9 +45,10 @@ impl MacToDeviceEventContent {
/// The payload for an in-room `MacEvent`.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[ruma_event(type = "m.key.verification.mac", kind = Message)]
#[cfg(feature = "unstable-pre-spec")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[ruma_event(type = "m.key.verification.mac", kind = Message)]
pub struct MacEventContent {
/// A map of the key ID to the MAC of the key, using the algorithm in the verification process.
///

View File

@ -100,6 +100,7 @@ pub enum StartMethod {
/// Method specific content of a unknown key verification method.
#[doc(hidden)]
#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(clippy::exhaustive_structs)]
pub struct _CustomContent {
/// The name of the method.
pub method: String,
@ -158,6 +159,7 @@ pub struct SasV1Content {
/// Mandatory initial set of fields for creating an `SasV1Content`.
#[derive(Clone, Debug, Deserialize)]
#[allow(clippy::exhaustive_structs)]
pub struct SasV1ContentInit {
/// The key agreement protocols the sending device understands.
///

View File

@ -195,6 +195,7 @@ pub use self::{
/// Extra information about an event that is not incorporated into the event's
/// hash.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct Unsigned {
/// The time in milliseconds that has elapsed since the event was sent. This
/// field is generated by the local homeserver, and may be incorrect if the
@ -216,6 +217,11 @@ pub struct Unsigned {
}
impl Unsigned {
/// Create a new `Unsigned` with fields set to `None`.
pub fn new() -> Self {
Self::default()
}
/// Whether this unsigned data is empty (all fields are `None`).
///
/// This method is used to determine whether to skip serializing the
@ -230,6 +236,7 @@ impl Unsigned {
/// Extra information about a redacted event that is not incorporated into the event's
/// hash.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct RedactedUnsigned {
/// The event that redacted this event, if any.
#[serde(skip_serializing_if = "Option::is_none")]
@ -237,6 +244,16 @@ pub struct RedactedUnsigned {
}
impl RedactedUnsigned {
/// Create a new `RedactedUnsigned` with field set to `None`.
pub fn new() -> Self {
Self::default()
}
/// Create a new `RedactedUnsigned` with the given redacted because.
pub fn new_because(redacted_because: Box<SyncRedactionEvent>) -> Self {
Self { redacted_because: Some(redacted_because) }
}
/// Whether this unsigned data is empty (`redacted_because` is `None`).
///
/// This method is used to determine whether to skip serializing the
@ -366,6 +383,7 @@ pub enum HasDeserializeFields {
/// Helper struct to determine if the event has been redacted.
#[doc(hidden)]
#[derive(Debug, Deserialize)]
#[allow(clippy::exhaustive_structs)]
pub struct UnsignedDeHelper {
/// This is the field that signals an event has been redacted.
pub redacted_because: Option<IgnoredAny>,
@ -374,6 +392,7 @@ pub struct UnsignedDeHelper {
/// Helper struct to determine the event kind from a `serde_json::value::RawValue`.
#[doc(hidden)]
#[derive(Debug, Deserialize)]
#[allow(clippy::exhaustive_structs)]
pub struct EventDeHelper {
/// the Matrix event type string "m.room.whatever".
#[serde(rename = "type")]

View File

@ -20,6 +20,7 @@ use crate::EventType;
/// Enum for PDU schemas
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(untagged)]
pub enum Pdu {
/// PDU for room versions 1 and 2.
@ -31,6 +32,7 @@ pub enum Pdu {
/// A 'persistent data unit' (event) for room versions 1 and 2.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(clippy::exhaustive_structs)]
pub struct RoomV1Pdu {
/// Event ID for the PDU.
pub event_id: EventId,
@ -93,6 +95,7 @@ pub struct RoomV1Pdu {
/// A 'persistent data unit' (event) for room versions 3 and beyond.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(clippy::exhaustive_structs)]
pub struct RoomV3Pdu {
/// The room this event belongs to.
pub room_id: RoomId,
@ -150,7 +153,15 @@ pub struct RoomV3Pdu {
/// Content hashes of a PDU.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct EventHash {
/// The SHA-256 hash.
pub sha256: String,
}
impl EventHash {
/// Create a new `EventHash` with the given SHA256 hash.
pub fn new(sha256: String) -> Self {
Self { sha256 }
}
}

View File

@ -10,6 +10,7 @@ pub type RoomEvent = StateEvent<RoomEventContent>;
/// The payload for `RoomEvent`.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[allow(clippy::exhaustive_structs)]
#[ruma_event(type = "m.policy.rule.room", kind = State)]
pub struct RoomEventContent(pub PolicyRuleEventContent);

View File

@ -10,5 +10,6 @@ pub type ServerEvent = StateEvent<ServerEventContent>;
/// The payload for `ServerEvent`.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[allow(clippy::exhaustive_structs)]
#[ruma_event(type = "m.policy.rule.server", kind = State)]
pub struct ServerEventContent(pub PolicyRuleEventContent);

View File

@ -10,5 +10,6 @@ pub type UserEvent = StateEvent<UserEventContent>;
/// The payload for `UserEvent`.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[allow(clippy::exhaustive_structs)]
#[ruma_event(type = "m.policy.rule.user", kind = State)]
pub struct UserEventContent(pub PolicyRuleEventContent);

View File

@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize};
/// Presence event.
#[derive(Clone, Debug, Event)]
#[allow(clippy::exhaustive_structs)]
pub struct PresenceEvent {
/// Data specific to the event type.
pub content: PresenceEventContent,

View File

@ -20,6 +20,7 @@ pub type ReceiptEvent = EphemeralRoomEvent<ReceiptEventContent>;
/// A mapping of event ID to a collection of receipts for this event ID. The event ID is the ID of
/// the event being acknowledged and *not* an ID for the receipt itself.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[allow(clippy::exhaustive_structs)]
#[ruma_event(type = "m.receipt", kind = EphemeralRoom)]
pub struct ReceiptEventContent(pub BTreeMap<EventId, Receipts>);

View File

@ -55,7 +55,7 @@ pub struct AnnotationChunk {
}
impl AnnotationChunk {
/// Creates a new `AnnotationChunk`.
/// Creates a new `AnnotationChunk` with the given chunk and next batch token.
pub fn new(chunk: Vec<BundledAnnotation>, next_batch: Option<String>) -> Self {
Self { chunk, next_batch }
}
@ -71,7 +71,7 @@ pub struct Relations {
}
impl Relations {
/// Creates a new `Relations` struct.
/// Creates a new `Relations` with the given annotation.
pub fn new(annotation: Option<AnnotationChunk>) -> Self {
Self { annotation }
}

View File

@ -135,6 +135,7 @@ pub struct EncryptedFile {
///
/// This struct will not be updated even if additional fields are added to `EncryptedFile` in a new
/// (non-breaking) release of the Matrix specification.
#[allow(clippy::exhaustive_structs)]
pub struct EncryptedFileInit {
/// The URL to the file.
pub url: MxcUri,
@ -188,6 +189,7 @@ pub struct JsonWebKey {
///
/// This struct will not be updated even if additional fields are added to `JsonWebKey` in a new
/// (non-breaking) release of the Matrix specification.
#[allow(clippy::exhaustive_structs)]
pub struct JsonWebKeyInit {
/// Key type. Must be `oct`.
pub kty: String,

View File

@ -49,7 +49,8 @@ impl RedactContent for AliasesEventContent {
}
/// An aliases event that has been redacted.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct RedactedAliasesEventContent {
/// A list of room aliases.
///
@ -58,6 +59,22 @@ pub struct RedactedAliasesEventContent {
pub aliases: Option<Vec<RoomAliasId>>,
}
impl RedactedAliasesEventContent {
/// Create a `RedactedAliasesEventContent` with the given aliases.
///
/// This is only valid for room version 5 and below.
pub fn new_v1(aliases: Vec<RoomAliasId>) -> Self {
Self { aliases: Some(aliases) }
}
/// Create a `RedactedAliasesEventContent` with the given aliases.
///
/// This is only valid for room version 6 and above.
pub fn new_v6() -> Self {
Self::default()
}
}
impl EventContent for RedactedAliasesEventContent {
fn event_type(&self) -> &str {
"m.room.aliases"

View File

@ -55,7 +55,8 @@ impl AvatarEventContent {
}
/// Metadata about an image (specific to avatars).
#[derive(Clone, Debug, Deserialize, Serialize)]
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct ImageInfo {
/// The height of the image in pixels.
#[serde(rename = "h", skip_serializing_if = "Option::is_none")]
@ -91,3 +92,10 @@ pub struct ImageInfo {
#[serde(skip_serializing_if = "Option::is_none")]
pub blurhash: Option<String>,
}
impl ImageInfo {
/// Create a new `ImageInfo` with all fields set to `None`.
pub fn new() -> Self {
Self::default()
}
}

View File

@ -125,6 +125,7 @@ pub struct MegolmV1AesSha2Content {
/// This struct will not be updated even if additional fields are added to `MegolmV1AesSha2Content`
/// in a new (non-breaking) release of the Matrix specification.
#[derive(Clone, Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct MegolmV1AesSha2ContentInit {
/// The encrypted content of the event.
pub ciphertext: String,

View File

@ -643,6 +643,7 @@ impl MessageFormat {
/// Common message event content fields for message types that have separate plain-text and
/// formatted representations.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[allow(clippy::exhaustive_structs)]
pub struct FormattedBody {
/// The format used in the `formatted_body`.
pub format: MessageFormat,

View File

@ -9,6 +9,7 @@ use crate::Unsigned;
/// Redaction event.
#[derive(Clone, Debug, Event)]
#[allow(clippy::exhaustive_structs)]
pub struct RedactionEvent {
/// Data specific to the event type.
pub content: RedactionEventContent,
@ -34,6 +35,7 @@ pub struct RedactionEvent {
/// Redaction event without a `room_id`.
#[derive(Clone, Debug, Event)]
#[allow(clippy::exhaustive_structs)]
pub struct SyncRedactionEvent {
/// Data specific to the event type.
pub content: RedactionEventContent,

View File

@ -45,6 +45,7 @@ pub enum Relation {
#[derive(Clone, Debug)]
#[cfg(feature = "unstable-pre-spec")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct Replacement {
/// The ID of the event being replacing.
pub event_id: EventId,

View File

@ -63,6 +63,7 @@ impl FromStr for UserTagName {
/// An error returned when attempting to create a UserTagName with a string that would make it
/// invalid.
#[derive(Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct InvalidUserTagName;
impl fmt::Display for InvalidUserTagName {

View File

@ -34,16 +34,16 @@ fn serialize_pdu_as_v1() {
state_key: Some("state".into()),
prev_events: vec![(
event_id!("$previousevent:matrix.org"),
EventHash { sha256: "123567".into() },
EventHash::new("123567".into()),
)],
depth: 2_u32.into(),
auth_events: vec![(
event_id!("$someauthevent:matrix.org"),
EventHash { sha256: "21389CFEDABC".into() },
EventHash::new("21389CFEDABC".into()),
)],
redacts: Some(event_id!("$9654:matrix.org")),
unsigned,
hashes: EventHash { sha256: "1233543bABACDEF".into() },
hashes: EventHash::new("1233543bABACDEF".into()),
signatures,
};
let pdu = Pdu::RoomV1Pdu(v1_pdu);
@ -103,7 +103,7 @@ fn serialize_pdu_as_v3() {
auth_events: vec![event_id!("$someauthevent:matrix.org")],
redacts: Some(event_id!("$9654:matrix.org")),
unsigned,
hashes: EventHash { sha256: "1233543bABACDEF".into() },
hashes: EventHash::new("1233543bABACDEF".into()),
signatures,
};
let pdu_stub = Pdu::RoomV3Pdu(v3_pdu);
@ -188,6 +188,8 @@ fn deserialize_pdu_as_v1() {
);
}
Pdu::RoomV3Pdu(_) => panic!("Matched V3 PDU"),
#[cfg(not(feature = "unstable-exhaustive-types"))]
_ => unreachable!("new PDU version"),
}
}
@ -233,5 +235,7 @@ fn deserialize_pdu_as_v3() {
Pdu::RoomV3Pdu(v3_pdu) => {
assert_eq!(v3_pdu.auth_events.first().unwrap(), &event_id!("$abc123:matrix.org"));
}
#[cfg(not(feature = "unstable-exhaustive-types"))]
_ => unreachable!("new PDU version"),
}
}

View File

@ -38,7 +38,7 @@ fn unsigned() -> RedactedUnsigned {
#[test]
fn redacted_message_event_serialize() {
let redacted = RedactedSyncMessageEvent {
content: RedactedMessageEventContent,
content: RedactedMessageEventContent::new(),
event_id: event_id!("$h29iv0s8:example.com"),
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)),
sender: user_id!("@carl:example.com"),
@ -59,7 +59,7 @@ fn redacted_message_event_serialize() {
#[test]
fn redacted_aliases_event_serialize_no_content() {
let redacted = RedactedSyncStateEvent {
content: RedactedAliasesEventContent { aliases: None },
content: RedactedAliasesEventContent::default(),
event_id: event_id!("$h29iv0s8:example.com"),
state_key: "".into(),
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)),
@ -82,7 +82,7 @@ fn redacted_aliases_event_serialize_no_content() {
#[test]
fn redacted_aliases_event_serialize_with_content() {
let redacted = RedactedSyncStateEvent {
content: RedactedAliasesEventContent { aliases: Some(vec![]) },
content: RedactedAliasesEventContent::new_v1(vec![]),
event_id: event_id!("$h29iv0s8:example.com"),
state_key: "".to_owned(),
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)),
@ -125,7 +125,7 @@ fn redacted_aliases_deserialize() {
.unwrap(),
AnySyncRoomEvent::RedactedState(AnyRedactedSyncStateEvent::RoomAliases(
RedactedSyncStateEvent {
content: RedactedAliasesEventContent { aliases },
content: RedactedAliasesEventContent { aliases, .. },
event_id,
..
},
@ -153,7 +153,7 @@ fn redacted_deserialize_any_room() {
.deserialize()
.unwrap(),
AnyRoomEvent::RedactedMessage(AnyRedactedMessageEvent::RoomMessage(RedactedMessageEvent {
content: RedactedMessageEventContent,
content: RedactedMessageEventContent { .. },
event_id, room_id, ..
})) if event_id == event_id!("$h29iv0s8:example.com")
&& room_id == room_id!("!roomid:room.com")
@ -192,7 +192,7 @@ fn redacted_deserialize_any_room_sync() {
.unwrap(),
AnySyncRoomEvent::RedactedMessage(AnyRedactedSyncMessageEvent::RoomMessage(
RedactedSyncMessageEvent {
content: RedactedMessageEventContent,
content: RedactedMessageEventContent { .. },
event_id,
..
}
@ -222,7 +222,7 @@ fn redacted_state_event_deserialize() {
AnySyncRoomEvent::RedactedState(AnyRedactedSyncStateEvent::RoomCreate(
RedactedSyncStateEvent {
content: RedactedCreateEventContent {
creator,
creator, ..
},
event_id,
state_key,
@ -311,7 +311,7 @@ fn redact_method_properly_redacts() {
assert_matches!(
event.redact(redaction, &RoomVersionId::Version6),
AnyRedactedMessageEvent::RoomMessage(RedactedMessageEvent {
content: RedactedMessageEventContent,
content: RedactedMessageEventContent { .. },
event_id,
room_id,
sender,
@ -338,7 +338,7 @@ fn redact_message_content() {
assert_matches!(
content.redact(&RoomVersionId::Version6),
AnyRedactedMessageEventContent::RoomMessage(RedactedMessageEventContent)
AnyRedactedMessageEventContent::RoomMessage(RedactedMessageEventContent { .. })
);
}
@ -356,7 +356,8 @@ fn redact_state_content() {
assert_matches!(
content.redact(&RoomVersionId::Version6),
AnyRedactedStateEventContent::RoomCreate(RedactedCreateEventContent {
creator
creator,
..
}) if creator == user_id!("@carl:example.com")
);
}

View File

@ -277,7 +277,7 @@ fn edit_deserialization_future() {
formatted: None,
..
}),
relates_to: Some(Relation::Replacement(Replacement { event_id, new_content })),
relates_to: Some(Relation::Replacement(Replacement { event_id, new_content, .. })),
..
} if body == "s/foo/bar"
&& event_id == ev_id
@ -321,6 +321,7 @@ fn verification_request_deserialization() {
to,
from_device,
methods,
..
}),
..
} if body == "@example:localhost is requesting to verify your key, ..."
@ -351,12 +352,9 @@ fn verification_request_serialization() {
"methods": methods
});
let content = MessageType::VerificationRequest(KeyVerificationRequestEventContent {
to: user_id,
from_device: device_id,
body,
methods,
});
let content = MessageType::VerificationRequest(KeyVerificationRequestEventContent::new(
body, methods, device_id, user_id,
));
assert_eq!(to_json_value(&content).unwrap(), json_data,);
}