serde-rs/test

serde_test does not catch error in fields passed to deserialize_struct

tspiteri opened this issue · 1 comments

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");
}

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 }