diff --git a/grovedb/src/reference_path.rs b/grovedb/src/reference_path.rs index ddc08a11..01ee1a44 100644 --- a/grovedb/src/reference_path.rs +++ b/grovedb/src/reference_path.rs @@ -205,6 +205,7 @@ impl ReferencePathType { path_from_reference_path_type(self, current_path, current_key) } + /// TODO: deprecate the rest pub fn absolute_qualified_path<'b, B: AsRef<[u8]>>( self, mut current_path: SubtreePathBuilder<'b, B>, @@ -242,7 +243,7 @@ impl ReferencePathType { append_path, ) => { let len = current_path.len(); - if no_of_elements_to_keep as usize > len || len < 2 { + if no_of_elements_to_keep as usize > len || len < 1 { return Err(Error::InvalidInput( "reference stored path cannot satisfy reference constraints", )); @@ -250,7 +251,7 @@ impl ReferencePathType { let parent_key = current_path .reverse_iter() - .nth(1) + .next() .expect("lengths were checked above") .to_vec(); @@ -520,7 +521,7 @@ impl ReferencePathType { #[cfg(test)] mod tests { use grovedb_merk::proofs::Query; - use grovedb_path::SubtreePath; + use grovedb_path::{SubtreePath, SubtreePathBuilder}; use grovedb_version::version::GroveVersion; use crate::{ @@ -542,6 +543,20 @@ mod tests { ); } + #[test] + fn test_upstream_root_height_reference_path_lib() { + let stored_path: SubtreePathBuilder<&[u8]> = + SubtreePathBuilder::owned_from_iter([b"a".as_ref(), b"b".as_ref(), b"m".as_ref()]); + // selects the first 2 elements from the stored path and appends the new path. + let ref1 = + ReferencePathType::UpstreamRootHeightReference(2, vec![b"c".to_vec(), b"d".to_vec()]); + let final_path = ref1.absolute_qualified_path(stored_path, b"").unwrap(); + assert_eq!( + final_path.to_vec(), + vec![b"a".to_vec(), b"b".to_vec(), b"c".to_vec(), b"d".to_vec()] + ); + } + #[test] fn test_upstream_root_height_with_parent_addition_reference() { let stored_path = vec![b"a".as_ref(), b"b".as_ref(), b"m".as_ref()]; @@ -563,6 +578,28 @@ mod tests { ); } + #[test] + fn test_upstream_root_height_with_parent_addition_reference_path_lib() { + let stored_path: SubtreePathBuilder<&[u8]> = + SubtreePathBuilder::owned_from_iter([b"a".as_ref(), b"b".as_ref(), b"m".as_ref()]); + // selects the first 2 elements from the stored path and appends the new path. + let ref1 = ReferencePathType::UpstreamRootHeightWithParentPathAdditionReference( + 2, + vec![b"c".to_vec(), b"d".to_vec()], + ); + let final_path = ref1.absolute_qualified_path(stored_path, b"").unwrap(); + assert_eq!( + final_path.to_vec(), + vec![ + b"a".to_vec(), + b"b".to_vec(), + b"c".to_vec(), + b"d".to_vec(), + b"m".to_vec() + ] + ); + } + #[test] fn test_upstream_from_element_height_reference() { let stored_path = vec![b"a".as_ref(), b"b".as_ref(), b"m".as_ref()]; @@ -578,6 +615,22 @@ mod tests { ); } + #[test] + fn test_upstream_from_element_height_reference_path_lib() { + let stored_path: SubtreePathBuilder<&[u8]> = + SubtreePathBuilder::owned_from_iter([b"a".as_ref(), b"b".as_ref(), b"m".as_ref()]); + // discards the last element from the stored_path + let ref1 = ReferencePathType::UpstreamFromElementHeightReference( + 1, + vec![b"c".to_vec(), b"d".to_vec()], + ); + let final_path = ref1.absolute_qualified_path(stored_path, b"").unwrap(); + assert_eq!( + final_path.to_vec(), + vec![b"a".to_vec(), b"b".to_vec(), b"c".to_vec(), b"d".to_vec()] + ); + } + #[test] fn test_cousin_reference_no_key() { let stored_path = vec![b"a".as_ref(), b"b".as_ref(), b"m".as_ref()]; @@ -600,6 +653,20 @@ mod tests { ); } + #[test] + fn test_cousin_reference_path_lib() { + let stored_path: SubtreePathBuilder<&[u8]> = + SubtreePathBuilder::owned_from_iter([b"a".as_ref(), b"b".as_ref()]); + let key = b"m".as_ref(); + // Replaces the immediate parent (in this case b) with the given key (c) + let ref1 = ReferencePathType::CousinReference(b"c".to_vec()); + let final_path = ref1.absolute_qualified_path(stored_path, key).unwrap(); + assert_eq!( + final_path.to_vec(), + vec![b"a".to_vec(), b"c".to_vec(), b"m".to_vec()] + ); + } + #[test] fn test_removed_cousin_reference_no_key() { let stored_path = vec![b"a".as_ref(), b"b".as_ref(), b"m".as_ref()]; @@ -622,6 +689,20 @@ mod tests { ); } + #[test] + fn test_removed_cousin_reference_path_lib() { + let stored_path: SubtreePathBuilder<&[u8]> = + SubtreePathBuilder::owned_from_iter([b"a".as_ref(), b"b".as_ref()]); + let key = b"m".as_ref(); + // Replaces the immediate parent (in this case b) with the given key (c) + let ref1 = ReferencePathType::RemovedCousinReference(vec![b"c".to_vec(), b"d".to_vec()]); + let final_path = ref1.absolute_qualified_path(stored_path, key).unwrap(); + assert_eq!( + final_path.to_vec(), + vec![b"a".to_vec(), b"c".to_vec(), b"d".to_vec(), b"m".to_vec()] + ); + } + #[test] fn test_sibling_reference() { let stored_path = vec![b"a".as_ref(), b"b".as_ref()]; @@ -634,6 +715,19 @@ mod tests { ); } + #[test] + fn test_sibling_reference_path_lib() { + let stored_path: SubtreePathBuilder<&[u8]> = + SubtreePathBuilder::owned_from_iter([b"a".as_ref(), b"b".as_ref()]); + let key = b"m".as_ref(); + let ref1 = ReferencePathType::SiblingReference(b"c".to_vec()); + let final_path = ref1.absolute_qualified_path(stored_path, key).unwrap(); + assert_eq!( + final_path.to_vec(), + vec![b"a".to_vec(), b"b".to_vec(), b"c".to_vec()] + ); + } + #[test] fn test_query_many_with_different_reference_types() { let grove_version = GroveVersion::latest();