diff --git a/Cargo.lock b/Cargo.lock index 1e079856c7a8..54f3212aefe5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2894,6 +2894,7 @@ dependencies = [ "num-bigint 0.4.3", "once_cell", "quickcheck", + "quickcheck_macros", "serde", "serde_json", "sha2 0.10.6", diff --git a/blockchain/blocks/Cargo.toml b/blockchain/blocks/Cargo.toml index 7c6da52bef46..f60a7934ffa4 100644 --- a/blockchain/blocks/Cargo.toml +++ b/blockchain/blocks/Cargo.toml @@ -30,4 +30,5 @@ thiserror.workspace = true async-std.workspace = true forest_test_utils.workspace = true hex.workspace = true +quickcheck_macros.workspace = true serde_json.workspace = true diff --git a/blockchain/blocks/src/tipset.rs b/blockchain/blocks/src/tipset.rs index ee06e792390b..c21e2c85cfff 100644 --- a/blockchain/blocks/src/tipset.rs +++ b/blockchain/blocks/src/tipset.rs @@ -55,6 +55,50 @@ impl quickcheck::Arbitrary for Tipset { } } +#[cfg(test)] +mod property_tests { + use super::tipset_json::{TipsetJson, TipsetJsonRef}; + use super::tipset_keys_json::TipsetKeysJson; + use super::{Tipset, TipsetKeys}; + use cid::Cid; + use quickcheck_macros::quickcheck; + use serde_json; + + #[derive(Clone)] + struct ArbitraryCid(Cid); + + impl quickcheck::Arbitrary for ArbitraryCid { + fn arbitrary(g: &mut quickcheck::Gen) -> Self { + ArbitraryCid(Cid::new_v1( + u64::arbitrary(g), + cid::multihash::Multihash::wrap(u64::arbitrary(g), &[u8::arbitrary(g)]).unwrap(), + )) + } + } + + impl quickcheck::Arbitrary for TipsetKeys { + fn arbitrary(g: &mut quickcheck::Gen) -> Self { + let arbitrary_cids: Vec = Vec::arbitrary(g); + let cids: Vec = arbitrary_cids.iter().map(|cid| cid.0).collect(); + Self { cids } + } + } + + #[quickcheck] + fn tipset_keys_roundtrip(tipset_keys: TipsetKeys) { + let serialized = serde_json::to_string(&TipsetKeysJson(tipset_keys.clone())).unwrap(); + let parsed: TipsetKeysJson = serde_json::from_str(&serialized).unwrap(); + assert_eq!(tipset_keys, parsed.0); + } + + #[quickcheck] + fn tipset_roundtrip(tipset: Tipset) { + let serialized = serde_json::to_string(&TipsetJsonRef(&tipset)).unwrap(); + let parsed: TipsetJson = serde_json::from_str(&serialized).unwrap(); + assert_eq!(&tipset, parsed.0.as_ref()); + } +} + impl From for Tipset { fn from(full_tipset: FullTipset) -> Self { let key = full_tipset.key;