serde_test does not catch error in fields passed to deserialize_struct
tspiteri opened this issue · 1 comments
tspiteri commented
The code below has a bug where deserialize_struct
is passed a fields
parameter with length one instead of two. This is not caught by serde_test
, and serde_json
is unaffected as well, but then bincode
will fail because it needs to know the number of fields for deserialization. Can serde_test
be used to catch this kind of bug?
extern crate bincode;
extern crate serde;
extern crate serde_json;
extern crate serde_test;
use bincode::Infinite;
use serde::de::{self, Deserialize, Deserializer, MapAccess, SeqAccess, Visitor};
use serde::ser::{Serialize, SerializeStruct, Serializer};
use std::fmt;
#[derive(Debug, PartialEq)]
struct Data {
a: i32,
b: i32,
}
impl Serialize for Data {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("Data", 2)?;
state.serialize_field("a", &self.a)?;
state.serialize_field("b", &self.b)?;
state.end()
}
}
impl<'de> Deserialize<'de> for Data {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
enum Field {
A,
B,
};
impl<'de> Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
where
D: Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("`a` or `b`")
}
fn visit_str<E>(self, value: &str) -> Result<Field, E>
where
E: de::Error,
{
match value {
"a" => Ok(Field::A),
"b" => Ok(Field::B),
_ => Err(de::Error::unknown_field(value, FIELDS)),
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
struct DataVisitor;
impl<'de> Visitor<'de> for DataVisitor {
type Value = Data;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("struct Data")
}
fn visit_seq<V>(self, mut seq: V) -> Result<Data, V::Error>
where
V: SeqAccess<'de>,
{
let a = seq.next_element()?
.ok_or_else(|| de::Error::invalid_length(0, &self))?;
let b = seq.next_element()?
.ok_or_else(|| de::Error::invalid_length(1, &self))?;
Ok(Data { a, b })
}
fn visit_map<V>(self, mut map: V) -> Result<Data, V::Error>
where
V: MapAccess<'de>,
{
let mut a = None;
let mut b = None;
while let Some(key) = map.next_key()? {
match key {
Field::A => {
if a.is_some() {
return Err(de::Error::duplicate_field("a"));
}
a = Some(map.next_value()?);
}
Field::B => {
if b.is_some() {
return Err(de::Error::duplicate_field("b"));
}
b = Some(map.next_value()?);
}
}
}
let a = a.ok_or_else(|| de::Error::missing_field("a"))?;
let b = b.ok_or_else(|| de::Error::missing_field("b"))?;
Ok(Data { a, b })
}
}
const FIELDS: &'static [&'static str] = &["a", "b"];
// error in code, BAD_FIELDS has a missing field
const BAD_FIELDS: &'static [&'static str] = &["a"];
deserializer.deserialize_struct("Data", BAD_FIELDS, DataVisitor)
}
}
fn check_test() {
use serde_test::{self, Token};
let data = Data { a: 1, b: 2 };
serde_test::assert_tokens(
&data,
&[
Token::Struct {
name: "Data",
len: 2,
},
Token::Str("a"),
Token::I32(1),
Token::Str("b"),
Token::I32(2),
Token::StructEnd,
],
);
}
fn check_json() {
let data = Data { a: 1, b: 2 };
let serialized = serde_json::to_string(&data).unwrap();
let deserialized: Data = serde_json::from_str(&serialized).unwrap();
assert_eq!(data, deserialized);
}
fn check_bincode() {
let data = Data { a: 1, b: 2 };
let serialized = bincode::serialize(&data, Infinite).unwrap();
let deserialized: Data = bincode::deserialize(&serialized).unwrap();
assert_eq!(data, deserialized);
}
fn main() {
check_test();
println!("serde_test check passed");
check_json();
println!("serde_json check passed");
check_bincode();
println!("bincode check fails, this is not printed");
}
dtolnay commented
Seems like a bug in serde_test. I released 1.0.20 with a fix.
expected Token::Struct { name: "Data", len: 2 }
but deserialization wants Token::Struct { name: "Data", len: 1 }