This is an automated email from the ASF dual-hosted git repository.

xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git


The following commit(s) were added to refs/heads/main by this push:
     new f4cd502f4 feat: add native & full capability (#2874)
f4cd502f4 is described below

commit f4cd502f412a24e7fdf5768ed919b0ea9f66f937
Author: yah01 <[email protected]>
AuthorDate: Sat Aug 19 12:48:48 2023 +0800

    feat: add native & full capability (#2874)
    
    * feat: add native & full capability
    
    Signed-off-by: yah01 <[email protected]>
    
    * fix move meta out
    
    Signed-off-by: yah01 <[email protected]>
    
    * fix tests
    
    Signed-off-by: yah01 <[email protected]>
    
    ---------
    
    Signed-off-by: yah01 <[email protected]>
---
 bin/oay/src/services/s3/service.rs                 |  2 +-
 core/src/layers/blocking.rs                        |  7 ++-
 core/src/layers/complete.rs                        | 57 +++++++++++++---------
 core/src/layers/immutable_index.rs                 |  2 +-
 core/src/layers/madsim.rs                          |  2 +-
 core/src/layers/retry.rs                           |  2 +-
 core/src/raw/accessor.rs                           | 29 ++++++-----
 core/src/raw/adapters/kv/api.rs                    |  2 +-
 core/src/raw/adapters/kv/backend.rs                |  2 +-
 core/src/raw/adapters/typed_kv/backend.rs          |  2 +-
 core/src/raw/oio/page/into_flat_page.rs            |  6 +--
 .../raw/oio/read/into_seekable_read_by_range.rs    |  2 +-
 core/src/services/azblob/backend.rs                |  2 +-
 core/src/services/azdfs/backend.rs                 |  2 +-
 core/src/services/cos/backend.rs                   |  2 +-
 core/src/services/dropbox/backend.rs               |  2 +-
 core/src/services/fs/backend.rs                    |  2 +-
 core/src/services/ftp/backend.rs                   |  2 +-
 core/src/services/gcs/backend.rs                   |  2 +-
 core/src/services/gdrive/backend.rs                |  2 +-
 core/src/services/ghac/backend.rs                  |  2 +-
 core/src/services/hdfs/backend.rs                  |  2 +-
 core/src/services/http/backend.rs                  |  2 +-
 core/src/services/ipfs/backend.rs                  |  2 +-
 core/src/services/ipmfs/backend.rs                 |  2 +-
 core/src/services/obs/backend.rs                   |  2 +-
 core/src/services/onedrive/backend.rs              |  2 +-
 core/src/services/oss/backend.rs                   |  2 +-
 core/src/services/s3/backend.rs                    |  2 +-
 core/src/services/sftp/backend.rs                  |  2 +-
 core/src/services/supabase/backend.rs              |  2 +-
 core/src/services/vercel_artifacts/backend.rs      |  2 +-
 core/src/services/wasabi/backend.rs                |  2 +-
 core/src/services/webdav/backend.rs                |  2 +-
 core/src/services/webhdfs/backend.rs               |  2 +-
 core/src/types/operator/blocking_operator.rs       |  2 +-
 core/src/types/operator/metadata.rs                | 52 +++-----------------
 core/src/types/operator/operator.rs                |  6 +--
 core/tests/behavior/append.rs                      |  8 +--
 core/tests/behavior/blocking_copy.rs               |  2 +-
 core/tests/behavior/blocking_list.rs               |  2 +-
 core/tests/behavior/blocking_read_only.rs          |  2 +-
 core/tests/behavior/blocking_rename.rs             |  2 +-
 core/tests/behavior/blocking_write.rs              | 12 ++---
 core/tests/behavior/copy.rs                        |  2 +-
 core/tests/behavior/fuzz.rs                        |  2 +-
 core/tests/behavior/list.rs                        |  4 +-
 core/tests/behavior/list_only.rs                   |  2 +-
 core/tests/behavior/presign.rs                     |  2 +-
 core/tests/behavior/read_only.rs                   | 10 ++--
 core/tests/behavior/rename.rs                      |  2 +-
 core/tests/behavior/write.rs                       | 50 ++++++++++---------
 52 files changed, 151 insertions(+), 172 deletions(-)

diff --git a/bin/oay/src/services/s3/service.rs 
b/bin/oay/src/services/s3/service.rs
index a41130112..56a4a4d6a 100644
--- a/bin/oay/src/services/s3/service.rs
+++ b/bin/oay/src/services/s3/service.rs
@@ -88,7 +88,7 @@ async fn handle_list_objects(
 ) -> Result<OkResponse, ErrorResponse> {
     debug!("got params: {:?}", params);
 
-    if !state.op.info().capability().list_with_start_after {
+    if !state.op.info().full_capability().list_with_start_after {
         return Err(ErrorResponse {
             code: StatusCode::NOT_IMPLEMENTED,
             err: Error {
diff --git a/core/src/layers/blocking.rs b/core/src/layers/blocking.rs
index c6fe23bb9..47dbcba40 100644
--- a/core/src/layers/blocking.rs
+++ b/core/src/layers/blocking.rs
@@ -80,10 +80,9 @@ impl<A: Accessor> LayeredAccessor for BlockingAccessor<A> {
     }
 
     fn metadata(&self) -> AccessorInfo {
-        let mut info = self.inner.info();
-        let cap = info.capability_mut();
-        cap.blocking = true;
-        info
+        let mut meta = self.inner.info();
+        meta.full_capability_mut().blocking = true;
+        meta
     }
 
     async fn create_dir(&self, path: &str, args: OpCreateDir) -> 
Result<RpCreateDir> {
diff --git a/core/src/layers/complete.rs b/core/src/layers/complete.rs
index d30da0b55..0dda5965c 100644
--- a/core/src/layers/complete.rs
+++ b/core/src/layers/complete.rs
@@ -131,9 +131,8 @@ impl<A: Accessor> Layer<A> for CompleteLayer {
     type LayeredAccessor = CompleteReaderAccessor<A>;
 
     fn layer(&self, inner: A) -> Self::LayeredAccessor {
-        let meta = inner.info();
         CompleteReaderAccessor {
-            meta,
+            meta: inner.info(),
             inner: Arc::new(inner),
         }
     }
@@ -157,7 +156,7 @@ impl<A: Accessor> CompleteReaderAccessor<A> {
         path: &str,
         args: OpRead,
     ) -> Result<(RpRead, CompleteReader<A, A::Reader>)> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.read {
             return new_capability_unsupported_error(Operation::Read);
         }
@@ -210,7 +209,7 @@ impl<A: Accessor> CompleteReaderAccessor<A> {
         path: &str,
         args: OpRead,
     ) -> Result<(RpRead, CompleteReader<A, A::BlockingReader>)> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.read || !capability.blocking {
             return new_capability_unsupported_error(Operation::BlockingRead);
         }
@@ -266,7 +265,7 @@ impl<A: Accessor> CompleteReaderAccessor<A> {
         path: &str,
         args: OpList,
     ) -> Result<(RpList, CompletePager<A, A::Pager>)> {
-        let cap = self.meta.capability();
+        let cap = self.meta.full_capability();
         if !cap.list {
             return Err(
                 Error::new(ErrorKind::Unsupported, "operation is not 
supported")
@@ -315,7 +314,7 @@ impl<A: Accessor> CompleteReaderAccessor<A> {
         path: &str,
         args: OpList,
     ) -> Result<(RpList, CompletePager<A, A::BlockingPager>)> {
-        let cap = self.meta.capability();
+        let cap = self.meta.full_capability();
         if !cap.list {
             return Err(
                 Error::new(ErrorKind::Unsupported, "operation is not 
supported")
@@ -376,6 +375,16 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
         &self.inner
     }
 
+    fn metadata(&self) -> AccessorInfo {
+        let mut meta = self.meta.clone();
+        let cap = meta.full_capability_mut();
+        if cap.read {
+            cap.read_can_next = true;
+            cap.read_can_seek = true;
+        }
+        meta
+    }
+
     async fn read(&self, path: &str, args: OpRead) -> Result<(RpRead, 
Self::Reader)> {
         self.complete_reader(path, args).await
     }
@@ -385,7 +394,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     async fn stat(&self, path: &str, args: OpStat) -> Result<RpStat> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.stat {
             return new_capability_unsupported_error(Operation::Stat);
         }
@@ -399,7 +408,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     fn blocking_stat(&self, path: &str, args: OpStat) -> Result<RpStat> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.stat || !capability.blocking {
             return new_capability_unsupported_error(Operation::BlockingStat);
         }
@@ -413,7 +422,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     async fn write(&self, path: &str, args: OpWrite) -> Result<(RpWrite, 
Self::Writer)> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.write {
             return new_capability_unsupported_error(Operation::Write);
         }
@@ -426,7 +435,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     fn blocking_write(&self, path: &str, args: OpWrite) -> Result<(RpWrite, 
Self::BlockingWriter)> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.write || !capability.blocking {
             return new_capability_unsupported_error(Operation::BlockingWrite);
         }
@@ -438,7 +447,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     async fn append(&self, path: &str, args: OpAppend) -> Result<(RpAppend, 
Self::Appender)> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.append {
             return new_capability_unsupported_error(Operation::Append);
         }
@@ -450,7 +459,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     async fn create_dir(&self, path: &str, args: OpCreateDir) -> 
Result<RpCreateDir> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.create_dir {
             return new_capability_unsupported_error(Operation::CreateDir);
         }
@@ -459,7 +468,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     fn blocking_create_dir(&self, path: &str, args: OpCreateDir) -> 
Result<RpCreateDir> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.create_dir || !capability.blocking {
             return 
new_capability_unsupported_error(Operation::BlockingCreateDir);
         }
@@ -468,7 +477,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     async fn delete(&self, path: &str, args: OpDelete) -> Result<RpDelete> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.delete {
             return new_capability_unsupported_error(Operation::Delete);
         }
@@ -477,7 +486,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     fn blocking_delete(&self, path: &str, args: OpDelete) -> Result<RpDelete> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.delete || !capability.blocking {
             return new_capability_unsupported_error(Operation::BlockingDelete);
         }
@@ -486,7 +495,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     async fn copy(&self, from: &str, to: &str, args: OpCopy) -> Result<RpCopy> 
{
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.copy {
             return new_capability_unsupported_error(Operation::Copy);
         }
@@ -495,7 +504,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     fn blocking_copy(&self, from: &str, to: &str, args: OpCopy) -> 
Result<RpCopy> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.copy || !capability.blocking {
             return new_capability_unsupported_error(Operation::BlockingCopy);
         }
@@ -504,7 +513,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     async fn rename(&self, from: &str, to: &str, args: OpRename) -> 
Result<RpRename> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.rename {
             return new_capability_unsupported_error(Operation::Rename);
         }
@@ -513,7 +522,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     fn blocking_rename(&self, from: &str, to: &str, args: OpRename) -> 
Result<RpRename> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.rename || !capability.blocking {
             return new_capability_unsupported_error(Operation::BlockingRename);
         }
@@ -522,7 +531,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     async fn list(&self, path: &str, args: OpList) -> Result<(RpList, 
Self::Pager)> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.list {
             return new_capability_unsupported_error(Operation::List);
         }
@@ -531,7 +540,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     fn blocking_list(&self, path: &str, args: OpList) -> Result<(RpList, 
Self::BlockingPager)> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.list || !capability.blocking {
             return new_capability_unsupported_error(Operation::BlockingList);
         }
@@ -540,7 +549,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     async fn presign(&self, path: &str, args: OpPresign) -> Result<RpPresign> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.presign {
             return new_capability_unsupported_error(Operation::Presign);
         }
@@ -549,7 +558,7 @@ impl<A: Accessor> LayeredAccessor for 
CompleteReaderAccessor<A> {
     }
 
     async fn batch(&self, args: OpBatch) -> Result<RpBatch> {
-        let capability = self.meta.capability();
+        let capability = self.meta.full_capability();
         if !capability.batch {
             return new_capability_unsupported_error(Operation::Batch);
         }
@@ -952,7 +961,7 @@ mod tests {
 
         fn info(&self) -> AccessorInfo {
             let mut info = AccessorInfo::default();
-            info.set_capability(self.capability);
+            info.set_full_capability(self.capability);
 
             info
         }
diff --git a/core/src/layers/immutable_index.rs 
b/core/src/layers/immutable_index.rs
index 374482151..dc167fbb5 100644
--- a/core/src/layers/immutable_index.rs
+++ b/core/src/layers/immutable_index.rs
@@ -152,7 +152,7 @@ impl<A: Accessor> LayeredAccessor for 
ImmutableIndexAccessor<A> {
     fn metadata(&self) -> AccessorInfo {
         let mut meta = self.inner.info();
 
-        let cap = meta.capability_mut();
+        let cap = meta.full_capability_mut();
         cap.list = true;
         cap.list_with_delimiter_slash = true;
         cap.list_without_delimiter = true;
diff --git a/core/src/layers/madsim.rs b/core/src/layers/madsim.rs
index 40b18d785..87d726c99 100644
--- a/core/src/layers/madsim.rs
+++ b/core/src/layers/madsim.rs
@@ -161,7 +161,7 @@ impl LayeredAccessor for MadsimAccessor {
         let mut info = AccessorInfo::default();
         info.set_name("madsim");
 
-        info.set_capability(Capability {
+        info.set_full_capability(Capability {
             read: true,
             write: true,
             ..Default::default()
diff --git a/core/src/layers/retry.rs b/core/src/layers/retry.rs
index e6d083a4d..d9febab02 100644
--- a/core/src/layers/retry.rs
+++ b/core/src/layers/retry.rs
@@ -1179,7 +1179,7 @@ mod tests {
 
         fn info(&self) -> AccessorInfo {
             let mut am = AccessorInfo::default();
-            am.set_capability(Capability {
+            am.set_full_capability(Capability {
                 read: true,
                 list: true,
                 list_with_delimiter_slash: true,
diff --git a/core/src/raw/accessor.rs b/core/src/raw/accessor.rs
index b6b74a159..ad8d3b095 100644
--- a/core/src/raw/accessor.rs
+++ b/core/src/raw/accessor.rs
@@ -398,7 +398,8 @@ impl Accessor for () {
             scheme: Scheme::Custom("dummy"),
             root: "".to_string(),
             name: "dummy".to_string(),
-            capability: Capability::default(),
+            native_capability: Capability::default(),
+            full_capability: Capability::default(),
         }
     }
 }
@@ -509,7 +510,8 @@ pub struct AccessorInfo {
     root: String,
     name: String,
 
-    capability: Capability,
+    native_capability: Capability,
+    full_capability: Capability,
 }
 
 impl AccessorInfo {
@@ -553,19 +555,24 @@ impl AccessorInfo {
         self
     }
 
-    /// Get backend's capabilities.
-    pub fn capability(&self) -> Capability {
-        self.capability
+    /// Get backend's native capabilities.
+    pub fn native_capability(&self) -> Capability {
+        self.native_capability
     }
 
-    /// Get backend's capabilities.
-    pub fn capability_mut(&mut self) -> &mut Capability {
-        &mut self.capability
+    /// Get service's full capabilities.
+    pub fn full_capability(&self) -> Capability {
+        self.full_capability
     }
 
-    /// Set capabilities for backend.
-    pub fn set_capability(&mut self, capability: Capability) -> &mut Self {
-        self.capability = capability;
+    /// Get service's full capabilities.
+    pub fn full_capability_mut(&mut self) -> &mut Capability {
+        &mut self.full_capability
+    }
+
+    /// Set full capabilities for service.
+    pub fn set_full_capability(&mut self, capability: Capability) -> &mut Self 
{
+        self.full_capability = capability;
         self
     }
 }
diff --git a/core/src/raw/adapters/kv/api.rs b/core/src/raw/adapters/kv/api.rs
index 0c1ad4f95..7ae2fe97e 100644
--- a/core/src/raw/adapters/kv/api.rs
+++ b/core/src/raw/adapters/kv/api.rs
@@ -169,7 +169,7 @@ impl From<Metadata> for AccessorInfo {
         let mut am = AccessorInfo::default();
         am.set_name(m.name());
         am.set_scheme(m.scheme());
-        am.set_capability(m.capabilities());
+        am.set_full_capability(m.capabilities());
 
         am
     }
diff --git a/core/src/raw/adapters/kv/backend.rs 
b/core/src/raw/adapters/kv/backend.rs
index 42bfed62d..91417d595 100644
--- a/core/src/raw/adapters/kv/backend.rs
+++ b/core/src/raw/adapters/kv/backend.rs
@@ -70,7 +70,7 @@ impl<S: Adapter> Accessor for Backend<S> {
         let mut am: AccessorInfo = self.kv.metadata().into();
         am.set_root(&self.root);
 
-        let cap = am.capability_mut();
+        let cap = am.full_capability_mut();
         if cap.read {
             cap.read_can_seek = true;
             cap.read_can_next = true;
diff --git a/core/src/raw/adapters/typed_kv/backend.rs 
b/core/src/raw/adapters/typed_kv/backend.rs
index af91d9042..b43530274 100644
--- a/core/src/raw/adapters/typed_kv/backend.rs
+++ b/core/src/raw/adapters/typed_kv/backend.rs
@@ -69,7 +69,7 @@ impl<S: Adapter> Accessor for Backend<S> {
         am.set_scheme(kv_info.scheme());
         am.set_name(kv_info.name());
         let kv_cap = kv_info.capabilities();
-        let cap = am.capability_mut();
+        let cap = am.full_capability_mut();
         if kv_cap.get {
             cap.read = true;
             cap.read_can_seek = true;
diff --git a/core/src/raw/oio/page/into_flat_page.rs 
b/core/src/raw/oio/page/into_flat_page.rs
index 1f2ffb992..5699b14d7 100644
--- a/core/src/raw/oio/page/into_flat_page.rs
+++ b/core/src/raw/oio/page/into_flat_page.rs
@@ -29,7 +29,7 @@ pub fn into_flat_page<A: Accessor, P>(acc: A, path: &str, 
size: usize) -> FlatPa
     {
         let meta = acc.info();
         debug_assert!(
-            meta.capability().list_with_delimiter_slash,
+            meta.full_capability().list_with_delimiter_slash,
             "service doesn't support list hierarchy, it must be a bug"
         );
     }
@@ -254,8 +254,8 @@ mod tests {
 
         fn info(&self) -> AccessorInfo {
             let mut am = AccessorInfo::default();
-            am.capability_mut().list = true;
-            am.capability_mut().list_with_delimiter_slash = true;
+            am.full_capability_mut().list = true;
+            am.full_capability_mut().list_with_delimiter_slash = true;
 
             am
         }
diff --git a/core/src/raw/oio/read/into_seekable_read_by_range.rs 
b/core/src/raw/oio/read/into_seekable_read_by_range.rs
index b996c61e9..18fd8a33b 100644
--- a/core/src/raw/oio/read/into_seekable_read_by_range.rs
+++ b/core/src/raw/oio/read/into_seekable_read_by_range.rs
@@ -421,7 +421,7 @@ mod tests {
 
         fn info(&self) -> AccessorInfo {
             let mut am = AccessorInfo::default();
-            am.set_capability(Capability {
+            am.set_full_capability(Capability {
                 read: true,
                 ..Default::default()
             });
diff --git a/core/src/services/azblob/backend.rs 
b/core/src/services/azblob/backend.rs
index b635f0203..5ec983cb7 100644
--- a/core/src/services/azblob/backend.rs
+++ b/core/src/services/azblob/backend.rs
@@ -518,7 +518,7 @@ impl Accessor for AzblobBackend {
         am.set_scheme(Scheme::Azblob)
             .set_root(&self.core.root)
             .set_name(&self.core.container)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
                 stat_with_if_match: true,
                 stat_with_if_none_match: true,
diff --git a/core/src/services/azdfs/backend.rs 
b/core/src/services/azdfs/backend.rs
index b629894a2..5320a3089 100644
--- a/core/src/services/azdfs/backend.rs
+++ b/core/src/services/azdfs/backend.rs
@@ -241,7 +241,7 @@ impl Accessor for AzdfsBackend {
         am.set_scheme(Scheme::Azdfs)
             .set_root(&self.core.root)
             .set_name(&self.core.filesystem)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
 
                 read: true,
diff --git a/core/src/services/cos/backend.rs b/core/src/services/cos/backend.rs
index 78236f2f6..1ec1caccb 100644
--- a/core/src/services/cos/backend.rs
+++ b/core/src/services/cos/backend.rs
@@ -279,7 +279,7 @@ impl Accessor for CosBackend {
         am.set_scheme(Scheme::Cos)
             .set_root(&self.core.root)
             .set_name(&self.core.bucket)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
                 stat_with_if_match: true,
                 stat_with_if_none_match: true,
diff --git a/core/src/services/dropbox/backend.rs 
b/core/src/services/dropbox/backend.rs
index 642d22801..29b4f12ac 100644
--- a/core/src/services/dropbox/backend.rs
+++ b/core/src/services/dropbox/backend.rs
@@ -59,7 +59,7 @@ impl Accessor for DropboxBackend {
         let mut ma = AccessorInfo::default();
         ma.set_scheme(Scheme::Dropbox)
             .set_root(&self.core.root)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
 
                 read: true,
diff --git a/core/src/services/fs/backend.rs b/core/src/services/fs/backend.rs
index 53da83e50..632e9fff4 100644
--- a/core/src/services/fs/backend.rs
+++ b/core/src/services/fs/backend.rs
@@ -256,7 +256,7 @@ impl Accessor for FsBackend {
         let mut am = AccessorInfo::default();
         am.set_scheme(Scheme::Fs)
             .set_root(&self.root.to_string_lossy())
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
 
                 read: true,
diff --git a/core/src/services/ftp/backend.rs b/core/src/services/ftp/backend.rs
index b4067305f..2e643d35f 100644
--- a/core/src/services/ftp/backend.rs
+++ b/core/src/services/ftp/backend.rs
@@ -274,7 +274,7 @@ impl Accessor for FtpBackend {
         let mut am = AccessorInfo::default();
         am.set_scheme(Scheme::Ftp)
             .set_root(&self.root)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
 
                 read: true,
diff --git a/core/src/services/gcs/backend.rs b/core/src/services/gcs/backend.rs
index 20e605099..db0318a26 100644
--- a/core/src/services/gcs/backend.rs
+++ b/core/src/services/gcs/backend.rs
@@ -404,7 +404,7 @@ impl Accessor for GcsBackend {
         am.set_scheme(Scheme::Gcs)
             .set_root(&self.core.root)
             .set_name(&self.core.bucket)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 create_dir: true,
 
                 stat: true,
diff --git a/core/src/services/gdrive/backend.rs 
b/core/src/services/gdrive/backend.rs
index 07e52a4d9..2aa1c4246 100644
--- a/core/src/services/gdrive/backend.rs
+++ b/core/src/services/gdrive/backend.rs
@@ -62,7 +62,7 @@ impl Accessor for GdriveBackend {
         let mut ma = AccessorInfo::default();
         ma.set_scheme(crate::Scheme::Gdrive)
             .set_root(&self.core.root)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 read: true,
                 write: true,
                 delete: true,
diff --git a/core/src/services/ghac/backend.rs 
b/core/src/services/ghac/backend.rs
index 7197cee2a..db24d063a 100644
--- a/core/src/services/ghac/backend.rs
+++ b/core/src/services/ghac/backend.rs
@@ -304,7 +304,7 @@ impl Accessor for GhacBackend {
         am.set_scheme(Scheme::Ghac)
             .set_root(&self.root)
             .set_name(&self.version)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
 
                 read: true,
diff --git a/core/src/services/hdfs/backend.rs 
b/core/src/services/hdfs/backend.rs
index 0a6a255fb..1e28b68d8 100644
--- a/core/src/services/hdfs/backend.rs
+++ b/core/src/services/hdfs/backend.rs
@@ -173,7 +173,7 @@ impl Accessor for HdfsBackend {
         let mut am = AccessorInfo::default();
         am.set_scheme(Scheme::Hdfs)
             .set_root(&self.root)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
 
                 read: true,
diff --git a/core/src/services/http/backend.rs 
b/core/src/services/http/backend.rs
index ec0e722d1..9135e723d 100644
--- a/core/src/services/http/backend.rs
+++ b/core/src/services/http/backend.rs
@@ -263,7 +263,7 @@ impl Accessor for HttpBackend {
         let mut ma = AccessorInfo::default();
         ma.set_scheme(Scheme::Http)
             .set_root(&self.root)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
                 stat_with_if_match: true,
                 stat_with_if_none_match: true,
diff --git a/core/src/services/ipfs/backend.rs 
b/core/src/services/ipfs/backend.rs
index 32ee1d0b3..2a1e0b09a 100644
--- a/core/src/services/ipfs/backend.rs
+++ b/core/src/services/ipfs/backend.rs
@@ -173,7 +173,7 @@ impl Accessor for IpfsBackend {
         let mut ma = AccessorInfo::default();
         ma.set_scheme(Scheme::Ipfs)
             .set_root(&self.root)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
 
                 read: true,
diff --git a/core/src/services/ipmfs/backend.rs 
b/core/src/services/ipmfs/backend.rs
index 8dd05e6fb..5d92d20f7 100644
--- a/core/src/services/ipmfs/backend.rs
+++ b/core/src/services/ipmfs/backend.rs
@@ -75,7 +75,7 @@ impl Accessor for IpmfsBackend {
         let mut am = AccessorInfo::default();
         am.set_scheme(Scheme::Ipmfs)
             .set_root(&self.root)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
 
                 read: true,
diff --git a/core/src/services/obs/backend.rs b/core/src/services/obs/backend.rs
index 7a5aa96b7..56957a899 100644
--- a/core/src/services/obs/backend.rs
+++ b/core/src/services/obs/backend.rs
@@ -342,7 +342,7 @@ impl Accessor for ObsBackend {
         am.set_scheme(Scheme::Obs)
             .set_root(&self.core.root)
             .set_name(&self.core.bucket)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
                 stat_with_if_match: true,
                 stat_with_if_none_match: true,
diff --git a/core/src/services/onedrive/backend.rs 
b/core/src/services/onedrive/backend.rs
index 3c55a07a2..236dae03b 100644
--- a/core/src/services/onedrive/backend.rs
+++ b/core/src/services/onedrive/backend.rs
@@ -74,7 +74,7 @@ impl Accessor for OnedriveBackend {
         let mut ma = AccessorInfo::default();
         ma.set_scheme(Scheme::Onedrive)
             .set_root(&self.root)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 read: true,
                 write: true,
                 stat: true,
diff --git a/core/src/services/oss/backend.rs b/core/src/services/oss/backend.rs
index 14cc08c2f..65156ccc3 100644
--- a/core/src/services/oss/backend.rs
+++ b/core/src/services/oss/backend.rs
@@ -397,7 +397,7 @@ impl Accessor for OssBackend {
         am.set_scheme(Scheme::Oss)
             .set_root(&self.core.root)
             .set_name(&self.core.bucket)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
                 stat_with_if_match: true,
                 stat_with_if_none_match: true,
diff --git a/core/src/services/s3/backend.rs b/core/src/services/s3/backend.rs
index 0a2babb53..54220b711 100644
--- a/core/src/services/s3/backend.rs
+++ b/core/src/services/s3/backend.rs
@@ -902,7 +902,7 @@ impl Accessor for S3Backend {
         am.set_scheme(Scheme::S3)
             .set_root(&self.core.root)
             .set_name(&self.core.bucket)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
                 stat_with_if_match: true,
                 stat_with_if_none_match: true,
diff --git a/core/src/services/sftp/backend.rs 
b/core/src/services/sftp/backend.rs
index 4cb68f95a..425568d13 100644
--- a/core/src/services/sftp/backend.rs
+++ b/core/src/services/sftp/backend.rs
@@ -233,7 +233,7 @@ impl Accessor for SftpBackend {
         let mut am = AccessorInfo::default();
         am.set_root(self.root.as_str())
             .set_scheme(Scheme::Sftp)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
 
                 read: true,
diff --git a/core/src/services/supabase/backend.rs 
b/core/src/services/supabase/backend.rs
index a893ecc50..18ef035e8 100644
--- a/core/src/services/supabase/backend.rs
+++ b/core/src/services/supabase/backend.rs
@@ -218,7 +218,7 @@ impl Accessor for SupabaseBackend {
         am.set_scheme(Scheme::Supabase)
             .set_root(&self.core.root)
             .set_name(&self.core.bucket)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
 
                 read: true,
diff --git a/core/src/services/vercel_artifacts/backend.rs 
b/core/src/services/vercel_artifacts/backend.rs
index b8a9d6491..866cb28cd 100644
--- a/core/src/services/vercel_artifacts/backend.rs
+++ b/core/src/services/vercel_artifacts/backend.rs
@@ -55,7 +55,7 @@ impl Accessor for VercelArtifactsBackend {
     fn info(&self) -> AccessorInfo {
         let mut ma = AccessorInfo::default();
         ma.set_scheme(Scheme::VercelArtifacts)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
 
                 read: true,
diff --git a/core/src/services/wasabi/backend.rs 
b/core/src/services/wasabi/backend.rs
index 954eec8f6..7aabc55c4 100644
--- a/core/src/services/wasabi/backend.rs
+++ b/core/src/services/wasabi/backend.rs
@@ -902,7 +902,7 @@ impl Accessor for WasabiBackend {
         am.set_scheme(Scheme::Wasabi)
             .set_root(&self.core.root)
             .set_name(&self.core.bucket)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
                 stat_with_if_match: true,
                 stat_with_if_none_match: true,
diff --git a/core/src/services/webdav/backend.rs 
b/core/src/services/webdav/backend.rs
index 49b1e981d..d472153fa 100644
--- a/core/src/services/webdav/backend.rs
+++ b/core/src/services/webdav/backend.rs
@@ -282,7 +282,7 @@ impl Accessor for WebdavBackend {
         let mut ma = AccessorInfo::default();
         ma.set_scheme(Scheme::Webdav)
             .set_root(&self.root)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
 
                 read: true,
diff --git a/core/src/services/webhdfs/backend.rs 
b/core/src/services/webhdfs/backend.rs
index 7bbe6c7c9..a8a17f068 100644
--- a/core/src/services/webhdfs/backend.rs
+++ b/core/src/services/webhdfs/backend.rs
@@ -409,7 +409,7 @@ impl Accessor for WebhdfsBackend {
         let mut am = AccessorInfo::default();
         am.set_scheme(Scheme::Webhdfs)
             .set_root(&self.root)
-            .set_capability(Capability {
+            .set_full_capability(Capability {
                 stat: true,
 
                 read: true,
diff --git a/core/src/types/operator/blocking_operator.rs 
b/core/src/types/operator/blocking_operator.rs
index ade1086da..0650d2ba8 100644
--- a/core/src/types/operator/blocking_operator.rs
+++ b/core/src/types/operator/blocking_operator.rs
@@ -71,7 +71,7 @@ impl BlockingOperator {
     pub(crate) fn from_inner(accessor: FusedAccessor) -> Self {
         let limit = accessor
             .info()
-            .capability()
+            .full_capability()
             .batch_max_operations
             .unwrap_or(1000);
         Self { accessor, limit }
diff --git a/core/src/types/operator/metadata.rs 
b/core/src/types/operator/metadata.rs
index 3d219dfca..397b5ef7e 100644
--- a/core/src/types/operator/metadata.rs
+++ b/core/src/types/operator/metadata.rs
@@ -47,53 +47,13 @@ impl OperatorInfo {
         self.0.name()
     }
 
-    /// Get [`Capability`] of operator.
-    pub fn capability(&self) -> Capability {
-        self.0.capability()
+    /// Get [`Full Capability`] of operator.
+    pub fn full_capability(&self) -> Capability {
+        self.0.full_capability()
     }
 
-    /// Check if current backend supports [`Accessor::read`] or not.
-    pub fn can_read(&self) -> bool {
-        self.0.capability().read
-    }
-
-    /// Check if current backend supports [`Accessor::write`] or not.
-    pub fn can_write(&self) -> bool {
-        self.0.capability().write
-    }
-
-    /// Check if current backend supports [`Accessor::append`] or not.
-    pub fn can_append(&self) -> bool {
-        self.0.capability().append
-    }
-
-    /// Check if current backend supports [`Accessor::copy`] or not.
-    pub fn can_copy(&self) -> bool {
-        self.0.capability().copy
-    }
-
-    /// Check if current backend supports [`Accessor::rename`] or not.
-    pub fn can_rename(&self) -> bool {
-        self.0.capability().rename
-    }
-
-    /// Check if current backend supports [`Accessor::list`] or not.
-    pub fn can_list(&self) -> bool {
-        self.0.capability().list
-    }
-
-    /// Check if current backend supports [`Accessor::presign`] or not.
-    pub fn can_presign(&self) -> bool {
-        self.0.capability().presign
-    }
-
-    /// Check if current backend supports batch operations or not.
-    pub fn can_batch(&self) -> bool {
-        self.0.capability().batch
-    }
-
-    /// Check if current backend supports blocking operations or not.
-    pub fn can_blocking(&self) -> bool {
-        self.0.capability().blocking
+    /// Get [`Native Capability`] of operator.
+    pub fn native_capability(&self) -> Capability {
+        self.0.native_capability()
     }
 }
diff --git a/core/src/types/operator/operator.rs 
b/core/src/types/operator/operator.rs
index 92959e726..9df7c7bbe 100644
--- a/core/src/types/operator/operator.rs
+++ b/core/src/types/operator/operator.rs
@@ -80,7 +80,7 @@ impl Operator {
     pub(crate) fn from_inner(accessor: FusedAccessor) -> Self {
         let limit = accessor
             .info()
-            .capability()
+            .full_capability()
             .batch_max_operations
             .unwrap_or(1000);
         Self { accessor, limit }
@@ -1059,7 +1059,7 @@ impl Operator {
     /// # }
     /// ```
     pub async fn remove_via(&self, input: impl Stream<Item = String> + Unpin) 
-> Result<()> {
-        if self.info().can_batch() {
+        if self.info().full_capability().batch {
             let mut input = input
                 .map(|v| (v, OpDelete::default().into()))
                 .chunks(self.limit());
@@ -1127,7 +1127,7 @@ impl Operator {
 
         let obs = self.lister_with(path).delimiter("").await?;
 
-        if self.info().can_batch() {
+        if self.info().full_capability().batch {
             let mut obs = obs.try_chunks(self.limit());
 
             while let Some(batches) = obs.next().await {
diff --git a/core/tests/behavior/append.rs b/core/tests/behavior/append.rs
index 0e5cf8801..782a323c5 100644
--- a/core/tests/behavior/append.rs
+++ b/core/tests/behavior/append.rs
@@ -27,7 +27,7 @@ use sha2::Sha256;
 use crate::*;
 
 pub fn behavior_append_tests(op: &Operator) -> Vec<Trial> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
 
     if !(cap.read && cap.write && cap.append) {
         return vec![];
@@ -84,7 +84,7 @@ pub async fn test_append_with_dir_path(op: Operator) -> 
Result<()> {
 
 /// Test append with cache control must success.
 pub async fn test_append_with_cache_control(op: Operator) -> Result<()> {
-    if !op.info().capability().append_with_cache_control {
+    if !op.info().full_capability().append_with_cache_control {
         return Ok(());
     }
 
@@ -110,7 +110,7 @@ pub async fn test_append_with_cache_control(op: Operator) 
-> Result<()> {
 
 /// Test append with content type must success.
 pub async fn test_append_with_content_type(op: Operator) -> Result<()> {
-    if !op.info().capability().append_with_content_type {
+    if !op.info().full_capability().append_with_content_type {
         return Ok(());
     }
 
@@ -137,7 +137,7 @@ pub async fn test_append_with_content_type(op: Operator) -> 
Result<()> {
 
 /// Write a single file with content disposition should succeed.
 pub async fn test_append_with_content_disposition(op: Operator) -> Result<()> {
-    if !op.info().capability().append_with_content_disposition {
+    if !op.info().full_capability().append_with_content_disposition {
         return Ok(());
     }
 
diff --git a/core/tests/behavior/blocking_copy.rs 
b/core/tests/behavior/blocking_copy.rs
index 43d0faec5..822369a22 100644
--- a/core/tests/behavior/blocking_copy.rs
+++ b/core/tests/behavior/blocking_copy.rs
@@ -20,7 +20,7 @@ use anyhow::Result;
 use crate::*;
 
 pub fn behavior_blocking_copy_tests(op: &Operator) -> Vec<Trial> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
 
     if !(cap.read && cap.write && cap.copy && cap.blocking) {
         return vec![];
diff --git a/core/tests/behavior/blocking_list.rs 
b/core/tests/behavior/blocking_list.rs
index 2f6e9e534..96f60bab1 100644
--- a/core/tests/behavior/blocking_list.rs
+++ b/core/tests/behavior/blocking_list.rs
@@ -24,7 +24,7 @@ use log::debug;
 use crate::*;
 
 pub fn behavior_blocking_list_tests(op: &Operator) -> Vec<Trial> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
 
     if !(cap.read && cap.write && cap.copy && cap.blocking && cap.list) {
         return vec![];
diff --git a/core/tests/behavior/blocking_read_only.rs 
b/core/tests/behavior/blocking_read_only.rs
index 847fa63e4..6c4f5e0ab 100644
--- a/core/tests/behavior/blocking_read_only.rs
+++ b/core/tests/behavior/blocking_read_only.rs
@@ -22,7 +22,7 @@ use sha2::Sha256;
 use crate::*;
 
 pub fn behavior_blocking_read_only_tests(op: &Operator) -> Vec<Trial> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
 
     if !(cap.read && !cap.write && cap.blocking) {
         return vec![];
diff --git a/core/tests/behavior/blocking_rename.rs 
b/core/tests/behavior/blocking_rename.rs
index 4506c2c5c..398a3f4da 100644
--- a/core/tests/behavior/blocking_rename.rs
+++ b/core/tests/behavior/blocking_rename.rs
@@ -20,7 +20,7 @@ use anyhow::Result;
 use crate::*;
 
 pub fn behavior_blocking_rename_tests(op: &Operator) -> Vec<Trial> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
 
     if !(cap.read && cap.write && cap.copy && cap.blocking && cap.rename) {
         return vec![];
diff --git a/core/tests/behavior/blocking_write.rs 
b/core/tests/behavior/blocking_write.rs
index 2b4f65a91..06d44a1b9 100644
--- a/core/tests/behavior/blocking_write.rs
+++ b/core/tests/behavior/blocking_write.rs
@@ -27,7 +27,7 @@ use sha2::Sha256;
 use crate::*;
 
 pub fn behavior_blocking_write_tests(op: &Operator) -> Vec<Trial> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
 
     if !(cap.read && cap.write && cap.blocking) {
         return vec![];
@@ -217,7 +217,7 @@ pub fn test_blocking_read_full(op: BlockingOperator) -> 
Result<()> {
 
 /// Read range content should match.
 pub fn test_blocking_read_range(op: BlockingOperator) -> Result<()> {
-    if !op.info().capability().read_with_range {
+    if !op.info().full_capability().read_with_range {
         return Ok(());
     }
 
@@ -246,7 +246,7 @@ pub fn test_blocking_read_range(op: BlockingOperator) -> 
Result<()> {
 
 /// Read large range content should match.
 pub fn test_blocking_read_large_range(op: BlockingOperator) -> Result<()> {
-    if !op.info().capability().read_with_range {
+    if !op.info().full_capability().read_with_range {
         return Ok(());
     }
 
@@ -286,7 +286,7 @@ pub fn test_blocking_read_not_exist(op: BlockingOperator) 
-> Result<()> {
 }
 
 pub fn test_blocking_fuzz_range_reader(op: BlockingOperator) -> Result<()> {
-    if !op.info().capability().read_with_range {
+    if !op.info().full_capability().read_with_range {
         return Ok(());
     }
 
@@ -323,7 +323,7 @@ pub fn test_blocking_fuzz_range_reader(op: 
BlockingOperator) -> Result<()> {
 }
 
 pub fn test_blocking_fuzz_offset_reader(op: BlockingOperator) -> Result<()> {
-    if !op.info().capability().read_with_range {
+    if !op.info().full_capability().read_with_range {
         return Ok(());
     }
 
@@ -360,7 +360,7 @@ pub fn test_blocking_fuzz_offset_reader(op: 
BlockingOperator) -> Result<()> {
 }
 
 pub fn test_blocking_fuzz_part_reader(op: BlockingOperator) -> Result<()> {
-    if !op.info().capability().read_with_range {
+    if !op.info().full_capability().read_with_range {
         return Ok(());
     }
 
diff --git a/core/tests/behavior/copy.rs b/core/tests/behavior/copy.rs
index 086fa160e..0e9353d95 100644
--- a/core/tests/behavior/copy.rs
+++ b/core/tests/behavior/copy.rs
@@ -20,7 +20,7 @@ use anyhow::Result;
 use crate::*;
 
 pub fn behavior_copy_tests(op: &Operator) -> Vec<Trial> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
 
     if !(cap.read && cap.write && cap.copy) {
         return vec![];
diff --git a/core/tests/behavior/fuzz.rs b/core/tests/behavior/fuzz.rs
index cca74763b..8a7b8187f 100644
--- a/core/tests/behavior/fuzz.rs
+++ b/core/tests/behavior/fuzz.rs
@@ -67,7 +67,7 @@ pub fn behavior_fuzz_tests(op: &Operator) -> Vec<Trial> {
 /// is invalid for given range `1..2`. However, the actual behavior is we seek 
to `0`
 /// and results in a panic.
 pub async fn test_fuzz_issue_2717(op: Operator) -> Result<()> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
 
     if !(cap.read && cap.write & cap.read_with_range) {
         return Ok(());
diff --git a/core/tests/behavior/list.rs b/core/tests/behavior/list.rs
index 79a36fe87..071c8dbc4 100644
--- a/core/tests/behavior/list.rs
+++ b/core/tests/behavior/list.rs
@@ -27,7 +27,7 @@ use log::debug;
 use crate::*;
 
 pub fn behavior_list_tests(op: &Operator) -> Vec<Trial> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
 
     if !(cap.read && cap.write && cap.list) {
         return vec![];
@@ -335,7 +335,7 @@ pub async fn test_list_dir_with_file_path(op: Operator) -> 
Result<()> {
 
 /// List with start after should start listing after the specified key
 pub async fn test_list_with_start_after(op: Operator) -> Result<()> {
-    if !op.info().capability().list_with_start_after {
+    if !op.info().full_capability().list_with_start_after {
         return Ok(());
     }
 
diff --git a/core/tests/behavior/list_only.rs b/core/tests/behavior/list_only.rs
index e7778461d..27de2a743 100644
--- a/core/tests/behavior/list_only.rs
+++ b/core/tests/behavior/list_only.rs
@@ -23,7 +23,7 @@ use futures::TryStreamExt;
 use crate::*;
 
 pub fn behavior_list_only_tests(op: &Operator) -> Vec<Trial> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
 
     if !cap.list || cap.write {
         return vec![];
diff --git a/core/tests/behavior/presign.rs b/core/tests/behavior/presign.rs
index 8e2b2d2f2..7ddc9082b 100644
--- a/core/tests/behavior/presign.rs
+++ b/core/tests/behavior/presign.rs
@@ -29,7 +29,7 @@ use sha2::Sha256;
 use crate::*;
 
 pub fn behavior_presign_tests(op: &Operator) -> Vec<Trial> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
 
     if !(cap.list && cap.write && cap.presign) {
         return vec![];
diff --git a/core/tests/behavior/read_only.rs b/core/tests/behavior/read_only.rs
index 5037e4426..85d897aaf 100644
--- a/core/tests/behavior/read_only.rs
+++ b/core/tests/behavior/read_only.rs
@@ -23,7 +23,7 @@ use sha2::Sha256;
 use crate::*;
 
 pub fn behavior_read_only_tests(op: &Operator) -> Vec<Trial> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
 
     if !cap.read || cap.write {
         return vec![];
@@ -97,7 +97,7 @@ pub async fn test_read_only_stat_not_exist(op: Operator) -> 
Result<()> {
 
 /// Stat with if_match should succeed, else get a ConditionNotMatch error.
 pub async fn test_read_only_stat_with_if_match(op: Operator) -> Result<()> {
-    if !op.info().capability().stat_with_if_match {
+    if !op.info().full_capability().stat_with_if_match {
         return Ok(());
     }
 
@@ -122,7 +122,7 @@ pub async fn test_read_only_stat_with_if_match(op: 
Operator) -> Result<()> {
 
 /// Stat with if_none_match should succeed, else get a ConditionNotMatch.
 pub async fn test_read_only_stat_with_if_none_match(op: Operator) -> 
Result<()> {
-    if !op.info().capability().stat_with_if_none_match {
+    if !op.info().full_capability().stat_with_if_none_match {
         return Ok(());
     }
 
@@ -271,7 +271,7 @@ pub async fn test_read_only_read_with_dir_path(op: 
Operator) -> Result<()> {
 
 /// Read with if_match should match, else get a ConditionNotMatch error.
 pub async fn test_read_only_read_with_if_match(op: Operator) -> Result<()> {
-    if !op.info().capability().read_with_if_match {
+    if !op.info().full_capability().read_with_if_match {
         return Ok(());
     }
 
@@ -300,7 +300,7 @@ pub async fn test_read_only_read_with_if_match(op: 
Operator) -> Result<()> {
 
 /// Read with if_none_match should match, else get a ConditionNotMatch error.
 pub async fn test_read_only_read_with_if_none_match(op: Operator) -> 
Result<()> {
-    if !op.info().capability().read_with_if_none_match {
+    if !op.info().full_capability().read_with_if_none_match {
         return Ok(());
     }
 
diff --git a/core/tests/behavior/rename.rs b/core/tests/behavior/rename.rs
index d6c64a805..ac4974c8f 100644
--- a/core/tests/behavior/rename.rs
+++ b/core/tests/behavior/rename.rs
@@ -20,7 +20,7 @@ use anyhow::Result;
 use crate::*;
 
 pub fn behavior_rename_tests(op: &Operator) -> Vec<Trial> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
 
     if !(cap.read && cap.write && cap.rename) {
         return vec![];
diff --git a/core/tests/behavior/write.rs b/core/tests/behavior/write.rs
index 53ee84581..590ae6c06 100644
--- a/core/tests/behavior/write.rs
+++ b/core/tests/behavior/write.rs
@@ -35,7 +35,7 @@ use sha2::Sha256;
 use crate::*;
 
 pub fn behavior_write_tests(op: &Operator) -> Vec<Trial> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
 
     if !(cap.read && cap.write) {
         return vec![];
@@ -168,7 +168,7 @@ pub async fn test_write_with_special_chars(op: Operator) -> 
Result<()> {
 
 /// Write a single file with cache control should succeed.
 pub async fn test_write_with_cache_control(op: Operator) -> Result<()> {
-    if !op.info().capability().write_with_cache_control {
+    if !op.info().full_capability().write_with_cache_control {
         return Ok(());
     }
 
@@ -194,7 +194,7 @@ pub async fn test_write_with_cache_control(op: Operator) -> 
Result<()> {
 
 /// Write a single file with content type should succeed.
 pub async fn test_write_with_content_type(op: Operator) -> Result<()> {
-    if !op.info().capability().write_with_content_type {
+    if !op.info().full_capability().write_with_content_type {
         return Ok(());
     }
 
@@ -221,7 +221,7 @@ pub async fn test_write_with_content_type(op: Operator) -> 
Result<()> {
 
 /// Write a single file with content disposition should succeed.
 pub async fn test_write_with_content_disposition(op: Operator) -> Result<()> {
-    if !op.info().capability().write_with_content_disposition {
+    if !op.info().full_capability().write_with_content_disposition {
         return Ok(());
     }
 
@@ -324,7 +324,7 @@ pub async fn test_stat_not_exist(op: Operator) -> 
Result<()> {
 
 /// Stat with if_match should succeed, else get a ConditionNotMatch error.
 pub async fn test_stat_with_if_match(op: Operator) -> Result<()> {
-    if !op.info().capability().stat_with_if_match {
+    if !op.info().full_capability().stat_with_if_match {
         return Ok(());
     }
 
@@ -356,7 +356,7 @@ pub async fn test_stat_with_if_match(op: Operator) -> 
Result<()> {
 
 /// Stat with if_none_match should succeed, else get a ConditionNotMatch.
 pub async fn test_stat_with_if_none_match(op: Operator) -> Result<()> {
-    if !op.info().capability().stat_with_if_none_match {
+    if !op.info().full_capability().stat_with_if_none_match {
         return Ok(());
     }
 
@@ -425,7 +425,7 @@ pub async fn test_read_full(op: Operator) -> Result<()> {
 
 /// Read range content should match.
 pub async fn test_read_range(op: Operator) -> Result<()> {
-    if !op.info().capability().read_with_range {
+    if !op.info().full_capability().read_with_range {
         return Ok(());
     }
 
@@ -455,7 +455,7 @@ pub async fn test_read_range(op: Operator) -> Result<()> {
 
 /// Read large range content should match.
 pub async fn test_read_large_range(op: Operator) -> Result<()> {
-    if !op.info().capability().read_with_range {
+    if !op.info().full_capability().read_with_range {
         return Ok(());
     }
 
@@ -486,7 +486,7 @@ pub async fn test_read_large_range(op: Operator) -> 
Result<()> {
 
 /// Read range content should match.
 pub async fn test_reader_range(op: Operator) -> Result<()> {
-    if !op.info().capability().read_with_range {
+    if !op.info().full_capability().read_with_range {
         return Ok(());
     }
 
@@ -519,7 +519,7 @@ pub async fn test_reader_range(op: Operator) -> Result<()> {
 
 /// Read range from should match.
 pub async fn test_reader_from(op: Operator) -> Result<()> {
-    if !op.info().capability().read_with_range {
+    if !op.info().full_capability().read_with_range {
         return Ok(());
     }
 
@@ -550,7 +550,7 @@ pub async fn test_reader_from(op: Operator) -> Result<()> {
 
 /// Read range tail should match.
 pub async fn test_reader_tail(op: Operator) -> Result<()> {
-    if !op.info().capability().read_with_range {
+    if !op.info().full_capability().read_with_range {
         return Ok(());
     }
 
@@ -600,7 +600,7 @@ pub async fn test_read_not_exist(op: Operator) -> 
Result<()> {
 
 /// Read with if_match should match, else get a ConditionNotMatch error.
 pub async fn test_read_with_if_match(op: Operator) -> Result<()> {
-    if !op.info().capability().read_with_if_match {
+    if !op.info().full_capability().read_with_if_match {
         return Ok(());
     }
 
@@ -631,7 +631,7 @@ pub async fn test_read_with_if_match(op: Operator) -> 
Result<()> {
 
 /// Read with if_none_match should match, else get a ConditionNotMatch error.
 pub async fn test_read_with_if_none_match(op: Operator) -> Result<()> {
-    if !op.info().capability().read_with_if_none_match {
+    if !op.info().full_capability().read_with_if_none_match {
         return Ok(());
     }
 
@@ -664,7 +664,7 @@ pub async fn test_read_with_if_none_match(op: Operator) -> 
Result<()> {
 }
 
 pub async fn test_fuzz_range_reader(op: Operator) -> Result<()> {
-    if !op.info().capability().read_with_range {
+    if !op.info().full_capability().read_with_range {
         return Ok(());
     }
 
@@ -705,7 +705,7 @@ pub async fn test_fuzz_range_reader(op: Operator) -> 
Result<()> {
 }
 
 pub async fn test_fuzz_offset_reader(op: Operator) -> Result<()> {
-    if !op.info().capability().read_with_range {
+    if !op.info().full_capability().read_with_range {
         return Ok(());
     }
 
@@ -746,7 +746,7 @@ pub async fn test_fuzz_offset_reader(op: Operator) -> 
Result<()> {
 }
 
 pub async fn test_fuzz_part_reader(op: Operator) -> Result<()> {
-    if !op.info().capability().read_with_range {
+    if !op.info().full_capability().read_with_range {
         return Ok(());
     }
 
@@ -832,7 +832,9 @@ pub async fn test_read_with_special_chars(op: Operator) -> 
Result<()> {
 
 /// Read file with override-cache-control should succeed.
 pub async fn test_read_with_override_cache_control(op: Operator) -> Result<()> 
{
-    if !(op.info().capability().read_with_override_cache_control && 
op.info().can_presign()) {
+    if !(op.info().full_capability().read_with_override_cache_control
+        && op.info().full_capability().presign)
+    {
         return Ok(());
     }
 
@@ -879,9 +881,9 @@ pub async fn test_read_with_override_cache_control(op: 
Operator) -> Result<()> {
 pub async fn test_read_with_override_content_disposition(op: Operator) -> 
Result<()> {
     if !(op
         .info()
-        .capability()
+        .full_capability()
         .read_with_override_content_disposition
-        && op.info().can_presign())
+        && op.info().full_capability().presign)
     {
         return Ok(());
     }
@@ -930,7 +932,9 @@ pub async fn 
test_read_with_override_content_disposition(op: Operator) -> Result
 
 /// Read file with override_content_type should succeed.
 pub async fn test_read_with_override_content_type(op: Operator) -> Result<()> {
-    if !(op.info().capability().read_with_override_content_type && 
op.info().can_presign()) {
+    if !(op.info().full_capability().read_with_override_content_type
+        && op.info().full_capability().presign)
+    {
         return Ok(());
     }
 
@@ -1144,7 +1148,7 @@ pub async fn test_writer_write(op: Operator) -> 
Result<()> {
 
 /// Streaming data into writer
 pub async fn test_writer_sink(op: Operator) -> Result<()> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
     if !(cap.write && cap.write_can_sink) {
         return Ok(());
     }
@@ -1184,7 +1188,7 @@ pub async fn test_writer_sink(op: Operator) -> Result<()> 
{
 
 /// Reading data into writer
 pub async fn test_writer_copy(op: Operator) -> Result<()> {
-    let cap = op.info().capability();
+    let cap = op.info().full_capability();
     if !(cap.write && cap.write_can_sink) {
         return Ok(());
     }
@@ -1259,7 +1263,7 @@ pub async fn test_writer_futures_copy(op: Operator) -> 
Result<()> {
 
 /// Add test for unsized writer
 pub async fn test_fuzz_unsized_writer(op: Operator) -> Result<()> {
-    if !op.info().capability().write_without_content_length {
+    if !op.info().full_capability().write_without_content_length {
         warn!("{op:?} doesn't support write without content length, test 
skip");
         return Ok(());
     }

Reply via email to