diff --git a/grovedb/src/batch.rs b/grovedb/src/batch.rs index e0e50531b..a25f4fdf8 100644 --- a/grovedb/src/batch.rs +++ b/grovedb/src/batch.rs @@ -475,8 +475,8 @@ mod tests { #[test] fn test_batch_validation_ok() { let db = make_grovedb(); - let element = Element::Item(b"ayy".to_vec()); - let element2 = Element::Item(b"ayy2".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); + let element2 = Element::new_item(b"ayy2".to_vec()); let ops = vec![ GroveDbOp::insert(vec![], b"key1".to_vec(), Element::empty_tree()), GroveDbOp::insert( @@ -530,7 +530,7 @@ mod tests { #[test] fn test_batch_validation_broken_chain() { let db = make_grovedb(); - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); let ops = vec![ GroveDbOp::insert(vec![], b"key1".to_vec(), Element::empty_tree()), GroveDbOp::insert( @@ -551,7 +551,7 @@ mod tests { #[test] fn test_batch_validation_broken_chain_aborts_whole_batch() { let db = make_grovedb(); - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); let ops = vec![ GroveDbOp::insert( vec![TEST_LEAF.to_vec()], @@ -583,7 +583,7 @@ mod tests { #[test] fn test_batch_validation_deletion_brokes_chain() { let db = make_grovedb(); - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); db.insert([], b"key1", Element::empty_tree(), None) .expect("cannot insert a subtree"); @@ -609,7 +609,7 @@ mod tests { #[test] fn test_batch_validation_deletion_and_insertion_restore_chain() { let db = make_grovedb(); - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); let ops = vec![ GroveDbOp::insert(vec![], b"key1".to_vec(), Element::empty_tree()), GroveDbOp::insert( @@ -640,7 +640,7 @@ mod tests { #[test] fn test_batch_validation_insert_into_existing_tree() { let db = make_grovedb(); - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); db.insert([TEST_LEAF], b"invalid", element.clone(), None) .expect("cannot insert value"); @@ -672,8 +672,8 @@ mod tests { #[test] fn test_batch_validation_nested_subtree_overwrite() { let db = make_grovedb(); - let element = Element::Item(b"ayy".to_vec()); - let element2 = Element::Item(b"ayy2".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); + let element2 = Element::new_item(b"ayy2".to_vec()); db.insert([TEST_LEAF], b"key_subtree", Element::empty_tree(), None) .expect("cannot insert a subtree"); db.insert([TEST_LEAF, b"key_subtree"], b"key2", element, None) @@ -721,7 +721,11 @@ mod tests { fn test_batch_validation_root_leaf_removal() { let db = make_grovedb(); let ops = vec![ - GroveDbOp::insert(vec![], TEST_LEAF.to_vec(), Element::Item(b"ayy".to_vec())), + GroveDbOp::insert( + vec![], + TEST_LEAF.to_vec(), + Element::new_item(b"ayy".to_vec()), + ), GroveDbOp::insert( vec![TEST_LEAF.to_vec()], b"key1".to_vec(), @@ -734,7 +738,7 @@ mod tests { #[test] fn test_merk_data_is_deleted() { let db = make_grovedb(); - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); db.insert([TEST_LEAF], b"key1", Element::empty_tree(), None) .expect("cannot insert a subtree"); @@ -743,7 +747,7 @@ mod tests { let ops = vec![GroveDbOp::insert( vec![TEST_LEAF.to_vec()], b"key1".to_vec(), - Element::Item(b"ayy2".to_vec()), + Element::new_item(b"ayy2".to_vec()), )]; assert_eq!( @@ -770,8 +774,8 @@ mod tests { .ok() .flatten() .expect("cannot get root hash"); - let element = Element::Item(b"ayy".to_vec()); - let element2 = Element::Item(b"ayy2".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); + let element2 = Element::new_item(b"ayy2".to_vec()); let ops = vec![ GroveDbOp::insert( @@ -848,7 +852,7 @@ mod tests { acc_path.push(p); } - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); let batch = vec![GroveDbOp::insert( acc_path.clone(), b"key".to_vec(), diff --git a/grovedb/src/lib.rs b/grovedb/src/lib.rs index 73a7702fd..dda73d29b 100644 --- a/grovedb/src/lib.rs +++ b/grovedb/src/lib.rs @@ -5,10 +5,7 @@ mod subtree; mod tests; mod util; mod visualize; -use std::{ - collections::{BTreeMap, HashMap}, - path::Path, -}; +use std::{collections::BTreeMap, path::Path}; pub use merk::proofs::{query::QueryItem, Query}; use merk::{self, Merk}; diff --git a/grovedb/src/operations/delete.rs b/grovedb/src/operations/delete.rs index ba128c3db..d7d2a03b5 100644 --- a/grovedb/src/operations/delete.rs +++ b/grovedb/src/operations/delete.rs @@ -121,6 +121,62 @@ impl GroveDb { delete_element()?; } } else { + fn to_slice(x: &Vec) -> &[u8] { + x.as_slice() + } + + if let Element::Reference(ref base_element_path, _) = element { + let (base_element_key, base_element_subtree_path) = base_element_path + .split_last() + .expect("reference path cannot be empty"); + + let base_element_subtree_path_as_slice = + base_element_subtree_path.iter().map(to_slice); + let mut base_element = self.get( + base_element_subtree_path_as_slice.clone(), + base_element_key, + transaction, + )?; + + match base_element { + Element::Tree(_) => {} + Element::Item(_, ref mut references) + | Element::Reference(_, ref mut references) => { + let mut path_owned: Vec> = + path_iter.clone().map(|x| x.to_vec()).collect(); + path_owned.push(key.to_vec()); + let position = references.iter().position(|path| path == &path_owned); + if let Some(index) = position { + references.remove(index); + merk_optional_tx!( + self.db, + base_element_subtree_path_as_slice, + transaction, + mut subtree, + { + base_element.insert(&mut subtree, base_element_key)?; + } + ); + } + } + } + } + + if let Element::Item(_, references) | Element::Reference(_, references) = element { + // recursively delete all references of to be deleted element + for reference in references { + let (referenced_key, reference_subtree_path) = reference + .split_last() + .expect("reference path cannot be empty"); + self.delete_internal( + reference_subtree_path.iter().map(to_slice), + referenced_key, + false, + transaction, + )?; + } + } + delete_element()?; } self.propagate_changes(path_iter, transaction)?; diff --git a/grovedb/src/operations/get.rs b/grovedb/src/operations/get.rs index 58518a3d8..1c12dda5b 100644 --- a/grovedb/src/operations/get.rs +++ b/grovedb/src/operations/get.rs @@ -20,7 +20,7 @@ impl GroveDb {

::IntoIter: DoubleEndedIterator + ExactSizeIterator + Clone, { match self.get_raw(path, key, transaction)? { - Element::Reference(reference_path) => { + Element::Reference(reference_path, _) => { self.follow_reference(reference_path, transaction) } other => Ok(other), @@ -48,7 +48,7 @@ impl GroveDb { } visited.insert(path); match current_element { - Element::Reference(reference_path) => path = reference_path, + Element::Reference(reference_path, _) => path = reference_path, other => return Ok(other), } hops_left -= 1; @@ -89,9 +89,9 @@ impl GroveDb { let results = elements .into_iter() .map(|element| match element { - Element::Reference(reference_path) => { + Element::Reference(reference_path, _) => { let maybe_item = self.follow_reference(reference_path, transaction)?; - if let Element::Item(item) = maybe_item { + if let Element::Item(item, _) = maybe_item { Ok(item) } else { Err(Error::InvalidQuery("the reference must result in an item")) @@ -127,15 +127,15 @@ impl GroveDb { let results = elements .into_iter() .map(|element| match element { - Element::Reference(reference_path) => { + Element::Reference(reference_path, _) => { let maybe_item = self.follow_reference(reference_path, transaction)?; - if let Element::Item(item) = maybe_item { + if let Element::Item(item, _) = maybe_item { Ok(item) } else { Err(Error::InvalidQuery("the reference must result in an item")) } } - Element::Item(item) => Ok(item), + Element::Item(item, _) => Ok(item), Element::Tree(_) => Err(Error::InvalidQuery( "path_queries can only refer to items and references", )), diff --git a/grovedb/src/operations/insert.rs b/grovedb/src/operations/insert.rs index 869080a7c..8daafa75c 100644 --- a/grovedb/src/operations/insert.rs +++ b/grovedb/src/operations/insert.rs @@ -29,7 +29,7 @@ impl GroveDb { self.propagate_changes(path_iter, transaction)?; } } - Element::Reference(ref reference_path) => { + Element::Reference(ref reference_path, _) => { if path_iter.len() == 0 { return Err(Error::InvalidPath( "only subtrees are allowed as root tree's leafs", @@ -37,18 +37,56 @@ impl GroveDb { } self.check_subtree_exists_invalid_path(path_iter.clone(), Some(key), transaction)?; - let referenced_element = - self.follow_reference(reference_path.to_owned(), transaction)?; + // reference path denotes the element we are directly referencing + let (referenced_key, referenced_subtree_path) = reference_path + .split_last() + .ok_or(Error::InvalidPath("invalid reference path"))?; + + let mut referenced_element = self.get_raw( + referenced_subtree_path.iter().map(|x| x.as_slice()), + referenced_key, + transaction, + )?; + + match referenced_element { + Element::Item(_, ref mut references) + | Element::Reference(_, ref mut references) => { + let mut path_owned: Vec> = + path_iter.clone().map(|x| x.to_vec()).collect(); + path_owned.push(key.to_vec()); + references.push(path_owned); + } + _ => { + return Err(Error::InvalidPath("cannot reference tree items")); + } + } + + // update the reference list of the referenced item + merk_optional_tx!( + self.db, + referenced_subtree_path.iter().map(|x| x.as_slice()), + transaction, + mut subtree, + { + referenced_element.insert(&mut subtree, referenced_key.as_slice())?; + } + ); + self.propagate_changes( + referenced_subtree_path.iter().map(|x| x.as_slice()), + transaction, + ); + + // insert the reference + let base_element = self.follow_reference(reference_path.to_owned(), transaction)?; merk_optional_tx!(self.db, path_iter.clone(), transaction, mut subtree, { - element.insert_reference(&mut subtree, key, referenced_element.serialize()?)?; + element.insert_reference(&mut subtree, key, base_element.serialize()?)?; }); self.propagate_changes(path_iter, transaction)?; } _ => { // If path is empty that means there is an attempt to insert - // something into a root tree and this branch is for anything - // but trees + // something into a root tree and this branch is for items if path_iter.len() == 0 { return Err(Error::InvalidPath( "only subtrees are allowed as root tree's leaves", diff --git a/grovedb/src/operations/proof/generate.rs b/grovedb/src/operations/proof/generate.rs index c1b070d54..212b81733 100644 --- a/grovedb/src/operations/proof/generate.rs +++ b/grovedb/src/operations/proof/generate.rs @@ -277,7 +277,7 @@ impl GroveDb { Op::Push(node) | Op::PushInverted(node) => match node { Node::KV(_, value) => { let elem = Element::deserialize(value); - if let Ok(Element::Reference(reference_path)) = elem { + if let Ok(Element::Reference(reference_path, _)) = elem { let referenced_elem = self.follow_reference(reference_path, None)?; *value = referenced_elem.serialize().unwrap(); } diff --git a/grovedb/src/operations/proof/verify.rs b/grovedb/src/operations/proof/verify.rs index 0baa21ff1..32b17bc03 100644 --- a/grovedb/src/operations/proof/verify.rs +++ b/grovedb/src/operations/proof/verify.rs @@ -120,7 +120,6 @@ impl ProofVerifier { continue; } - if subquery_key.is_some() { if subquery_value.is_none() { self.verify_subquery_key( diff --git a/grovedb/src/subtree.rs b/grovedb/src/subtree.rs index 3e26e6c80..ce40ed352 100644 --- a/grovedb/src/subtree.rs +++ b/grovedb/src/subtree.rs @@ -23,9 +23,9 @@ use crate::{ #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] pub enum Element { /// An ordinary value - Item(Vec), + Item(Vec, Vec>>), /// A reference to an object by its path - Reference(Vec>), + Reference(Vec>, Vec>>), /// A subtree, contains a root hash of the underlying Merk. /// Hash is stored to make Merk become different when its subtrees have /// changed, otherwise changes won't be reflected in parent trees. @@ -55,25 +55,69 @@ impl Element { Element::Tree(Default::default()) } + pub fn new_item(item_value: Vec) -> Self { + Element::Item(item_value, vec![]) + } + + pub fn new_reference(reference_path: Vec>) -> Self { + Element::Reference(reference_path, vec![]) + } + /// Get the size of an element in bytes pub fn byte_size(&self) -> usize { match self { - Element::Item(item) => item.len(), - Element::Reference(path_reference) => { - path_reference.iter().map(|inner| inner.len()).sum() + Element::Item(item, references) => { + item.len() + + references + .iter() + .map(|inner| inner.iter().map(|inner| inner.len()).sum::()) + .sum::() + } + Element::Reference(path_reference, references) => { + path_reference + .iter() + .map(|inner| inner.len()) + .sum::() + + references + .iter() + .map(|inner| inner.iter().map(|inner| inner.len()).sum::()) + .sum::() } Element::Tree(_) => 32, } } /// Get the size of the serialization of an element in bytes + // TODO: Fix size calculation for item type and reference type pub fn serialized_byte_size(&self) -> usize { match self { - Element::Item(item) => { - let len = item.len(); - len + len.required_space() + 1 // 1 for enum + Element::Item(item, references) => { + let len_of_item = item.len(); + let len_of_references = references + .iter() + .map(|inner| inner.iter().map(|inner| inner.len()).sum::()) + .sum::(); + + len_of_item + + len_of_item.required_space() + + len_of_references + + len_of_references.required_space() + + 1 // 1 for enum } - Element::Reference(path_reference) => { + Element::Reference(path_reference, references) => { + let len_of_references = references + .iter() + .map(|inner| { + inner + .iter() + .map(|inner| { + let inner_len = inner.len(); + inner_len + inner_len.required_space() + }) + .sum::() + }) + .sum::(); + path_reference .iter() .map(|inner| { @@ -82,6 +126,8 @@ impl Element { }) .sum::() + path_reference.len().required_space() + + len_of_references + + len_of_references.required_space() + 1 // for the enum } Element::Tree(_) => 33, // 32 + 1 for enum @@ -561,13 +607,13 @@ mod tests { Element::empty_tree() .insert(&mut merk, b"mykey") .expect("expected successful insertion"); - Element::Item(b"value".to_vec()) + Element::new_item(b"value".to_vec()) .insert(&mut merk, b"another-key") .expect("expected successful insertion 2"); assert_eq!( Element::get(&merk, b"another-key").expect("expected successful get"), - Element::Item(b"value".to_vec()), + Element::new_item(b"value".to_vec()), ); } @@ -583,24 +629,24 @@ mod tests { "020000000000000000000000000000000000000000000000000000000000000000" ); - let item = Element::Item(hex::decode("abcdef").expect("expected to decode")); + let item = Element::new_item(hex::decode("abcdef").expect("expected to decode")); let serialized = item.serialize().expect("expected to serialize"); - assert_eq!(serialized.len(), 5); + assert_eq!(serialized.len(), 6); assert_eq!(serialized.len(), item.serialized_byte_size()); // The item is variable length 3 bytes, so it's enum 2 then 32 bytes of zeroes - assert_eq!(hex::encode(serialized), "0003abcdef"); + assert_eq!(hex::encode(serialized), "0003abcdef00"); - let reference = Element::Reference(vec![ + let reference = Element::new_reference(vec![ vec![0], hex::decode("abcd").expect("expected to decode"), vec![5], ]); let serialized = reference.serialize().expect("expected to serialize"); - assert_eq!(serialized.len(), 9); + assert_eq!(serialized.len(), 10); assert_eq!(serialized.len(), reference.serialized_byte_size()); // The item is variable length 2 bytes, so it's enum 1 then 1 byte for length, // then 1 byte for 0, then 1 byte 02 for abcd, then 1 byte '1' for 05 - assert_eq!(hex::encode(serialized), "0103010002abcd0105"); + assert_eq!(hex::encode(serialized), "0103010002abcd010500"); } #[test] @@ -611,16 +657,16 @@ mod tests { let storage_context = storage.get_storage_context([TEST_LEAF]); let mut merk = Merk::open(storage_context).expect("cannot open Merk"); - Element::Item(b"ayyd".to_vec()) + Element::new_item(b"ayyd".to_vec()) .insert(&mut merk, b"d") .expect("expected successful insertion"); - Element::Item(b"ayyc".to_vec()) + Element::new_item(b"ayyc".to_vec()) .insert(&mut merk, b"c") .expect("expected successful insertion"); - Element::Item(b"ayya".to_vec()) + Element::new_item(b"ayya".to_vec()) .insert(&mut merk, b"a") .expect("expected successful insertion"); - Element::Item(b"ayyb".to_vec()) + Element::new_item(b"ayyb".to_vec()) .insert(&mut merk, b"b") .expect("expected successful insertion"); @@ -632,8 +678,8 @@ mod tests { Element::get_query(&storage, &[TEST_LEAF], &query, None) .expect("expected successful get_query"), vec![ - Element::Item(b"ayya".to_vec()), - Element::Item(b"ayyc".to_vec()) + Element::new_item(b"ayya".to_vec()), + Element::new_item(b"ayyc".to_vec()) ] ); @@ -645,9 +691,9 @@ mod tests { Element::get_query(&storage, &[TEST_LEAF], &query, None) .expect("expected successful get_query"), vec![ - Element::Item(b"ayya".to_vec()), - Element::Item(b"ayyb".to_vec()), - Element::Item(b"ayyc".to_vec()) + Element::new_item(b"ayya".to_vec()), + Element::new_item(b"ayyb".to_vec()), + Element::new_item(b"ayyc".to_vec()) ] ); @@ -659,9 +705,9 @@ mod tests { Element::get_query(&storage, &[TEST_LEAF], &query, None) .expect("expected successful get_query"), vec![ - Element::Item(b"ayyb".to_vec()), - Element::Item(b"ayyc".to_vec()), - Element::Item(b"ayyd".to_vec()) + Element::new_item(b"ayyb".to_vec()), + Element::new_item(b"ayyc".to_vec()), + Element::new_item(b"ayyd".to_vec()) ] ); @@ -674,9 +720,9 @@ mod tests { Element::get_query(&storage, &[TEST_LEAF], &query, None) .expect("expected successful get_query"), vec![ - Element::Item(b"ayya".to_vec()), - Element::Item(b"ayyb".to_vec()), - Element::Item(b"ayyc".to_vec()) + Element::new_item(b"ayya".to_vec()), + Element::new_item(b"ayyb".to_vec()), + Element::new_item(b"ayyc".to_vec()) ] ); } @@ -689,16 +735,16 @@ mod tests { let storage_context = storage.get_storage_context([TEST_LEAF]); let mut merk = Merk::open(storage_context).expect("cannot open Merk"); - Element::Item(b"ayyd".to_vec()) + Element::new_item(b"ayyd".to_vec()) .insert(&mut merk, b"d") .expect("expected successful insertion"); - Element::Item(b"ayyc".to_vec()) + Element::new_item(b"ayyc".to_vec()) .insert(&mut merk, b"c") .expect("expected successful insertion"); - Element::Item(b"ayya".to_vec()) + Element::new_item(b"ayya".to_vec()) .insert(&mut merk, b"a") .expect("expected successful insertion"); - Element::Item(b"ayyb".to_vec()) + Element::new_item(b"ayyb".to_vec()) .insert(&mut merk, b"b") .expect("expected successful insertion"); @@ -713,9 +759,9 @@ mod tests { assert_eq!( elements, vec![ - Element::Item(b"ayya".to_vec()), - Element::Item(b"ayyb".to_vec()), - Element::Item(b"ayyc".to_vec()), + Element::new_item(b"ayya".to_vec()), + Element::new_item(b"ayyb".to_vec()), + Element::new_item(b"ayyc".to_vec()), ] ); assert_eq!(skipped, 0); @@ -729,9 +775,9 @@ mod tests { assert_eq!( elements, vec![ - Element::Item(b"ayyc".to_vec()), - Element::Item(b"ayyb".to_vec()), - Element::Item(b"ayya".to_vec()), + Element::new_item(b"ayyc".to_vec()), + Element::new_item(b"ayyb".to_vec()), + Element::new_item(b"ayya".to_vec()), ] ); assert_eq!(skipped, 0); @@ -745,16 +791,16 @@ mod tests { let storage_context = storage.get_storage_context([TEST_LEAF]); let mut merk = Merk::open(storage_context).expect("cannot open Merk"); - Element::Item(b"ayyd".to_vec()) + Element::new_item(b"ayyd".to_vec()) .insert(&mut merk, b"d") .expect("expected successful insertion"); - Element::Item(b"ayyc".to_vec()) + Element::new_item(b"ayyc".to_vec()) .insert(&mut merk, b"c") .expect("expected successful insertion"); - Element::Item(b"ayya".to_vec()) + Element::new_item(b"ayya".to_vec()) .insert(&mut merk, b"a") .expect("expected successful insertion"); - Element::Item(b"ayyb".to_vec()) + Element::new_item(b"ayyb".to_vec()) .insert(&mut merk, b"b") .expect("expected successful insertion"); @@ -765,10 +811,10 @@ mod tests { let ascending_query = SizedQuery::new(query.clone(), None, None); fn check_elements_no_skipped((elements, skipped): (Vec, u16), reverse: bool) { let mut expected = vec![ - Element::Item(b"ayya".to_vec()), - Element::Item(b"ayyb".to_vec()), - Element::Item(b"ayyc".to_vec()), - Element::Item(b"ayyd".to_vec()), + Element::new_item(b"ayya".to_vec()), + Element::new_item(b"ayyb".to_vec()), + Element::new_item(b"ayyc".to_vec()), + Element::new_item(b"ayyd".to_vec()), ]; if reverse { expected.reverse(); @@ -813,16 +859,16 @@ mod tests { let storage_context = storage.get_storage_context([TEST_LEAF]); let mut merk = Merk::open(storage_context).expect("cannot open Merk"); - Element::Item(b"ayyd".to_vec()) + Element::new_item(b"ayyd".to_vec()) .insert(&mut merk, b"d") .expect("expected successful insertion"); - Element::Item(b"ayyc".to_vec()) + Element::new_item(b"ayyc".to_vec()) .insert(&mut merk, b"c") .expect("expected successful insertion"); - Element::Item(b"ayya".to_vec()) + Element::new_item(b"ayya".to_vec()) .insert(&mut merk, b"a") .expect("expected successful insertion"); - Element::Item(b"ayyb".to_vec()) + Element::new_item(b"ayyb".to_vec()) .insert(&mut merk, b"b") .expect("expected successful insertion"); @@ -839,8 +885,8 @@ mod tests { assert_eq!( elements, vec![ - Element::Item(b"ayya".to_vec()), - Element::Item(b"ayyc".to_vec()), + Element::new_item(b"ayya".to_vec()), + Element::new_item(b"ayyc".to_vec()), ] ); assert_eq!(skipped, 0); @@ -858,8 +904,8 @@ mod tests { assert_eq!( elements, vec![ - Element::Item(b"ayyc".to_vec()), - Element::Item(b"ayya".to_vec()), + Element::new_item(b"ayyc".to_vec()), + Element::new_item(b"ayya".to_vec()), ] ); assert_eq!(skipped, 0); @@ -869,7 +915,7 @@ mod tests { let (elements, skipped) = Element::get_sized_query(&storage, &[TEST_LEAF], &limit_query, None) .expect("expected successful get_query"); - assert_eq!(elements, vec![Element::Item(b"ayyc".to_vec()),]); + assert_eq!(elements, vec![Element::new_item(b"ayyc".to_vec())]); assert_eq!(skipped, 0); // Test range query @@ -883,8 +929,8 @@ mod tests { assert_eq!( elements, vec![ - Element::Item(b"ayya".to_vec()), - Element::Item(b"ayyb".to_vec()) + Element::new_item(b"ayya".to_vec()), + Element::new_item(b"ayyb".to_vec()) ] ); assert_eq!(skipped, 0); @@ -896,8 +942,8 @@ mod tests { assert_eq!( elements, vec![ - Element::Item(b"ayyb".to_vec()), - Element::Item(b"ayyc".to_vec()) + Element::new_item(b"ayyb".to_vec()), + Element::new_item(b"ayyc".to_vec()) ] ); assert_eq!(skipped, 1); @@ -914,8 +960,8 @@ mod tests { assert_eq!( elements, vec![ - Element::Item(b"ayyb".to_vec()), - Element::Item(b"ayya".to_vec()) + Element::new_item(b"ayyb".to_vec()), + Element::new_item(b"ayya".to_vec()) ] ); assert_eq!(skipped, 1); @@ -931,9 +977,9 @@ mod tests { assert_eq!( elements, vec![ - Element::Item(b"ayyb".to_vec()), - Element::Item(b"ayyc".to_vec()), - Element::Item(b"ayyd".to_vec()), + Element::new_item(b"ayyb".to_vec()), + Element::new_item(b"ayyc".to_vec()), + Element::new_item(b"ayyd".to_vec()), ] ); assert_eq!(skipped, 0); @@ -949,8 +995,8 @@ mod tests { assert_eq!( elements, vec![ - Element::Item(b"ayyc".to_vec()), - Element::Item(b"ayyb".to_vec()), + Element::new_item(b"ayyc".to_vec()), + Element::new_item(b"ayyb".to_vec()), ] ); assert_eq!(skipped, 1); @@ -967,8 +1013,8 @@ mod tests { assert_eq!( elements, vec![ - Element::Item(b"ayyb".to_vec()), - Element::Item(b"ayya".to_vec()), + Element::new_item(b"ayyb".to_vec()), + Element::new_item(b"ayya".to_vec()), ] ); assert_eq!(skipped, 1); diff --git a/grovedb/src/tests.rs b/grovedb/src/tests.rs index 096590e7d..b81dc322f 100644 --- a/grovedb/src/tests.rs +++ b/grovedb/src/tests.rs @@ -134,7 +134,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [TEST_LEAF, b"innertree"], b"key1", - Element::Item(b"value1".to_vec()), + Element::new_item(b"value1".to_vec()), None, ) .expect("successful subtree insert"); @@ -142,7 +142,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [TEST_LEAF, b"innertree"], b"key2", - Element::Item(b"value2".to_vec()), + Element::new_item(b"value2".to_vec()), None, ) .expect("successful subtree insert"); @@ -150,7 +150,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [TEST_LEAF, b"innertree"], b"key3", - Element::Item(b"value3".to_vec()), + Element::new_item(b"value3".to_vec()), None, ) .expect("successful subtree insert"); @@ -158,7 +158,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [TEST_LEAF, b"innertree4"], b"key4", - Element::Item(b"value4".to_vec()), + Element::new_item(b"value4".to_vec()), None, ) .expect("successful subtree insert"); @@ -166,7 +166,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [TEST_LEAF, b"innertree4"], b"key5", - Element::Item(b"value5".to_vec()), + Element::new_item(b"value5".to_vec()), None, ) .expect("successful subtree insert"); @@ -174,7 +174,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [ANOTHER_TEST_LEAF, b"innertree2"], b"key3", - Element::Item(b"value3".to_vec()), + Element::new_item(b"value3".to_vec()), None, ) .expect("successful subtree insert"); @@ -182,7 +182,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [ANOTHER_TEST_LEAF, b"innertree3"], b"key4", - Element::Item(b"value4".to_vec()), + Element::new_item(b"value4".to_vec()), None, ) .expect("successful subtree insert"); @@ -223,7 +223,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [DEEP_LEAF, b"deep_node_1", b"deeper_node_1"], b"key1", - Element::Item(b"value1".to_vec()), + Element::new_item(b"value1".to_vec()), None, ) .expect("successful subtree insert"); @@ -231,7 +231,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [DEEP_LEAF, b"deep_node_1", b"deeper_node_1"], b"key2", - Element::Item(b"value2".to_vec()), + Element::new_item(b"value2".to_vec()), None, ) .expect("successful subtree insert"); @@ -239,7 +239,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [DEEP_LEAF, b"deep_node_1", b"deeper_node_1"], b"key3", - Element::Item(b"value3".to_vec()), + Element::new_item(b"value3".to_vec()), None, ) .expect("successful subtree insert"); @@ -247,7 +247,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [DEEP_LEAF, b"deep_node_1", b"deeper_node_2"], b"key4", - Element::Item(b"value4".to_vec()), + Element::new_item(b"value4".to_vec()), None, ) .expect("successful subtree insert"); @@ -255,7 +255,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [DEEP_LEAF, b"deep_node_1", b"deeper_node_2"], b"key5", - Element::Item(b"value5".to_vec()), + Element::new_item(b"value5".to_vec()), None, ) .expect("successful subtree insert"); @@ -263,7 +263,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [DEEP_LEAF, b"deep_node_1", b"deeper_node_2"], b"key6", - Element::Item(b"value6".to_vec()), + Element::new_item(b"value6".to_vec()), None, ) .expect("successful subtree insert"); @@ -272,7 +272,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [DEEP_LEAF, b"deep_node_2", b"deeper_node_3"], b"key7", - Element::Item(b"value7".to_vec()), + Element::new_item(b"value7".to_vec()), None, ) .expect("successful subtree insert"); @@ -280,7 +280,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [DEEP_LEAF, b"deep_node_2", b"deeper_node_3"], b"key8", - Element::Item(b"value8".to_vec()), + Element::new_item(b"value8".to_vec()), None, ) .expect("successful subtree insert"); @@ -288,7 +288,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [DEEP_LEAF, b"deep_node_2", b"deeper_node_3"], b"key9", - Element::Item(b"value9".to_vec()), + Element::new_item(b"value9".to_vec()), None, ) .expect("successful subtree insert"); @@ -296,7 +296,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [DEEP_LEAF, b"deep_node_2", b"deeper_node_4"], b"key10", - Element::Item(b"value10".to_vec()), + Element::new_item(b"value10".to_vec()), None, ) .expect("successful subtree insert"); @@ -304,7 +304,7 @@ fn make_deep_tree() -> TempGroveDb { .insert( [DEEP_LEAF, b"deep_node_2", b"deeper_node_4"], b"key11", - Element::Item(b"value11".to_vec()), + Element::new_item(b"value11".to_vec()), None, ) .expect("successful subtree insert"); @@ -320,7 +320,7 @@ fn test_init() { #[test] fn test_insert_value_to_merk() { let db = make_grovedb(); - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); db.insert([TEST_LEAF], b"key", element.clone(), None) .expect("successful insert"); assert_eq!( @@ -332,7 +332,7 @@ fn test_insert_value_to_merk() { #[test] fn test_insert_value_to_subtree() { let db = make_grovedb(); - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); // Insert a subtree first db.insert([TEST_LEAF], b"key1", Element::empty_tree(), None) @@ -351,7 +351,7 @@ fn test_insert_value_to_subtree() { fn test_changes_propagated() { let db = make_grovedb(); let old_hash = db.root_hash(None).unwrap(); - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); // Insert some nested subtrees db.insert([TEST_LEAF], b"key1", Element::empty_tree(), None) @@ -374,7 +374,6 @@ fn test_changes_propagated() { assert_ne!(old_hash, db.root_hash(None).unwrap()); } -// TODO: Add solid test cases to this #[test] fn test_references() { let db = make_grovedb(); @@ -383,26 +382,24 @@ fn test_references() { db.insert( [TEST_LEAF, b"merk_1"], b"key1", - Element::Item(b"value1".to_vec()), + Element::new_item(b"value1".to_vec()), None, ) .expect("successful subtree insert"); db.insert( [TEST_LEAF, b"merk_1"], b"key2", - Element::Item(b"value2".to_vec()), + Element::new_item(b"value2".to_vec()), None, ) .expect("successful subtree insert"); db.insert([TEST_LEAF], b"merk_2", Element::empty_tree(), None) .expect("successful subtree insert"); - // db.insert([TEST_LEAF, b"merk_2"], b"key2", Element::Item(b"value2".to_vec()), - // None).expect("successful subtree insert"); db.insert( [TEST_LEAF, b"merk_2"], b"key1", - Element::Reference(vec![ + Element::new_reference(vec![ TEST_LEAF.to_vec(), b"merk_1".to_vec(), b"key1".to_vec(), @@ -413,7 +410,7 @@ fn test_references() { db.insert( [TEST_LEAF, b"merk_2"], b"key2", - Element::Reference(vec![ + Element::new_reference(vec![ TEST_LEAF.to_vec(), b"merk_1".to_vec(), b"key2".to_vec(), @@ -422,17 +419,52 @@ fn test_references() { ) .expect("successful subtree insert"); + // Verify the base element is updated on reference insertion + assert_eq!( + db.get([TEST_LEAF, b"merk_1"], b"key1", None) + .expect("successful get"), + Element::Item( + b"value1".to_vec(), + vec![vec![ + TEST_LEAF.to_vec(), + b"merk_2".to_vec(), + b"key1".to_vec() + ]] + ) + ); + assert_eq!( + db.get([TEST_LEAF, b"merk_1"], b"key2", None) + .expect("successful get"), + Element::Item( + b"value2".to_vec(), + vec![vec![ + TEST_LEAF.to_vec(), + b"merk_2".to_vec(), + b"key2".to_vec() + ]] + ) + ); + let subtree_storage = db.db.db.get_storage_context([TEST_LEAF, b"merk_1"]); - let subtree = Merk::open(subtree_storage).expect("cannot open merk"); + let value_subtree = Merk::open(subtree_storage).expect("cannot open merk"); let subtree_storage = db.db.db.get_storage_context([TEST_LEAF, b"merk_2"]); - let subtree = Merk::open(subtree_storage).expect("cannot open merk"); + let reference_subtree = Merk::open(subtree_storage).expect("cannot open merk"); + + // Verify that they have the same root hash + assert_eq!(value_subtree.root_hash(), reference_subtree.root_hash()); } #[test] fn test_follow_references() { let db = make_grovedb(); - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); + + // Insert an item to refer to + db.insert([TEST_LEAF], b"key2", Element::empty_tree(), None) + .expect("successful subtree 1 insert"); + db.insert([TEST_LEAF, b"key2"], b"key3", element.clone(), None) + .expect("successful value insert"); // Insert an item to refer to db.insert([TEST_LEAF], b"key2", Element::empty_tree(), None) @@ -444,7 +476,7 @@ fn test_follow_references() { db.insert( [TEST_LEAF], b"reference_key", - Element::Reference(vec![TEST_LEAF.to_vec(), b"key2".to_vec(), b"key3".to_vec()]), + Element::new_reference(vec![TEST_LEAF.to_vec(), b"key2".to_vec(), b"key3".to_vec()]), None, ) .expect("successful reference insert"); @@ -452,7 +484,10 @@ fn test_follow_references() { assert_eq!( db.get([TEST_LEAF], b"reference_key", None) .expect("successful get"), - element + Element::Item( + b"ayy".to_vec(), + vec![vec![TEST_LEAF.to_vec(), b"reference_key".to_vec()]] + ) ); } @@ -463,7 +498,7 @@ fn test_reference_must_point_to_item() { let result = db.insert( [TEST_LEAF], b"reference_key_1", - Element::Reference(vec![TEST_LEAF.to_vec(), b"reference_key_2".to_vec()]), + Element::new_reference(vec![TEST_LEAF.to_vec(), b"reference_key_2".to_vec()]), None, ); @@ -482,14 +517,19 @@ fn test_too_many_indirections() { let keygen = |idx| format!("key{}", idx).bytes().collect::>(); - db.insert([TEST_LEAF], b"key0", Element::Item(b"oops".to_vec()), None) - .expect("successful item insert"); + db.insert( + [TEST_LEAF], + b"key0", + Element::new_item(b"oops".to_vec()), + None, + ) + .expect("successful item insert"); for i in 1..=(MAX_REFERENCE_HOPS) { db.insert( [TEST_LEAF], &keygen(i), - Element::Reference(vec![TEST_LEAF.to_vec(), keygen(i - 1)]), + Element::new_reference(vec![TEST_LEAF.to_vec(), keygen(i - 1)]), None, ) .expect("successful reference insert"); @@ -499,7 +539,7 @@ fn test_too_many_indirections() { db.insert( [TEST_LEAF], &keygen(MAX_REFERENCE_HOPS + 1), - Element::Reference(vec![TEST_LEAF.to_vec(), keygen(MAX_REFERENCE_HOPS)]), + Element::new_reference(vec![TEST_LEAF.to_vec(), keygen(MAX_REFERENCE_HOPS)]), None, ), Err(Error::ReferenceLimit) @@ -509,7 +549,7 @@ fn test_too_many_indirections() { #[test] fn test_tree_structure_is_persistent() { let tmp_dir = TempDir::new().unwrap(); - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); // Create a scoped GroveDB let prev_root_hash = { let mut db = GroveDb::open(tmp_dir.path()).unwrap(); @@ -602,7 +642,7 @@ fn test_path_query_proofs_without_subquery_with_reference() { .insert( [TEST_LEAF, b"innertree"], b"key1", - Element::Item(b"value1".to_vec()), + Element::new_item(b"value1".to_vec()), None, ) .expect("successful subtree insert"); @@ -610,7 +650,7 @@ fn test_path_query_proofs_without_subquery_with_reference() { .insert( [TEST_LEAF, b"innertree"], b"key2", - Element::Item(b"value2".to_vec()), + Element::new_item(b"value2".to_vec()), None, ) .expect("successful subtree insert"); @@ -618,7 +658,7 @@ fn test_path_query_proofs_without_subquery_with_reference() { .insert( [TEST_LEAF, b"innertree"], b"key3", - Element::Item(b"value3".to_vec()), + Element::new_item(b"value3".to_vec()), None, ) .expect("successful subtree insert"); @@ -626,7 +666,7 @@ fn test_path_query_proofs_without_subquery_with_reference() { .insert( [ANOTHER_TEST_LEAF, b"innertree2"], b"key3", - Element::Item(b"value3".to_vec()), + Element::new_item(b"value3".to_vec()), None, ) .expect("successful subtree insert"); @@ -634,7 +674,7 @@ fn test_path_query_proofs_without_subquery_with_reference() { .insert( [ANOTHER_TEST_LEAF, b"innertree2"], b"key4", - Element::Reference(vec![ + Element::new_reference(vec![ TEST_LEAF.to_vec(), b"innertree".to_vec(), b"key1".to_vec(), @@ -646,7 +686,7 @@ fn test_path_query_proofs_without_subquery_with_reference() { .insert( [ANOTHER_TEST_LEAF, b"innertree3"], b"key4", - Element::Item(b"value4".to_vec()), + Element::new_item(b"value4".to_vec()), None, ) .expect("successful subtree insert"); @@ -654,7 +694,7 @@ fn test_path_query_proofs_without_subquery_with_reference() { .insert( [ANOTHER_TEST_LEAF, b"innertree2"], b"key5", - Element::Reference(vec![ + Element::new_reference(vec![ ANOTHER_TEST_LEAF.to_vec(), b"innertree3".to_vec(), b"key4".to_vec(), @@ -677,8 +717,27 @@ fn test_path_query_proofs_without_subquery_with_reference() { GroveDb::execute_proof(proof.as_slice(), path_query).expect("should execute proof"); assert_eq!(hash, temp_db.root_hash(None).unwrap().unwrap()); - let r1 = Element::Item(b"value1".to_vec()).serialize().unwrap(); - let r2 = Element::Item(b"value4".to_vec()).serialize().unwrap(); + + let r1 = Element::Item( + b"value1".to_vec(), + vec![vec![ + ANOTHER_TEST_LEAF.to_vec(), + b"innertree2".to_vec(), + b"key4".to_vec(), + ]], + ) + .serialize() + .unwrap(); + let r2 = Element::Item( + b"value4".to_vec(), + vec![vec![ + ANOTHER_TEST_LEAF.to_vec(), + b"innertree2".to_vec(), + b"key5".to_vec(), + ]], + ) + .serialize() + .unwrap(); assert_eq!( result_set, @@ -728,7 +787,7 @@ fn test_path_query_proofs_without_subquery() { .insert( [TEST_LEAF, b"innertree"], b"key1", - Element::Item(b"value1".to_vec()), + Element::new_item(b"value1".to_vec()), None, ) .expect("successful subtree insert"); @@ -736,7 +795,7 @@ fn test_path_query_proofs_without_subquery() { .insert( [TEST_LEAF, b"innertree"], b"key2", - Element::Item(b"value2".to_vec()), + Element::new_item(b"value2".to_vec()), None, ) .expect("successful subtree insert"); @@ -744,7 +803,7 @@ fn test_path_query_proofs_without_subquery() { .insert( [TEST_LEAF, b"innertree"], b"key3", - Element::Item(b"value3".to_vec()), + Element::new_item(b"value3".to_vec()), None, ) .expect("successful subtree insert"); @@ -752,7 +811,7 @@ fn test_path_query_proofs_without_subquery() { .insert( [ANOTHER_TEST_LEAF, b"innertree2"], b"key3", - Element::Item(b"value3".to_vec()), + Element::new_item(b"value3".to_vec()), None, ) .expect("successful subtree insert"); @@ -760,7 +819,7 @@ fn test_path_query_proofs_without_subquery() { .insert( [ANOTHER_TEST_LEAF, b"innertree3"], b"key4", - Element::Item(b"value4".to_vec()), + Element::new_item(b"value4".to_vec()), None, ) .expect("successful subtree insert"); @@ -776,7 +835,7 @@ fn test_path_query_proofs_without_subquery() { GroveDb::execute_proof(proof.as_slice(), path_query).expect("should execute proof"); assert_eq!(hash, temp_db.root_hash(None).unwrap().unwrap()); - let r1 = Element::Item(b"value1".to_vec()).serialize().unwrap(); + let r1 = Element::new_item(b"value1".to_vec()).serialize().unwrap(); assert_eq!(result_set, vec![(b"key1".to_vec(), r1)]); // Range query + limit @@ -792,7 +851,7 @@ fn test_path_query_proofs_without_subquery() { GroveDb::execute_proof(proof.as_slice(), path_query).expect("should execute proof"); assert_eq!(hash, temp_db.root_hash(None).unwrap().unwrap()); - let r1 = Element::Item(b"value2".to_vec()).serialize().unwrap(); + let r1 = Element::new_item(b"value2".to_vec()).serialize().unwrap(); assert_eq!(result_set, vec![(b"key2".to_vec(), r1)]); // Range query + offset + limit @@ -808,7 +867,7 @@ fn test_path_query_proofs_without_subquery() { GroveDb::execute_proof(proof.as_slice(), path_query).expect("should execute proof"); assert_eq!(hash, temp_db.root_hash(None).unwrap().unwrap()); - let r1 = Element::Item(b"value3".to_vec()).serialize().unwrap(); + let r1 = Element::new_item(b"value3".to_vec()).serialize().unwrap(); assert_eq!(result_set, vec![(b"key3".to_vec(), r1)]); // Range query + direction + limit @@ -824,8 +883,8 @@ fn test_path_query_proofs_without_subquery() { GroveDb::execute_proof(proof.as_slice(), path_query).expect("should execute proof"); assert_eq!(hash, temp_db.root_hash(None).unwrap().unwrap()); - let r1 = Element::Item(b"value3".to_vec()).serialize().unwrap(); - let r2 = Element::Item(b"value2".to_vec()).serialize().unwrap(); + let r1 = Element::new_item(b"value3".to_vec()).serialize().unwrap(); + let r2 = Element::new_item(b"value2".to_vec()).serialize().unwrap(); assert_eq!( result_set, vec![(b"key3".to_vec(), r1), (b"key2".to_vec(), r2)] @@ -866,29 +925,7 @@ fn test_path_query_proofs_with_default_subquery() { b"value4".to_vec(), b"value5".to_vec(), ]; - let elements = values.map(|x| Element::Item(x).serialize().unwrap()); - let expected_result_set: Vec<(Vec, Vec)> = keys.into_iter().zip(elements).collect(); - assert_eq!(result_set, expected_result_set); - - let mut query = Query::new(); - query.insert_range_after(b"innertree".to_vec()..); - - let mut subq = Query::new(); - subq.insert_all(); - query.set_subquery(subq); - - let path_query = PathQuery::new_unsized(vec![TEST_LEAF.to_vec()], query); - - let proof = temp_db.prove(path_query.clone()).unwrap(); - let (hash, result_set) = - GroveDb::execute_proof(proof.as_slice(), path_query).expect("should execute proof"); - - assert_eq!(hash, temp_db.root_hash(None).unwrap().unwrap()); - assert_eq!(result_set.len(), 2); - - let keys = [b"key4".to_vec(), b"key5".to_vec()]; - let values = [b"value4".to_vec(), b"value5".to_vec()]; - let elements = values.map(|x| Element::Item(x).serialize().unwrap()); + let elements = values.map(|x| Element::new_item(x).serialize().unwrap()); let expected_result_set: Vec<(Vec, Vec)> = keys.into_iter().zip(elements).collect(); assert_eq!(result_set, expected_result_set); @@ -913,7 +950,7 @@ fn test_path_query_proofs_with_default_subquery() { let keys = [b"key2".to_vec(), b"key3".to_vec(), b"key4".to_vec()]; let values = [b"value2".to_vec(), b"value3".to_vec(), b"value4".to_vec()]; - let elements = values.map(|x| Element::Item(x).serialize().unwrap()); + let elements = values.map(|x| Element::new_item(x).serialize().unwrap()); let expected_result_set: Vec<(Vec, Vec)> = keys.into_iter().zip(elements).collect(); assert_eq!(result_set, expected_result_set); @@ -965,7 +1002,7 @@ fn test_path_query_proofs_with_default_subquery() { b"value10".to_vec(), b"value11".to_vec(), ]; - let elements = values.map(|x| Element::Item(x).serialize().unwrap()); + let elements = values.map(|x| Element::new_item(x).serialize().unwrap()); let expected_result_set: Vec<(Vec, Vec)> = keys.into_iter().zip(elements).collect(); assert_eq!(result_set, expected_result_set); } @@ -994,7 +1031,7 @@ fn test_path_query_proofs_with_subquery_key() { let keys = [b"key1".to_vec(), b"key2".to_vec(), b"key3".to_vec()]; let values = [b"value1".to_vec(), b"value2".to_vec(), b"value3".to_vec()]; - let elements = values.map(|x| Element::Item(x).serialize().unwrap()); + let elements = values.map(|x| Element::new_item(x).serialize().unwrap()); let expected_result_set: Vec<(Vec, Vec)> = keys.into_iter().zip(elements).collect(); assert_eq!(result_set, expected_result_set); } @@ -1086,7 +1123,7 @@ fn test_path_query_proofs_with_conditional_subquery() { b"value10".to_vec(), b"value11".to_vec(), ]; - let elements = values.map(|x| Element::Item(x).serialize().unwrap()); + let elements = values.map(|x| Element::new_item(x).serialize().unwrap()); let expected_result_set: Vec<(Vec, Vec)> = keys.into_iter().zip(elements).collect(); assert_eq!(result_set, expected_result_set); } @@ -1130,7 +1167,7 @@ fn test_path_query_proofs_with_sized_query() { let keys = [b"key4".to_vec(), b"key5".to_vec(), b"key6".to_vec()]; let values = [b"value4".to_vec(), b"value5".to_vec(), b"value6".to_vec()]; - let elements = values.map(|x| Element::Item(x).serialize().unwrap()); + let elements = values.map(|x| Element::new_item(x).serialize().unwrap()); let expected_result_set: Vec<(Vec, Vec)> = keys.into_iter().zip(elements).collect(); assert_eq!(result_set, expected_result_set); } @@ -1173,7 +1210,7 @@ fn test_path_query_proofs_with_direction() { let keys = [b"key10".to_vec(), b"key6".to_vec(), b"key5".to_vec()]; let values = [b"value10".to_vec(), b"value6".to_vec(), b"value5".to_vec()]; - let elements = values.map(|x| Element::Item(x).serialize().unwrap()); + let elements = values.map(|x| Element::new_item(x).serialize().unwrap()); let expected_result_set: Vec<(Vec, Vec)> = keys.into_iter().zip(elements).collect(); assert_eq!(result_set, expected_result_set); @@ -1225,7 +1262,7 @@ fn test_path_query_proofs_with_direction() { b"value8".to_vec(), b"value9".to_vec(), ]; - let elements = values.map(|x| Element::Item(x).serialize().unwrap()); + let elements = values.map(|x| Element::new_item(x).serialize().unwrap()); let expected_result_set: Vec<(Vec, Vec)> = keys.into_iter().zip(elements).collect(); assert_eq!(result_set, expected_result_set); } @@ -1233,7 +1270,7 @@ fn test_path_query_proofs_with_direction() { // #[test] // fn test_checkpoint() { // let mut db = make_grovedb(); -// let element1 = Element::Item(b"ayy".to_vec()); +// let element1 = Element::new_item(b"ayy".to_vec()); // // db.insert([], b"key1", Element::empty_tree()) // .expect("cannot insert a subtree 1 into GroveDB"); @@ -1265,8 +1302,8 @@ fn test_path_query_proofs_with_direction() { // element1 // ); // -// let element2 = Element::Item(b"ayy2".to_vec()); -// let element3 = Element::Item(b"ayy3".to_vec()); +// let element2 = Element::new_item(b"ayy2".to_vec()); +// let element3 = Element::new_item(b"ayy3".to_vec()); // // checkpoint // .insert([b"key1"], b"key4", element2.clone()) @@ -1344,7 +1381,7 @@ fn test_is_empty_tree() { db.insert( [TEST_LEAF, b"innertree"], b"key1", - Element::Item(b"hello".to_vec()), + Element::new_item(b"hello".to_vec()), None, ) .unwrap(); @@ -1364,7 +1401,7 @@ fn transaction_insert_item_with_transaction_should_use_transaction() { let result = db.get([TEST_LEAF], item_key, None); assert!(matches!(result, Err(Error::PathKeyNotFound(_)))); - let element1 = Element::Item(b"ayy".to_vec()); + let element1 = Element::new_item(b"ayy".to_vec()); db.insert([TEST_LEAF], item_key, element1, Some(&transaction)) .expect("cannot insert an item into GroveDB"); @@ -1377,7 +1414,7 @@ fn transaction_insert_item_with_transaction_should_use_transaction() { let result_with_transaction = db .get([TEST_LEAF], item_key, Some(&transaction)) .expect("Expected to work"); - assert_eq!(result_with_transaction, Element::Item(b"ayy".to_vec())); + assert_eq!(result_with_transaction, Element::new_item(b"ayy".to_vec())); // Test that commit works // transaction.commit(); @@ -1387,7 +1424,7 @@ fn transaction_insert_item_with_transaction_should_use_transaction() { let result = db .get([TEST_LEAF], item_key, None) .expect("Expected transaction to work"); - assert_eq!(result, Element::Item(b"ayy".to_vec())); + assert_eq!(result, Element::new_item(b"ayy".to_vec())); } #[test] @@ -1432,7 +1469,7 @@ fn transaction_should_be_aborted_when_rollback_is_called() { let db = make_grovedb(); let transaction = db.start_transaction(); - let element1 = Element::Item(b"ayy".to_vec()); + let element1 = Element::new_item(b"ayy".to_vec()); let result = db.insert([TEST_LEAF], item_key, element1, Some(&transaction)); @@ -1450,7 +1487,7 @@ fn transaction_should_be_aborted() { let transaction = db.start_transaction(); let item_key = b"key3"; - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); db.insert([TEST_LEAF], item_key, element, Some(&transaction)) .unwrap(); @@ -1465,8 +1502,8 @@ fn transaction_should_be_aborted() { #[test] fn test_subtree_pairs_iterator() { let db = make_grovedb(); - let element = Element::Item(b"ayy".to_vec()); - let element2 = Element::Item(b"lmao".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); + let element2 = Element::new_item(b"lmao".to_vec()); // Insert some nested subtrees db.insert([TEST_LEAF], b"subtree1", Element::empty_tree(), None) @@ -1530,7 +1567,7 @@ fn test_subtree_pairs_iterator() { #[test] fn test_element_deletion() { let db = make_grovedb(); - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); db.insert([TEST_LEAF], b"key", element, None) .expect("successful insert"); let root_hash = db.root_hash(None).unwrap(); @@ -1542,9 +1579,107 @@ fn test_element_deletion() { assert_ne!(root_hash, db.root_hash(None).unwrap()); } +#[test] +fn test_referenced_element_deletion() { + dbg!("hello"); + let db = make_grovedb(); + let element = Element::new_item(b"ayy".to_vec()); + db.insert([TEST_LEAF], b"key", element, None) + .expect("successful insert"); + let other_elem = Element::new_item(b"wow".to_vec()); + db.insert([TEST_LEAF], b"key2", other_elem, None) + .expect("successful insert"); + let reference = Element::new_reference(vec![TEST_LEAF.to_vec(), b"key".to_vec()]); + db.insert([ANOTHER_TEST_LEAF], b"reference_key", reference, None) + .expect("successful insert"); + let reference2 = Element::new_reference(vec![TEST_LEAF.to_vec(), b"key".to_vec()]); + db.insert([ANOTHER_TEST_LEAF], b"reference_key_2", reference2, None) + .expect("successful insert"); + let reference3 = Element::new_reference(vec![ + ANOTHER_TEST_LEAF.to_vec(), + b"reference_key_2".to_vec(), + ]); + db.insert([TEST_LEAF], b"reference_of_reference", reference3, None) + .expect("successful insert"); + + let root_hash = db.root_hash(None).unwrap(); + assert!(db.delete([TEST_LEAF], b"key", None).is_ok()); + assert!(matches!( + db.get([TEST_LEAF], b"key", None), + Err(Error::PathKeyNotFound(_)) + )); + assert!(matches!( + db.get([ANOTHER_TEST_LEAF], b"reference_key", None), + Err(Error::PathKeyNotFound(_)) + )); + assert!(matches!( + db.get([ANOTHER_TEST_LEAF], b"reference_key_2", None), + Err(Error::PathKeyNotFound(_)) + )); + assert!(matches!( + db.get([TEST_LEAF], b"reference_of_reference", None), + Err(Error::PathKeyNotFound(_)) + )); + assert!(matches!(db.get([TEST_LEAF], b"key2", None), Ok(_))); + assert_ne!(root_hash, db.root_hash(None).unwrap()); +} + +#[test] +fn test_reference_deletion() { + let db = make_grovedb(); + let element = Element::new_item(b"ayy".to_vec()); + db.insert([TEST_LEAF], b"key", element, None) + .expect("successful insert"); + let reference = Element::new_reference(vec![TEST_LEAF.to_vec(), b"key".to_vec()]); + db.insert([ANOTHER_TEST_LEAF], b"reference_key", reference, None) + .expect("successful insert"); + let reference2 = Element::new_reference(vec![TEST_LEAF.to_vec(), b"key".to_vec()]); + db.insert([ANOTHER_TEST_LEAF], b"reference_key_2", reference2, None) + .expect("successful insert"); + + let element = db + .get([TEST_LEAF], b"key", None) + .expect("should get element"); + if let Element::Item(_, references) = element { + assert_eq!(references.len(), 2); + } else { + panic!("should be able to fetch item"); + } + + // delete one reference + assert!(db + .delete([ANOTHER_TEST_LEAF], b"reference_key", None) + .is_ok()); + + // element should not point to reference anymore + let element = db + .get([TEST_LEAF], b"key", None) + .expect("should get element"); + if let Element::Item(_, references) = element { + assert_eq!(references.len(), 1); + } else { + panic!("should be able to fetch item"); + } + + // delete other reference + assert!(db + .delete([ANOTHER_TEST_LEAF], b"reference_key_2", None) + .is_ok()); + + // element should not point to reference anymore + let element = db + .get([TEST_LEAF], b"key", None) + .expect("should get element"); + if let Element::Item(_, references) = element { + assert_eq!(references.len(), 0); + } else { + panic!("should be able to fetch item"); + } +} + #[test] fn test_find_subtrees() { - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); let db = make_grovedb(); // Insert some nested subtrees db.insert([TEST_LEAF], b"key1", Element::empty_tree(), None) @@ -1573,7 +1708,7 @@ fn test_find_subtrees() { #[test] fn test_get_subtree() { let db = make_grovedb(); - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); // Returns error is subtree is not valid { @@ -1608,7 +1743,7 @@ fn test_get_subtree() { let subtree_storage = db.db.db.get_storage_context([TEST_LEAF, b"key1", b"key2"]); let subtree = Merk::open(subtree_storage).expect("cannot open merk"); let result_element = Element::get(&subtree, b"key3").unwrap(); - assert_eq!(result_element, Element::Item(b"ayy".to_vec())); + assert_eq!(result_element, Element::new_item(b"ayy".to_vec())); } // Insert a new tree with transaction let transaction = db.start_transaction(); @@ -1636,18 +1771,18 @@ fn test_get_subtree() { .get_transactional_storage_context([TEST_LEAF, b"key1", b"innertree"], &transaction); let subtree = Merk::open(subtree_storage).expect("cannot open merk"); let result_element = Element::get(&subtree, b"key4").unwrap(); - assert_eq!(result_element, Element::Item(b"ayy".to_vec())); + assert_eq!(result_element, Element::new_item(b"ayy".to_vec())); // Should be able to retrieve instances created before transaction let subtree_storage = db.db.db.get_storage_context([TEST_LEAF, b"key1", b"key2"]); let subtree = Merk::open(subtree_storage).expect("cannot open merk"); let result_element = Element::get(&subtree, b"key3").unwrap(); - assert_eq!(result_element, Element::Item(b"ayy".to_vec())); + assert_eq!(result_element, Element::new_item(b"ayy".to_vec())); } #[test] fn test_subtree_deletion() { - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); let db = make_grovedb(); // Insert some nested subtrees db.insert([TEST_LEAF], b"key1", Element::empty_tree(), None) @@ -1677,7 +1812,7 @@ fn test_subtree_deletion() { #[test] fn test_subtree_deletion_if_empty() { - let element = Element::Item(b"value".to_vec()); + let element = Element::new_item(b"value".to_vec()); let db = make_grovedb(); let transaction = db.start_transaction(); @@ -1769,7 +1904,7 @@ fn test_subtree_deletion_if_empty() { #[test] fn test_subtree_deletion_if_empty_without_transaction() { - let element = Element::Item(b"value".to_vec()); + let element = Element::new_item(b"value".to_vec()); let db = make_grovedb(); // Insert some nested subtrees @@ -1851,28 +1986,28 @@ fn test_get_full_query() { db.insert( [TEST_LEAF, b"key1"], b"key3", - Element::Item(b"ayya".to_vec()), + Element::new_item(b"ayya".to_vec()), None, ) .expect("successful value insert"); db.insert( [TEST_LEAF, b"key1"], b"key4", - Element::Item(b"ayyb".to_vec()), + Element::new_item(b"ayyb".to_vec()), None, ) .expect("successful value insert"); db.insert( [TEST_LEAF, b"key1"], b"key5", - Element::Item(b"ayyc".to_vec()), + Element::new_item(b"ayyc".to_vec()), None, ) .expect("successful value insert"); db.insert( [TEST_LEAF, b"key2"], b"key6", - Element::Item(b"ayyd".to_vec()), + Element::new_item(b"ayyd".to_vec()), None, ) .expect("successful value insert"); @@ -1891,16 +2026,16 @@ fn test_get_full_query() { db.get_path_queries_raw(&[&path_query1, &path_query2], None) .expect("expected successful get_query"), vec![ - subtree::Element::Item(b"ayya".to_vec()), - subtree::Element::Item(b"ayyb".to_vec()), - subtree::Element::Item(b"ayyd".to_vec()), + subtree::Element::new_item(b"ayya".to_vec()), + subtree::Element::new_item(b"ayyb".to_vec()), + subtree::Element::new_item(b"ayyd".to_vec()), ] ); } #[test] fn test_aux_uses_separate_cf() { - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); let db = make_grovedb(); // Insert some nested subtrees db.insert([TEST_LEAF], b"key1", Element::empty_tree(), None) @@ -1947,7 +2082,7 @@ fn test_aux_uses_separate_cf() { #[test] fn test_aux_with_transaction() { - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); let aux_value = b"ayylmao".to_vec(); let key = b"key".to_vec(); let db = make_grovedb(); @@ -2000,7 +2135,7 @@ fn populate_tree_for_non_unique_range_subquery(db: &TempGroveDb) { db.insert( [TEST_LEAF, i_vec.as_slice(), b"\0"], &j_vec.clone(), - Element::Item(j_vec), + Element::new_item(j_vec), None, ) .expect("successful value insert"); @@ -2049,7 +2184,7 @@ fn populate_tree_for_non_unique_double_range_subquery(db: &TempGroveDb) { db.insert( [TEST_LEAF, i_vec.as_slice(), b"a", &j_vec, b"\0"], &k_vec.clone(), - Element::Item(k_vec), + Element::new_item(k_vec), None, ) .expect("successful value insert"); @@ -2090,7 +2225,7 @@ fn populate_tree_by_reference_for_non_unique_range_subquery(db: &TempGroveDb) { db.insert( [TEST_LEAF, b"\0"], &random_key, - Element::Item(j_vec.clone()), + Element::new_item(j_vec.clone()), None, ) .expect("successful value insert"); @@ -2098,7 +2233,7 @@ fn populate_tree_by_reference_for_non_unique_range_subquery(db: &TempGroveDb) { db.insert( [TEST_LEAF, b"1", i_vec.clone().as_slice(), b"\0"], &random_key, - Element::Reference(vec![ + Element::new_reference(vec![ TEST_LEAF.to_vec(), b"\0".to_vec(), random_key.to_vec(), @@ -2120,7 +2255,7 @@ fn populate_tree_for_unique_range_subquery(db: &TempGroveDb) { db.insert( [TEST_LEAF, &i_vec.clone()], b"\0", - Element::Item(i_vec), + Element::new_item(i_vec), None, ) .expect("successful value insert"); @@ -2145,7 +2280,7 @@ fn populate_tree_by_reference_for_unique_range_subquery(db: &TempGroveDb) { db.insert( [TEST_LEAF, b"\0"], &i_vec, - Element::Item(i_vec.clone()), + Element::new_item(i_vec.clone()), None, ) .expect("successful value insert"); @@ -2154,7 +2289,7 @@ fn populate_tree_by_reference_for_unique_range_subquery(db: &TempGroveDb) { db.insert( [TEST_LEAF, b"1", i_vec.clone().as_slice()], b"\0", - Element::Reference(vec![TEST_LEAF.to_vec(), b"\0".to_vec(), i_vec.clone()]), + Element::new_reference(vec![TEST_LEAF.to_vec(), b"\0".to_vec(), i_vec.clone()]), None, ) .expect("successful value insert"); @@ -2173,7 +2308,7 @@ fn populate_tree_for_unique_range_subquery_with_non_unique_null_values(db: &mut db.insert( [TEST_LEAF, &[], b"\0"], &i_vec, - Element::Item(i_vec.clone()), + Element::new_item(i_vec.clone()), None, ) .expect("successful value insert"); @@ -2193,7 +2328,7 @@ fn deserialize_and_extract_item_bytes(raw_bytes: &[u8]) -> Result, Error dbg!(raw_bytes); let elem = Element::deserialize(raw_bytes)?; return match elem { - Element::Item(item) => Ok(item), + Element::Item(item, _) => Ok(item), _ => Err(Error::CorruptedPath("expected only item type")), }; } @@ -3214,8 +3349,13 @@ fn test_root_hash() { let db = make_grovedb(); // Check hashes are different if tree is edited let old_root_hash = db.root_hash(None); - db.insert([TEST_LEAF], b"key1", Element::Item(b"ayy".to_vec()), None) - .expect("unable to insert an item"); + db.insert( + [TEST_LEAF], + b"key1", + Element::new_item(b"ayy".to_vec()), + None, + ) + .expect("unable to insert an item"); assert_ne!(old_root_hash.unwrap(), db.root_hash(None).unwrap()); // Check isolation @@ -3224,7 +3364,7 @@ fn test_root_hash() { db.insert( [TEST_LEAF], b"key2", - Element::Item(b"ayy".to_vec()), + Element::new_item(b"ayy".to_vec()), Some(&transaction), ) .expect("unable to insert an item"); @@ -3238,7 +3378,7 @@ fn test_root_hash() { #[test] fn test_subtree_deletion_with_transaction() { - let element = Element::Item(b"ayy".to_vec()); + let element = Element::new_item(b"ayy".to_vec()); let db = make_grovedb(); let transaction = db.start_transaction(); diff --git a/grovedb/src/visualize.rs b/grovedb/src/visualize.rs index 8c2c6eb81..72d9b09aa 100644 --- a/grovedb/src/visualize.rs +++ b/grovedb/src/visualize.rs @@ -8,11 +8,11 @@ use crate::{subtree::Element, util::storage_context_optional_tx, GroveDb, Transa impl Visualize for Element { fn visualize(&self, mut drawer: Drawer) -> Result> { match self { - Element::Item(value) => { + Element::Item(value, _) => { drawer.write(b"item: ")?; drawer = value.visualize(drawer)?; } - Element::Reference(_ref) => { + Element::Reference(_ref, _) => { drawer.write(b"ref")?; // drawer.write(b"ref: [path: ")?; // let mut path_iter = path.iter(); @@ -129,7 +129,7 @@ mod tests { #[test] fn test_element_item_str() { let v = b"ayylmao".to_vec(); - let e = Element::Item(v.clone()); + let e = Element::new_item(v.clone()); let element_hex = to_hex(&v); let mut result = Vec::new(); let drawer = Drawer::new(&mut result); @@ -146,7 +146,7 @@ mod tests { #[test] fn test_element_item_no_tr() { let v = vec![1, 3, 3, 7, 255]; - let e = Element::Item(v.clone()); + let e = Element::new_item(v.clone()); let element_hex = to_hex(&v); let mut result = Vec::new(); let drawer = Drawer::new(&mut result); @@ -162,7 +162,7 @@ mod tests { fn test_visualize_reference() { let p1 = b"ayy".to_vec(); let p2 = b"lmao".to_vec(); - let e = Element::Reference(vec![p1.clone(), p2.clone()]); + let e = Element::new_reference(vec![p1.clone(), p2.clone()]); let mut result = Vec::new(); let drawer = Drawer::new(&mut result); e.visualize(drawer).expect("visualize IO error"); diff --git a/node-grove/src/converter.rs b/node-grove/src/converter.rs index 0af84e485..4f6934bca 100644 --- a/node-grove/src/converter.rs +++ b/node-grove/src/converter.rs @@ -3,8 +3,8 @@ use neon::{borrow::Borrow, prelude::*}; fn element_to_string(element: Element) -> String { match element { - Element::Item(_) => "item".to_string(), - Element::Reference(_) => "reference".to_string(), + Element::Item(..) => "item".to_string(), + Element::Reference(..) => "reference".to_string(), Element::Tree(_) => "tree".to_string(), } } @@ -22,12 +22,12 @@ pub fn js_object_to_element<'a, C: Context<'a>>( "item" => { let js_buffer = value.downcast_or_throw::(cx)?; let item = js_buffer_to_vec_u8(js_buffer, cx); - Ok(Element::Item(item)) + Ok(Element::Item(item, vec![])) } "reference" => { let js_array = value.downcast_or_throw::(cx)?; let reference = js_array_of_buffers_to_vec(js_array, cx)?; - Ok(Element::Reference(reference)) + Ok(Element::Reference(reference, vec![])) } "tree" => { let js_buffer = value.downcast_or_throw::(cx)?; @@ -54,11 +54,11 @@ pub fn element_to_js_object<'a, C: Context<'a>>( js_object.set(cx, "type", js_type_string)?; let js_value: Handle = match element { - Element::Item(item) => { + Element::Item(item, _) => { let js_buffer = JsBuffer::external(cx, item); js_buffer.upcast() } - Element::Reference(reference) => nested_vecs_to_js(reference, cx)?, + Element::Reference(reference, _) => nested_vecs_to_js(reference, cx)?, Element::Tree(tree) => { let js_buffer = JsBuffer::external(cx, tree); js_buffer.upcast()