From 4035d254ad538dd642fe031fbecfae55d9a4f31d Mon Sep 17 00:00:00 2001 From: Michael Sproul Date: Wed, 12 Apr 2023 16:46:48 +1000 Subject: [PATCH] Implement Arbitrary (#7) --- Cargo.toml | 2 ++ src/interface.rs | 3 ++- src/leaf.rs | 10 ++++++++-- src/list.rs | 12 +++++++++--- src/packed_leaf.rs | 6 ++++-- src/tree.rs | 8 ++++++-- src/update_map.rs | 5 ++++- src/utils.rs | 18 ++++++++++++++++-- src/vector.rs | 12 +++++++++--- 9 files changed, 60 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3abc682..a59ad0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,8 @@ triomphe = "0.1.5" typenum = "1.14.0" vec_map = "0.8.2" smallvec = "1.8.0" +arbitrary = { version = "1.2.3", features = ["derive"] } +ethereum-types = { version = "0.14.1", features = ["arbitrary"] } [dev-dependencies] ssz_types = "0.5.0" diff --git a/src/interface.rs b/src/interface.rs index 1ec7c0c..4ecb7f3 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -5,6 +5,7 @@ use crate::{ iter::Iter, Cow, Error, }; +use arbitrary::Arbitrary; use std::collections::BTreeMap; use std::marker::PhantomData; use tree_hash::{Hash256, TreeHash}; @@ -37,7 +38,7 @@ where ) -> Result<(), Error>; } -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, Arbitrary)] pub struct Interface where T: TreeHash + Clone, diff --git a/src/leaf.rs b/src/leaf.rs index 709f59b..bd64bfe 100644 --- a/src/leaf.rs +++ b/src/leaf.rs @@ -1,13 +1,19 @@ -use crate::Arc; +use crate::{ + utils::{arb_arc, arb_rwlock}, + Arc, +}; +use arbitrary::Arbitrary; use derivative::Derivative; use parking_lot::RwLock; use tree_hash::Hash256; -#[derive(Debug, Derivative)] +#[derive(Debug, Derivative, Arbitrary)] #[derivative(PartialEq, Hash)] pub struct Leaf { #[derivative(PartialEq = "ignore", Hash = "ignore")] + #[arbitrary(with = arb_rwlock)] pub hash: RwLock, + #[arbitrary(with = arb_arc)] pub value: Arc, } diff --git a/src/list.rs b/src/list.rs index e8dc47b..7a8faae 100644 --- a/src/list.rs +++ b/src/list.rs @@ -4,8 +4,9 @@ use crate::interface_iter::{InterfaceIter, InterfaceIterCow}; use crate::iter::Iter; use crate::serde::ListVisitor; use crate::update_map::MaxMap; -use crate::utils::{int_log, opt_packing_depth, updated_length, Length}; +use crate::utils::{arb_arc, int_log, opt_packing_depth, updated_length, Length}; use crate::{Arc, Cow, Error, Tree, UpdateMap}; +use arbitrary::Arbitrary; use derivative::Derivative; use itertools::process_results; use serde::{ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer}; @@ -16,20 +17,25 @@ use tree_hash::{Hash256, PackedEncoding, TreeHash}; use typenum::Unsigned; use vec_map::VecMap; -#[derive(Debug, Clone, Derivative)] +#[derive(Debug, Clone, Derivative, Arbitrary)] #[derivative(PartialEq( bound = "T: TreeHash + PartialEq + Clone, N: Unsigned, U: UpdateMap + PartialEq" ))] +#[arbitrary(bound = "T: Arbitrary<'arbitrary> + TreeHash + PartialEq + Clone")] +#[arbitrary(bound = "N: Unsigned, U: Arbitrary<'arbitrary> + UpdateMap + PartialEq")] pub struct List = MaxMap>> { pub(crate) interface: Interface, U>, } -#[derive(Debug, Clone, Derivative)] +#[derive(Debug, Clone, Derivative, Arbitrary)] #[derivative(PartialEq(bound = "T: TreeHash + PartialEq + Clone, N: Unsigned"))] +#[arbitrary(bound = "T: Arbitrary<'arbitrary> + TreeHash + PartialEq + Clone, N: Unsigned")] pub struct ListInner { + #[arbitrary(with = arb_arc)] pub(crate) tree: Arc>, pub(crate) length: Length, pub(crate) depth: usize, + #[arbitrary(default)] _phantom: PhantomData, } diff --git a/src/packed_leaf.rs b/src/packed_leaf.rs index 0862fbf..b0f3770 100644 --- a/src/packed_leaf.rs +++ b/src/packed_leaf.rs @@ -1,13 +1,15 @@ -use crate::{Error, UpdateMap}; +use crate::{utils::arb_rwlock, Error, UpdateMap}; +use arbitrary::Arbitrary; use derivative::Derivative; use parking_lot::RwLock; use std::ops::ControlFlow; use tree_hash::{Hash256, TreeHash, BYTES_PER_CHUNK}; -#[derive(Debug, Derivative)] +#[derive(Debug, Derivative, Arbitrary)] #[derivative(PartialEq, Hash)] pub struct PackedLeaf { #[derivative(PartialEq = "ignore", Hash = "ignore")] + #[arbitrary(with = arb_rwlock)] pub hash: RwLock, pub(crate) values: Vec, } diff --git a/src/tree.rs b/src/tree.rs index 31bc0b0..5b99058 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,5 +1,6 @@ -use crate::utils::{opt_hash, opt_packing_depth, opt_packing_factor}; +use crate::utils::{arb_arc, arb_rwlock, opt_hash, opt_packing_depth, opt_packing_factor}; use crate::{Arc, Error, Leaf, PackedLeaf, UpdateMap}; +use arbitrary::Arbitrary; use derivative::Derivative; use ethereum_hashing::{hash32_concat, ZERO_HASHES}; use parking_lot::RwLock; @@ -10,15 +11,18 @@ use std::collections::BTreeMap; use std::ops::ControlFlow; use tree_hash::{Hash256, TreeHash}; -#[derive(Debug, Derivative)] +#[derive(Debug, Derivative, Arbitrary)] #[derivative(PartialEq, Hash)] pub enum Tree { Leaf(Leaf), PackedLeaf(PackedLeaf), Node { #[derivative(PartialEq = "ignore", Hash = "ignore")] + #[arbitrary(with = arb_rwlock)] hash: RwLock, + #[arbitrary(with = arb_arc)] left: Arc, + #[arbitrary(with = arb_arc)] right: Arc, }, Zero(usize), diff --git a/src/update_map.rs b/src/update_map.rs index 827bb5d..eb7ea4a 100644 --- a/src/update_map.rs +++ b/src/update_map.rs @@ -1,5 +1,6 @@ use crate::cow::{BTreeCow, Cow, VecCow}; use crate::utils::max_btree_index; +use arbitrary::Arbitrary; use std::collections::{btree_map::Entry, BTreeMap}; use std::ops::ControlFlow; use vec_map::VecMap; @@ -162,8 +163,10 @@ impl UpdateMap for VecMap { } } -#[derive(Debug, Default, Clone, PartialEq)] +#[derive(Debug, Default, Clone, PartialEq, Arbitrary)] +#[arbitrary(bound = "M: Default")] pub struct MaxMap { + #[arbitrary(default)] inner: M, max_key: usize, } diff --git a/src/utils.rs b/src/utils.rs index 943c7ff..eeef206 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,9 +1,11 @@ -use crate::UpdateMap; +use crate::{Arc, UpdateMap}; +use arbitrary::Arbitrary; +use parking_lot::RwLock; use std::collections::BTreeMap; use tree_hash::{Hash256, TreeHash, TreeHashType}; /// Length type, to avoid confusion with depth and other `usize` parameters. -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Arbitrary)] pub struct Length(pub usize); impl Length { @@ -60,3 +62,15 @@ pub fn opt_hash( ) -> Option { hashes?.get(&(depth, prefix)).copied() } + +pub fn arb_arc<'a, T: Arbitrary<'a>>( + u: &mut arbitrary::Unstructured<'a>, +) -> arbitrary::Result> { + T::arbitrary(u).map(Arc::new) +} + +pub fn arb_rwlock<'a, T: Arbitrary<'a>>( + u: &mut arbitrary::Unstructured<'a>, +) -> arbitrary::Result> { + T::arbitrary(u).map(RwLock::new) +} diff --git a/src/vector.rs b/src/vector.rs index 3d080a1..cce220d 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -2,8 +2,9 @@ use crate::interface::{ImmList, Interface, MutList}; use crate::interface_iter::InterfaceIter; use crate::iter::Iter; use crate::update_map::MaxMap; -use crate::utils::Length; +use crate::utils::{arb_arc, Length}; use crate::{Arc, Cow, Error, List, Tree, UpdateMap}; +use arbitrary::Arbitrary; use derivative::Derivative; use serde::{Deserialize, Serialize}; use ssz::{Decode, Encode, SszEncoder, TryFromIter, BYTES_PER_LENGTH_OFFSET}; @@ -14,7 +15,7 @@ use tree_hash::{Hash256, PackedEncoding, TreeHash}; use typenum::Unsigned; use vec_map::VecMap; -#[derive(Debug, Derivative, Clone, Serialize, Deserialize)] +#[derive(Debug, Derivative, Clone, Serialize, Deserialize, Arbitrary)] #[derivative(PartialEq( bound = "T: TreeHash + Clone + PartialEq, N: Unsigned, U: UpdateMap + PartialEq" ))] @@ -24,15 +25,20 @@ use vec_map::VecMap; #[serde(bound( deserialize = "T: TreeHash + Clone + Deserialize<'de>, N: Unsigned, U: UpdateMap" ))] +#[arbitrary(bound = "T: Arbitrary<'arbitrary> + TreeHash + Clone")] +#[arbitrary(bound = "N: Unsigned, U: Arbitrary<'arbitrary> + UpdateMap")] pub struct Vector = MaxMap>> { pub(crate) interface: Interface, U>, } -#[derive(Debug, Derivative, Clone)] +#[derive(Debug, Derivative, Clone, Arbitrary)] #[derivative(PartialEq(bound = "T: TreeHash + Clone + PartialEq, N: Unsigned"))] +#[arbitrary(bound = "T: Arbitrary<'arbitrary> + TreeHash + Clone, N: Unsigned")] pub struct VectorInner { + #[arbitrary(with = arb_arc)] pub(crate) tree: Arc>, pub(crate) depth: usize, + #[arbitrary(default)] _phantom: PhantomData, }