diff --git a/core/src/layers/capability_check.rs b/core/src/layers/capability_check.rs index 1ca1ffa994be..0066e031b3f1 100644 --- a/core/src/layers/capability_check.rs +++ b/core/src/layers/capability_check.rs @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -use crate::layers::correctness_check::new_unsupported_args_error; +use crate::layers::correctness_check::new_unsupported_error; use crate::raw::*; use std::fmt::{Debug, Formatter}; use std::sync::Arc; @@ -93,61 +93,40 @@ impl LayeredAccess for CapabilityAccessor { } async fn read(&self, path: &str, args: OpRead) -> crate::Result<(RpRead, Self::Reader)> { - let capability = self.info.full_capability(); - if !capability.read_with_version && args.version().is_some() { - return Err(new_unsupported_args_error( - self.info.as_ref(), - Operation::Read, - "version", - )); - } - self.inner.read(path, args).await } async fn write(&self, path: &str, args: OpWrite) -> crate::Result<(RpWrite, Self::Writer)> { let capability = self.info.full_capability(); if !capability.write_with_content_type && args.content_type().is_some() { - return Err(new_unsupported_args_error( + return Err(new_unsupported_error( self.info.as_ref(), Operation::Write, "content_type", )); } - - self.inner.write(path, args).await - } - - async fn stat(&self, path: &str, args: OpStat) -> crate::Result { - let capability = self.info.full_capability(); - if !capability.stat_with_version && args.version().is_some() { - return Err(new_unsupported_args_error( + if !capability.write_with_cache_control && args.cache_control().is_some() { + return Err(new_unsupported_error( self.info.as_ref(), - Operation::Stat, - "version", + Operation::Write, + "cache_control", )); } - - self.inner.stat(path, args).await - } - - async fn delete(&self, path: &str, args: OpDelete) -> crate::Result { - let capability = self.info.full_capability(); - if !capability.delete_with_version && args.version().is_some() { - return Err(new_unsupported_args_error( + if !capability.write_with_content_disposition && args.content_disposition().is_some() { + return Err(new_unsupported_error( self.info.as_ref(), - Operation::Delete, - "version", + Operation::Write, + "content_disposition", )); } - self.inner.delete(path, args).await + self.inner.write(path, args).await } async fn list(&self, path: &str, args: OpList) -> crate::Result<(RpList, Self::Lister)> { let capability = self.info.full_capability(); if !capability.list_with_version && args.version() { - return Err(new_unsupported_args_error( + return Err(new_unsupported_error( self.info.as_ref(), Operation::List, "version", @@ -162,16 +141,7 @@ impl LayeredAccess for CapabilityAccessor { path: &str, args: OpRead, ) -> crate::Result<(RpRead, Self::BlockingReader)> { - let capability = self.info.full_capability(); - if !capability.read_with_version && args.version().is_some() { - return Err(new_unsupported_args_error( - self.info.as_ref(), - Operation::BlockingRead, - "version", - )); - } - - self.inner.blocking_read(path, args) + self.inner().blocking_read(path, args) } fn blocking_write( @@ -181,40 +151,28 @@ impl LayeredAccess for CapabilityAccessor { ) -> crate::Result<(RpWrite, Self::BlockingWriter)> { let capability = self.info.full_capability(); if !capability.write_with_content_type && args.content_type().is_some() { - return Err(new_unsupported_args_error( + return Err(new_unsupported_error( self.info.as_ref(), Operation::BlockingWrite, "content_type", )); } - - self.inner.blocking_write(path, args) - } - - fn blocking_stat(&self, path: &str, args: OpStat) -> crate::Result { - let capability = self.info.full_capability(); - if !capability.stat_with_version && args.version().is_some() { - return Err(new_unsupported_args_error( + if !capability.write_with_cache_control && args.cache_control().is_some() { + return Err(new_unsupported_error( self.info.as_ref(), - Operation::BlockingStat, - "version", + Operation::BlockingWrite, + "cache_control", )); } - - self.inner.blocking_stat(path, args) - } - - fn blocking_delete(&self, path: &str, args: OpDelete) -> crate::Result { - let capability = self.info.full_capability(); - if !capability.delete_with_version && args.version().is_some() { - return Err(new_unsupported_args_error( + if !capability.write_with_content_disposition && args.content_disposition().is_some() { + return Err(new_unsupported_error( self.info.as_ref(), - Operation::BlockingDelete, - "version", + Operation::BlockingWrite, + "content_disposition", )); } - self.inner.blocking_delete(path, args) + self.inner.blocking_write(path, args) } fn blocking_list( @@ -224,7 +182,7 @@ impl LayeredAccess for CapabilityAccessor { ) -> crate::Result<(RpList, Self::BlockingLister)> { let capability = self.info.full_capability(); if !capability.list_with_version && args.version() { - return Err(new_unsupported_args_error( + return Err(new_unsupported_error( self.info.as_ref(), Operation::BlockingList, "version", @@ -238,13 +196,7 @@ impl LayeredAccess for CapabilityAccessor { #[cfg(test)] mod tests { use super::*; - use crate::raw::{ - oio, OpCopy, OpCreateDir, OpPresign, OpRename, PresignedRequest, RpCopy, RpCreateDir, - RpPresign, RpRename, - }; - use crate::{Capability, EntryMode, ErrorKind, Metadata, Operator}; - use http::HeaderMap; - use http::Method as HttpMethod; + use crate::{Capability, ErrorKind, Operator}; #[derive(Debug)] struct MockService { @@ -266,45 +218,13 @@ mod tests { info.into() } - async fn create_dir(&self, _: &str, _: OpCreateDir) -> crate::Result { - Ok(RpCreateDir {}) - } - - async fn stat(&self, _: &str, _: OpStat) -> crate::Result { - Ok(RpStat::new(Metadata::new(EntryMode::Unknown))) - } - - async fn read(&self, _: &str, _: OpRead) -> crate::Result<(RpRead, Self::Reader)> { - Ok((RpRead::new(), Box::new(bytes::Bytes::new()))) - } - async fn write(&self, _: &str, _: OpWrite) -> crate::Result<(RpWrite, Self::Writer)> { Ok((RpWrite::new(), Box::new(()))) } - async fn delete(&self, _: &str, _: OpDelete) -> crate::Result { - Ok(RpDelete {}) - } - async fn list(&self, _: &str, _: OpList) -> crate::Result<(RpList, Self::Lister)> { Ok((RpList {}, Box::new(()))) } - - async fn copy(&self, _: &str, _: &str, _: OpCopy) -> crate::Result { - Ok(RpCopy {}) - } - - async fn rename(&self, _: &str, _: &str, _: OpRename) -> crate::Result { - Ok(RpRename {}) - } - - async fn presign(&self, _: &str, _: OpPresign) -> crate::Result { - Ok(RpPresign::new(PresignedRequest::new( - HttpMethod::POST, - "https://example.com/presign".parse().expect("should parse"), - HeaderMap::new(), - ))) - } } fn new_test_operator(capability: Capability) -> Operator { @@ -314,78 +234,41 @@ mod tests { } #[tokio::test] - async fn test_read_with() { + async fn test_writer_with() { let op = new_test_operator(Capability { - read: true, + write: true, ..Default::default() }); - let res = op.read_with("path").version("version").await; + let res = op.writer_with("path").content_type("type").await; assert!(res.is_err()); - assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); - - let op = new_test_operator(Capability { - read: true, - read_with_version: true, - ..Default::default() - }); - let res = op.read_with("path").version("version").await; - assert!(res.is_ok()) - } - #[tokio::test] - async fn test_stat_with() { - let op = new_test_operator(Capability { - stat: true, - ..Default::default() - }); - let res = op.stat_with("path").version("version").await; + let res = op.writer_with("path").cache_control("cache").await; assert!(res.is_err()); - assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); - let op = new_test_operator(Capability { - stat: true, - stat_with_version: true, - ..Default::default() - }); - let res = op.stat_with("path").version("version").await; - assert!(res.is_ok()) - } - - #[tokio::test] - async fn test_writer_with() { - let op = new_test_operator(Capability { - write: true, - ..Default::default() - }); - let res = op.writer_with("path").content_type("type").await; + let res = op + .writer_with("path") + .content_disposition("disposition") + .await; assert!(res.is_err()); let op = new_test_operator(Capability { write: true, write_with_content_type: true, + write_with_cache_control: true, + write_with_content_disposition: true, ..Default::default() }); let res = op.writer_with("path").content_type("type").await; assert!(res.is_ok()); - } - #[tokio::test] - async fn test_delete_with() { - let op = new_test_operator(Capability { - delete: true, - ..Default::default() - }); - let res = op.delete_with("path").version("version").await; - assert!(res.is_err()); - assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); + let res = op.writer_with("path").cache_control("cache").await; + assert!(res.is_ok()); - let op = new_test_operator(Capability { - delete: true, - delete_with_version: true, - ..Default::default() - }); - let res = op.delete_with("path").version("version").await; - assert!(res.is_ok()) + let res = op + .writer_with("path") + .content_disposition("disposition") + .await; + assert!(res.is_ok()); } #[tokio::test] diff --git a/core/src/layers/complete.rs b/core/src/layers/complete.rs index bc06549014c4..31a3fb03e273 100644 --- a/core/src/layers/complete.rs +++ b/core/src/layers/complete.rs @@ -136,7 +136,7 @@ impl CompleteAccessor { return Ok(RpCreateDir::default()); } - return self.inner.create_dir(path, args).await; + self.inner.create_dir(path, args).await } fn complete_blocking_create_dir(&self, path: &str, args: OpCreateDir) -> Result { @@ -151,7 +151,7 @@ impl CompleteAccessor { return Ok(RpCreateDir::default()); } - return self.inner.blocking_create_dir(path, args); + self.inner.blocking_create_dir(path, args) } async fn complete_stat(&self, path: &str, args: OpStat) -> Result { diff --git a/core/src/layers/correctness_check.rs b/core/src/layers/correctness_check.rs index 0de038bab0d9..a2368d54d154 100644 --- a/core/src/layers/correctness_check.rs +++ b/core/src/layers/correctness_check.rs @@ -19,7 +19,7 @@ use std::fmt::{Debug, Formatter}; use std::sync::Arc; use crate::raw::*; -use crate::{Error, ErrorKind}; +use crate::*; /// Add a correctness capability check layer for every operation /// @@ -49,24 +49,9 @@ impl Layer for CorrectnessCheckLayer { } } -pub(crate) fn new_unsupported_error(info: &AccessorInfo, op: impl Into<&'static str>) -> Error { +pub(crate) fn new_unsupported_error(info: &AccessorInfo, op: Operation, args: &str) -> Error { let scheme = info.scheme(); - let op = op.into(); - - Error::new( - ErrorKind::Unsupported, - format!("service {scheme} doesn't support operation {op}"), - ) - .with_operation(op) -} - -pub(crate) fn new_unsupported_args_error( - info: &AccessorInfo, - op: impl Into<&'static str>, - args: &str, -) -> Error { - let scheme = info.scheme(); - let op = op.into(); + let op = op.into_static(); Error::new( ErrorKind::Unsupported, @@ -105,48 +90,37 @@ impl LayeredAccess for CorrectnessAccessor { self.info.clone() } - async fn create_dir(&self, path: &str, args: OpCreateDir) -> crate::Result { + async fn read(&self, path: &str, args: OpRead) -> Result<(RpRead, Self::Reader)> { let capability = self.info.full_capability(); - if !capability.create_dir { + if !capability.read_with_version && args.version().is_some() { return Err(new_unsupported_error( self.info.as_ref(), - Operation::CreateDir, + Operation::Read, + "version", )); } - self.inner.create_dir(path, args).await - } - - async fn read(&self, path: &str, args: OpRead) -> crate::Result<(RpRead, Self::Reader)> { - let capability = self.info.full_capability(); - if !capability.read { - return Err(new_unsupported_error(self.info.as_ref(), Operation::Read)); - } - self.inner.read(path, args).await } - async fn write(&self, path: &str, args: OpWrite) -> crate::Result<(RpWrite, Self::Writer)> { + async fn write(&self, path: &str, args: OpWrite) -> Result<(RpWrite, Self::Writer)> { let capability = self.info.full_capability(); - if !capability.write { - return Err(new_unsupported_error(&self.info, Operation::Write)); - } if args.append() && !capability.write_can_append { - return Err(new_unsupported_args_error( + return Err(new_unsupported_error( &self.info, Operation::Write, "append", )); } if args.if_not_exists() && !capability.write_with_if_not_exists { - return Err(new_unsupported_args_error( + return Err(new_unsupported_error( &self.info, Operation::Write, "if_not_exists", )); } if args.if_none_match().is_some() && !capability.write_with_if_none_match { - return Err(new_unsupported_args_error( + return Err(new_unsupported_error( self.info.as_ref(), Operation::Write, "if_none_match", @@ -156,125 +130,67 @@ impl LayeredAccess for CorrectnessAccessor { self.inner.write(path, args).await } - async fn copy(&self, from: &str, to: &str, args: OpCopy) -> crate::Result { - let capability = self.info.full_capability(); - if !capability.copy { - return Err(new_unsupported_error(self.info.as_ref(), Operation::Copy)); - } - - self.inner.copy(from, to, args).await - } - - async fn rename(&self, from: &str, to: &str, args: OpRename) -> crate::Result { - let capability = self.info.full_capability(); - if !capability.rename { - return Err(new_unsupported_error(self.info.as_ref(), Operation::Rename)); - } - - self.inner.rename(from, to, args).await - } - - async fn stat(&self, path: &str, args: OpStat) -> crate::Result { - let capability = self.info.full_capability(); - if !capability.stat { - return Err(new_unsupported_error(self.info.as_ref(), Operation::Stat)); - } - - self.inner.stat(path, args).await - } - - async fn delete(&self, path: &str, args: OpDelete) -> crate::Result { - let capability = self.info.full_capability(); - if !capability.delete { - return Err(new_unsupported_error(self.info.as_ref(), Operation::Delete)); - } - - self.inner.delete(path, args).await - } - - async fn list(&self, path: &str, args: OpList) -> crate::Result<(RpList, Self::Lister)> { - let capability = self.info.full_capability(); - if !capability.list { - return Err(new_unsupported_error(self.info.as_ref(), Operation::List)); - } - - self.inner.list(path, args).await - } - - async fn batch(&self, args: OpBatch) -> crate::Result { - let capability = self.info.full_capability(); - if !capability.batch { - return Err(new_unsupported_error(self.info.as_ref(), Operation::Batch)); - } - - self.inner.batch(args).await - } - - async fn presign(&self, path: &str, args: OpPresign) -> crate::Result { + async fn stat(&self, path: &str, args: OpStat) -> Result { let capability = self.info.full_capability(); - if !capability.presign { + if !capability.stat_with_version && args.version().is_some() { return Err(new_unsupported_error( self.info.as_ref(), - Operation::Presign, + Operation::Stat, + "version", )); } - self.inner.presign(path, args).await + self.inner.stat(path, args).await } - fn blocking_create_dir(&self, path: &str, args: OpCreateDir) -> crate::Result { + async fn delete(&self, path: &str, args: OpDelete) -> Result { let capability = self.info.full_capability(); - if !capability.create_dir || !capability.blocking { + if !capability.delete_with_version && args.version().is_some() { return Err(new_unsupported_error( self.info.as_ref(), - Operation::BlockingCreateDir, + Operation::Delete, + "version", )); } - self.inner.blocking_create_dir(path, args) + self.inner.delete(path, args).await + } + + async fn list(&self, path: &str, args: OpList) -> Result<(RpList, Self::Lister)> { + self.inner.list(path, args).await } - fn blocking_read( - &self, - path: &str, - args: OpRead, - ) -> crate::Result<(RpRead, Self::BlockingReader)> { + fn blocking_read(&self, path: &str, args: OpRead) -> Result<(RpRead, Self::BlockingReader)> { let capability = self.info.full_capability(); - if !capability.read || !capability.blocking { + if !capability.read_with_version && args.version().is_some() { return Err(new_unsupported_error( self.info.as_ref(), Operation::BlockingRead, + "version", )); } self.inner.blocking_read(path, args) } - fn blocking_write( - &self, - path: &str, - args: OpWrite, - ) -> crate::Result<(RpWrite, Self::BlockingWriter)> { + fn blocking_write(&self, path: &str, args: OpWrite) -> Result<(RpWrite, Self::BlockingWriter)> { let capability = self.info.full_capability(); - if !capability.write || !capability.blocking { - return Err(new_unsupported_error(&self.info, Operation::BlockingWrite)); - } if args.append() && !capability.write_can_append { - return Err(new_unsupported_args_error( + return Err(new_unsupported_error( &self.info, Operation::BlockingWrite, "append", )); } if args.if_not_exists() && !capability.write_with_if_not_exists { - return Err(new_unsupported_args_error( + return Err(new_unsupported_error( &self.info, Operation::BlockingWrite, "if_not_exists", )); } if args.if_none_match().is_some() && !capability.write_with_if_none_match { - return Err(new_unsupported_args_error( + return Err(new_unsupported_error( self.info.as_ref(), Operation::BlockingWrite, "if_none_match", @@ -284,80 +200,42 @@ impl LayeredAccess for CorrectnessAccessor { self.inner.blocking_write(path, args) } - fn blocking_copy(&self, from: &str, to: &str, args: OpCopy) -> crate::Result { - let capability = self.info.full_capability(); - if !capability.copy || !capability.blocking { - return Err(new_unsupported_error( - self.info.as_ref(), - Operation::BlockingCopy, - )); - } - - self.inner().blocking_copy(from, to, args) - } - - fn blocking_rename(&self, from: &str, to: &str, args: OpRename) -> crate::Result { - let capability = self.info.full_capability(); - if !capability.rename || !capability.blocking { - return Err(new_unsupported_error( - self.info.as_ref(), - Operation::BlockingRename, - )); - } - - self.inner().blocking_rename(from, to, args) - } - - fn blocking_stat(&self, path: &str, args: OpStat) -> crate::Result { + fn blocking_stat(&self, path: &str, args: OpStat) -> Result { let capability = self.info.full_capability(); - if !capability.stat || !capability.blocking { + if !capability.stat_with_version && args.version().is_some() { return Err(new_unsupported_error( self.info.as_ref(), Operation::BlockingStat, + "version", )); } self.inner.blocking_stat(path, args) } - fn blocking_delete(&self, path: &str, args: OpDelete) -> crate::Result { + fn blocking_delete(&self, path: &str, args: OpDelete) -> Result { let capability = self.info.full_capability(); - if !capability.delete || !capability.blocking { + if !capability.delete_with_version && args.version().is_some() { return Err(new_unsupported_error( self.info.as_ref(), Operation::BlockingDelete, + "version", )); } self.inner().blocking_delete(path, args) } - fn blocking_list( - &self, - path: &str, - args: OpList, - ) -> crate::Result<(RpList, Self::BlockingLister)> { - let capability = self.info.full_capability(); - if !capability.list || !capability.blocking { - return Err(new_unsupported_error( - self.info.as_ref(), - Operation::BlockingList, - )); - } - + fn blocking_list(&self, path: &str, args: OpList) -> Result<(RpList, Self::BlockingLister)> { self.inner.blocking_list(path, args) } } #[cfg(test)] mod tests { - use std::time::Duration; - use super::*; - use crate::raw::{oio, PresignedRequest}; + use crate::raw::oio; use crate::{Capability, EntryMode, Metadata, Operator}; - use http::HeaderMap; - use http::Method as HttpMethod; #[derive(Debug)] struct MockService { @@ -379,45 +257,25 @@ mod tests { info.into() } - async fn create_dir(&self, _: &str, _: OpCreateDir) -> crate::Result { - Ok(RpCreateDir {}) - } - - async fn stat(&self, _: &str, _: OpStat) -> crate::Result { + async fn stat(&self, _: &str, _: OpStat) -> Result { Ok(RpStat::new(Metadata::new(EntryMode::Unknown))) } - async fn read(&self, _: &str, _: OpRead) -> crate::Result<(RpRead, Self::Reader)> { + async fn read(&self, _: &str, _: OpRead) -> Result<(RpRead, Self::Reader)> { Ok((RpRead::new(), Box::new(bytes::Bytes::new()))) } - async fn write(&self, _: &str, _: OpWrite) -> crate::Result<(RpWrite, Self::Writer)> { + async fn write(&self, _: &str, _: OpWrite) -> Result<(RpWrite, Self::Writer)> { Ok((RpWrite::new(), Box::new(()))) } - async fn delete(&self, _: &str, _: OpDelete) -> crate::Result { + async fn delete(&self, _: &str, _: OpDelete) -> Result { Ok(RpDelete {}) } - async fn list(&self, _: &str, _: OpList) -> crate::Result<(RpList, Self::Lister)> { + async fn list(&self, _: &str, _: OpList) -> Result<(RpList, Self::Lister)> { Ok((RpList {}, Box::new(()))) } - - async fn copy(&self, _: &str, _: &str, _: OpCopy) -> crate::Result { - Ok(RpCopy {}) - } - - async fn rename(&self, _: &str, _: &str, _: OpRename) -> crate::Result { - Ok(RpRename {}) - } - - async fn presign(&self, _: &str, _: OpPresign) -> crate::Result { - Ok(RpPresign::new(PresignedRequest::new( - HttpMethod::POST, - "https://example.com/presign".parse().expect("should parse"), - HeaderMap::new(), - ))) - } } fn new_test_operator(capability: Capability) -> Operator { @@ -428,49 +286,40 @@ mod tests { #[tokio::test] async fn test_read() { - let op = new_test_operator(Capability::default()); - let res = op.read("path").await; + let op = new_test_operator(Capability { + read: true, + ..Default::default() + }); + let res = op.read_with("path").version("version").await; assert!(res.is_err()); assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); let op = new_test_operator(Capability { read: true, - stat: true, + read_with_version: true, ..Default::default() }); - let res = op.read("path").await; - assert!(res.is_ok()) + let res = op.read_with("path").version("version").await; + assert!(res.is_ok()); } #[tokio::test] async fn test_stat() { - let op = new_test_operator(Capability::default()); - let res = op.stat("path").await; - assert!(res.is_err()); - assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); - let op = new_test_operator(Capability { stat: true, ..Default::default() }); - let res = op.stat("path").await; - assert!(res.is_ok()) - } - - #[tokio::test] - async fn test_writer() { - let op = new_test_operator(Capability::default()); - let bs: Vec = vec![]; - let res = op.write("path", bs).await; + let res = op.stat_with("path").version("version").await; assert!(res.is_err()); assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); let op = new_test_operator(Capability { - write: true, + stat: true, + stat_with_version: true, ..Default::default() }); - let res = op.writer("path").await; - assert!(res.is_ok()) + let res = op.stat_with("path").version("version").await; + assert!(res.is_ok()); } #[tokio::test] @@ -481,18 +330,21 @@ mod tests { }); let res = op.write_with("path", "".as_bytes()).append(true).await; assert!(res.is_err()); + assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); let res = op .write_with("path", "".as_bytes()) .if_not_exists(true) .await; assert!(res.is_err()); + assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); let res = op .write_with("path", "".as_bytes()) .if_none_match("etag") .await; assert!(res.is_err()); + assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); let op = new_test_operator(Capability { write: true, @@ -505,94 +357,22 @@ mod tests { assert!(res.is_ok()); } - #[tokio::test] - async fn test_create_dir() { - let op = new_test_operator(Capability::default()); - let res = op.create_dir("path/").await; - assert!(res.is_err()); - assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); - - let op = new_test_operator(Capability { - create_dir: true, - ..Default::default() - }); - let res = op.create_dir("path/").await; - assert!(res.is_ok()) - } - #[tokio::test] async fn test_delete() { - let op = new_test_operator(Capability::default()); - let res = op.delete("path").await; - assert!(res.is_err()); - assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); - let op = new_test_operator(Capability { delete: true, ..Default::default() }); - let res = op.delete("path").await; - assert!(res.is_ok()) - } - - #[tokio::test] - async fn test_copy() { - let op = new_test_operator(Capability::default()); - let res = op.copy("path_a", "path_b").await; - assert!(res.is_err()); - assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); - - let op = new_test_operator(Capability { - copy: true, - ..Default::default() - }); - let res = op.copy("path_a", "path_b").await; - assert!(res.is_ok()) - } - - #[tokio::test] - async fn test_rename() { - let op = new_test_operator(Capability::default()); - let res = op.rename("path_a", "path_b").await; + let res = op.delete_with("path").version("version").await; assert!(res.is_err()); assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); let op = new_test_operator(Capability { - rename: true, - ..Default::default() - }); - let res = op.rename("path_a", "path_b").await; - assert!(res.is_ok()) - } - - #[tokio::test] - async fn test_list() { - let op = new_test_operator(Capability::default()); - let res = op.list("path/").await; - assert!(res.is_err()); - assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); - - let op = new_test_operator(Capability { - list: true, - list_with_recursive: true, - ..Default::default() - }); - let res = op.list("path/").await; - assert!(res.is_ok()) - } - - #[tokio::test] - async fn test_presign() { - let op = new_test_operator(Capability::default()); - let res = op.presign_read("path", Duration::from_secs(1)).await; - assert!(res.is_err()); - assert_eq!(res.unwrap_err().kind(), ErrorKind::Unsupported); - - let op = new_test_operator(Capability { - presign: true, + delete: true, + delete_with_version: true, ..Default::default() }); - let res = op.presign_read("path", Duration::from_secs(1)).await; + let res = op.delete_with("path").version("version").await; assert!(res.is_ok()) } }