From 3bad559980be99ff289dc78cd35916cf53067548 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Fri, 21 Jun 2019 17:00:28 -0700 Subject: [PATCH] Add serialization and deserialization tests. --- tests/ruma_events_macros.rs | 162 +++++++++++++++++++++++++++++++++++- 1 file changed, 159 insertions(+), 3 deletions(-) diff --git a/tests/ruma_events_macros.rs b/tests/ruma_events_macros.rs index ffc0c87d..807aa133 100644 --- a/tests/ruma_events_macros.rs +++ b/tests/ruma_events_macros.rs @@ -1,9 +1,9 @@ -use std::fmt::Debug; +use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; -use serde::{Deserialize, Serialize}; +use serde::{de::{Error as SerdeError, Visitor}, Deserialize, Deserializer, Serialize, Serializer}; /// The type of an event. -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, PartialEq)] pub enum EventType { /// m.direct Direct, @@ -18,6 +18,65 @@ pub enum EventType { Custom(String), } +impl Display for EventType { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + let event_type_str = match *self { + EventType::Direct => "m.direct", + EventType::RoomAliases => "m.room.aliases", + EventType::RoomRedaction => "m.room.redaction", + EventType::Custom(ref event_type) => event_type, + }; + + write!(f, "{}", event_type_str) + } +} + +impl<'a> From<&'a str> for EventType { + fn from(s: &'a str) -> EventType { + match s { + "m.direct" => EventType::Direct, + "m.room.aliases" => EventType::RoomAliases, + "m.room.redaction" => EventType::RoomRedaction, + event_type => EventType::Custom(event_type.to_string()), + } + } +} + +impl Serialize for EventType { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + +impl<'de> Deserialize<'de> for EventType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct EventTypeVisitor; + + impl<'de> Visitor<'de> for EventTypeVisitor { + type Value = EventType; + + fn expecting(&self, formatter: &mut Formatter<'_>) -> FmtResult { + write!(formatter, "a Matrix event type as a string") + } + + fn visit_str(self, v: &str) -> Result + where + E: SerdeError, + { + Ok(EventType::from(v)) + } + } + + deserializer.deserialize_str(EventTypeVisitor) + } +} + /// A basic event. pub trait Event where @@ -64,6 +123,7 @@ pub trait StateEvent: RoomEvent { fn state_key(&self) -> &str; } +#[derive(Debug)] pub struct InvalidEvent; impl From for InvalidEvent { @@ -74,7 +134,12 @@ impl From for InvalidEvent { // See note about wrapping macro expansion in a module from `src/lib.rs` pub mod common_case { + use std::convert::TryFrom; + + use js_int::UInt; use ruma_events_macros::ruma_event; + use ruma_identifiers::{EventId, RoomAliasId, RoomId, UserId}; + use serde_json::Value; ruma_event! { /// Informs the room about what room aliases it has been given. @@ -87,6 +152,97 @@ pub mod common_case { } } } + + #[test] + fn serialization_with_optional_fields_as_none() { + let event = AliasesEvent { + content: AliasesEventContent { + aliases: Vec::with_capacity(0), + }, + event_id: EventId::try_from("$h29iv0s8:example.com").unwrap(), + origin_server_ts: UInt::try_from(1).unwrap(), + prev_content: None, + room_id: None, + sender: UserId::try_from("@carl:example.com").unwrap(), + state_key: "example.com".to_string(), + unsigned: None, + }; + + let actual = serde_json::to_string(&event).unwrap(); + let expected = r#"{"content":{"aliases":[]},"event_id":"$h29iv0s8:example.com","origin_server_ts":1,"sender":"@carl:example.com","state_key":"example.com","type":"m.room.aliases"}"#; + + assert_eq!(actual, expected); + } + + #[test] + fn serialization_with_some_optional_fields_as_some() { + let event = AliasesEvent { + content: AliasesEventContent { + aliases: vec![RoomAliasId::try_from("#room:example.org").unwrap()], + }, + event_id: EventId::try_from("$h29iv0s8:example.com").unwrap(), + origin_server_ts: UInt::try_from(1).unwrap(), + prev_content: Some(AliasesEventContent { + aliases: Vec::with_capacity(0), + }), + room_id: Some(RoomId::try_from("!n8f893n9:example.com").unwrap()), + sender: UserId::try_from("@carl:example.com").unwrap(), + state_key: "example.com".to_string(), + unsigned: None, + }; + + let actual = serde_json::to_string(&event).unwrap(); + let expected = r##"{"content":{"aliases":["#room:example.org"]},"event_id":"$h29iv0s8:example.com","origin_server_ts":1,"prev_content":{"aliases":[]},"room_id":"!n8f893n9:example.com","sender":"@carl:example.com","state_key":"example.com","type":"m.room.aliases"}"##; + + assert_eq!(actual, expected); + } + + #[test] + fn serialization_with_all_optional_fields_as_some() { + let event = AliasesEvent { + content: AliasesEventContent { + aliases: vec![RoomAliasId::try_from("#room:example.org").unwrap()], + }, + event_id: EventId::try_from("$h29iv0s8:example.com").unwrap(), + origin_server_ts: UInt::try_from(1).unwrap(), + prev_content: Some(AliasesEventContent { + aliases: Vec::with_capacity(0), + }), + room_id: Some(RoomId::try_from("!n8f893n9:example.com").unwrap()), + sender: UserId::try_from("@carl:example.com").unwrap(), + state_key: "example.com".to_string(), + unsigned: Some(serde_json::from_str::(r#"{"foo":"bar"}"#).unwrap()), + }; + + let actual = serde_json::to_string(&event).unwrap(); + let expected = r##"{"content":{"aliases":["#room:example.org"]},"event_id":"$h29iv0s8:example.com","origin_server_ts":1,"prev_content":{"aliases":[]},"room_id":"!n8f893n9:example.com","sender":"@carl:example.com","state_key":"example.com","unsigned":{"foo":"bar"},"type":"m.room.aliases"}"##; + + assert_eq!(actual, expected); + } + + #[test] + fn deserialization() { + let json = r##"{"content":{"aliases":["#room:example.org"]},"event_id":"$h29iv0s8:example.com","origin_server_ts":1,"prev_content":{"aliases":[]},"room_id":"!n8f893n9:example.com","sender":"@carl:example.com","state_key":"example.com","unsigned":{"foo":"bar"},"type":"m.room.aliases"}"##; + + let actual: AliasesEvent = json.parse().unwrap(); + + let expected = AliasesEvent { + content: AliasesEventContent { + aliases: vec![RoomAliasId::try_from("#room:example.org").unwrap()], + }, + event_id: EventId::try_from("$h29iv0s8:example.com").unwrap(), + origin_server_ts: UInt::try_from(1).unwrap(), + prev_content: Some(AliasesEventContent { + aliases: Vec::with_capacity(0), + }), + room_id: Some(RoomId::try_from("!n8f893n9:example.com").unwrap()), + sender: UserId::try_from("@carl:example.com").unwrap(), + state_key: "example.com".to_string(), + unsigned: Some(serde_json::from_str::(r#"{"foo":"bar"}"#).unwrap()), + }; + + assert_eq!(actual, expected); + } } pub mod custom_event_type {