mirror of
https://github.com/zaphar/merkle-dag.git
synced 2025-07-22 18:50:13 -04:00
Add another test for for idempotency
This commit is contained in:
parent
b8f3d9c630
commit
be789a2fee
@ -8,3 +8,10 @@ license = "Apache License 2.0"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
|
||||
[dependencies.proptest]
|
||||
version = "1.0.0"
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
default = []
|
@ -23,6 +23,8 @@ mod node;
|
||||
pub enum EdgeError {
|
||||
NoSuchDependents,
|
||||
}
|
||||
// TODO(jwall): In order to avoid copies it is probably smart to have some concept of
|
||||
// a node pool.
|
||||
|
||||
/// A Merkle-DAG implementation. This is a modification on the standard Merkle Tree data structure
|
||||
/// but instead of a tree it is a DAG and as a result can have multiple roots. A merkle-dag specifies
|
||||
@ -114,3 +116,6 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
#[cfg(all(test, feature = "proptest"))]
|
||||
mod proptest;
|
||||
|
58
src/proptest.rs
Normal file
58
src/proptest.rs
Normal file
@ -0,0 +1,58 @@
|
||||
// Copyright 2022 Jeremy Wall (Jeremy@marzhilsltudios.com)
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
use proptest::prelude::*;
|
||||
use std::collections::{hash_map::DefaultHasher, BTreeMap, BTreeSet};
|
||||
|
||||
use crate::DAG;
|
||||
|
||||
fn edge_strategy(nodes_count: usize) -> impl Strategy<Value = (Vec<String>, BTreeSet<usize>)> {
|
||||
prop::collection::vec(".*", 4..nodes_count).prop_flat_map(|payloads| {
|
||||
let nodes_len = payloads.len();
|
||||
// TODO(jwall): Generate valid DAGs
|
||||
// select a random set of payloads to be roots.
|
||||
// select a random set of non root payloads to be dependencies
|
||||
(
|
||||
// our total list of nodes.
|
||||
Just(payloads),
|
||||
// our random list of roots.
|
||||
prop::collection::btree_set(1..nodes_len, 1..(nodes_len / 2)),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn test_dag_add_node_properties((nodes, parent_idxs) in edge_strategy(100)) {
|
||||
// TODO implement the tests now
|
||||
let mut dag = DAG::<String, DefaultHasher, 8>::new();
|
||||
let parent_count = parent_idxs.len();
|
||||
let mut dependents = BTreeMap::new();
|
||||
for (idx, n) in nodes.iter().cloned().enumerate() {
|
||||
if !parent_idxs.contains(&idx) {
|
||||
let node_id = dag.add_node(n, BTreeSet::new()).unwrap();
|
||||
let parent = idx % parent_count;
|
||||
if dependents.contains_key(&parent) {
|
||||
dependents.get_mut(&parent).map(|v: &mut BTreeSet<[u8; 8]>| v.insert(node_id));
|
||||
} else {
|
||||
dependents.insert(parent, BTreeSet::from([node_id]));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (pidx, dep_ids) in dependents {
|
||||
dag.add_node(nodes[pidx].clone(), dep_ids).unwrap();
|
||||
}
|
||||
assert!(dag.get_roots().len() <= parent_count);
|
||||
assert!(dag.get_nodes().len() <= nodes.len());
|
||||
}
|
||||
}
|
22
src/test.rs
22
src/test.rs
@ -61,3 +61,25 @@ fn test_adding_nodes_is_idempotent() {
|
||||
assert_eq!(root_size, dag.get_roots().len());
|
||||
assert_eq!(nodes_size, dag.get_nodes().len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_adding_nodes_is_idempotent_regardless_of_dep_order() {
|
||||
let mut dag = DAG::<&str, DefaultHasher, 8>::new();
|
||||
let quake_node_id = dag.add_node("quake", BTreeSet::new()).unwrap();
|
||||
let qualm_node_id = dag.add_node("qualm", BTreeSet::new()).unwrap();
|
||||
let quell_node_id = dag.add_node("quell", BTreeSet::new()).unwrap();
|
||||
let dep_ids = BTreeSet::from([quake_node_id, qualm_node_id, quell_node_id]);
|
||||
dag.add_node("foo", dep_ids).unwrap();
|
||||
let root_size = dag.get_roots().len();
|
||||
let nodes_size = dag.get_nodes().len();
|
||||
|
||||
let dep_ids = BTreeSet::from([quell_node_id, quake_node_id, qualm_node_id]);
|
||||
dag.add_node("foo", dep_ids).unwrap();
|
||||
assert_eq!(root_size, dag.get_roots().len());
|
||||
assert_eq!(nodes_size, dag.get_nodes().len());
|
||||
|
||||
let dep_ids = BTreeSet::from([qualm_node_id, quell_node_id, quake_node_id]);
|
||||
dag.add_node("foo", dep_ids).unwrap();
|
||||
assert_eq!(root_size, dag.get_roots().len());
|
||||
assert_eq!(nodes_size, dag.get_nodes().len());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user