Factor the Token De/Serializer into serde_test

This commit is contained in:
David Tolnay 2016-06-28 21:47:54 -07:00
parent fb0e62951f
commit 6d64104375
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
14 changed files with 718 additions and 638 deletions

14
serde_test/Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "serde_test"
version = "0.1.0"
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
license = "MIT/Apache-2.0"
description = "Token De/Serializer for testing De/Serialize implementations"
repository = "https://github.com/serde-rs/serde"
documentation = "https://serde-rs.github.io/serde/serde/"
readme = "../README.md"
keywords = ["serde", "serialization"]
include = ["Cargo.toml", "src/**/*.rs"]
[dependencies]
serde = { version = "0.7.11", path = "../serde" }

50
serde_test/src/assert.rs Normal file
View File

@ -0,0 +1,50 @@
use serde::{Serialize, Deserialize};
use de::Deserializer;
use error::Error;
use ser::Serializer;
use token::Token;
use std::fmt::Debug;
pub fn assert_tokens<T>(value: &T, tokens: Vec<Token<'static>>)
where T: Serialize + Deserialize + PartialEq + Debug,
{
assert_ser_tokens(value, &tokens[..]);
assert_de_tokens(value, tokens);
}
pub fn assert_ser_tokens<T>(value: &T, tokens: &[Token])
where T: Serialize,
{
let mut ser = Serializer::new(tokens.iter());
assert_eq!(Serialize::serialize(value, &mut ser), Ok(()));
assert_eq!(ser.next_token(), None);
}
// Expect an error deserializing tokens into a T
pub fn assert_ser_tokens_error<T>(value: &T, tokens: &[Token], error: Error)
where T: Serialize + PartialEq + Debug,
{
let mut ser = Serializer::new(tokens.iter());
let v: Result<(), Error> = Serialize::serialize(value, &mut ser);
assert_eq!(v.as_ref(), Err(&error));
}
pub fn assert_de_tokens<T>(value: &T, tokens: Vec<Token<'static>>)
where T: Deserialize + PartialEq + Debug,
{
let mut de = Deserializer::new(tokens.into_iter());
let v: Result<T, Error> = Deserialize::deserialize(&mut de);
assert_eq!(v.as_ref(), Ok(value));
assert_eq!(de.next_token(), None);
}
// Expect an error deserializing tokens into a T
pub fn assert_de_tokens_error<T>(tokens: Vec<Token<'static>>, error: Error)
where T: Deserialize + PartialEq + Debug,
{
let mut de = Deserializer::new(tokens.into_iter());
let v: Result<T, Error> = Deserialize::deserialize(&mut de);
assert_eq!(v, Err(error));
}

File diff suppressed because it is too large Load Diff

75
serde_test/src/error.rs Normal file
View File

@ -0,0 +1,75 @@
use std::{error, fmt};
use serde::{ser, de};
use token::Token;
#[derive(Clone, PartialEq, Debug)]
pub enum Error {
SyntaxError,
EndOfStreamError,
UnknownFieldError(String),
UnknownVariantError(String),
MissingFieldError(&'static str),
DuplicateFieldError(&'static str),
InvalidName(&'static str),
InvalidValue(String),
UnexpectedToken(Token<'static>),
ValueError(de::value::Error),
}
impl ser::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error {
Error::SyntaxError
}
fn invalid_value(msg: &str) -> Error {
Error::InvalidValue(msg.to_owned())
}
}
impl de::Error for Error {
fn custom<T: Into<String>>(_: T) -> Error {
Error::SyntaxError
}
fn end_of_stream() -> Error {
Error::EndOfStreamError
}
fn invalid_value(msg: &str) -> Error {
Error::InvalidValue(msg.to_owned())
}
fn unknown_field(field: &str) -> Error {
Error::UnknownFieldError(field.to_owned())
}
fn unknown_variant(variant: &str) -> Error {
Error::UnknownVariantError(variant.to_owned())
}
fn missing_field(field: &'static str) -> Error {
Error::MissingFieldError(field)
}
fn duplicate_field(field: &'static str) -> Error {
Error::DuplicateFieldError(field)
}
}
impl fmt::Display for Error {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
formatter.write_str(format!("{:?}", self).as_ref())
}
}
impl error::Error for Error {
fn description(&self) -> &str {
"Serde Error"
}
fn cause(&self) -> Option<&error::Error> {
None
}
}

22
serde_test/src/lib.rs Normal file
View File

@ -0,0 +1,22 @@
extern crate serde;
mod assert;
pub use assert::{
assert_tokens,
assert_ser_tokens,
assert_ser_tokens_error,
assert_de_tokens,
assert_de_tokens_error,
};
mod ser;
pub use ser::Serializer;
mod de;
pub use de::Deserializer;
mod token;
pub use token::Token;
mod error;
pub use error::Error;

350
serde_test/src/ser.rs Normal file
View File

@ -0,0 +1,350 @@
use std::marker::PhantomData;
use serde::ser::{
self,
MapVisitor,
SeqVisitor,
Serialize,
};
use error::Error;
use token::Token;
pub struct Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
tokens: I,
phantom: PhantomData<&'a Token<'a>>,
}
impl<'a, I> Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
pub fn new(tokens: I) -> Serializer<'a, I> {
Serializer {
tokens: tokens,
phantom: PhantomData,
}
}
pub fn next_token(&mut self) -> Option<&'a Token<'a>> {
self.tokens.next()
}
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::SeqEnd));
Ok(())
}
fn visit_map<V>(&mut self, mut visitor: V) -> Result<(), Error>
where V: MapVisitor
{
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::MapEnd));
Ok(())
}
}
impl<'a, I> ser::Serializer for Serializer<'a, I>
where I: Iterator<Item=&'a Token<'a>>,
{
type Error = Error;
fn serialize_unit(&mut self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Unit));
Ok(())
}
fn serialize_newtype_variant<T>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumNewType(name, variant)));
value.serialize(self)
}
fn serialize_unit_struct(&mut self, name: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::UnitStruct(name)));
Ok(())
}
fn serialize_unit_variant(&mut self,
name: &str,
_variant_index: usize,
variant: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::EnumUnit(name, variant)));
Ok(())
}
fn serialize_bool(&mut self, v: bool) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Bool(v)));
Ok(())
}
fn serialize_isize(&mut self, v: isize) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Isize(v)));
Ok(())
}
fn serialize_i8(&mut self, v: i8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I8(v)));
Ok(())
}
fn serialize_i16(&mut self, v: i16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I16(v)));
Ok(())
}
fn serialize_i32(&mut self, v: i32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I32(v)));
Ok(())
}
fn serialize_i64(&mut self, v: i64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::I64(v)));
Ok(())
}
fn serialize_usize(&mut self, v: usize) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Usize(v)));
Ok(())
}
fn serialize_u8(&mut self, v: u8) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U8(v)));
Ok(())
}
fn serialize_u16(&mut self, v: u16) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U16(v)));
Ok(())
}
fn serialize_u32(&mut self, v: u32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U32(v)));
Ok(())
}
fn serialize_u64(&mut self, v: u64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::U64(v)));
Ok(())
}
fn serialize_f32(&mut self, v: f32) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F32(v)));
Ok(())
}
fn serialize_f64(&mut self, v: f64) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::F64(v)));
Ok(())
}
fn serialize_char(&mut self, v: char) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Char(v)));
Ok(())
}
fn serialize_str(&mut self, v: &str) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Str(v)));
Ok(())
}
fn serialize_none(&mut self) -> Result<(), Error> {
assert_eq!(self.tokens.next(), Some(&Token::Option(false)));
Ok(())
}
fn serialize_some<V>(&mut self, value: V) -> Result<(), Error>
where V: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::Option(true)));
value.serialize(self)
}
fn serialize_seq<V>(&mut self, visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::SeqStart(len)));
self.visit_seq(visitor)
}
fn serialize_fixed_size_array<V>(&mut self, visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len().expect("arrays must have a length");
assert_eq!(self.tokens.next(), Some(&Token::SeqArrayStart(len)));
self.visit_seq(visitor)
}
fn serialize_seq_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::SeqSep));
value.serialize(self)
}
fn serialize_tuple<V>(&mut self, mut visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len().expect("arrays must have a length");
assert_eq!(self.tokens.next(), Some(&Token::TupleStart(len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::TupleEnd));
Ok(())
}
fn serialize_tuple_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: Serialize
{
assert_eq!(self.tokens.next(), Some(&Token::TupleSep));
value.serialize(self)
}
fn serialize_newtype_struct<T>(&mut self,
name: &'static str,
value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::StructNewType(name)));
value.serialize(self)
}
fn serialize_tuple_struct<V>(&mut self, name: &str, mut visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::TupleStructStart(name, len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::TupleStructEnd));
Ok(())
}
fn serialize_tuple_struct_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::TupleStructSep));
value.serialize(self)
}
fn serialize_tuple_variant<V>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
mut visitor: V) -> Result<(), Error>
where V: SeqVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqStart(name, variant, len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqEnd));
Ok(())
}
fn serialize_tuple_variant_elt<T>(&mut self, value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumSeqSep));
value.serialize(self)
}
fn serialize_map<V>(&mut self, visitor: V) -> Result<(), Error>
where V: MapVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::MapStart(len)));
self.visit_map(visitor)
}
fn serialize_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Error>
where K: Serialize,
V: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::MapSep));
try!(key.serialize(self));
value.serialize(self)
}
fn serialize_struct<V>(&mut self, name: &str, mut visitor: V) -> Result<(), Error>
where V: MapVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::StructStart(name, len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::StructEnd));
Ok(())
}
fn serialize_struct_elt<T>(&mut self, key: &'static str, value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::StructSep));
try!(key.serialize(self));
value.serialize(self)
}
fn serialize_struct_variant<V>(&mut self,
name: &str,
_variant_index: usize,
variant: &str,
mut visitor: V) -> Result<(), Error>
where V: MapVisitor
{
let len = visitor.len();
assert_eq!(self.tokens.next(), Some(&Token::EnumMapStart(name, variant, len)));
while let Some(()) = try!(visitor.visit(self)) { }
assert_eq!(self.tokens.next(), Some(&Token::EnumMapEnd));
Ok(())
}
fn serialize_struct_variant_elt<T>(&mut self, key: &'static str, value: T) -> Result<(), Error>
where T: Serialize,
{
assert_eq!(self.tokens.next(), Some(&Token::EnumMapSep));
try!(key.serialize(self));
value.serialize(self)
}
}

60
serde_test/src/token.rs Normal file
View File

@ -0,0 +1,60 @@
#[derive(Clone, PartialEq, Debug)]
pub enum Token<'a> {
Bool(bool),
Isize(isize),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
Usize(usize),
U8(u8),
U16(u16),
U32(u32),
U64(u64),
F32(f32),
F64(f64),
Char(char),
Str(&'a str),
String(String),
Bytes(&'a [u8]),
Option(bool),
Unit,
UnitStruct(&'a str),
StructNewType(&'a str),
EnumStart(&'a str),
EnumUnit(&'a str, &'a str),
EnumNewType(&'a str, &'a str),
SeqStart(Option<usize>),
SeqArrayStart(usize),
SeqSep,
SeqEnd,
TupleStart(usize),
TupleSep,
TupleEnd,
TupleStructStart(&'a str, Option<usize>),
TupleStructSep,
TupleStructEnd,
MapStart(Option<usize>),
MapSep,
MapEnd,
StructStart(&'a str, Option<usize>),
StructSep,
StructEnd,
EnumSeqStart(&'a str, &'a str, Option<usize>),
EnumSeqSep,
EnumSeqEnd,
EnumMapStart(&'a str, &'a str, Option<usize>),
EnumMapSep,
EnumMapEnd,
}

View File

@ -20,6 +20,7 @@ serde_codegen = { version = "*", path = "../serde_codegen", features = ["with-sy
fnv = "1.0"
rustc-serialize = "^0.3.16"
serde = { version = "*", path = "../serde" }
serde_test = { version = "*", path = "../serde_test" }
[dependencies]
clippy = { version = "^0.*", optional = true }

View File

@ -5,7 +5,7 @@ macro_rules! declare_ser_tests {
#[test]
fn $name() {
$(
::token::assert_ser_tokens(&$value, $tokens);
self::serde_test::assert_ser_tokens(&$value, $tokens);
)+
}
)+

View File

@ -1,8 +1,6 @@
#[macro_use]
mod macros;
mod token;
mod test_annotations;
mod test_bytes;
mod test_de;

View File

@ -1,7 +1,8 @@
extern crate serde;
use self::serde::{Serialize, Serializer, Deserialize, Deserializer};
use token::{
extern crate serde_test;
use self::serde_test::{
Error,
Token,
assert_tokens,

View File

@ -2,14 +2,17 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::net;
use std::path::PathBuf;
extern crate serde;
use self::serde::Deserialize;
extern crate fnv;
use self::fnv::FnvHasher;
use token::{
extern crate serde_test;
use self::serde_test::{
Error,
Token,
assert_de_tokens,
assert_de_tokens_ignore,
assert_de_tokens_error,
};
@ -73,6 +76,46 @@ macro_rules! declare_error_tests {
}
}
fn assert_de_tokens_ignore(ignorable_tokens: Vec<Token<'static>>) {
#[derive(PartialEq, Debug, Deserialize)]
struct IgnoreBase {
a: i32,
}
let expected = IgnoreBase{a: 1};
// Embed the tokens to be ignored in the normal token
// stream for an IgnoreBase type
let concated_tokens : Vec<Token<'static>> = vec![
Token::MapStart(Some(2)),
Token::MapSep,
Token::Str("a"),
Token::I32(1),
Token::MapSep,
Token::Str("ignored")
]
.into_iter()
.chain(ignorable_tokens.into_iter())
.chain(vec![
Token::MapEnd,
].into_iter())
.collect();
let mut de = serde_test::Deserializer::new(concated_tokens.into_iter());
let v: Result<IgnoreBase, Error> = Deserialize::deserialize(&mut de);
// We run this test on every token stream for convenience, but
// some token streams don't make sense embedded as a map value,
// so we ignore those. SyntaxError is the real sign of trouble.
if let Err(Error::UnexpectedToken(_)) = v {
return;
}
assert_eq!(v.as_ref(), Ok(&expected));
assert_eq!(de.next_token(), None);
}
//////////////////////////////////////////////////////////////////////////
declare_tests! {

View File

@ -1,11 +1,12 @@
use std::marker::PhantomData;
use token::{Token, assert_tokens, assert_ser_tokens, assert_de_tokens};
extern crate serde_test;
use self::serde_test::{
Token,
assert_tokens,
assert_ser_tokens,
assert_de_tokens,
};
/*
trait Trait {
type Type;
}
*/
use std::marker::PhantomData;
// That tests that the derived Serialize implementation doesn't trigger
// any warning about `serializer` not being used, in case of empty enums.

View File

@ -3,7 +3,12 @@ use std::net;
use std::path::{Path, PathBuf};
use std::str;
use token::{self, Token};
extern crate serde_test;
use self::serde_test::{
Error,
Token,
assert_ser_tokens_error,
};
extern crate fnv;
use self::fnv::FnvHasher;
@ -355,16 +360,16 @@ fn test_cannot_serialize_paths() {
let path = unsafe {
str::from_utf8_unchecked(b"Hello \xF0\x90\x80World")
};
token::assert_ser_tokens_error(
assert_ser_tokens_error(
&Path::new(path),
&[Token::Str("Hello <20>World")],
token::Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
let mut path_buf = PathBuf::new();
path_buf.push(path);
token::assert_ser_tokens_error(
assert_ser_tokens_error(
&path_buf,
&[Token::Str("Hello <20>World")],
token::Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
Error::InvalidValue("Path contains invalid UTF-8 characters".to_owned()));
}