diff --git a/src/storage/store/store_async/object_store.rs b/src/storage/store/store_async/object_store.rs index a75be0ad..24747a7c 100644 --- a/src/storage/store/store_async/object_store.rs +++ b/src/storage/store/store_async/object_store.rs @@ -151,10 +151,9 @@ impl AsyncWritableStorageTraits for AsyncObjectSto async fn set_partial_values( &self, - _key_start_values: &[StoreKeyStartValue], + key_start_values: &[StoreKeyStartValue], ) -> Result<(), StorageError> { - // This is implemented in the parent - unreachable!() + crate::storage::async_store_set_partial_values(self, key_start_values).await } async fn erase(&self, key: &StoreKey) -> Result { @@ -247,3 +246,151 @@ impl AsyncListableStorageTraits for AsyncObjectSto Ok(StoreKeysPrefixes { keys, prefixes }) } } + +#[cfg(test)] +mod tests { + use crate::storage::{ + AsyncListableStorageTraits, AsyncReadableStorageTraits, AsyncWritableStorageTraits, + StoreKeyStartValue, StorePrefix, + }; + + use super::*; + use std::error::Error; + + #[tokio::test] + async fn memory_set() -> Result<(), Box> { + let store = AsyncObjectStore::new(object_store::memory::InMemory::new()); + let key = "a/b".try_into()?; + store.set(&key, &[0, 1, 2]).await?; + assert_eq!(store.get(&key).await?.unwrap(), &[0, 1, 2]); + store + .set_partial_values(&[StoreKeyStartValue::new(key.clone(), 1, &[3, 4])]) + .await?; + assert_eq!(store.get(&key).await?.unwrap(), &[0, 3, 4]); + Ok(()) + } + + #[tokio::test] + async fn memory_list() -> Result<(), Box> { + let store = AsyncObjectStore::new(object_store::memory::InMemory::new()); + + store.set(&"a/b".try_into()?, &[]).await?; + store.set(&"a/c".try_into()?, &[]).await?; + store.set(&"a/d/e".try_into()?, &[]).await?; + store.set(&"a/d/f".try_into()?, &[]).await?; + store.erase(&"a/d/e".try_into()?).await?; + assert_eq!( + store.list().await?, + &["a/b".try_into()?, "a/c".try_into()?, "a/d/f".try_into()?] + ); + assert_eq!( + store.list_prefix(&"a/".try_into()?).await?, + &["a/b".try_into()?, "a/c".try_into()?, "a/d/f".try_into()?] + ); + assert_eq!( + store.list_prefix(&"a/d/".try_into()?).await?, + &["a/d/f".try_into()?] + ); + assert_eq!( + store.list_prefix(&"".try_into()?).await?, + &["a/b".try_into()?, "a/c".try_into()?, "a/d/f".try_into()?] + ); + Ok(()) + } + + #[tokio::test] + async fn memory_list_dir() -> Result<(), Box> { + let store = AsyncObjectStore::new(object_store::memory::InMemory::new()); + store.set(&"a/b".try_into()?, &[]).await?; + store.set(&"a/c".try_into()?, &[]).await?; + store.set(&"a/d/e".try_into()?, &[]).await?; + store.set(&"a/f/g".try_into()?, &[]).await?; + store.set(&"a/f/h".try_into()?, &[]).await?; + store.set(&"b/c/d".try_into()?, &[]).await?; + + let list_dir = store.list_dir(&"a/".try_into()?).await?; + + assert_eq!(list_dir.keys(), &["a/b".try_into()?, "a/c".try_into()?,]); + assert_eq!( + list_dir.prefixes(), + &["a/d/".try_into()?, "a/f/".try_into()?,] + ); + Ok(()) + } + + #[tokio::test] + async fn filesystem_set() -> Result<(), Box> { + let path = tempfile::TempDir::new()?; + let store = AsyncObjectStore::new(object_store::local::LocalFileSystem::new_with_prefix( + path.path(), + )?); + + let key = "a/b".try_into()?; + store.set(&key, &[0, 1, 2]).await?; + assert_eq!(store.get(&key).await?.unwrap(), &[0, 1, 2]); + store + .set_partial_values(&[StoreKeyStartValue::new(key.clone(), 1, &[3, 4])]) + .await?; + assert_eq!(store.get(&key).await?.unwrap(), &[0, 3, 4]); + Ok(()) + } + + #[tokio::test] + async fn filesystem_list() -> Result<(), Box> { + let path = tempfile::TempDir::new()?; + let store = AsyncObjectStore::new(object_store::local::LocalFileSystem::new_with_prefix( + path.path(), + )?); + + store.set(&"a/b".try_into()?, &[]).await?; + store.set(&"a/c".try_into()?, &[]).await?; + store.set(&"a/d/e".try_into()?, &[]).await?; + store.set(&"a/d/f".try_into()?, &[]).await?; + store.erase(&"a/d/e".try_into()?).await?; + assert_eq!( + store.list().await?, + &["a/b".try_into()?, "a/c".try_into()?, "a/d/f".try_into()?] + ); + assert_eq!( + store.list_prefix(&"a/".try_into()?).await?, + &["a/b".try_into()?, "a/c".try_into()?, "a/d/f".try_into()?] + ); + assert_eq!( + store.list_prefix(&"a/d/".try_into()?).await?, + &["a/d/f".try_into()?] + ); + assert_eq!( + store.list_prefix(&"".try_into()?).await?, + &["a/b".try_into()?, "a/c".try_into()?, "a/d/f".try_into()?] + ); + + // assert!(crate::storage::node_exists(&store, &"/a/b".try_into()?).await?); + // assert!(crate::storage::node_exists_listable(&store, &"/a/b".try_into()?).await?); + + Ok(()) + } + + #[tokio::test] + async fn filesystem_list_dir() -> Result<(), Box> { + let path = tempfile::TempDir::new()?; + let store = AsyncObjectStore::new(object_store::local::LocalFileSystem::new_with_prefix( + path.path(), + )?); + + store.set(&"a/b".try_into()?, &[]).await?; + store.set(&"a/c".try_into()?, &[]).await?; + store.set(&"a/d/e".try_into()?, &[]).await?; + store.set(&"a/f/g".try_into()?, &[]).await?; + store.set(&"a/f/h".try_into()?, &[]).await?; + store.set(&"b/c/d".try_into()?, &[]).await?; + + let list_dir = store.list_dir(&StorePrefix::new("a/")?).await?; + + assert_eq!(list_dir.keys(), &["a/b".try_into()?, "a/c".try_into()?,]); + assert_eq!( + list_dir.prefixes(), + &["a/d/".try_into()?, "a/f/".try_into()?,] + ); + Ok(()) + } +}