From 4c49f09515308b5794e1a1bebbf08a0210c625f9 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Mon, 2 Sep 2019 18:05:20 +0300 Subject: [PATCH] extra quick-checks and fixes for deleting from full root --- src/tree.rs | 105 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 11 deletions(-) diff --git a/src/tree.rs b/src/tree.rs index c3e0bed..008a19a 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -153,7 +153,7 @@ impl Tree { merge_stack.push(new_leaf_link); while let Some(next_peak) = peaks.pop() { - let next_merge = merge_stack.pop().expect("there should be at least one, checked below"); + let next_merge = merge_stack.pop().expect("there should be at least one, initial or re-pushed"); if let Some(stored) = { let peak = self.resolve_link(next_peak); @@ -171,7 +171,7 @@ impl Tree { merge_stack.push(next_peak); } - let mut new_root = merge_stack.pop().expect("There should be at least one node in stack"); + let mut new_root = merge_stack.pop().expect("Loop above cannot reduce the merge_stack"); while let Some(next_child) = merge_stack.pop() { new_root = self.push_generated( combine_nodes( @@ -211,7 +211,7 @@ impl Tree { let (leaves, root_left_child) = { let n = self.resolve_link(root); ( - n.node.data.end_height - n.node.data.start_height + 1, + n.node.leaf_count(), n.node.left.expect("Root should have left child while deleting") ) }; @@ -239,21 +239,21 @@ impl Tree { .expect("If left exists, right should exist as well"); truncated += 1; } else { + if root.node.complete() { truncated += 1; } break; } } - let root = peaks.drain(0..1).nth(0).expect("At lest 2 elements in peaks"); - let new_root = peaks.into_iter().fold( - root, - |root, next_peak| - self.push_generated( + let mut new_root = peaks.drain(0..1).nth(0).expect("At lest 2 elements in peaks"); + + for next_peak in peaks.into_iter() { + new_root = self.push_generated( combine_nodes( - self.resolve_link(root), + self.resolve_link(new_root), self.resolve_link(next_peak) ) - ) - ); + ); + } for _ in 0..truncated { self.pop(); } @@ -601,6 +601,22 @@ mod tests { assert_eq!(tree.len(), 16); } + #[test] + fn tree_len() { + let (mut root, mut tree) = initial(); + + assert_eq!(tree.len(), 3); + + for i in 0..2 { + root = tree.append_leaf(root, leaf(i+3)).new_root; + } + assert_eq!(tree.len(), 7); + + root = tree.truncate_leaf(root).new_root; + + assert_eq!(tree.len(), 4); + } + quickcheck! { fn there_and_back(number: u32) -> TestResult { @@ -631,5 +647,72 @@ mod tests { TestResult::from_bool(tree.resolve_link(root).node.leaf_count() == number) } } + + fn parity(number: u32) -> TestResult { + if number > 2048 * 2048 || number < 3 { + TestResult::discard() + } else { + let (mut root, mut tree) = initial(); + for i in 1..(number-1) { + root = tree.append_leaf(root, leaf(i+2)).new_root; + } + + TestResult::from_bool( + if number & number - 1 == 0 { + if let NodeLink::Stored(_) = root { true } + else { false } + } else { + if let NodeLink::Generated(_) = root { true } + else { false } + } + ) + } + } + + fn parity_with_truncate(add: u32, delete: u32) -> TestResult { + // First we add `add` number of leaves, then delete `delete` number of leaves + // What is left should be consistent with generated-stored structure + if add > 2048 * 2048 || add < delete { + TestResult::discard() + } else { + let (mut root, mut tree) = initial(); + for i in 0..add { + root = tree.append_leaf(root, leaf(i+3)).new_root; + } + for _ in 0..delete { + root = tree.truncate_leaf(root).new_root; + } + + let total = add - delete + 2; + + TestResult::from_bool( + if total & total - 1 == 0 { + if let NodeLink::Stored(_) = root { true } + else { false } + } else { + if let NodeLink::Generated(_) = root { true } + else { false } + } + ) + } + } + + fn stored_length(add: u32, delete: u32) -> TestResult { + if add > 2048 * 2048 || add < delete { + TestResult::discard() + } else { + let (mut root, mut tree) = initial(); + for i in 0..add { + root = tree.append_leaf(root, leaf(i+3)).new_root; + } + for _ in 0..delete { + root = tree.truncate_leaf(root).new_root; + } + + let total = add - delete + 2; + + TestResult::from_bool(total * total > tree.len()) + } + } } } \ No newline at end of file