diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/rust/serde_cbor/tests | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/serde_cbor/tests')
-rw-r--r-- | third_party/rust/serde_cbor/tests/bennofs.rs | 60 | ||||
-rw-r--r-- | third_party/rust/serde_cbor/tests/canonical.rs | 104 | ||||
-rw-r--r-- | third_party/rust/serde_cbor/tests/crash.cbor | bin | 0 -> 190 bytes | |||
-rw-r--r-- | third_party/rust/serde_cbor/tests/de.rs | 747 | ||||
-rw-r--r-- | third_party/rust/serde_cbor/tests/enum.rs | 236 | ||||
-rw-r--r-- | third_party/rust/serde_cbor/tests/kietaub.cbor | bin | 0 -> 212 bytes | |||
-rw-r--r-- | third_party/rust/serde_cbor/tests/ser.rs | 254 | ||||
-rw-r--r-- | third_party/rust/serde_cbor/tests/std_types.rs | 186 | ||||
-rw-r--r-- | third_party/rust/serde_cbor/tests/tags.rs | 48 | ||||
-rw-r--r-- | third_party/rust/serde_cbor/tests/value.rs | 100 |
10 files changed, 1735 insertions, 0 deletions
diff --git a/third_party/rust/serde_cbor/tests/bennofs.rs b/third_party/rust/serde_cbor/tests/bennofs.rs new file mode 100644 index 0000000000..1b289f40d4 --- /dev/null +++ b/third_party/rust/serde_cbor/tests/bennofs.rs @@ -0,0 +1,60 @@ +#[macro_use] +extern crate serde_derive; + +use serde::Serialize; +use serde_cbor::ser::SliceWrite; +use serde_cbor::{self, Serializer}; + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +struct Example { + foo: Foo, + payload: u8, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +struct Foo { + x: u8, + color: Color, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +enum Color { + Red, + Blue, + Yellow(u8), +} + +const EXAMPLE: Example = Example { + foo: Foo { + x: 0xAA, + color: Color::Yellow(40), + }, + payload: 0xCC, +}; + +#[cfg(feature = "std")] +mod std_tests { + use super::*; + + #[test] + fn test() { + let serialized = serde_cbor::ser::to_vec_packed(&EXAMPLE).expect("bennofs 1"); + println!("{:?}", serialized); + let deserialized: Example = serde_cbor::from_slice(&serialized).expect("bennofs 2"); + assert_eq!(EXAMPLE, deserialized); + } +} + +#[test] +fn test() { + let mut slice = [0u8; 64]; + let writer = SliceWrite::new(&mut slice); + let mut serializer = Serializer::new(writer).packed_format(); + EXAMPLE.serialize(&mut serializer).unwrap(); + let writer = serializer.into_inner(); + let end = writer.bytes_written(); + let slice = writer.into_inner(); + let deserialized: Example = + serde_cbor::de::from_slice_with_scratch(&slice[..end], &mut []).unwrap(); + assert_eq!(EXAMPLE, deserialized); +} diff --git a/third_party/rust/serde_cbor/tests/canonical.rs b/third_party/rust/serde_cbor/tests/canonical.rs new file mode 100644 index 0000000000..438e29e7d4 --- /dev/null +++ b/third_party/rust/serde_cbor/tests/canonical.rs @@ -0,0 +1,104 @@ +#[cfg(feature = "std")] +mod std_tests { + use serde_cbor::value::Value; + + #[test] + fn integer_canonical_sort_order() { + let expected = [ + 0, + 23, + 24, + 255, + 256, + 65535, + 65536, + 4294967295, + -1, + -24, + -25, + -256, + -257, + -65536, + -65537, + -4294967296, + ] + .iter() + .map(|i| Value::Integer(*i)) + .collect::<Vec<_>>(); + + let mut sorted = expected.clone(); + sorted.sort(); + + assert_eq!(expected, sorted); + } + + #[test] + fn string_canonical_sort_order() { + let expected = ["", "a", "b", "aa"] + .iter() + .map(|s| Value::Text(s.to_string())) + .collect::<Vec<_>>(); + + let mut sorted = expected.clone(); + sorted.sort(); + + assert_eq!(expected, sorted); + } + + #[test] + fn bytes_canonical_sort_order() { + let expected = vec![vec![], vec![0u8], vec![1u8], vec![0u8, 0u8]] + .into_iter() + .map(|v| Value::Bytes(v)) + .collect::<Vec<_>>(); + + let mut sorted = expected.clone(); + sorted.sort(); + + assert_eq!(expected, sorted); + } + + #[test] + fn simple_data_canonical_sort_order() { + let expected = vec![Value::Bool(false), Value::Bool(true), Value::Null]; + + let mut sorted = expected.clone(); + sorted.sort(); + + assert_eq!(expected, sorted); + } + + #[test] + fn major_type_canonical_sort_order() { + let expected = vec![ + Value::Integer(0), + Value::Integer(-1), + Value::Bytes(vec![]), + Value::Text("".to_string()), + Value::Null, + ]; + + let mut sorted = expected.clone(); + sorted.sort(); + + assert_eq!(expected, sorted); + } + + #[test] + fn test_rfc_example() { + // See: https://tools.ietf.org/html/draft-ietf-cbor-7049bis-04#section-4.10 + let expected = vec![ + Value::Integer(10), + Value::Integer(100), + Value::Integer(-1), + Value::Text("z".to_owned()), + Value::Text("aa".to_owned()), + Value::Array(vec![Value::Integer(100)]), + Value::Array(vec![Value::Integer(-1)]), + Value::Bool(false), + ]; + let mut sorted = expected.clone(); + sorted.sort(); + assert_eq!(expected, sorted); + } +} diff --git a/third_party/rust/serde_cbor/tests/crash.cbor b/third_party/rust/serde_cbor/tests/crash.cbor Binary files differnew file mode 100644 index 0000000000..a3bc785ca3 --- /dev/null +++ b/third_party/rust/serde_cbor/tests/crash.cbor diff --git a/third_party/rust/serde_cbor/tests/de.rs b/third_party/rust/serde_cbor/tests/de.rs new file mode 100644 index 0000000000..01d7914502 --- /dev/null +++ b/third_party/rust/serde_cbor/tests/de.rs @@ -0,0 +1,747 @@ +#[macro_use] +extern crate serde_derive; + +use serde_cbor; +use serde_cbor::de; + +#[test] +fn test_str() { + let s: &str = + de::from_slice_with_scratch(&[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72], &mut []).unwrap(); + assert_eq!(s, "foobar"); +} + +#[test] +fn test_bytes() { + let s: &[u8] = + de::from_slice_with_scratch(&[0x46, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72], &mut []).unwrap(); + assert_eq!(s, b"foobar"); +} + +#[test] +fn test_int() { + let num: i64 = de::from_slice_with_scratch(&[0x39, 0x07, 0xde], &mut []).unwrap(); + assert_eq!(num, -2015); +} + +#[test] +fn test_float() { + let float: f64 = de::from_slice_with_scratch(b"\xfa\x47\xc3\x50\x00", &mut []).unwrap(); + assert_eq!(float, 100000.0); +} + +#[test] +fn test_indefinite_object() { + #[derive(Debug, Deserialize, PartialEq)] + struct Foo { + a: u64, + b: [u64; 2], + } + let expected = Foo { a: 1, b: [2, 3] }; + let actual: Foo = + de::from_slice_with_scratch(b"\xbfaa\x01ab\x9f\x02\x03\xff\xff", &mut []).unwrap(); + assert_eq!(expected, actual); +} + +#[cfg(feature = "std")] +mod std_tests { + use std::collections::BTreeMap; + + use serde::de as serde_de; + use serde_cbor::value::Value; + use serde_cbor::{de, error, to_vec, Deserializer}; + + #[test] + fn test_string1() { + let value: error::Result<Value> = + de::from_slice(&[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]); + assert_eq!(value.unwrap(), Value::Text("foobar".to_owned())); + } + + #[test] + fn test_string2() { + let value: error::Result<Value> = de::from_slice(&[ + 0x71, 0x49, 0x20, 0x6d, 0x65, 0x74, 0x20, 0x61, 0x20, 0x74, 0x72, 0x61, 0x76, 0x65, + 0x6c, 0x6c, 0x65, 0x72, + ]); + assert_eq!(value.unwrap(), Value::Text("I met a traveller".to_owned())); + } + + #[test] + fn test_string3() { + let slice = b"\x78\x2fI met a traveller from an antique land who said"; + let value: error::Result<Value> = de::from_slice(slice); + assert_eq!( + value.unwrap(), + Value::Text("I met a traveller from an antique land who said".to_owned()) + ); + } + + #[test] + fn test_byte_string() { + let value: error::Result<Value> = + de::from_slice(&[0x46, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]); + assert_eq!(value.unwrap(), Value::Bytes(b"foobar".to_vec())); + } + + #[test] + fn test_numbers1() { + let value: error::Result<Value> = de::from_slice(&[0x00]); + assert_eq!(value.unwrap(), Value::Integer(0)); + } + + #[test] + fn test_numbers2() { + let value: error::Result<Value> = de::from_slice(&[0x1a, 0x00, 0xbc, 0x61, 0x4e]); + assert_eq!(value.unwrap(), Value::Integer(12345678)); + } + + #[test] + fn test_numbers3() { + let value: error::Result<Value> = de::from_slice(&[0x39, 0x07, 0xde]); + assert_eq!(value.unwrap(), Value::Integer(-2015)); + } + + #[test] + fn test_bool() { + let value: error::Result<Value> = de::from_slice(b"\xf4"); + assert_eq!(value.unwrap(), Value::Bool(false)); + } + + #[test] + fn test_trailing_bytes() { + let value: error::Result<Value> = de::from_slice(b"\xf4trailing"); + assert!(value.is_err()); + } + + #[test] + fn test_list1() { + let value: error::Result<Value> = de::from_slice(b"\x83\x01\x02\x03"); + assert_eq!( + value.unwrap(), + Value::Array(vec![ + Value::Integer(1), + Value::Integer(2), + Value::Integer(3) + ]) + ); + } + + #[test] + fn test_list2() { + let value: error::Result<Value> = de::from_slice(b"\x82\x01\x82\x02\x81\x03"); + assert_eq!( + value.unwrap(), + Value::Array(vec![ + Value::Integer(1), + Value::Array(vec![ + Value::Integer(2), + Value::Array(vec![Value::Integer(3)]) + ]) + ]) + ); + } + + #[test] + fn test_object() { + let value: error::Result<Value> = de::from_slice(b"\xa5aaaAabaBacaCadaDaeaE"); + let mut object = BTreeMap::new(); + object.insert(Value::Text("a".to_owned()), Value::Text("A".to_owned())); + object.insert(Value::Text("b".to_owned()), Value::Text("B".to_owned())); + object.insert(Value::Text("c".to_owned()), Value::Text("C".to_owned())); + object.insert(Value::Text("d".to_owned()), Value::Text("D".to_owned())); + object.insert(Value::Text("e".to_owned()), Value::Text("E".to_owned())); + assert_eq!(value.unwrap(), Value::Map(object)); + } + + #[test] + fn test_indefinite_object() { + let value: error::Result<Value> = de::from_slice(b"\xbfaa\x01ab\x9f\x02\x03\xff\xff"); + let mut object = BTreeMap::new(); + object.insert(Value::Text("a".to_owned()), Value::Integer(1)); + object.insert( + Value::Text("b".to_owned()), + Value::Array(vec![Value::Integer(2), Value::Integer(3)]), + ); + assert_eq!(value.unwrap(), Value::Map(object)); + } + + #[test] + fn test_indefinite_list() { + let value: error::Result<Value> = de::from_slice(b"\x9f\x01\x02\x03\xff"); + assert_eq!( + value.unwrap(), + Value::Array(vec![ + Value::Integer(1), + Value::Integer(2), + Value::Integer(3) + ]) + ); + } + + #[test] + fn test_indefinite_string() { + let value: error::Result<Value> = + de::from_slice(b"\x7f\x65Mary \x64Had \x62a \x67Little \x60\x64Lamb\xff"); + assert_eq!( + value.unwrap(), + Value::Text("Mary Had a Little Lamb".to_owned()) + ); + } + + #[test] + fn test_indefinite_byte_string() { + let value: error::Result<Value> = de::from_slice(b"\x5f\x42\x01\x23\x42\x45\x67\xff"); + assert_eq!(value.unwrap(), Value::Bytes(b"\x01#Eg".to_vec())); + } + + #[test] + fn test_multiple_indefinite_strings() { + let input = b"\x82\x7f\x65Mary \x64Had \x62a \x67Little \x60\x64Lamb\xff\x5f\x42\x01\x23\x42\x45\x67\xff"; + _test_multiple_indefinite_strings(de::from_slice(input)); + _test_multiple_indefinite_strings(de::from_mut_slice(input.to_vec().as_mut())); + let mut buf = [0u8; 64]; + _test_multiple_indefinite_strings(de::from_slice_with_scratch(input, &mut buf)); + } + fn _test_multiple_indefinite_strings(value: error::Result<Value>) { + // This assures that buffer rewinding in infinite buffers works as intended. + assert_eq!( + value.unwrap(), + Value::Array(vec![ + Value::Text("Mary Had a Little Lamb".to_owned()), + Value::Bytes(b"\x01#Eg".to_vec()) + ]) + ); + } + + #[test] + fn test_float() { + let value: error::Result<Value> = de::from_slice(b"\xfa\x47\xc3\x50\x00"); + assert_eq!(value.unwrap(), Value::Float(100000.0)); + } + + #[test] + fn test_self_describing() { + let value: error::Result<Value> = + de::from_slice(&[0xd9, 0xd9, 0xf7, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]); + let expected = Value::Text("foobar".to_owned()); + let strip_tags = |x: Value| { + if let Value::Tag(_, inner) = x { + *inner + } else { + x + } + }; + assert_eq!(strip_tags(value.unwrap()), expected); + } + + #[test] + fn test_f16() { + let mut x: Value = de::from_slice(&[0xf9, 0x41, 0x00]).unwrap(); + assert_eq!(x, Value::Float(2.5)); + x = de::from_slice(&[0xf9, 0x41, 0x90]).unwrap(); + assert_eq!(x, Value::Float(2.78125)); + x = de::from_slice(&[0xf9, 0x50, 0x90]).unwrap(); + assert_eq!(x, Value::Float(36.5)); + x = de::from_slice(&[0xf9, 0xd0, 0x90]).unwrap(); + assert_eq!(x, Value::Float(-36.5)); + } + + #[test] + fn test_crazy_list() { + let slice = b"\x88\x1b\x00\x00\x00\x1c\xbe\x99\x1d\xc7\x3b\x00\x7a\xcf\x51\xdc\x51\x70\xdb\x3a\x1b\x3a\x06\xdd\xf5\xf6\xf7\xfb\x41\x76\x5e\xb1\xf8\x00\x00\x00\xf9\x7c\x00"; + let value: Vec<Value> = de::from_slice(slice).unwrap(); + assert_eq!( + value, + vec![ + Value::Integer(123456789959), + Value::Integer(-34567897654325468), + Value::Integer(-456787678), + Value::Bool(true), + Value::Null, + Value::Null, + Value::Float(23456543.5), + Value::Float(::std::f64::INFINITY) + ] + ); + } + + #[test] + fn test_nan() { + let value: f64 = de::from_slice(b"\xf9\x7e\x00").unwrap(); + assert!(value.is_nan()); + } + + #[test] + fn test_32f16() { + let value: f32 = de::from_slice(b"\xf9\x50\x00").unwrap(); + assert_eq!(value, 32.0f32); + } + + #[test] + // The file was reported as not working by user kie0tauB + // but it parses to a cbor value. + fn test_kietaub_file() { + let file = include_bytes!("kietaub.cbor"); + let value_result: error::Result<Value> = de::from_slice(file); + value_result.unwrap(); + } + + #[test] + fn test_option_roundtrip() { + let obj1 = Some(10u32); + + let v = to_vec(&obj1).unwrap(); + let obj2: Result<Option<u32>, _> = serde_cbor::de::from_reader(&v[..]); + println!("{:?}", obj2); + + assert_eq!(obj1, obj2.unwrap()); + } + + #[test] + fn test_option_none_roundtrip() { + let obj1 = None; + + let v = to_vec(&obj1).unwrap(); + println!("{:?}", v); + let obj2: Result<Option<u32>, _> = serde_cbor::de::from_reader(&v[..]); + + assert_eq!(obj1, obj2.unwrap()); + } + + #[test] + fn test_variable_length_map() { + let slice = b"\xbf\x67\x6d\x65\x73\x73\x61\x67\x65\x64\x70\x6f\x6e\x67\xff"; + let value: Value = de::from_slice(slice).unwrap(); + let mut map = BTreeMap::new(); + map.insert( + Value::Text("message".to_string()), + Value::Text("pong".to_string()), + ); + assert_eq!(value, Value::Map(map)) + } + + #[test] + fn test_object_determinism_roundtrip() { + let expected = b"\xa2aa\x01ab\x82\x02\x03"; + + // 0.1% chance of not catching failure + for _ in 0..10 { + assert_eq!( + &to_vec(&de::from_slice::<Value>(expected).unwrap()).unwrap(), + expected + ); + } + } + + #[test] + fn stream_deserializer() { + let slice = b"\x01\x66foobar"; + let mut it = Deserializer::from_slice(slice).into_iter::<Value>(); + assert_eq!(Value::Integer(1), it.next().unwrap().unwrap()); + assert_eq!( + Value::Text("foobar".to_string()), + it.next().unwrap().unwrap() + ); + assert!(it.next().is_none()); + } + + #[test] + fn stream_deserializer_eof() { + let slice = b"\x01\x66foob"; + let mut it = Deserializer::from_slice(slice).into_iter::<Value>(); + assert_eq!(Value::Integer(1), it.next().unwrap().unwrap()); + assert!(it.next().unwrap().unwrap_err().is_eof()); + } + + #[test] + fn stream_deserializer_eof_in_indefinite() { + let slice = b"\x7f\x65Mary \x64Had \x62a \x60\x67Little \x60\x64Lamb\xff"; + let indices: &[usize] = &[ + 2, // announcement but no data + 10, // mid-buffer EOF + 12, // neither new element nor end marker + ]; + for end_of_slice in indices { + let mut it = Deserializer::from_slice(&slice[..*end_of_slice]).into_iter::<Value>(); + assert!(it.next().unwrap().unwrap_err().is_eof()); + + let mut mutcopy = slice[..*end_of_slice].to_vec(); + let mut it = Deserializer::from_mut_slice(mutcopy.as_mut()).into_iter::<Value>(); + assert!(it.next().unwrap().unwrap_err().is_eof()); + + let mut buf = [0u8; 64]; + let mut it = Deserializer::from_slice_with_scratch(&slice[..*end_of_slice], &mut buf) + .into_iter::<Value>(); + assert!(it.next().unwrap().unwrap_err().is_eof()); + } + } + + #[test] + fn crash() { + let file = include_bytes!("crash.cbor"); + let value_result: error::Result<Value> = de::from_slice(file); + assert_eq!( + value_result.unwrap_err().classify(), + serde_cbor::error::Category::Syntax + ); + } + + fn from_slice_stream<'a, T>(slice: &'a [u8]) -> error::Result<(&'a [u8], T)> + where + T: serde_de::Deserialize<'a>, + { + let mut deserializer = Deserializer::from_slice(slice); + let value = serde_de::Deserialize::deserialize(&mut deserializer)?; + let rest = &slice[deserializer.byte_offset()..]; + + Ok((rest, value)) + } + + #[test] + fn test_slice_offset() { + let v: Vec<u8> = vec![ + 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, + ]; + let (rest, value): (&[u8], String) = from_slice_stream(&v[..]).unwrap(); + assert_eq!(value, "foobar"); + assert_eq!(rest, &[0x66, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72]); + let (rest, value): (&[u8], String) = from_slice_stream(rest).unwrap(); + assert_eq!(value, "foobar"); + assert_eq!(rest, &[]); + } + + #[derive(Debug, Copy, Clone)] + struct Options { + standard: bool, + legacy: bool, + packed: bool, + named: bool, + } + + impl Default for Options { + fn default() -> Self { + Options { + standard: true, + legacy: true, + packed: true, + named: true, + } + } + } + + impl Options { + fn no_standard(self) -> Self { + Options { + standard: false, + ..self + } + } + + fn no_legacy(self) -> Self { + Options { + legacy: false, + ..self + } + } + + fn no_packed(self) -> Self { + Options { + packed: false, + ..self + } + } + + fn no_named(self) -> Self { + Options { + named: false, + ..self + } + } + } + + fn from_slice_stream_options<'a, T>( + slice: &'a [u8], + options: Options, + ) -> error::Result<(&'a [u8], T)> + where + T: serde_de::Deserialize<'a>, + { + let deserializer = Deserializer::from_slice(slice); + let deserializer = if !options.packed { + deserializer.disable_packed_format() + } else { + deserializer + }; + let deserializer = if !options.named { + deserializer.disable_named_format() + } else { + deserializer + }; + let deserializer = if !options.standard { + deserializer.disable_standard_enums() + } else { + deserializer + }; + let mut deserializer = if !options.legacy { + deserializer.disable_legacy_enums() + } else { + deserializer + }; + let value = serde_de::Deserialize::deserialize(&mut deserializer)?; + let rest = &slice[deserializer.byte_offset()..]; + + Ok((rest, value)) + } + + #[test] + fn test_deserializer_enums() { + #[derive(Debug, PartialEq, Deserialize)] + enum Enum { + Unit, + NewType(i32), + Tuple(String, bool), + Struct { x: i32, y: i32 }, + } + + // This is the format used in serde >= 0.10 + // + // Serialization of Enum::NewType(10) + let v: Vec<u8> = vec![ + 0xa1, // map 1pair + 0x67, 0x4e, 0x65, 0x77, 0x54, 0x79, 0x70, 0x65, // utf8 string: NewType + 0x1a, // u32 + 0x00, 0x00, 0x00, 0x0a, // 10 (dec) + ]; + let (_rest, value): (&[u8], Enum) = from_slice_stream(&v[..]).unwrap(); + assert_eq!(value, Enum::NewType(10)); + let (_rest, value): (&[u8], Enum) = + from_slice_stream_options(&v[..], Options::default().no_legacy()).unwrap(); + assert_eq!(value, Enum::NewType(10)); + let value: error::Result<(&[u8], Enum)> = + from_slice_stream_options(&v[..], Options::default().no_standard()); + assert_eq!( + value.unwrap_err().classify(), + serde_cbor::error::Category::Syntax + ); + let value: error::Result<(&[u8], Enum)> = + from_slice_stream_options(&v[..], Options::default().no_standard().no_legacy()); + assert_eq!( + value.unwrap_err().classify(), + serde_cbor::error::Category::Syntax + ); + // Serialization of Enum::Unit + let v: Vec<u8> = vec![ + 0x64, 0x55, 0x6e, 0x69, 0x74, // utf8 string: Unit + ]; + let (_rest, value): (&[u8], Enum) = from_slice_stream(&v[..]).unwrap(); + assert_eq!(value, Enum::Unit); + let (_rest, value): (&[u8], Enum) = + from_slice_stream_options(&v[..], Options::default().no_legacy()).unwrap(); + assert_eq!(value, Enum::Unit); + let (_rest, value): (&[u8], Enum) = + from_slice_stream_options(&v[..], Options::default().no_standard()).unwrap(); + assert_eq!(value, Enum::Unit); + let value: error::Result<(&[u8], Enum)> = + from_slice_stream_options(&v[..], Options::default().no_legacy().no_standard()); + assert_eq!( + value.unwrap_err().classify(), + serde_cbor::error::Category::Syntax + ); + + // This is the format used in serde <= 0.9 + let v: Vec<u8> = vec![ + 0x82, // array 2 items + 0x67, 0x4e, 0x65, 0x77, 0x54, 0x79, 0x70, 0x65, // utf8 string: NewType + 0x1a, // u32 + 0x00, 0x00, 0x00, 0x0a, // 10 (dec) + ]; + let (_rest, value): (&[u8], Enum) = from_slice_stream(&v[..]).unwrap(); + assert_eq!(value, Enum::NewType(10)); + let value: error::Result<(&[u8], Enum)> = + from_slice_stream_options(&v[..], Options::default().no_legacy()); + assert_eq!( + value.unwrap_err().classify(), + serde_cbor::error::Category::Syntax + ); + let value: error::Result<(&[u8], Enum)> = + from_slice_stream_options(&v[..], Options::default().no_standard()); + assert_eq!(value.unwrap().1, Enum::NewType(10)); + let value: error::Result<(&[u8], Enum)> = + from_slice_stream_options(&v[..], Options::default().no_standard().no_legacy()); + assert_eq!( + value.unwrap_err().classify(), + serde_cbor::error::Category::Syntax + ); + } + + #[test] + fn test_packed_deserialization() { + #[derive(Debug, PartialEq, Deserialize)] + struct User { + user_id: u32, + password_hash: [u8; 4], + } + + // unpacked + let v: Vec<u8> = vec![ + 0xa2, // map 2pair + 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, // utf8 string: user_id + 0x0a, // integer: 10 + // utf8 string: password_hash + 0x6d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, + 0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4] + ]; + + let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap(); + assert_eq!( + value, + User { + user_id: 10, + password_hash: [1, 2, 3, 4], + } + ); + let (_rest, value): (&[u8], User) = + from_slice_stream_options(&v[..], Options::default().no_packed()).unwrap(); + assert_eq!( + value, + User { + user_id: 10, + password_hash: [1, 2, 3, 4], + } + ); + let value: error::Result<(&[u8], User)> = + from_slice_stream_options(&v[..], Options::default().no_named()); + assert_eq!( + value.unwrap_err().classify(), + serde_cbor::error::Category::Syntax + ); + + // unpacked - indefinite length + let v: Vec<u8> = vec![ + 0xbf, // map to be followed by a break + 0x67, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, // utf8 string: user_id + 0x0a, // integer: 10 + // utf8 string: password_hash + 0x6d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, + 0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4] + 0xff, // break + ]; + + let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap(); + assert_eq!( + value, + User { + user_id: 10, + password_hash: [1, 2, 3, 4], + } + ); + let (_rest, value): (&[u8], User) = + from_slice_stream_options(&v[..], Options::default().no_packed()).unwrap(); + assert_eq!( + value, + User { + user_id: 10, + password_hash: [1, 2, 3, 4], + } + ); + let value: error::Result<(&[u8], User)> = + from_slice_stream_options(&v[..], Options::default().no_named()); + assert_eq!( + value.unwrap_err().classify(), + serde_cbor::error::Category::Syntax + ); + + // packed + let v: Vec<u8> = vec![ + 0xa2, // map 2pair + 0x00, // index 0 + 0x0a, // integer: 10 + 0x01, // index 1 + 0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4] + ]; + + let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap(); + assert_eq!( + value, + User { + user_id: 10, + password_hash: [1, 2, 3, 4], + } + ); + let (_rest, value): (&[u8], User) = + from_slice_stream_options(&v[..], Options::default().no_named()).unwrap(); + assert_eq!( + value, + User { + user_id: 10, + password_hash: [1, 2, 3, 4], + } + ); + let value: error::Result<(&[u8], User)> = + from_slice_stream_options(&v[..], Options::default().no_packed()); + assert_eq!( + value.unwrap_err().classify(), + serde_cbor::error::Category::Syntax + ); + + // packed - indefinite length + let v: Vec<u8> = vec![ + 0xbf, // map, to be followed by a break + 0x00, // index 0 + 0x0a, // integer: 10 + 0x01, // index 1 + 0x84, 0x01, 0x02, 0x03, 0x04, // 4 byte array [1, 2, 3, 4] + 0xff, // break + ]; + + let (_rest, value): (&[u8], User) = from_slice_stream(&v[..]).unwrap(); + assert_eq!( + value, + User { + user_id: 10, + password_hash: [1, 2, 3, 4], + } + ); + let (_rest, value): (&[u8], User) = + from_slice_stream_options(&v[..], Options::default().no_named()).unwrap(); + assert_eq!( + value, + User { + user_id: 10, + password_hash: [1, 2, 3, 4], + } + ); + let value: error::Result<(&[u8], User)> = + from_slice_stream_options(&v[..], Options::default().no_packed()); + assert_eq!( + value.unwrap_err().classify(), + serde_cbor::error::Category::Syntax + ); + } + + use serde_cbor::{de::from_slice, ser::to_vec_packed}; + use std::net::{IpAddr, Ipv4Addr}; + #[test] + fn test_ipaddr_deserialization() { + let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); + let buf = to_vec_packed(&ip).unwrap(); + let deserialized_ip = from_slice::<IpAddr>(&buf).unwrap(); + assert_eq!(ip, deserialized_ip); + + let buf = to_vec(&ip).unwrap(); + let deserialized_ip = from_slice::<IpAddr>(&buf).unwrap(); + assert_eq!(ip, deserialized_ip); + } + + #[test] + fn attempt_stack_overflow() { + // Create a tag 17, followed by 999 more tag 17: + // 17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(17(... + // This causes deep recursion in the decoder and may + // exhaust the stack and therfore result in a stack overflow. + let input = vec![0xd1; 1000]; + let err = serde_cbor::from_slice::<serde_cbor::Value>(&input).expect_err("recursion limit"); + assert!(err.is_syntax()); + } +} diff --git a/third_party/rust/serde_cbor/tests/enum.rs b/third_party/rust/serde_cbor/tests/enum.rs new file mode 100644 index 0000000000..630500d6b5 --- /dev/null +++ b/third_party/rust/serde_cbor/tests/enum.rs @@ -0,0 +1,236 @@ +use serde::Serialize; +use serde_cbor; +use serde_cbor::ser::{Serializer, SliceWrite}; + +#[macro_use] +extern crate serde_derive; + +#[test] +fn test_simple_data_enum_roundtrip() { + #[derive(Debug, Serialize, Deserialize, PartialEq)] + enum DataEnum { + A(u32), + B(f32), + } + + let a = DataEnum::A(42); + + let mut slice = [0u8; 64]; + let writer = SliceWrite::new(&mut slice); + let mut serializer = Serializer::new(writer); + a.serialize(&mut serializer).unwrap(); + let writer = serializer.into_inner(); + let end = writer.bytes_written(); + let slice = writer.into_inner(); + let deserialized: DataEnum = + serde_cbor::de::from_slice_with_scratch(&slice[..end], &mut []).unwrap(); + assert_eq!(a, deserialized); +} + +#[cfg(feature = "std")] +mod std_tests { + use std::collections::BTreeMap; + + use serde_cbor::ser::{IoWrite, Serializer}; + use serde_cbor::value::Value; + use serde_cbor::{from_slice, to_vec}; + + pub fn to_vec_legacy<T>(value: &T) -> serde_cbor::Result<Vec<u8>> + where + T: serde::ser::Serialize, + { + let mut vec = Vec::new(); + value.serialize(&mut Serializer::new(&mut IoWrite::new(&mut vec)).legacy_enums())?; + Ok(vec) + } + + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + enum Enum { + A, + B, + } + + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct EnumStruct { + e: Enum, + } + + #[test] + fn test_enum() { + let enum_struct = EnumStruct { e: Enum::B }; + let raw = &to_vec(&enum_struct).unwrap(); + println!("raw enum {:?}", raw); + let re: EnumStruct = from_slice(raw).unwrap(); + assert_eq!(enum_struct, re); + } + + #[repr(u16)] + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + enum ReprEnum { + A, + B, + } + + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct ReprEnumStruct { + e: ReprEnum, + } + + #[test] + fn test_repr_enum() { + let repr_enum_struct = ReprEnumStruct { e: ReprEnum::B }; + let re: ReprEnumStruct = from_slice(&to_vec(&repr_enum_struct).unwrap()).unwrap(); + assert_eq!(repr_enum_struct, re); + } + + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + enum DataEnum { + A(u32), + B(bool, u8), + C { x: u8, y: String }, + } + + #[test] + fn test_data_enum() { + let data_enum_a = DataEnum::A(4); + let re_a: DataEnum = from_slice(&to_vec(&data_enum_a).unwrap()).unwrap(); + assert_eq!(data_enum_a, re_a); + let data_enum_b = DataEnum::B(true, 42); + let re_b: DataEnum = from_slice(&to_vec(&data_enum_b).unwrap()).unwrap(); + assert_eq!(data_enum_b, re_b); + let data_enum_c = DataEnum::C { + x: 3, + y: "foo".to_owned(), + }; + println!("{:?}", &to_vec(&data_enum_c).unwrap()); + let re_c: DataEnum = from_slice(&to_vec(&data_enum_c).unwrap()).unwrap(); + assert_eq!(data_enum_c, re_c); + } + + #[test] + fn test_serialize() { + assert_eq!(to_vec_legacy(&Enum::A).unwrap(), &[97, 65]); + assert_eq!(to_vec_legacy(&Enum::B).unwrap(), &[97, 66]); + assert_eq!( + to_vec_legacy(&DataEnum::A(42)).unwrap(), + &[130, 97, 65, 24, 42] + ); + assert_eq!( + to_vec_legacy(&DataEnum::B(true, 9)).unwrap(), + &[131, 97, 66, 245, 9] + ); + } + + #[test] + fn test_newtype_struct() { + #[derive(Debug, Deserialize, Serialize, PartialEq, Eq)] + pub struct Newtype(u8); + assert_eq!(to_vec(&142u8).unwrap(), to_vec(&Newtype(142u8)).unwrap()); + assert_eq!(from_slice::<Newtype>(&[24, 142]).unwrap(), Newtype(142)); + } + + #[derive(Deserialize, PartialEq, Debug)] + enum Foo { + #[serde(rename = "require")] + Require, + } + + #[test] + fn test_variable_length_array() { + let slice = b"\x9F\x67\x72\x65\x71\x75\x69\x72\x65\xFF"; + let value: Vec<Foo> = from_slice(slice).unwrap(); + assert_eq!(value, [Foo::Require]); + } + + #[derive(Serialize, Deserialize, PartialEq, Debug)] + enum Bar { + Empty, + Number(i32), + Flag(String, bool), + Point { x: i32, y: i32 }, + } + + #[test] + fn test_enum_as_map() { + // unit variants serialize like bare strings + let empty_s = to_vec_legacy(&Bar::Empty).unwrap(); + let empty_str_s = to_vec_legacy(&"Empty").unwrap(); + assert_eq!(empty_s, empty_str_s); + + // tuple-variants serialize like ["<variant>", values..] + let number_s = to_vec_legacy(&Bar::Number(42)).unwrap(); + let number_vec = vec![Value::Text("Number".to_string()), Value::Integer(42)]; + let number_vec_s = to_vec_legacy(&number_vec).unwrap(); + assert_eq!(number_s, number_vec_s); + + let flag_s = to_vec_legacy(&Bar::Flag("foo".to_string(), true)).unwrap(); + let flag_vec = vec![ + Value::Text("Flag".to_string()), + Value::Text("foo".to_string()), + Value::Bool(true), + ]; + let flag_vec_s = to_vec_legacy(&flag_vec).unwrap(); + assert_eq!(flag_s, flag_vec_s); + + // struct-variants serialize like ["<variant>", {struct..}] + let point_s = to_vec_legacy(&Bar::Point { x: 5, y: -5 }).unwrap(); + let mut struct_map = BTreeMap::new(); + struct_map.insert(Value::Text("x".to_string()), Value::Integer(5)); + struct_map.insert(Value::Text("y".to_string()), Value::Integer(-5)); + let point_vec = vec![ + Value::Text("Point".to_string()), + Value::Map(struct_map.clone()), + ]; + let point_vec_s = to_vec_legacy(&point_vec).unwrap(); + assert_eq!(point_s, point_vec_s); + + // enum_as_map matches serde_json's default serialization for enums. + + // unit variants still serialize like bare strings + let empty_s = to_vec(&Bar::Empty).unwrap(); + assert_eq!(empty_s, empty_str_s); + + // 1-element tuple variants serialize like {"<variant>": value} + let number_s = to_vec(&Bar::Number(42)).unwrap(); + let mut number_map = BTreeMap::new(); + number_map.insert("Number", 42); + let number_map_s = to_vec(&number_map).unwrap(); + assert_eq!(number_s, number_map_s); + + // multi-element tuple variants serialize like {"<variant>": [values..]} + let flag_s = to_vec(&Bar::Flag("foo".to_string(), true)).unwrap(); + let mut flag_map = BTreeMap::new(); + flag_map.insert( + "Flag", + vec![Value::Text("foo".to_string()), Value::Bool(true)], + ); + let flag_map_s = to_vec(&flag_map).unwrap(); + assert_eq!(flag_s, flag_map_s); + + // struct-variants serialize like {"<variant>", {struct..}} + let point_s = to_vec(&Bar::Point { x: 5, y: -5 }).unwrap(); + let mut point_map = BTreeMap::new(); + point_map.insert("Point", Value::Map(struct_map)); + let point_map_s = to_vec(&point_map).unwrap(); + assert_eq!(point_s, point_map_s); + + // deserialization of all encodings should just work + let empty_str_ds = from_slice(&empty_str_s).unwrap(); + assert_eq!(Bar::Empty, empty_str_ds); + + let number_vec_ds = from_slice(&number_vec_s).unwrap(); + assert_eq!(Bar::Number(42), number_vec_ds); + let number_map_ds = from_slice(&number_map_s).unwrap(); + assert_eq!(Bar::Number(42), number_map_ds); + + let flag_vec_ds = from_slice(&flag_vec_s).unwrap(); + assert_eq!(Bar::Flag("foo".to_string(), true), flag_vec_ds); + let flag_map_ds = from_slice(&flag_map_s).unwrap(); + assert_eq!(Bar::Flag("foo".to_string(), true), flag_map_ds); + + let point_vec_ds = from_slice(&point_vec_s).unwrap(); + assert_eq!(Bar::Point { x: 5, y: -5 }, point_vec_ds); + let point_map_ds = from_slice(&point_map_s).unwrap(); + assert_eq!(Bar::Point { x: 5, y: -5 }, point_map_ds); + } +} diff --git a/third_party/rust/serde_cbor/tests/kietaub.cbor b/third_party/rust/serde_cbor/tests/kietaub.cbor Binary files differnew file mode 100644 index 0000000000..866a093132 --- /dev/null +++ b/third_party/rust/serde_cbor/tests/kietaub.cbor diff --git a/third_party/rust/serde_cbor/tests/ser.rs b/third_party/rust/serde_cbor/tests/ser.rs new file mode 100644 index 0000000000..d374ce2faf --- /dev/null +++ b/third_party/rust/serde_cbor/tests/ser.rs @@ -0,0 +1,254 @@ +use serde::Serialize; +use serde_cbor::ser::{Serializer, SliceWrite}; + +#[test] +fn test_str() { + serialize_and_compare("foobar", b"ffoobar"); +} + +#[test] +fn test_list() { + serialize_and_compare(&[1, 2, 3], b"\x83\x01\x02\x03"); +} + +#[test] +fn test_float() { + serialize_and_compare(12.3f64, b"\xfb@(\x99\x99\x99\x99\x99\x9a"); +} + +#[test] +fn test_integer() { + // u8 + serialize_and_compare(24, b"\x18\x18"); + // i8 + serialize_and_compare(-5, b"\x24"); + // i16 + serialize_and_compare(-300, b"\x39\x01\x2b"); + // i32 + serialize_and_compare(-23567997, b"\x3a\x01\x67\x9e\x7c"); + // u64 + serialize_and_compare(::core::u64::MAX, b"\x1b\xff\xff\xff\xff\xff\xff\xff\xff"); +} + +fn serialize_and_compare<T: Serialize>(value: T, expected: &[u8]) { + let mut slice = [0u8; 64]; + let writer = SliceWrite::new(&mut slice); + let mut serializer = Serializer::new(writer); + value.serialize(&mut serializer).unwrap(); + let writer = serializer.into_inner(); + let end = writer.bytes_written(); + let slice = writer.into_inner(); + assert_eq!(&slice[..end], expected); +} + +#[cfg(feature = "std")] +mod std_tests { + use serde::Serializer; + use serde_cbor::ser; + use serde_cbor::{from_slice, to_vec}; + use std::collections::BTreeMap; + + #[test] + fn test_string() { + let value = "foobar".to_owned(); + assert_eq!(&to_vec(&value).unwrap()[..], b"ffoobar"); + } + + #[test] + fn test_list() { + let value = vec![1, 2, 3]; + assert_eq!(&to_vec(&value).unwrap()[..], b"\x83\x01\x02\x03"); + } + + #[test] + fn test_object() { + let mut object = BTreeMap::new(); + object.insert("a".to_owned(), "A".to_owned()); + object.insert("b".to_owned(), "B".to_owned()); + object.insert("c".to_owned(), "C".to_owned()); + object.insert("d".to_owned(), "D".to_owned()); + object.insert("e".to_owned(), "E".to_owned()); + let vec = to_vec(&object).unwrap(); + let test_object = from_slice(&vec[..]).unwrap(); + assert_eq!(object, test_object); + } + + #[test] + fn test_object_list_keys() { + let mut object = BTreeMap::new(); + object.insert(vec![0i64], ()); + object.insert(vec![100i64], ()); + object.insert(vec![-1i64], ()); + object.insert(vec![-2i64], ()); + object.insert(vec![0i64, 0i64], ()); + object.insert(vec![0i64, -1i64], ()); + let vec = to_vec(&serde_cbor::value::to_value(object.clone()).unwrap()).unwrap(); + assert_eq!( + vec![ + 166, 129, 0, 246, 129, 24, 100, 246, 129, 32, 246, 129, 33, 246, 130, 0, 0, 246, + 130, 0, 32, 246 + ], + vec + ); + let test_object = from_slice(&vec[..]).unwrap(); + assert_eq!(object, test_object); + } + + #[test] + fn test_object_object_keys() { + use std::iter::FromIterator; + let mut object = BTreeMap::new(); + let keys = vec![ + vec!["a"], + vec!["b"], + vec!["c"], + vec!["d"], + vec!["aa"], + vec!["a", "aa"], + ] + .into_iter() + .map(|v| BTreeMap::from_iter(v.into_iter().map(|s| (s.to_owned(), ())))); + + for key in keys { + object.insert(key, ()); + } + let vec = to_vec(&serde_cbor::value::to_value(object.clone()).unwrap()).unwrap(); + assert_eq!( + vec![ + 166, 161, 97, 97, 246, 246, 161, 97, 98, 246, 246, 161, 97, 99, 246, 246, 161, 97, + 100, 246, 246, 161, 98, 97, 97, 246, 246, 162, 97, 97, 246, 98, 97, 97, 246, 246 + ], + vec + ); + let test_object = from_slice(&vec[..]).unwrap(); + assert_eq!(object, test_object); + } + + #[test] + fn test_float() { + let vec = to_vec(&12.3f64).unwrap(); + assert_eq!(vec, b"\xfb@(\x99\x99\x99\x99\x99\x9a"); + } + + #[test] + fn test_f32() { + let vec = to_vec(&4000.5f32).unwrap(); + assert_eq!(vec, b"\xfa\x45\x7a\x08\x00"); + } + + #[test] + fn test_infinity() { + let vec = to_vec(&::std::f64::INFINITY).unwrap(); + assert_eq!(vec, b"\xf9|\x00"); + } + + #[test] + fn test_neg_infinity() { + let vec = to_vec(&::std::f64::NEG_INFINITY).unwrap(); + assert_eq!(vec, b"\xf9\xfc\x00"); + } + + #[test] + fn test_nan() { + let vec = to_vec(&::std::f32::NAN).unwrap(); + assert_eq!(vec, b"\xf9\x7e\x00"); + } + + #[test] + fn test_integer() { + // u8 + let vec = to_vec(&24).unwrap(); + assert_eq!(vec, b"\x18\x18"); + // i8 + let vec = to_vec(&-5).unwrap(); + assert_eq!(vec, b"\x24"); + // i16 + let vec = to_vec(&-300).unwrap(); + assert_eq!(vec, b"\x39\x01\x2b"); + // i32 + let vec = to_vec(&-23567997).unwrap(); + assert_eq!(vec, b"\x3a\x01\x67\x9e\x7c"); + // u64 + let vec = to_vec(&::std::u64::MAX).unwrap(); + assert_eq!(vec, b"\x1b\xff\xff\xff\xff\xff\xff\xff\xff"); + } + + #[test] + fn test_self_describing() { + let mut vec = Vec::new(); + { + let mut serializer = ser::Serializer::new(&mut vec); + serializer.self_describe().unwrap(); + serializer.serialize_u64(9).unwrap(); + } + assert_eq!(vec, b"\xd9\xd9\xf7\x09"); + } + + #[test] + fn test_ip_addr() { + use std::net::Ipv4Addr; + + let addr = Ipv4Addr::new(8, 8, 8, 8); + let vec = to_vec(&addr).unwrap(); + println!("{:?}", vec); + assert_eq!(vec.len(), 5); + let test_addr: Ipv4Addr = from_slice(&vec).unwrap(); + assert_eq!(addr, test_addr); + } + + /// Test all of CBOR's fixed-length byte string types + #[test] + fn test_byte_string() { + // Very short byte strings have 1-byte headers + let short = vec![0, 1, 2, 255]; + let mut short_s = Vec::new(); + serde_cbor::Serializer::new(&mut short_s) + .serialize_bytes(&short) + .unwrap(); + assert_eq!(&short_s[..], [0x44, 0, 1, 2, 255]); + + // byte strings > 23 bytes have 2-byte headers + let medium = vec![ + 0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 255, + ]; + let mut medium_s = Vec::new(); + serde_cbor::Serializer::new(&mut medium_s) + .serialize_bytes(&medium) + .unwrap(); + assert_eq!( + &medium_s[..], + [ + 0x58, 24, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 255 + ] + ); + + // byte strings > 256 bytes have 3-byte headers + let long_vec = (0..256).map(|i| (i & 0xFF) as u8).collect::<Vec<_>>(); + let mut long_s = Vec::new(); + serde_cbor::Serializer::new(&mut long_s) + .serialize_bytes(&long_vec) + .unwrap(); + assert_eq!(&long_s[0..3], [0x59, 1, 0]); + assert_eq!(&long_s[3..], &long_vec[..]); + + // byte strings > 2^16 bytes have 5-byte headers + let very_long_vec = (0..65536).map(|i| (i & 0xFF) as u8).collect::<Vec<_>>(); + let mut very_long_s = Vec::new(); + serde_cbor::Serializer::new(&mut very_long_s) + .serialize_bytes(&very_long_vec) + .unwrap(); + assert_eq!(&very_long_s[0..5], [0x5a, 0, 1, 0, 0]); + assert_eq!(&very_long_s[5..], &very_long_vec[..]); + + // byte strings > 2^32 bytes have 9-byte headers, but they take too much RAM + // to test in Travis. + } + + #[test] + fn test_half() { + let vec = to_vec(&42.5f32).unwrap(); + assert_eq!(vec, b"\xF9\x51\x50"); + assert_eq!(from_slice::<f32>(&vec[..]).unwrap(), 42.5f32); + } +} diff --git a/third_party/rust/serde_cbor/tests/std_types.rs b/third_party/rust/serde_cbor/tests/std_types.rs new file mode 100644 index 0000000000..7a7ded484c --- /dev/null +++ b/third_party/rust/serde_cbor/tests/std_types.rs @@ -0,0 +1,186 @@ +#[macro_use] +extern crate serde_derive; + +#[cfg(feature = "std")] +mod std_tests { + use std::u8; + + use serde_cbor::de::from_mut_slice; + use serde_cbor::ser::{to_vec, to_vec_packed}; + use serde_cbor::{from_reader, from_slice}; + + fn to_binary(s: &'static str) -> Vec<u8> { + assert!(s.len() % 2 == 0); + let mut b = Vec::with_capacity(s.len() / 2); + for i in 0..s.len() / 2 { + b.push(u8::from_str_radix(&s[i * 2..(i + 1) * 2], 16).unwrap()); + } + b + } + + macro_rules! testcase { + ($name:ident, f64, $expr:expr, $s:expr) => { + #[test] + fn $name() { + let expr: f64 = $expr; + let mut serialized = to_binary($s); + assert_eq!(to_vec(&expr).unwrap(), serialized); + let parsed: f64 = from_slice(&serialized[..]).unwrap(); + if !expr.is_nan() { + assert_eq!(expr, parsed); + } else { + assert!(parsed.is_nan()) + } + + let parsed: f64 = from_reader(&mut &serialized[..]).unwrap(); + if !expr.is_nan() { + assert_eq!(expr, parsed); + } else { + assert!(parsed.is_nan()) + } + + let parsed: f64 = from_mut_slice(&mut serialized[..]).unwrap(); + if !expr.is_nan() { + assert_eq!(expr, parsed); + } else { + assert!(parsed.is_nan()) + } + } + }; + ($name:ident, $ty:ty, $expr:expr, $s:expr) => { + #[test] + fn $name() { + let expr: $ty = $expr; + let mut serialized = to_binary($s); + assert_eq!( + to_vec(&expr).expect("ser1 works"), + serialized, + "serialization differs" + ); + let parsed: $ty = from_slice(&serialized[..]).expect("de1 works"); + assert_eq!(parsed, expr, "parsed result differs"); + let packed = &to_vec_packed(&expr).expect("serializing packed")[..]; + let parsed_from_packed: $ty = from_slice(packed).expect("parsing packed"); + assert_eq!(parsed_from_packed, expr, "packed roundtrip fail"); + + let parsed: $ty = from_reader(&mut &serialized[..]).unwrap(); + assert_eq!(parsed, expr, "parsed result differs"); + let mut packed = to_vec_packed(&expr).expect("serializing packed"); + let parsed_from_packed: $ty = + from_reader(&mut &packed[..]).expect("parsing packed"); + assert_eq!(parsed_from_packed, expr, "packed roundtrip fail"); + + let parsed: $ty = from_mut_slice(&mut serialized[..]).unwrap(); + assert_eq!(parsed, expr, "parsed result differs"); + let parsed_from_packed: $ty = + from_mut_slice(&mut packed[..]).expect("parsing packed"); + assert_eq!(parsed_from_packed, expr, "packed roundtrip fail"); + } + }; + } + + testcase!(test_bool_false, bool, false, "f4"); + testcase!(test_bool_true, bool, true, "f5"); + testcase!(test_isize_neg_256, isize, -256, "38ff"); + testcase!(test_isize_neg_257, isize, -257, "390100"); + testcase!(test_isize_255, isize, 255, "18ff"); + testcase!(test_i8_5, i8, 5, "05"); + testcase!(test_i8_23, i8, 23, "17"); + testcase!(test_i8_24, i8, 24, "1818"); + testcase!(test_i8_neg_128, i8, -128, "387f"); + testcase!(test_u32_98745874, u32, 98745874, "1a05e2be12"); + testcase!(test_f32_1234_point_5, f32, 1234.5, "fa449a5000"); + testcase!(test_f64_12345_point_6, f64, 12345.6, "fb40c81ccccccccccd"); + testcase!(test_f64_nan, f64, ::std::f64::NAN, "f97e00"); + testcase!(test_f64_infinity, f64, ::std::f64::INFINITY, "f97c00"); + testcase!(test_f64_neg_infinity, f64, -::std::f64::INFINITY, "f9fc00"); + testcase!(test_char_null, char, '\x00', "6100"); + testcase!(test_char_broken_heart, char, '💔', "64f09f9294"); + testcase!( + test_str_pangram_de, + String, + "aâø↓é".to_owned(), + "6a61c3a2c3b8e28693c3a9" + ); + testcase!(test_unit, (), (), "f6"); + + #[derive(Debug, PartialEq, Deserialize, Serialize)] + struct UnitStruct; + testcase!(test_unit_struct, UnitStruct, UnitStruct, "f6"); + + #[derive(Debug, PartialEq, Deserialize, Serialize)] + struct NewtypeStruct(bool); + testcase!( + test_newtype_struct, + NewtypeStruct, + NewtypeStruct(true), + "f5" + ); + + testcase!(test_option_none, Option<u8>, None, "f6"); + testcase!(test_option_some, Option<u8>, Some(42), "182a"); + + #[derive(Debug, PartialEq, Deserialize, Serialize)] + struct Person { + name: String, + year_of_birth: u16, + profession: Option<String>, + } + + testcase!(test_person_struct, + Person, + Person { + name: "Grace Hopper".to_string(), + year_of_birth: 1906, + profession: Some("computer scientist".to_string()), + }, + "a3646e616d656c477261636520486f707065726d796561725f6f665f62697274681907726a70726f66657373696f6e72636f6d707574657220736369656e74697374"); + + #[derive(Debug, PartialEq, Deserialize, Serialize)] + struct OptionalPerson { + name: String, + #[serde(skip_serializing_if = "Option::is_none")] + year_of_birth: Option<u16>, + profession: Option<String>, + } + + testcase!(test_optional_person_struct, + OptionalPerson, + OptionalPerson { + name: "Grace Hopper".to_string(), + year_of_birth: None, + profession: Some("computer scientist".to_string()), + }, + "a2646e616d656c477261636520486f707065726a70726f66657373696f6e72636f6d707574657220736369656e74697374"); + + #[derive(Debug, PartialEq, Deserialize, Serialize)] + enum Color { + Red, + Blue, + Yellow, + Other(u64), + Alpha(u64, u8), + } + + testcase!(test_color_enum, Color, Color::Blue, "64426c7565"); + testcase!( + test_color_enum_transparent, + Color, + Color::Other(42), + "a1654f74686572182a" + ); + testcase!( + test_color_enum_with_alpha, + Color, + Color::Alpha(234567, 60), + "a165416c706861821a00039447183c" + ); + testcase!(test_i128_a, i128, -1i128, "20"); + testcase!( + test_i128_b, + i128, + -18446744073709551616i128, + "3BFFFFFFFFFFFFFFFF" + ); + testcase!(test_u128, u128, 17, "11"); +} diff --git a/third_party/rust/serde_cbor/tests/tags.rs b/third_party/rust/serde_cbor/tests/tags.rs new file mode 100644 index 0000000000..92534c023d --- /dev/null +++ b/third_party/rust/serde_cbor/tests/tags.rs @@ -0,0 +1,48 @@ +#[cfg(feature = "tags")] +mod tagtests { + use serde_cbor::value::Value; + use serde_cbor::{from_slice, to_vec}; + + fn decode_hex(s: &str) -> std::result::Result<Vec<u8>, std::num::ParseIntError> { + (0..s.len()) + .step_by(2) + .map(|i| u8::from_str_radix(&s[i..i + 2], 16)) + .collect() + } + + // get bytes from http://cbor.me/ trees + fn parse_cbor_me(example: &str) -> std::result::Result<Vec<u8>, std::num::ParseIntError> { + let hex = example + .split("\n") + .flat_map(|line| line.split("#").take(1)) + .collect::<Vec<&str>>() + .join("") + .replace(" ", ""); + decode_hex(&hex) + } + + #[test] + fn tagged_cbor_roundtrip() { + let data = r#" +C1 # tag(1) + 82 # array(2) + C2 # tag(2) + 63 # text(3) + 666F6F # "foo" + C3 # tag(3) + A1 # map(1) + C4 # tag(4) + 61 # text(1) + 61 # "a" + C5 # tag(5) + 61 # text(1) + 62 # "b" + "#; + let bytes1 = parse_cbor_me(&data).unwrap(); + let value1: Value = from_slice(&bytes1).unwrap(); + let bytes2 = to_vec(&value1).unwrap(); + let value2: Value = from_slice(&bytes2).unwrap(); + assert_eq!(bytes1, bytes2); + assert_eq!(value1, value2); + } +} diff --git a/third_party/rust/serde_cbor/tests/value.rs b/third_party/rust/serde_cbor/tests/value.rs new file mode 100644 index 0000000000..554d74266c --- /dev/null +++ b/third_party/rust/serde_cbor/tests/value.rs @@ -0,0 +1,100 @@ +#[macro_use] +extern crate serde_derive; + +#[cfg(feature = "std")] +mod std_tests { + use serde_cbor; + + use std::collections::BTreeMap; + + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] + struct TupleStruct(String, i32, u64); + + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] + struct UnitStruct; + + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] + struct Struct<'a> { + tuple_struct: TupleStruct, + tuple: (String, f32, f64), + map: BTreeMap<String, String>, + bytes: &'a [u8], + array: Vec<String>, + unit_array: Vec<UnitStruct>, + } + + use serde_cbor::value::Value; + use std::iter::FromIterator; + + #[test] + fn serde() { + let tuple_struct = TupleStruct(format!("test"), -60, 3000); + + let tuple = (format!("hello"), -50.0040957, -12.094635556478); + + let map = BTreeMap::from_iter( + [ + (format!("key1"), format!("value1")), + (format!("key2"), format!("value2")), + (format!("key3"), format!("value3")), + (format!("key4"), format!("value4")), + ] + .iter() + .cloned(), + ); + + let bytes = b"test byte string"; + + let array = vec![format!("one"), format!("two"), format!("three")]; + let unit_array = vec![UnitStruct, UnitStruct, UnitStruct]; + + let data = Struct { + tuple_struct, + tuple, + map, + bytes, + array, + unit_array, + }; + + let value = serde_cbor::value::to_value(data.clone()).unwrap(); + println!("{:?}", value); + + let data_ser = serde_cbor::to_vec(&value).unwrap(); + let data_de_value: Value = serde_cbor::from_slice(&data_ser).unwrap(); + + fn as_object(value: &Value) -> &BTreeMap<Value, Value> { + if let Value::Map(ref v) = value { + return v; + } + panic!() + } + + for ((k1, v1), (k2, v2)) in as_object(&value) + .iter() + .zip(as_object(&data_de_value).iter()) + { + assert_eq!(k1, k2); + assert_eq!(v1, v2); + } + + assert_eq!(value, data_de_value); + } + + #[derive(Debug, Deserialize, Serialize)] + struct SmallStruct { + spam: u32, + eggs: u32, + } + + #[test] + fn small_struct() { + // Test whether the packed format works. + // Field names should not be serialized, + // instead field indizes are serialized. + let value = SmallStruct { spam: 17, eggs: 42 }; + let data = serde_cbor::ser::to_vec_packed(&value).unwrap(); + let reference = b"\xa2\x00\x11\x01\x18\x2a"; + assert_eq!(data, reference); + } +} |