diff --git a/sdk/program/src/borsh.rs b/sdk/program/src/borsh.rs index 65cc03b37d0588..90ce42f661f82f 100644 --- a/sdk/program/src/borsh.rs +++ b/sdk/program/src/borsh.rs @@ -171,3 +171,120 @@ macro_rules! impl_get_instance_packed_len { } } pub(crate) use impl_get_instance_packed_len; + +#[cfg(test)] +macro_rules! impl_tests { + ($borsh:ident) => { + use { + super::*, + std::{collections::HashMap, mem::size_of}, + $borsh::{maybestd::io::ErrorKind, BorshDeserialize, BorshSerialize}, + }; + + type Child = [u8; 64]; + type Parent = Vec; + + #[test] + fn unchecked_deserialization() { + let parent = vec![[0u8; 64], [1u8; 64], [2u8; 64]]; + + // exact size, both work + let mut byte_vec = vec![0u8; 4 + get_packed_len::() * 3]; + let mut bytes = byte_vec.as_mut_slice(); + parent.serialize(&mut bytes).unwrap(); + let deserialized = Parent::try_from_slice(&byte_vec).unwrap(); + assert_eq!(deserialized, parent); + let deserialized = try_from_slice_unchecked::(&byte_vec).unwrap(); + assert_eq!(deserialized, parent); + + // too big, only unchecked works + let mut byte_vec = vec![0u8; 4 + get_packed_len::() * 10]; + let mut bytes = byte_vec.as_mut_slice(); + parent.serialize(&mut bytes).unwrap(); + let err = Parent::try_from_slice(&byte_vec).unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InvalidData); + let deserialized = try_from_slice_unchecked::(&byte_vec).unwrap(); + assert_eq!(deserialized, parent); + } + + #[test] + fn packed_len() { + assert_eq!(get_packed_len::(), size_of::()); + assert_eq!(get_packed_len::(), size_of::() * 64); + } + + #[test] + fn instance_packed_len_matches_packed_len() { + let child = [0u8; 64]; + assert_eq!( + get_packed_len::(), + get_instance_packed_len(&child).unwrap(), + ); + assert_eq!( + get_packed_len::(), + get_instance_packed_len(&0u8).unwrap(), + ); + assert_eq!( + get_packed_len::(), + get_instance_packed_len(&0u16).unwrap(), + ); + assert_eq!( + get_packed_len::(), + get_instance_packed_len(&0u32).unwrap(), + ); + assert_eq!( + get_packed_len::(), + get_instance_packed_len(&0u64).unwrap(), + ); + assert_eq!( + get_packed_len::(), + get_instance_packed_len(&0u128).unwrap(), + ); + assert_eq!( + get_packed_len::<[u8; 10]>(), + get_instance_packed_len(&[0u8; 10]).unwrap(), + ); + assert_eq!( + get_packed_len::<(i8, i16, i32, i64, i128)>(), + get_instance_packed_len(&(i8::MAX, i16::MAX, i32::MAX, i64::MAX, i128::MAX)) + .unwrap(), + ); + } + + #[test] + fn instance_packed_len_with_vec() { + let parent = vec![ + [0u8; 64], [1u8; 64], [2u8; 64], [3u8; 64], [4u8; 64], [5u8; 64], + ]; + assert_eq!( + get_instance_packed_len(&parent).unwrap(), + 4 + parent.len() * get_packed_len::() + ); + } + + #[test] + fn instance_packed_len_with_varying_sizes_in_hashmap() { + let mut data = HashMap::new(); + let key1 = "the first string, it's actually really really long".to_string(); + let value1 = "".to_string(); + let key2 = "second string, shorter".to_string(); + let value2 = "a real value".to_string(); + let key3 = "third".to_string(); + let value3 = "an even longer value".to_string(); + data.insert(key1.clone(), value1.clone()); + data.insert(key2.clone(), value2.clone()); + data.insert(key3.clone(), value3.clone()); + assert_eq!( + get_instance_packed_len(&data).unwrap(), + 4 + get_instance_packed_len(&key1).unwrap() + + get_instance_packed_len(&value1).unwrap() + + get_instance_packed_len(&key2).unwrap() + + get_instance_packed_len(&value2).unwrap() + + get_instance_packed_len(&key3).unwrap() + + get_instance_packed_len(&value3).unwrap() + ); + } + }; +} +#[cfg(test)] +pub(crate) use impl_tests; diff --git a/sdk/program/src/borsh0_10.rs b/sdk/program/src/borsh0_10.rs index 0a351e2a1623e7..d4830fa2bfe494 100644 --- a/sdk/program/src/borsh0_10.rs +++ b/sdk/program/src/borsh0_10.rs @@ -12,191 +12,6 @@ impl_get_instance_packed_len!(borsh); #[cfg(test)] mod tests { - use { - super::*, - borsh::{maybestd::io::ErrorKind, BorshDeserialize, BorshSchema, BorshSerialize}, - std::{collections::HashMap, mem::size_of}, - }; - - #[derive(PartialEq, Eq, Clone, Debug, BorshSerialize, BorshDeserialize, BorshSchema)] - enum TestEnum { - NoValue, - Number(u32), - Struct { - #[allow(dead_code)] - number: u64, - #[allow(dead_code)] - array: [u8; 8], - }, - } - - // for test simplicity - impl Default for TestEnum { - fn default() -> Self { - Self::NoValue - } - } - - #[derive(Default, BorshSerialize, BorshDeserialize, BorshSchema)] - struct TestStruct { - pub array: [u64; 16], - pub number_u128: u128, - pub number_u32: u32, - pub tuple: (u8, u16), - pub enumeration: TestEnum, - pub r#bool: bool, - } - - #[derive(Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize, BorshSchema)] - struct Child { - pub data: [u8; 64], - } - - #[derive(Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize, BorshSchema)] - struct Parent { - pub data: Vec, - } - - #[test] - fn unchecked_deserialization() { - let data = vec![ - Child { data: [0u8; 64] }, - Child { data: [1u8; 64] }, - Child { data: [2u8; 64] }, - ]; - let parent = Parent { data }; - - // exact size, both work - let mut byte_vec = vec![0u8; 4 + get_packed_len::() * 3]; - let mut bytes = byte_vec.as_mut_slice(); - parent.serialize(&mut bytes).unwrap(); - let deserialized = Parent::try_from_slice(&byte_vec).unwrap(); - assert_eq!(deserialized, parent); - let deserialized = try_from_slice_unchecked::(&byte_vec).unwrap(); - assert_eq!(deserialized, parent); - - // too big, only unchecked works - let mut byte_vec = vec![0u8; 4 + get_packed_len::() * 10]; - let mut bytes = byte_vec.as_mut_slice(); - parent.serialize(&mut bytes).unwrap(); - let err = Parent::try_from_slice(&byte_vec).unwrap_err(); - assert_eq!(err.kind(), ErrorKind::InvalidData); - let deserialized = try_from_slice_unchecked::(&byte_vec).unwrap(); - assert_eq!(deserialized, parent); - } - - #[test] - fn packed_len() { - assert_eq!( - get_packed_len::(), - size_of::() + size_of::() + u8::BITS as usize - ); - assert_eq!( - get_packed_len::(), - size_of::() * 16 - + size_of::() - + size_of::() - + size_of::() - + size_of::() - + size_of::() - + get_packed_len::() - ); - } - - #[test] - fn instance_packed_len_matches_packed_len() { - let enumeration = TestEnum::Struct { - number: u64::MAX, - array: [255; 8], - }; - assert_eq!( - get_packed_len::(), - get_instance_packed_len(&enumeration).unwrap(), - ); - let test_struct = TestStruct { - enumeration, - ..TestStruct::default() - }; - assert_eq!( - get_packed_len::(), - get_instance_packed_len(&test_struct).unwrap(), - ); - assert_eq!( - get_packed_len::(), - get_instance_packed_len(&0u8).unwrap(), - ); - assert_eq!( - get_packed_len::(), - get_instance_packed_len(&0u16).unwrap(), - ); - assert_eq!( - get_packed_len::(), - get_instance_packed_len(&0u32).unwrap(), - ); - assert_eq!( - get_packed_len::(), - get_instance_packed_len(&0u64).unwrap(), - ); - assert_eq!( - get_packed_len::(), - get_instance_packed_len(&0u128).unwrap(), - ); - assert_eq!( - get_packed_len::<[u8; 10]>(), - get_instance_packed_len(&[0u8; 10]).unwrap(), - ); - assert_eq!( - get_packed_len::<(i8, i16, i32, i64, i128)>(), - get_instance_packed_len(&(i8::MAX, i16::MAX, i32::MAX, i64::MAX, i128::MAX)).unwrap(), - ); - } - - #[test] - fn instance_packed_len_with_vec() { - let data = vec![ - Child { data: [0u8; 64] }, - Child { data: [1u8; 64] }, - Child { data: [2u8; 64] }, - Child { data: [3u8; 64] }, - Child { data: [4u8; 64] }, - Child { data: [5u8; 64] }, - ]; - let parent = Parent { data }; - assert_eq!( - get_instance_packed_len(&parent).unwrap(), - 4 + parent.data.len() * get_packed_len::() - ); - } - - #[derive(Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize, BorshSchema)] - struct StructWithHashMap { - data: HashMap, - } - - #[test] - fn instance_packed_len_with_varying_sizes_in_hashmap() { - let mut data = HashMap::new(); - let string1 = "the first string, it's actually really really long".to_string(); - let enum1 = TestEnum::NoValue; - let string2 = "second string, shorter".to_string(); - let enum2 = TestEnum::Number(u32::MAX); - let string3 = "third".to_string(); - let enum3 = TestEnum::Struct { - number: 0, - array: [0; 8], - }; - data.insert(string1.clone(), enum1.clone()); - data.insert(string2.clone(), enum2.clone()); - data.insert(string3.clone(), enum3.clone()); - let instance = StructWithHashMap { data }; - assert_eq!( - get_instance_packed_len(&instance).unwrap(), - 4 + get_instance_packed_len(&string1).unwrap() - + get_instance_packed_len(&enum1).unwrap() - + get_instance_packed_len(&string2).unwrap() - + get_instance_packed_len(&enum2).unwrap() - + get_instance_packed_len(&string3).unwrap() - + get_instance_packed_len(&enum3).unwrap() - ); - } + use crate::borsh::impl_tests; + impl_tests!(borsh); } diff --git a/sdk/program/src/borsh0_9.rs b/sdk/program/src/borsh0_9.rs index 62140b18514cce..83f62bc0037d4d 100644 --- a/sdk/program/src/borsh0_9.rs +++ b/sdk/program/src/borsh0_9.rs @@ -34,112 +34,6 @@ impl_get_instance_packed_len!( #[cfg(test)] #[allow(deprecated)] mod tests { - use { - super::*, - borsh0_9::{maybestd::io::ErrorKind, BorshDeserialize, BorshSerialize}, - std::{collections::HashMap, mem::size_of}, - }; - - type Child = [u8; 64]; - type Parent = Vec; - - #[test] - fn unchecked_deserialization() { - let parent = vec![[0u8; 64], [1u8; 64], [2u8; 64]]; - - // exact size, both work - let mut byte_vec = vec![0u8; 4 + get_packed_len::() * 3]; - let mut bytes = byte_vec.as_mut_slice(); - parent.serialize(&mut bytes).unwrap(); - let deserialized = Parent::try_from_slice(&byte_vec).unwrap(); - assert_eq!(deserialized, parent); - let deserialized = try_from_slice_unchecked::(&byte_vec).unwrap(); - assert_eq!(deserialized, parent); - - // too big, only unchecked works - let mut byte_vec = vec![0u8; 4 + get_packed_len::() * 10]; - let mut bytes = byte_vec.as_mut_slice(); - parent.serialize(&mut bytes).unwrap(); - let err = Parent::try_from_slice(&byte_vec).unwrap_err(); - assert_eq!(err.kind(), ErrorKind::InvalidData); - let deserialized = try_from_slice_unchecked::(&byte_vec).unwrap(); - assert_eq!(deserialized, parent); - } - - #[test] - fn packed_len() { - assert_eq!(get_packed_len::(), size_of::()); - assert_eq!(get_packed_len::(), size_of::() * 64); - } - - #[test] - fn instance_packed_len_matches_packed_len() { - let child = [0u8; 64]; - assert_eq!( - get_packed_len::(), - get_instance_packed_len(&child).unwrap(), - ); - assert_eq!( - get_packed_len::(), - get_instance_packed_len(&0u8).unwrap(), - ); - assert_eq!( - get_packed_len::(), - get_instance_packed_len(&0u16).unwrap(), - ); - assert_eq!( - get_packed_len::(), - get_instance_packed_len(&0u32).unwrap(), - ); - assert_eq!( - get_packed_len::(), - get_instance_packed_len(&0u64).unwrap(), - ); - assert_eq!( - get_packed_len::(), - get_instance_packed_len(&0u128).unwrap(), - ); - assert_eq!( - get_packed_len::<[u8; 10]>(), - get_instance_packed_len(&[0u8; 10]).unwrap(), - ); - assert_eq!( - get_packed_len::<(i8, i16, i32, i64, i128)>(), - get_instance_packed_len(&(i8::MAX, i16::MAX, i32::MAX, i64::MAX, i128::MAX)).unwrap(), - ); - } - - #[test] - fn instance_packed_len_with_vec() { - let parent = vec![ - [0u8; 64], [1u8; 64], [2u8; 64], [3u8; 64], [4u8; 64], [5u8; 64], - ]; - assert_eq!( - get_instance_packed_len(&parent).unwrap(), - 4 + parent.len() * get_packed_len::() - ); - } - - #[test] - fn instance_packed_len_with_varying_sizes_in_hashmap() { - let mut data = HashMap::new(); - let key1 = "the first string, it's actually really really long".to_string(); - let value1 = "".to_string(); - let key2 = "second string, shorter".to_string(); - let value2 = "a real value".to_string(); - let key3 = "third".to_string(); - let value3 = "an even longer value".to_string(); - data.insert(key1.clone(), value1.clone()); - data.insert(key2.clone(), value2.clone()); - data.insert(key3.clone(), value3.clone()); - assert_eq!( - get_instance_packed_len(&data).unwrap(), - 4 + get_instance_packed_len(&key1).unwrap() - + get_instance_packed_len(&value1).unwrap() - + get_instance_packed_len(&key2).unwrap() - + get_instance_packed_len(&value2).unwrap() - + get_instance_packed_len(&key3).unwrap() - + get_instance_packed_len(&value3).unwrap() - ); - } + use crate::borsh::impl_tests; + impl_tests!(borsh0_9); }