extern crate serde;
extern crate serde_bytes;
#[macro_use]
extern crate serde_derive;
extern crate zlo;
use std::fmt::Debug;
use std::collections::HashMap;
use std::borrow::Cow;
use zlo::{Infinite, Bounded};
use zlo::{serialized_size, Error, Result};
use zlo::{serialize, deserialize, deserialize_from};
fn the_same<V>(element: V)
where V: serde::Serialize+serde::de::DeserializeOwned+PartialEq+Debug+'static
{
let encoded = serialize(&element, Infinite).unwrap();
let decoded = deserialize(&encoded[..]).unwrap();
assert_eq!(element, decoded);
}
#[test]
fn test_numbers() {
the_same(5u8);
the_same(5u16);
the_same(5u32);
the_same(5u64);
the_same(5usize);
the_same(5i8);
the_same(5i16);
the_same(5i32);
the_same(5i64);
the_same(5isize);
the_same(-5i8);
the_same(-5i16);
the_same(-5i32);
the_same(-5i64);
the_same(-5isize);
the_same(-100f32);
the_same(0f32);
the_same(5f32);
the_same(-100f64);
the_same(5f64);
}
#[test]
fn test_string() {
the_same("".to_string());
the_same("a".to_string());
}
#[test]
fn test_tuple() {
the_same((1isize,));
the_same((1isize, 2isize, 3isize));
the_same((1isize, "foo".to_string(), ()));
}
#[test]
fn test_basic_struct() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Easy {
x: isize,
s: String,
y: usize
}
the_same(Easy{x: -4, s: "foo".to_string(), y: 10});
}
#[test]
fn test_nested_struct() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Easy {
x: isize,
s: String,
y: usize
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Nest {
f: Easy,
b: usize,
s: Easy
}
the_same(Nest {
f: Easy {x: -1, s: "foo".to_string(), y: 20},
b: 100,
s: Easy {x: -100, s: "bar".to_string(), y: 20}
});
}
#[test]
fn test_struct_newtype() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct NewtypeStr(usize);
the_same(NewtypeStr(5));
}
#[test]
fn test_struct_tuple() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct TubStr(usize, String, f32);
the_same(TubStr(5, "hello".to_string(), 3.2));
}
#[test]
fn test_option() {
the_same(Some(5usize));
the_same(Some("foo bar".to_string()));
the_same(None::<usize>);
}
#[test]
fn test_enum() {
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum TestEnum {
NoArg,
OneArg(usize),
Args(usize, usize),
AnotherNoArg,
StructLike{x: usize, y: f32}
}
the_same(TestEnum::NoArg);
the_same(TestEnum::OneArg(4));
the_same(TestEnum::Args(4, 5));
the_same(TestEnum::AnotherNoArg);
the_same(TestEnum::StructLike{x: 4, y: 3.14159});
the_same([TestEnum::NoArg, TestEnum::OneArg(5), TestEnum::AnotherNoArg,
TestEnum::StructLike{x: 4, y:1.4}]);
}
#[test]
fn test_vec() {
let v: Vec<u8> = vec![];
the_same(v);
the_same(vec![1u64]);
the_same(vec![1u64,2,3,4,5,6]);
}
#[test]
fn test_map() {
let mut m = HashMap::new();
m.insert(4u64, "foo".to_string());
m.insert(0u64, "bar".to_string());
the_same(m);
}
#[test]
fn test_bool() {
the_same(true);
the_same(false);
}
#[test]
fn test_unicode() {
the_same("Ã¥".to_string());
the_same("aåååååååa".to_string());
}
#[test]
fn test_fixed_size_array() {
the_same([24u32; 32]);
the_same([1u64, 2, 3, 4, 5, 6, 7, 8]);
the_same([0u8; 19]);
}
#[test]
fn deserializing_errors() {
fn isize_invalid_deserialize<T: Debug>(res: Result<T>) {
match res {
Err(Error::InvalidEncoding{..}) => {},
Err(Error::Custom(ref s)) if s.contains("invalid encoding") => {},
Err(Error::Custom(ref s)) if s.contains("invalid value") => {},
other => panic!("Expecting InvalidEncoding, got {:?}", other),
}
}
isize_invalid_deserialize(deserialize::<String>(&[3, 0, 0xff, 0xff, 0xff, 0xff]));
#[derive(Serialize, Deserialize, Debug)]
enum Test {
One,
Two,
};
isize_invalid_deserialize(deserialize::<Test>(&[0xff; 5]));
}
#[test]
fn char_serialization() {
let chars = "Aa\0☺♪";
for c in chars.chars() {
let encoded = serialize(&c, Bounded::new_bytes(4)).expect("serializing char failed");
let decoded: char = deserialize(&encoded).expect("deserializing failed");
assert_eq!(decoded, c);
}
}
#[test]
fn too_big_char_deserialize() {
let serialized = [0x41];
let deserialized: Result<char> = deserialize_from(&mut &serialized[..], Bounded::new_bytes(1));
assert!(deserialized.is_ok());
assert_eq!(deserialized.unwrap(), 'A');
}
#[test]
fn too_big_serialize() {
assert!(serialize(&1u32, Bounded::new_bytes(1)).is_err());
assert!(serialize(&2u32, Bounded::new_bytes(2)).is_ok());
assert!(serialize(&"abcde", Bounded::new_bytes(2 + 4)).is_err());
assert!(serialize(&"abcde", Bounded::new_bytes(2 + 5)).is_ok());
}
#[test]
fn test_proxy_encoded_size() {
assert_eq!(1, serialized_size(&0u8));
assert_eq!(1, serialized_size(&0u16));
assert_eq!(1, serialized_size(&0u32));
assert_eq!(1, serialized_size(&0u64));
assert_eq!(9, serialized_size(&1u8));
assert_eq!(10, serialized_size(&1u16));
assert_eq!(10, serialized_size(&1u32));
assert_eq!(10, serialized_size(&1u64));
assert_eq!(1 * 9, serialized_size(&0xffu8));
assert_eq!(2 * 9, serialized_size(&0xffffu16));
assert_eq!(4 * 9, serialized_size(&0xffffffffu32));
assert_eq!(8 * 9, serialized_size(&0xffffffffffffffffu64));
assert_eq!(1, serialized_size(&""));
assert_eq!(10 + 8, serialized_size(&"a"));
assert_eq!(10 * 2 + 1, serialized_size(&[0u32, 1u32, 2u32]));
}
#[test]
fn test_size_predictions() {
macro_rules! assert_8 {
($a:expr, $b:expr) => {
assert_eq!($a, ($b + 7) / 8)
}
}
assert_8!(serialize(&0u8, Infinite).unwrap().len() as u64, serialized_size(&0u8));
assert_8!(serialize(&0u16, Infinite).unwrap().len() as u64, serialized_size(&0u16));
assert_8!(serialize(&0u32, Infinite).unwrap().len() as u64, serialized_size(&0u32));
assert_8!(serialize(&0u64, Infinite).unwrap().len() as u64, serialized_size(&0u64));
assert_8!(serialize(&1u8, Infinite).unwrap().len() as u64, serialized_size(&1u8));
assert_8!(serialize(&1u16, Infinite).unwrap().len() as u64, serialized_size(&1u16));
assert_8!(serialize(&1u32, Infinite).unwrap().len() as u64, serialized_size(&1u32));
assert_8!(serialize(&1u64, Infinite).unwrap().len() as u64, serialized_size(&1u64));
assert_8!(serialize(&0xffu8, Infinite).unwrap().len() as u64,
serialized_size(&0xffu8));
assert_8!(serialize(&0xffffu16, Infinite).unwrap().len() as u64,
serialized_size(&0xffffu16));
assert_8!(serialize(&0xffffffffu32, Infinite).unwrap().len() as u64,
serialized_size(&0xffffffffu32));
assert_8!(serialize(&0xffffffffffffffffu64, Infinite).unwrap().len() as u64,
serialized_size(&0xffffffffffffffffu64));
assert_8!(serialize(&"", Infinite).unwrap().len() as u64,
serialized_size(&""));
assert_8!(serialize(&"a", Infinite).unwrap().len() as u64,
serialized_size(&"a"));
assert_8!(serialize(&[0u32, 1u32, 2u32], Infinite).unwrap().len() as u64,
serialized_size(&[0u32, 1u32, 2u32]));
}
#[test]
fn encode_box() {
the_same(Box::new(5));
}
#[test]
fn test_cow_serialize() {
let large_object = vec![1u32,2,3,4,5,6];
let mut large_map = HashMap::new();
large_map.insert(1, 2);
#[derive(Serialize, Deserialize, Debug)]
enum Message<'a> {
M1(Cow<'a, Vec<u32>>),
M2(Cow<'a, HashMap<u32, u32>>)
}
{
let serialized = serialize(&Message::M1(Cow::Borrowed(&large_object)), Infinite).unwrap();
let deserialized: Message<'static> = deserialize_from(&mut &serialized[..], Infinite).unwrap();
match deserialized {
Message::M1(b) => assert_eq!(&b.into_owned(), &large_object),
_ => assert!(false)
}
}
{
let serialized = serialize(&Message::M2(Cow::Borrowed(&large_map)), Infinite).unwrap();
let deserialized: Message<'static> = deserialize_from(&mut &serialized[..], Infinite).unwrap();
match deserialized {
Message::M2(b) => assert_eq!(&b.into_owned(), &large_map),
_ => assert!(false)
}
}
}
#[test]
fn test_strbox_serialize() {
let strx: &'static str = "hello world";
let serialized = serialize(&Cow::Borrowed(strx), Infinite).unwrap();
let deserialized: Cow<'static, String> = deserialize_from(&mut &serialized[..], Infinite).unwrap();
let stringx: String = deserialized.into_owned();
assert!(strx == &stringx[..]);
}
#[test]
fn test_slicebox_serialize() {
let slice = [1u32, 2, 3 ,4, 5];
let serialized = serialize(&Cow::Borrowed(&slice[..]), Infinite).unwrap();
println!("{:?}", serialized);
let deserialized: Cow<'static, Vec<u32>> = deserialize_from(&mut &serialized[..], Infinite).unwrap();
{
let sb: &[u32] = &deserialized;
assert!(slice == sb);
}
let vecx: Vec<u32> = deserialized.into_owned();
assert!(slice == &vecx[..]);
}
#[test]
fn test_multi_strings_serialize() {
assert!(serialize(&("foo", "bar", "baz"), Infinite).is_ok());
}
#[test]
fn test_oom_protection() {
use std::io::Cursor;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct FakeVec {
len: u64,
byte: u8
}
let x = serialize(&FakeVec { len: 0xffffffffffffffffu64, byte: 1 }, Bounded::new_bytes(11)).unwrap();
let y: Result<Vec<u8>> = deserialize_from(&mut Cursor::new(&x[..]), Bounded::new_bytes(11));
assert!(y.is_err());
}
#[test]
fn path_buf() {
use std::path::{Path, PathBuf};
let path = Path::new("foo").to_path_buf();
let serde_encoded = serialize(&path, Infinite).unwrap();
let decoded: PathBuf = deserialize(&serde_encoded).unwrap();
assert!(path.to_str() == decoded.to_str());
}
#[test]
fn serde_bytes() {
use serde_bytes::ByteBuf;
the_same(ByteBuf::from(vec![1,2,3,4,5]));
}
#[test]
#[ignore]
fn fuzzer_f32() {
let mut buf = vec![];
for exp in 0 .. 0xff {
for frac in (0 .. 0xffff).flat_map(|x| (0 .. 0xf).map(move |y| (x << 7) | y)) {
assert_eq!(frac >> 23, 0);
buf.clear();
let bits = 0x80000000 | (exp << 23) | frac;
let x = f32::from_bits(bits);
zlo::serialize_into(&mut buf, &x, Infinite).unwrap();
let a: f32 = zlo::deserialize(&buf).unwrap();
assert_eq!(x.to_bits(), a.to_bits());
}
println!("fuzzer_f32\t{}", exp * 100 / 0xff);
}
}
#[test]
#[ignore]
fn fuzzer_f64() {
let mut buf = vec![];
for exp in 0 .. 0x800_u64 {
for frac in (0 .. 0xff)
.map(|x| x << 44)
.flat_map(|x| (0 .. 0xf).map(move |y| x | y))
{
assert_eq!(frac >> 52, 0);
buf.clear();
let bits = 0x8000000000000000 | (exp << 52) | frac;
let x = f64::from_bits(bits);
zlo::serialize_into(&mut buf, &x, Infinite).unwrap();
let a: f64 = zlo::deserialize(&buf).unwrap();
assert_eq!(x.to_bits(), a.to_bits());
}
println!("fuzzer_f64\t{}", exp * 100 / 0x800);
}
}