From aad7a7987f423218b817488654a328c5800f777e Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Fri, 3 Nov 2017 16:12:43 +0100 Subject: [PATCH] Add an example to the Configure trait --- serde_test/src/assert.rs | 43 ++--------------- serde_test/src/configure.rs | 74 +++++++++++++++++++++++++++-- serde_test/src/de.rs | 22 ++------- serde_test/src/lib.rs | 10 ++-- serde_test/src/ser.rs | 42 ++++++++-------- test_suite/tests/test_de.rs | 34 ++++++------- test_suite/tests/test_identifier.rs | 7 +-- test_suite/tests/test_remote.rs | 64 ++++++++----------------- test_suite/tests/test_roundtrip.rs | 14 ++---- test_suite/tests/test_ser.rs | 33 +++++-------- 10 files changed, 157 insertions(+), 186 deletions(-) diff --git a/serde_test/src/assert.rs b/serde_test/src/assert.rs index 34eb6a75..95c7b923 100644 --- a/serde_test/src/assert.rs +++ b/serde_test/src/assert.rs @@ -6,7 +6,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use de::Deserializer; use ser::Serializer; @@ -47,20 +47,8 @@ pub fn assert_tokens<'de, T>(value: &T, tokens: &'de [Token]) where T: Serialize + Deserialize<'de> + PartialEq + Debug, { - assert_tokens_readable(value, tokens, None); -} - -// Not public API -#[doc(hidden)] -/// Runs both `assert_ser_tokens` and `assert_de_tokens`. -/// -/// See: `assert_tokens` -pub fn assert_tokens_readable<'de, T>(value: &T, tokens: &'de [Token], human_readable: Option) -where - T: Serialize + Deserialize<'de> + PartialEq + Debug, -{ - assert_ser_tokens_readable(value, tokens, human_readable); - assert_de_tokens_readable(value, tokens, human_readable); + assert_ser_tokens(value, tokens); + assert_de_tokens(value, tokens); } /// Asserts that `value` serializes to the given `tokens`. @@ -96,19 +84,7 @@ pub fn assert_ser_tokens(value: &T, tokens: &[Token]) where T: Serialize, { - assert_ser_tokens_readable(value, tokens, None) -} - -// Not public API -#[doc(hidden)] -/// Asserts that `value` serializes to the given `tokens`. -/// -/// See: `assert_ser_tokens` -pub fn assert_ser_tokens_readable(value: &T, tokens: &[Token], human_readable: Option) -where - T: Serialize, -{ - let mut ser = Serializer::readable(tokens, human_readable); + let mut ser = Serializer::new(tokens); match value.serialize(&mut ser) { Ok(_) => {} Err(err) => panic!("value failed to serialize: {}", err), @@ -207,16 +183,7 @@ pub fn assert_de_tokens<'de, T>(value: &T, tokens: &'de [Token]) where T: Deserialize<'de> + PartialEq + Debug, { - assert_de_tokens_readable(value, tokens, None) -} - -// Not public API -#[doc(hidden)] -pub fn assert_de_tokens_readable<'de, T>(value: &T, tokens: &'de [Token], human_readable: Option) -where - T: Deserialize<'de> + PartialEq + Debug, -{ - let mut de = Deserializer::readable(tokens, human_readable); + let mut de = Deserializer::new(tokens); match T::deserialize(&mut de) { Ok(v) => assert_eq!(v, *value), Err(e) => panic!("tokens failed to deserialize: {}", e), diff --git a/serde_test/src/configure.rs b/serde_test/src/configure.rs index e92ccafc..57384745 100644 --- a/serde_test/src/configure.rs +++ b/serde_test/src/configure.rs @@ -4,19 +4,85 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple, SerializeTupleStruct, SerializeTupleVariant}; +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Readable(T); +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Compact(T); -pub trait Configure { - fn readable(&self) -> Readable<&Self> { +/// Trait which lets values mark wheter they should serialize or deserialize to or from their +/// human-readable or compact representation. +/// +/// ``` +/// extern crate serde; +/// extern crate serde_test; +/// +/// use serde::{Deserialize, Deserializer, Serialize, Serializer}; +/// use serde_test::{Configure, Token, assert_tokens}; +/// +/// #[derive(Debug, PartialEq)] +/// struct Example(u8, u8); +/// +/// impl Serialize for Example { +/// fn serialize(&self, serializer: S) -> Result +/// where S: Serializer, +/// { +/// if serializer.is_human_readable() { +/// format!("{}.{}", self.0, self.1).serialize(serializer) +/// } else { +/// (self.0, self.1).serialize(serializer) +/// } +/// } +/// } +/// +/// impl<'de> Deserialize<'de> for Example { +/// fn deserialize(deserializer: D) -> Result +/// where D: Deserializer<'de>, +/// { +/// use serde::de::Error; +/// if deserializer.is_human_readable() { +/// let s = String::deserialize(deserializer)?; +/// let parts: Vec<_> = s.split('.').collect(); +/// Ok(Example( +/// parts[0].parse().map_err(D::Error::custom)?, +/// parts[1].parse().map_err(D::Error::custom)?, +/// )) +/// } else { +/// let (x, y) = Deserialize::deserialize(deserializer)?; +/// Ok(Example(x, y)) +/// } +/// } +/// } +/// +/// fn main() { +/// assert_tokens( +/// &Example(1, 0).compact(), +/// &[ +/// Token::Tuple { len: 2 }, +/// Token::U8(1), +/// Token::U8(0), +/// Token::TupleEnd, +/// ], +/// ); +/// assert_tokens( +/// &Example(1, 0).readable(), +/// &[ +/// Token::Str("1.0"), +/// ], +/// ); +/// } +/// ``` +pub trait Configure : Sized { + /// Marks `self` as using `is_human_readable == true` + fn readable(self) -> Readable { Readable(self) } - fn compact(&self) -> Compact<&Self> { + /// Marks `self` as using `is_human_readable == false` + fn compact(self) -> Compact { Compact(self) } } -impl Configure for T {} +impl Configure for T {} impl Serialize for Readable where diff --git a/serde_test/src/de.rs b/serde_test/src/de.rs index 782e706b..623d11b8 100644 --- a/serde_test/src/de.rs +++ b/serde_test/src/de.rs @@ -16,7 +16,6 @@ use token::Token; #[derive(Debug)] pub struct Deserializer<'de> { tokens: &'de [Token], - is_human_readable: Option, } macro_rules! assert_next_token { @@ -49,13 +48,7 @@ macro_rules! end_of_tokens { impl<'de> Deserializer<'de> { pub fn new(tokens: &'de [Token]) -> Self { - Deserializer::readable(tokens, None) - } - - // Not public API - #[doc(hidden)] - pub fn readable(tokens: &'de [Token], is_human_readable: Option) -> Self { - Deserializer { tokens: tokens, is_human_readable: is_human_readable } + Deserializer { tokens: tokens } } fn peek_token_opt(&self) -> Option { @@ -373,15 +366,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { } fn is_human_readable(&self) -> bool { - match self.is_human_readable { - Some(is) => is, - None => { - panic!("There is no serde_test API currently for testing types \ - that have different human-readable and compact \ - representation. See \ - https://github.com/serde-rs/serde/issues/1065."); - } - } + panic!( + "Types which have different human-readable and compact representations\ + must explicitly mark their test cases with `serde_test::Configure`" + ); } } diff --git a/serde_test/src/lib.rs b/serde_test/src/lib.rs index 94fa5fd4..7d5c65ac 100644 --- a/serde_test/src/lib.rs +++ b/serde_test/src/lib.rs @@ -169,14 +169,10 @@ mod token; mod assert; pub use token::Token; -pub use assert::{assert_tokens, assert_ser_tokens, assert_ser_tokens_error, - assert_de_tokens, assert_de_tokens_error}; +pub use assert::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, + assert_ser_tokens_error, assert_tokens}; -pub use configure::{Configure, Compact, Readable}; - -// Not public API. -#[doc(hidden)] -pub use assert::{assert_tokens_readable, assert_de_tokens_readable, assert_ser_tokens_readable}; +pub use configure::{Compact, Configure, Readable}; // Not public API. #[doc(hidden)] diff --git a/serde_test/src/ser.rs b/serde_test/src/ser.rs index 5fd5ecf5..d443c883 100644 --- a/serde_test/src/ser.rs +++ b/serde_test/src/ser.rs @@ -15,19 +15,12 @@ use token::Token; #[derive(Debug)] pub struct Serializer<'a> { tokens: &'a [Token], - is_human_readable: Option, } impl<'a> Serializer<'a> { /// Creates the serializer. pub fn new(tokens: &'a [Token]) -> Self { - Serializer::readable(tokens, None) - } - - // Not public API - #[doc(hidden)] - pub fn readable(tokens: &'a [Token], is_human_readable: Option) -> Self { - Serializer { tokens: tokens, is_human_readable: is_human_readable } + Serializer { tokens: tokens } } /// Pulls the next token off of the serializer, ignoring it. @@ -254,10 +247,16 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> { assert_next_token!(self, Str(variant)); let len = Some(len); assert_next_token!(self, Seq { len }); - Ok(Variant { ser: self, end: Token::SeqEnd }) + Ok(Variant { + ser: self, + end: Token::SeqEnd, + }) } else { assert_next_token!(self, TupleVariant { name, variant, len }); - Ok(Variant { ser: self, end: Token::TupleVariantEnd }) + Ok(Variant { + ser: self, + end: Token::TupleVariantEnd, + }) } } @@ -283,23 +282,24 @@ impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> { assert_next_token!(self, Str(variant)); let len = Some(len); assert_next_token!(self, Map { len }); - Ok(Variant { ser: self, end: Token::MapEnd }) + Ok(Variant { + ser: self, + end: Token::MapEnd, + }) } else { assert_next_token!(self, StructVariant { name, variant, len }); - Ok(Variant { ser: self, end: Token::StructVariantEnd }) + Ok(Variant { + ser: self, + end: Token::StructVariantEnd, + }) } } fn is_human_readable(&self) -> bool { - match self.is_human_readable { - Some(is) => is, - None => { - panic!("There is no serde_test API currently for testing types \ - that have different human-readable and compact \ - representation. See \ - https://github.com/serde-rs/serde/issues/1065."); - } - } + panic!( + "Types which have different human-readable and compact representations\ + must explicitly mark their test cases with `serde_test::Configure`" + ); } } diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 5adae5ac..f5780936 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -29,7 +29,7 @@ extern crate fnv; use self::fnv::FnvHasher; extern crate serde_test; -use self::serde_test::{Token, assert_de_tokens, assert_de_tokens_error, assert_de_tokens_readable}; +use self::serde_test::{assert_de_tokens, assert_de_tokens_error, Configure, Token}; #[macro_use] mod macros; @@ -49,16 +49,14 @@ struct TupleStruct(i32, i32, i32); struct Struct { a: i32, b: i32, - #[serde(skip_deserializing)] - c: i32, + #[serde(skip_deserializing)] c: i32, } #[derive(PartialEq, Debug, Deserialize)] #[serde(deny_unknown_fields)] struct StructDenyUnknown { a: i32, - #[serde(skip_deserializing)] - b: i32, + #[serde(skip_deserializing)] b: i32, } #[derive(PartialEq, Debug, Deserialize)] @@ -79,15 +77,13 @@ impl Default for StructDefault { #[derive(PartialEq, Debug, Deserialize)] struct StructSkipAll { - #[serde(skip_deserializing)] - a: i32, + #[serde(skip_deserializing)] a: i32, } #[derive(PartialEq, Debug, Deserialize)] #[serde(deny_unknown_fields)] struct StructSkipAllDenyUnknown { - #[serde(skip_deserializing)] - a: i32, + #[serde(skip_deserializing)] a: i32, } #[derive(PartialEq, Debug, Deserialize)] @@ -112,7 +108,7 @@ enum EnumSkipAll { macro_rules! declare_tests { ( - readable: $readable:tt + $readable:tt $($name:ident { $($value:expr => $tokens:expr,)+ })+ ) => { $( @@ -120,7 +116,7 @@ macro_rules! declare_tests { fn $name() { $( // Test ser/de roundtripping - assert_de_tokens_readable(&$value, $tokens, Some($readable)); + assert_de_tokens(&$value.$readable(), $tokens); // Test that the tokens are ignorable assert_de_tokens_ignore($tokens); @@ -168,13 +164,11 @@ fn assert_de_tokens_ignore(ignorable_tokens: &[Token]) { Token::Map { len: Some(2) }, Token::Str("a"), Token::I32(1), - Token::Str("ignored"), - ] - .into_iter() - .chain(ignorable_tokens.to_vec().into_iter()) - .chain(vec![Token::MapEnd].into_iter()) - .collect(); + ].into_iter() + .chain(ignorable_tokens.to_vec().into_iter()) + .chain(vec![Token::MapEnd].into_iter()) + .collect(); let mut de = serde_test::Deserializer::new(&concated_tokens); let base = IgnoreBase::deserialize(&mut de).unwrap(); @@ -774,7 +768,8 @@ declare_tests! { } declare_tests! { - readable: true + readable + test_net_ipv4addr_readable { "1.2.3.4".parse::().unwrap() => &[Token::Str("1.2.3.4")], } @@ -792,7 +787,8 @@ declare_tests! { } declare_tests! { - readable: false + compact + test_net_ipv4addr_compact { net::Ipv4Addr::from(*b"1234") => &seq![ Token::Tuple { len: 4 }, diff --git a/test_suite/tests/test_identifier.rs b/test_suite/tests/test_identifier.rs index 83a0d3b1..b13b6695 100644 --- a/test_suite/tests/test_identifier.rs +++ b/test_suite/tests/test_identifier.rs @@ -9,10 +9,8 @@ #[macro_use] extern crate serde_derive; -extern crate serde; - extern crate serde_test; -use serde_test::{Token, assert_de_tokens}; +use serde_test::{assert_de_tokens, Token}; #[test] fn test_variant_identifier() { @@ -51,8 +49,7 @@ fn test_unit_fallthrough() { enum F { Aaa, Bbb, - #[serde(other)] - Other, + #[serde(other)] Other, } assert_de_tokens(&F::Other, &[Token::Str("x")]); diff --git a/test_suite/tests/test_remote.rs b/test_suite/tests/test_remote.rs index 30ccbb27..c0b2700e 100644 --- a/test_suite/tests/test_remote.rs +++ b/test_suite/tests/test_remote.rs @@ -9,8 +9,6 @@ #[macro_use] extern crate serde_derive; -extern crate serde; - mod remote { pub struct Unit; @@ -87,32 +85,23 @@ mod remote { #[derive(Serialize, Deserialize)] struct Test { - #[serde(with = "UnitDef")] - unit: remote::Unit, + #[serde(with = "UnitDef")] unit: remote::Unit, - #[serde(with = "PrimitivePrivDef")] - primitive_priv: remote::PrimitivePriv, + #[serde(with = "PrimitivePrivDef")] primitive_priv: remote::PrimitivePriv, - #[serde(with = "PrimitivePubDef")] - primitive_pub: remote::PrimitivePub, + #[serde(with = "PrimitivePubDef")] primitive_pub: remote::PrimitivePub, - #[serde(with = "NewtypePrivDef")] - newtype_priv: remote::NewtypePriv, + #[serde(with = "NewtypePrivDef")] newtype_priv: remote::NewtypePriv, - #[serde(with = "NewtypePubDef")] - newtype_pub: remote::NewtypePub, + #[serde(with = "NewtypePubDef")] newtype_pub: remote::NewtypePub, - #[serde(with = "TuplePrivDef")] - tuple_priv: remote::TuplePriv, + #[serde(with = "TuplePrivDef")] tuple_priv: remote::TuplePriv, - #[serde(with = "TuplePubDef")] - tuple_pub: remote::TuplePub, + #[serde(with = "TuplePubDef")] tuple_pub: remote::TuplePub, - #[serde(with = "StructPrivDef")] - struct_priv: remote::StructPriv, + #[serde(with = "StructPrivDef")] struct_priv: remote::StructPriv, - #[serde(with = "StructPubDef")] - struct_pub: remote::StructPub, + #[serde(with = "StructPubDef")] struct_pub: remote::StructPub, } #[derive(Serialize, Deserialize)] @@ -121,10 +110,7 @@ struct UnitDef; #[derive(Serialize, Deserialize)] #[serde(remote = "remote::PrimitivePriv")] -struct PrimitivePrivDef( - #[serde(getter = "remote::PrimitivePriv::get")] - u8 -); +struct PrimitivePrivDef(#[serde(getter = "remote::PrimitivePriv::get")] u8); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::PrimitivePub")] @@ -133,53 +119,41 @@ struct PrimitivePubDef(u8); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::NewtypePriv")] struct NewtypePrivDef( - #[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")] - remote::Unit + #[serde(getter = "remote::NewtypePriv::get", with = "UnitDef")] remote::Unit, ); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::NewtypePub")] -struct NewtypePubDef( - #[serde(with = "UnitDef")] - remote::Unit -); +struct NewtypePubDef(#[serde(with = "UnitDef")] remote::Unit); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::TuplePriv")] struct TuplePrivDef( - #[serde(getter = "remote::TuplePriv::first")] - u8, - #[serde(getter = "remote::TuplePriv::second", with = "UnitDef")] - remote::Unit + #[serde(getter = "remote::TuplePriv::first")] u8, + #[serde(getter = "remote::TuplePriv::second", with = "UnitDef")] remote::Unit, ); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::TuplePub")] -struct TuplePubDef( - u8, - #[serde(with = "UnitDef")] - remote::Unit -); +struct TuplePubDef(u8, #[serde(with = "UnitDef")] remote::Unit); #[derive(Serialize, Deserialize)] #[serde(remote = "remote::StructPriv")] struct StructPrivDef { - #[serde(getter = "remote::StructPriv::a")] - a: u8, + #[serde(getter = "remote::StructPriv::a")] a: u8, #[serde(getter = "remote::StructPriv::b")] - #[serde(with= "UnitDef")] + #[serde(with = "UnitDef")] b: remote::Unit, } #[derive(Serialize, Deserialize)] #[serde(remote = "remote::StructPub")] struct StructPubDef { - #[allow(dead_code)] - a: u8, + #[allow(dead_code)] a: u8, #[allow(dead_code)] - #[serde(with= "UnitDef")] + #[serde(with = "UnitDef")] b: remote::Unit, } diff --git a/test_suite/tests/test_roundtrip.rs b/test_suite/tests/test_roundtrip.rs index 0e417341..300fe8d3 100644 --- a/test_suite/tests/test_roundtrip.rs +++ b/test_suite/tests/test_roundtrip.rs @@ -7,7 +7,7 @@ // except according to those terms. extern crate serde_test; -use self::serde_test::{Token, assert_tokens_readable}; +use self::serde_test::{assert_tokens, Configure, Token}; use std::net; @@ -17,9 +17,8 @@ mod macros; #[test] fn ip_addr_roundtrip() { - - assert_tokens_readable( - &net::IpAddr::from(*b"1234"), + assert_tokens( + &net::IpAddr::from(*b"1234").compact(), &seq![ Token::NewtypeVariant { name: "IpAddr", variant: "V4" }, @@ -27,15 +26,13 @@ fn ip_addr_roundtrip() { seq b"1234".iter().map(|&b| Token::U8(b)), Token::TupleEnd, ], - Some(false), ); } #[test] fn socked_addr_roundtrip() { - - assert_tokens_readable( - &net::SocketAddr::from((*b"1234567890123456", 1234)), + assert_tokens( + &net::SocketAddr::from((*b"1234567890123456", 1234)).compact(), &seq![ Token::NewtypeVariant { name: "SocketAddr", variant: "V6" }, @@ -48,6 +45,5 @@ fn socked_addr_roundtrip() { Token::U16(1234), Token::TupleEnd, ], - Some(false), ); } diff --git a/test_suite/tests/test_ser.rs b/test_suite/tests/test_ser.rs index 4198d566..7b1af691 100644 --- a/test_suite/tests/test_ser.rs +++ b/test_suite/tests/test_ser.rs @@ -21,11 +21,8 @@ use std::num::Wrapping; #[cfg(unix)] use std::str; -extern crate serde; - extern crate serde_test; -use self::serde_test::{Token, assert_ser_tokens, assert_ser_tokens_error, - assert_ser_tokens_readable}; +use self::serde_test::{assert_ser_tokens, assert_ser_tokens_error, Configure, Token}; extern crate fnv; use self::fnv::FnvHasher; @@ -54,28 +51,24 @@ enum Enum { One(i32), Seq(i32, i32), Map { a: i32, b: i32 }, - #[serde(skip_serializing)] - SkippedUnit, - #[serde(skip_serializing)] - SkippedOne(i32), - #[serde(skip_serializing)] - SkippedSeq(i32, i32), - #[serde(skip_serializing)] - SkippedMap { _a: i32, _b: i32 }, + #[serde(skip_serializing)] SkippedUnit, + #[serde(skip_serializing)] SkippedOne(i32), + #[serde(skip_serializing)] SkippedSeq(i32, i32), + #[serde(skip_serializing)] SkippedMap { _a: i32, _b: i32 }, } ////////////////////////////////////////////////////////////////////////// macro_rules! declare_tests { ( - readable: $readable:tt + $readable:tt $($name:ident { $($value:expr => $tokens:expr,)+ })+ ) => { $( #[test] fn $name() { $( - assert_ser_tokens_readable(&$value, $tokens, Some($readable)); + assert_ser_tokens(&$value.$readable(), $tokens); )+ } )+ @@ -408,7 +401,8 @@ declare_tests! { } declare_tests! { - readable: true + readable + test_net_ipv4addr_readable { "1.2.3.4".parse::().unwrap() => &[Token::Str("1.2.3.4")], } @@ -426,7 +420,8 @@ declare_tests! { } declare_tests! { - readable: false + compact + test_net_ipv4addr_compact { net::Ipv4Addr::from(*b"1234") => &seq![ Token::Tuple { len: 4 }, @@ -524,11 +519,7 @@ fn test_cannot_serialize_paths() { let mut path_buf = PathBuf::new(); path_buf.push(path); - assert_ser_tokens_error( - &path_buf, - &[], - "path contains invalid UTF-8 characters", - ); + assert_ser_tokens_error(&path_buf, &[], "path contains invalid UTF-8 characters"); } #[test]