Skip to content

Commit

Permalink
Merge #4468
Browse files Browse the repository at this point in the history
4468: Add tests serialization r=AurelienFT a=AurelienFT

massa-serialization has 93% coverage on this PR.

Co-authored-by: AurelienFT <[email protected]>
  • Loading branch information
bors[bot] and AurelienFT authored Oct 12, 2023
2 parents eb3bc44 + 1a2cb0e commit c8f85ab
Show file tree
Hide file tree
Showing 4 changed files with 256 additions and 1 deletion.
9 changes: 8 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ num = "=0.4"
num_enum = "0.7"
paginate = "1.1"
parking_lot = "0.12"
paste = "1.0"
pbkdf2 = { version = "=0.12", features = ["simple"] }
prometheus = "0.13"
rand = "0.8"
Expand Down
3 changes: 3 additions & 0 deletions massa-serialization/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ thiserror = {workspace = true}
nom = {workspace = true}
unsigned-varint = {workspace = true, "features" = ["nom"]}
num = {workspace = true}

[dev-dependencies]
paste = {workspace = true}
244 changes: 244 additions & 0 deletions massa-serialization/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,3 +479,247 @@ where
.parse(buffer)
}
}

#[cfg(test)]
mod tests {
use crate::{DeserializeError, Deserializer, Serializer};
use num::rational::Ratio;
use paste::paste;

// This macro creates a suite of tests for all types of numbers declared as parameters. Ths list of the
// tests for each type :
// - Test with a normal case that everything works
// - Test with a normal case but a more bigger number that everything works
// - Test with a number that is out of the range of the deserializer
// - Test to give an empty buffer to the deserializer
macro_rules! gen_test_varint {
($($type:ident, $bs:ident, $ds:ident);*) => {
$(
paste! {
#[test]
fn [<test_ $type _serializer_deserializer_works>]() {
let [< $type _serializer >] = super::$bs::new();
let number = [<3 $type >];
let mut buffer = Vec::new();
[< $type _serializer >].serialize(&number, &mut buffer).expect(concat!("Failed to serialize ", stringify!($type), " 3"));
assert_eq!(buffer, vec![3]);
let [< $type _deserializer >] = super::$ds::new(std::ops::Bound::Included([<0 $type >]), std::ops::Bound::Included(number));
let result = [< $type _deserializer >].deserialize::<DeserializeError>(&buffer);
assert!(result.is_ok());
let (rest, value) = result.unwrap();
assert!(rest.is_empty());
assert_eq!(value, number);
}

#[test]
fn [<test $type _serializer_deserializer_works_big_number>]() {
let [< $type _serializer >] = super::$bs::new();
let number = [<60_500 $type>];
let mut buffer = Vec::new();
[< $type _serializer >].serialize(&number, &mut buffer).expect(concat!("Failed to serialize ", stringify!($type), " 10_000_000"));
assert_eq!(buffer, vec![212, 216, 3]);
let [< $type _deserializer >] = super::$ds::new(std::ops::Bound::Included([<0 $type >]), std::ops::Bound::Included(number));
let result = [< $type _deserializer >].deserialize::<DeserializeError>(&buffer);
assert!(result.is_ok());
let (rest, value) = result.unwrap();
assert!(rest.is_empty());
assert_eq!(value, number);
}

#[test]
fn [<test_ $type _serializer_deserializer_bad_limits>]() {
let [< $type _serializer >] = super::$bs::new();
let number = [<3 $type >];
let mut buffer = Vec::new();
[< $type _serializer >].serialize(&number, &mut buffer).expect(concat!("Failed to serialize ", stringify!($type), " 3"));
assert_eq!(buffer, vec![3]);
let [< $type _deserializer >] = super::$ds::new(std::ops::Bound::Included([<0 $type >]), std::ops::Bound::Excluded(number));
let result = [< $type _deserializer >].deserialize::<DeserializeError>(&buffer);
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(format!("{}", err), concat!("Parsing Error: Failed ", stringify!($type), " deserialization / Fail / Input: [3]\n"));
}

#[test]
fn [<test_ $type _serializer_deserializer_empty_vec>]() {
let buffer = vec![];
let [< $type _deserializer >] = super::$ds::new(std::ops::Bound::Included([<0 $type >]), std::ops::Bound::Included($type::MAX));
let result = [< $type _deserializer >].deserialize::<DeserializeError>(&buffer);
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(format!("{}", err), concat!("Parsing Error: Failed ", stringify!($type), " deserialization / Fail / Input: []\n"));
}
}
)*
};
}

gen_test_varint!(
u16, U16VarIntSerializer, U16VarIntDeserializer;
u32, U32VarIntSerializer, U32VarIntDeserializer;
u64, U64VarIntSerializer, U64VarIntDeserializer
);

#[test]
fn test_u64_empty_vec() {
let buffer = vec![];
let u64_deserializer = super::U64VarIntDeserializer::new(
std::ops::Bound::Included(0),
std::ops::Bound::Included(3),
);
let result = u64_deserializer.deserialize::<DeserializeError>(&buffer);
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(
format!("{}", err),
"Parsing Error: Failed u64 deserialization / Fail / Input: []\n"
);
}

#[test]
fn test_option_serializer_value_works() {
let option_serializer = super::OptionSerializer::new(super::U64VarIntSerializer::new());
let mut buffer = Vec::new();
option_serializer
.serialize(&Some(3u64), &mut buffer)
.expect("Failed to serialize Some(3)");
assert_eq!(buffer, vec![b'1', 3]);
let option_deserializer =
super::OptionDeserializer::new(super::U64VarIntDeserializer::new(
std::ops::Bound::Included(0),
std::ops::Bound::Included(3),
));
let result = option_deserializer.deserialize::<DeserializeError>(&buffer);
assert!(result.is_ok());
let (rest, value) = result.unwrap();
assert!(rest.is_empty());
assert_eq!(value, Some(3u64));
}

#[test]
fn test_option_serializer_none_works() {
let option_serializer = super::OptionSerializer::new(super::U64VarIntSerializer::new());
let mut buffer = Vec::new();
option_serializer
.serialize(&None, &mut buffer)
.expect("Failed to serialize None");
assert_eq!(buffer, vec![b'0']);
let option_deserializer =
super::OptionDeserializer::new(super::U64VarIntDeserializer::new(
std::ops::Bound::Included(0),
std::ops::Bound::Included(3),
));
let result = option_deserializer.deserialize::<DeserializeError>(&buffer);
assert!(result.is_ok());
let (rest, value) = result.unwrap();
assert!(rest.is_empty());
assert_eq!(value, None);
}

#[test]
fn test_option_bad_serialized_vec() {
let buffer = vec![2];
let option_deserializer =
super::OptionDeserializer::new(super::U64VarIntDeserializer::new(
std::ops::Bound::Included(0),
std::ops::Bound::Included(3),
));
let result = option_deserializer.deserialize::<DeserializeError>(&buffer);
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(format!("{}", err), "Parsing Error: Option<_> deserializer failed / Alternative / Some(_) / Tag / Input: [2]\n");
}

#[test]
fn test_option_empty_vec() {
let buffer = vec![];
let option_deserializer =
super::OptionDeserializer::new(super::U64VarIntDeserializer::new(
std::ops::Bound::Included(0),
std::ops::Bound::Included(3),
));
let result = option_deserializer.deserialize::<DeserializeError>(&buffer);
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(format!("{}", err), "Parsing Error: Option<_> deserializer failed / Alternative / Some(_) / Tag / Input: []\n");
}

#[test]
fn test_bool_serializer_deserializer_works() {
let bool_serializer = super::BoolSerializer::new();
let mut buffer = Vec::new();
bool_serializer
.serialize(&true, &mut buffer)
.expect("Failed to serialize true");
assert_eq!(buffer, vec![1]);
let bool_deserializer = super::BoolDeserializer::new();
let result = bool_deserializer.deserialize::<DeserializeError>(&buffer);
assert!(result.is_ok());
let (rest, value) = result.unwrap();
assert!(rest.is_empty());
assert_eq!(value, true);
}

#[test]
fn test_bool_bad_serialized_vec() {
let buffer = vec![2];
let bool_deserializer = super::BoolDeserializer::new();
let result = bool_deserializer.deserialize::<DeserializeError>(&buffer);
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(
format!("{}", err),
"Parsing Error: Failed bool deserialization / Fail / Input: [2]\n"
);
}

#[test]
fn test_bool_empty_vec() {
let buffer = vec![];
let bool_deserializer = super::BoolDeserializer::new();
let result = bool_deserializer.deserialize::<DeserializeError>(&buffer);
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(
format!("{}", err),
"Parsing Error: Failed bool deserialization / Fail / Input: []\n"
);
}

#[test]
fn test_ratio_serializer_deserializer_works() {
let ratio_serializer = super::RatioSerializer::new(super::U64VarIntSerializer::new());
let mut buffer = Vec::new();
ratio_serializer
.serialize(&Ratio::new(3u64, 4u64), &mut buffer)
.expect("Failed to serialize Ratio(3, 4)");
assert_eq!(buffer, vec![3, 4]);
let ratio_deserializer = super::RatioDeserializer::new(super::U64VarIntDeserializer::new(
std::ops::Bound::Included(0),
std::ops::Bound::Included(4),
));
let result = ratio_deserializer.deserialize::<DeserializeError>(&buffer);
assert!(result.is_ok());
let (rest, value) = result.unwrap();
assert!(rest.is_empty());
assert_eq!(value, Ratio::new(3u64, 4u64));
}

#[test]
fn test_ratio_serializer_deserializer_bad_limits() {
let ratio_serializer = super::RatioSerializer::new(super::U64VarIntSerializer::new());
let mut buffer = Vec::new();
ratio_serializer
.serialize(&Ratio::new(3u64, 4u64), &mut buffer)
.expect("Failed to serialize Ratio(3, 4)");
assert_eq!(buffer, vec![3, 4]);
let ratio_deserializer = super::RatioDeserializer::new(super::U64VarIntDeserializer::new(
std::ops::Bound::Included(0),
std::ops::Bound::Included(3),
));
let result = ratio_deserializer.deserialize::<DeserializeError>(&buffer);
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(format!("{}", err), "Parsing Error: Ratio<_> deserializer failed / denom deser failed / Failed u64 deserialization / Fail / Input: [4]\n");
}
}

0 comments on commit c8f85ab

Please sign in to comment.