You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2023/04/22 10:43:23 UTC

[incubator-opendal] 01/01: refactor: Allow reusing the same operator to speed up tests

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

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

commit 894d0107cf2e4a557a2a9aec12ce860e7ecd96f8
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Sat Apr 22 18:42:51 2023 +0800

    refactor: Allow reusing the same operator to speed up tests
    
    Signed-off-by: Xuanwo <gi...@xuanwo.io>
---
 core/tests/behavior/blocking_copy.rs   | 41 ++++++++++------------
 core/tests/behavior/blocking_list.rs   | 39 ++++++++++-----------
 core/tests/behavior/blocking_read.rs   | 39 ++++++++++-----------
 core/tests/behavior/blocking_rename.rs | 41 ++++++++++------------
 core/tests/behavior/blocking_write.rs  | 39 ++++++++++-----------
 core/tests/behavior/copy.rs            | 39 ++++++++++-----------
 core/tests/behavior/list.rs            | 41 ++++++++++------------
 core/tests/behavior/list_only.rs       | 35 +++++++++----------
 core/tests/behavior/main.rs            | 63 ++++++++++++++++++++--------------
 core/tests/behavior/presign.rs         | 35 +++++++++----------
 core/tests/behavior/read_only.rs       | 35 +++++++++----------
 core/tests/behavior/rename.rs          | 39 ++++++++++-----------
 core/tests/behavior/write.rs           | 35 +++++++++----------
 13 files changed, 248 insertions(+), 273 deletions(-)

diff --git a/core/tests/behavior/blocking_copy.rs b/core/tests/behavior/blocking_copy.rs
index 8cf724c4..346b8b45 100644
--- a/core/tests/behavior/blocking_copy.rs
+++ b/core/tests/behavior/blocking_copy.rs
@@ -30,31 +30,28 @@ use super::utils::*;
 macro_rules! behavior_blocking_copy_test {
     ($service:ident, $($(#[$meta:meta])* $test:ident),*,) => {
         paste::item! {
-            mod [<services_ $service:lower _blocking_copy>] {
+            $(
+                #[test]
                 $(
-                    #[test]
-                    $(
-                        #[$meta]
-                    )*
-                    fn [< $test >]() -> anyhow::Result<()> {
-                        let op = $crate::utils::init_service::<opendal::services::$service>(true);
-                        match op {
-                            Some(op) if op.info().can_read()
-                                && op.info().can_write()
-                                && op.info().can_copy()
-                                && op.info().can_blocking() => $crate::blocking_copy::$test(op.blocking()),
-                            Some(_) => {
-                                log::warn!("service {} doesn't support blocking_copy, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            },
-                            None => {
-                                log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            }
+                    #[$meta]
+                )*
+                fn [<blocking_copy_ $test >]() -> anyhow::Result<()> {
+                    match OPERATOR.as_ref() {
+                        Some(op) if op.info().can_read()
+                            && op.info().can_write()
+                            && op.info().can_copy()
+                            && op.info().can_blocking() => $crate::blocking_copy::$test(op.blocking()),
+                        Some(_) => {
+                            log::warn!("service {} doesn't support blocking_copy, ignored", opendal::Scheme::$service);
+                            Ok(())
+                        },
+                        None => {
+                            log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
+                            Ok(())
                         }
                     }
-                )*
-            }
+                }
+            )*
         }
     };
 }
diff --git a/core/tests/behavior/blocking_list.rs b/core/tests/behavior/blocking_list.rs
index c84084d3..4cc4abdf 100644
--- a/core/tests/behavior/blocking_list.rs
+++ b/core/tests/behavior/blocking_list.rs
@@ -34,30 +34,27 @@ use super::utils::*;
 macro_rules! behavior_blocking_list_test {
     ($service:ident, $($(#[$meta:meta])* $test:ident),*,) => {
         paste::item! {
-            mod [<services_ $service:lower _blocking_list>] {
+            $(
+                #[test]
                 $(
-                    #[test]
-                    $(
-                        #[$meta]
-                    )*
-                    fn [< $test >]() -> anyhow::Result<()> {
-                        let op = $crate::utils::init_service::<opendal::services::$service>(true);
-                        match op {
-                            Some(op) if op.info().can_read()
-                                && op.info().can_write()
-                                && op.info().can_blocking() && (op.info().can_list()||op.info().can_scan()) => $crate::blocking_list::$test(op.blocking()),
-                            Some(_) => {
-                                log::warn!("service {} doesn't support blocking_list, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            },
-                            None => {
-                                log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            }
+                    #[$meta]
+                )*
+                fn [<blocking_list_ $test >]() -> anyhow::Result<()> {
+                    match OPERATOR.as_ref() {
+                        Some(op) if op.info().can_read()
+                            && op.info().can_write()
+                            && op.info().can_blocking() && (op.info().can_list()||op.info().can_scan()) => $crate::blocking_list::$test(op.blocking()),
+                        Some(_) => {
+                            log::warn!("service {} doesn't support blocking_list, ignored", opendal::Scheme::$service);
+                            Ok(())
+                        },
+                        None => {
+                            log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
+                            Ok(())
                         }
                     }
-                )*
-            }
+                }
+            )*
         }
     };
 }
diff --git a/core/tests/behavior/blocking_read.rs b/core/tests/behavior/blocking_read.rs
index 2f4e77a7..2033398c 100644
--- a/core/tests/behavior/blocking_read.rs
+++ b/core/tests/behavior/blocking_read.rs
@@ -30,30 +30,27 @@ use sha2::Sha256;
 macro_rules! behavior_blocking_read_test {
     ($service:ident, $($(#[$meta:meta])* $test:ident),*,) => {
         paste::item! {
-            mod [<services_ $service:lower _blocking_read>] {
+            $(
+                #[test]
                 $(
-                    #[test]
-                    $(
-                        #[$meta]
-                    )*
-                    fn [< $test >]() -> anyhow::Result<()> {
-                        let op = $crate::utils::init_service::<opendal::services::$service>(true);
-                        match op {
-                            Some(op) if op.info().can_read()
-                                && !op.info().can_write()
-                                && op.info().can_blocking() => $crate::blocking_read::$test(op.blocking()),
-                            Some(_) => {
-                                log::warn!("service {} doesn't support blocking_read, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            },
-                            None => {
-                                log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            }
+                    #[$meta]
+                )*
+                fn [<blocking_read_ $test >]() -> anyhow::Result<()> {
+                    match OPERATOR.as_ref() {
+                        Some(op) if op.info().can_read()
+                            && !op.info().can_write()
+                            && op.info().can_blocking() => $crate::blocking_read::$test(op.blocking()),
+                        Some(_) => {
+                            log::warn!("service {} doesn't support blocking_read, ignored", opendal::Scheme::$service);
+                            Ok(())
+                        },
+                        None => {
+                            log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
+                            Ok(())
                         }
                     }
-                )*
-            }
+                }
+            )*
         }
     };
 }
diff --git a/core/tests/behavior/blocking_rename.rs b/core/tests/behavior/blocking_rename.rs
index 7222b230..3973a954 100644
--- a/core/tests/behavior/blocking_rename.rs
+++ b/core/tests/behavior/blocking_rename.rs
@@ -30,31 +30,28 @@ use super::utils::*;
 macro_rules! behavior_blocking_rename_test {
     ($service:ident, $($(#[$meta:meta])* $test:ident),*,) => {
         paste::item! {
-            mod [<services_ $service:lower _blocking_rename>] {
+            $(
+                #[test]
                 $(
-                    #[test]
-                    $(
-                        #[$meta]
-                    )*
-                    fn [< $test >]() -> anyhow::Result<()> {
-                        let op = $crate::utils::init_service::<opendal::services::$service>(true);
-                        match op {
-                            Some(op) if op.info().can_read()
-                                && op.info().can_write()
-                                && op.info().can_rename()
-                                && op.info().can_blocking() => $crate::blocking_rename::$test(op.blocking()),
-                            Some(_) => {
-                                log::warn!("service {} doesn't support blocking_rename, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            },
-                            None => {
-                                log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            }
+                    #[$meta]
+                )*
+                fn [<blocking_rename_ $test >]() -> anyhow::Result<()> {
+                    match OPERATOR.as_ref() {
+                        Some(op) if op.info().can_read()
+                            && op.info().can_write()
+                            && op.info().can_rename()
+                            && op.info().can_blocking() => $crate::blocking_rename::$test(op.blocking()),
+                        Some(_) => {
+                            log::warn!("service {} doesn't support blocking_rename, ignored", opendal::Scheme::$service);
+                            Ok(())
+                        },
+                        None => {
+                            log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
+                            Ok(())
                         }
                     }
-                )*
-            }
+                }
+            )*
         }
     };
 }
diff --git a/core/tests/behavior/blocking_write.rs b/core/tests/behavior/blocking_write.rs
index a444b1ca..d1bd392b 100644
--- a/core/tests/behavior/blocking_write.rs
+++ b/core/tests/behavior/blocking_write.rs
@@ -36,30 +36,27 @@ use super::utils::*;
 macro_rules! behavior_blocking_write_test {
     ($service:ident, $($(#[$meta:meta])* $test:ident),*,) => {
         paste::item! {
-            mod [<services_ $service:lower _blocking_write>] {
+            $(
+                #[test]
                 $(
-                    #[test]
-                    $(
-                        #[$meta]
-                    )*
-                    fn [< $test >]() -> anyhow::Result<()> {
-                        let op = $crate::utils::init_service::<opendal::services::$service>(true);
-                        match op {
-                            Some(op) if op.info().can_read()
-                                && op.info().can_write()
-                                && op.info().can_blocking() => $crate::blocking_write::$test(op.blocking()),
-                            Some(_) => {
-                                log::warn!("service {} doesn't support blocking_write, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            },
-                            None => {
-                                log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            }
+                    #[$meta]
+                )*
+                fn [<blocking_write_ $test >]() -> anyhow::Result<()> {
+                    match OPERATOR.as_ref() {
+                        Some(op) if op.info().can_read()
+                            && op.info().can_write()
+                            && op.info().can_blocking() => $crate::blocking_write::$test(op.blocking()),
+                        Some(_) => {
+                            log::warn!("service {} doesn't support blocking_write, ignored", opendal::Scheme::$service);
+                            Ok(())
+                        },
+                        None => {
+                            log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
+                            Ok(())
                         }
                     }
-                )*
-            }
+                }
+            )*
         }
     };
 }
diff --git a/core/tests/behavior/copy.rs b/core/tests/behavior/copy.rs
index e09f6b8d..ff9dfc91 100644
--- a/core/tests/behavior/copy.rs
+++ b/core/tests/behavior/copy.rs
@@ -29,30 +29,27 @@ use super::utils::*;
 macro_rules! behavior_copy_test {
     ($service:ident, $($(#[$meta:meta])* $test:ident),*,) => {
         paste::item! {
-            mod [<services_ $service:lower _copy>] {
+            $(
+                #[tokio::test]
                 $(
-                    #[tokio::test]
-                    $(
-                        #[$meta]
-                    )*
-                    async fn [< $test >]() -> anyhow::Result<()> {
-                        let op = $crate::utils::init_service::<opendal::services::$service>(true);
-                        match op {
-                            Some(op) if op.info().can_read()
-                              && op.info().can_write()
-                              && op.info().can_copy() => $crate::copy::$test(op).await,
-                            Some(_) => {
-                                log::warn!("service {} doesn't support copy, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            },
-                            None => {
-                                log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            }
+                    #[$meta]
+                )*
+                async fn [<copy_ $test >]() -> anyhow::Result<()> {
+                    match OPERATOR.as_ref() {
+                        Some(op) if op.info().can_read()
+                            && op.info().can_write()
+                            && op.info().can_copy() => $crate::copy::$test(op.clone()).await,
+                        Some(_) => {
+                            log::warn!("service {} doesn't support copy, ignored", opendal::Scheme::$service);
+                            Ok(())
+                        },
+                        None => {
+                            log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
+                            Ok(())
                         }
                     }
-                )*
-            }
+                }
+            )*
         }
     };
 }
diff --git a/core/tests/behavior/list.rs b/core/tests/behavior/list.rs
index 3c8d5347..293cff24 100644
--- a/core/tests/behavior/list.rs
+++ b/core/tests/behavior/list.rs
@@ -37,31 +37,28 @@ use super::utils::*;
 macro_rules! behavior_list_test {
     ($service:ident, $($(#[$meta:meta])* $test:ident),*,) => {
         paste::item! {
-            mod [<services_ $service:lower _list>] {
+            $(
+                #[tokio::test]
                 $(
-                    #[tokio::test]
-                    $(
-                        #[$meta]
-                    )*
-                    async fn [< $test >]() -> anyhow::Result<()> {
-                        let op = $crate::utils::init_service::<opendal::services::$service>(true);
-                        match op {
-                            Some(op) if op.info().can_read()
-                                && op.info().can_write()
-                                && (op.info().can_list()
-                                    || op.info().can_scan()) => $crate::list::$test(op).await,
-                            Some(_) => {
-                                log::warn!("service {} doesn't support list, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            },
-                            None => {
-                                log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            }
+                    #[$meta]
+                )*
+                async fn [<list_ $test >]() -> anyhow::Result<()> {
+                    match OPERATOR.as_ref() {
+                        Some(op) if op.info().can_read()
+                            && op.info().can_write()
+                            && (op.info().can_list()
+                                || op.info().can_scan()) => $crate::list::$test(op.clone()).await,
+                        Some(_) => {
+                            log::warn!("service {} doesn't support list, ignored", opendal::Scheme::$service);
+                            Ok(())
+                        },
+                        None => {
+                            log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
+                            Ok(())
                         }
                     }
-                )*
-            }
+                }
+            )*
         }
     };
 }
diff --git a/core/tests/behavior/list_only.rs b/core/tests/behavior/list_only.rs
index a8a292a4..8647336a 100644
--- a/core/tests/behavior/list_only.rs
+++ b/core/tests/behavior/list_only.rs
@@ -29,28 +29,25 @@ use opendal::Operator;
 macro_rules! behavior_list_only_test {
     ($service:ident, $($(#[$meta:meta])* $test:ident),*,) => {
         paste::item! {
-            mod [<services_ $service:lower _list_only>] {
+            $(
+                #[tokio::test]
                 $(
-                    #[tokio::test]
-                    $(
-                        #[$meta]
-                    )*
-                    async fn [< $test >]() -> anyhow::Result<()> {
-                        let op = $crate::utils::init_service::<opendal::services::$service>(false);
-                        match op {
-                            Some(op) if op.info().can_list() && !op.info().can_write() => $crate::list_only::$test(op).await,
-                            Some(_) => {
-                                log::warn!("service {} doesn't support list, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            },
-                            None => {
-                                log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            }
+                    #[$meta]
+                )*
+                async fn [<list_only_ $test >]() -> anyhow::Result<()> {
+                    match READ_ONLY_OPERATOR.as_ref() {
+                        Some(op) if op.info().can_list() && !op.info().can_write() => $crate::list_only::$test(op.clone()).await,
+                        Some(_) => {
+                            log::warn!("service {} doesn't support list, ignored", opendal::Scheme::$service);
+                            Ok(())
+                        },
+                        None => {
+                            log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
+                            Ok(())
                         }
                     }
-                )*
-            }
+                }
+            )*
         }
     };
 }
diff --git a/core/tests/behavior/main.rs b/core/tests/behavior/main.rs
index 63d63b16..0b131918 100644
--- a/core/tests/behavior/main.rs
+++ b/core/tests/behavior/main.rs
@@ -46,32 +46,43 @@ mod utils;
 /// Update function list while changed.
 macro_rules! behavior_tests {
     ($($service:ident),*) => {
-        $(
-            // can_read && !can_write
-            behavior_read_tests!($service);
-            // can_read && !can_write && can_blocking
-            behavior_blocking_read_tests!($service);
-            // can_read && can_write
-            behavior_write_tests!($service);
-            // can_read && can_write && can_blocking
-            behavior_blocking_write_tests!($service);
-            // can_read && can_write && can_copy
-            behavior_copy_tests!($service);
-            // can read && can_write && can_blocking && can_copy
-            behavior_blocking_copy_tests!($service);
-            // can_read && can_write && can_move
-            behavior_rename_tests!($service);
-            // can_read && can_write && can_blocking && can_move
-            behavior_blocking_rename_tests!($service);
-            // can_read && can_write && can_list
-            behavior_list_tests!($service);
-            // can_read && can_write && can_presign
-            behavior_presign_tests!($service);
-            // can_read && can_write && can_blocking && can_list
-            behavior_blocking_list_tests!($service);
-            // can_list && !can_write
-            behavior_list_only_tests!($service);
-        )*
+        paste::item! {
+            $(
+                mod [<services_ $service:lower>] {
+                    static OPERATOR: once_cell::sync::Lazy<Option<opendal::Operator>> = once_cell::sync::Lazy::new(||
+                        $crate::utils::init_service::<opendal::services::$service>(true)
+                    );
+                    static READ_ONLY_OPERATOR: once_cell::sync::Lazy<Option<opendal::Operator>> = once_cell::sync::Lazy::new(||
+                        $crate::utils::init_service::<opendal::services::$service>(false)
+                    );
+
+                    // can_read && !can_write
+                    behavior_read_tests!($service);
+                    // can_read && !can_write && can_blocking
+                    behavior_blocking_read_tests!($service);
+                    // can_read && can_write
+                    behavior_write_tests!($service);
+                    // can_read && can_write && can_blocking
+                    behavior_blocking_write_tests!($service);
+                    // can_read && can_write && can_copy
+                    behavior_copy_tests!($service);
+                    // can read && can_write && can_blocking && can_copy
+                    behavior_blocking_copy_tests!($service);
+                    // can_read && can_write && can_move
+                    behavior_rename_tests!($service);
+                    // can_read && can_write && can_blocking && can_move
+                    behavior_blocking_rename_tests!($service);
+                    // can_read && can_write && can_list
+                    behavior_list_tests!($service);
+                    // can_read && can_write && can_presign
+                    behavior_presign_tests!($service);
+                    // can_read && can_write && can_blocking && can_list
+                    behavior_blocking_list_tests!($service);
+                    // can_list && !can_write
+                    behavior_list_only_tests!($service);
+                }
+         )*
+        }
     };
 }
 
diff --git a/core/tests/behavior/presign.rs b/core/tests/behavior/presign.rs
index 8e42f902..2f29cd8c 100644
--- a/core/tests/behavior/presign.rs
+++ b/core/tests/behavior/presign.rs
@@ -37,28 +37,25 @@ use super::utils::*;
 macro_rules! behavior_presign_test {
     ($service:ident, $($(#[$meta:meta])* $test:ident),*,) => {
         paste::item! {
-            mod [<services_ $service:lower _presign>] {
+            $(
+                #[tokio::test]
                 $(
-                    #[tokio::test]
-                    $(
-                        #[$meta]
-                    )*
-                    async fn [< $test >]() -> anyhow::Result<()> {
-                        let op = $crate::utils::init_service::<opendal::services::$service>(true);
-                        match op {
-                            Some(op) if op.info().can_read() && op.info().can_write() && op.info().can_presign() => $crate::presign::$test(op).await,
-                            Some(_) => {
-                                log::warn!("service {} doesn't support presign, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            },
-                            None => {
-                                log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            }
+                    #[$meta]
+                )*
+                async fn [<presign_ $test >]() -> anyhow::Result<()> {
+                    match OPERATOR.as_ref() {
+                        Some(op) if op.info().can_read() && op.info().can_write() && op.info().can_presign() => $crate::presign::$test(op.clone()).await,
+                        Some(_) => {
+                            log::warn!("service {} doesn't support presign, ignored", opendal::Scheme::$service);
+                            Ok(())
+                        },
+                        None => {
+                            log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
+                            Ok(())
                         }
                     }
-                )*
-            }
+                }
+            )*
         }
     };
 }
diff --git a/core/tests/behavior/read_only.rs b/core/tests/behavior/read_only.rs
index 71054a74..edb36753 100644
--- a/core/tests/behavior/read_only.rs
+++ b/core/tests/behavior/read_only.rs
@@ -30,28 +30,25 @@ use sha2::Sha256;
 macro_rules! behavior_read_test {
     ($service:ident, $($(#[$meta:meta])* $test:ident),*,) => {
         paste::item! {
-            mod [<services_ $service:lower _read_only>] {
+            $(
+                #[tokio::test]
                 $(
-                    #[tokio::test]
-                    $(
-                        #[$meta]
-                    )*
-                    async fn [< $test >]() -> anyhow::Result<()> {
-                        let op = $crate::utils::init_service::<opendal::services::$service>(false);
-                        match op {
-                            Some(op) if op.info().can_read() && !op.info().can_write() => $crate::read_only::$test(op).await,
-                            Some(_) => {
-                                log::warn!("service {} doesn't support read_only, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            },
-                            None => {
-                                log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            }
+                    #[$meta]
+                )*
+                async fn [<read_only_ $test >]() -> anyhow::Result<()> {
+                    match READ_ONLY_OPERATOR.as_ref() {
+                        Some(op) if op.info().can_read() && !op.info().can_write() => $crate::read_only::$test(op.clone()).await,
+                        Some(_) => {
+                            log::warn!("service {} doesn't support read_only, ignored", opendal::Scheme::$service);
+                            Ok(())
+                        },
+                        None => {
+                            log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
+                            Ok(())
                         }
                     }
-                )*
-            }
+                }
+            )*
         }
     };
 }
diff --git a/core/tests/behavior/rename.rs b/core/tests/behavior/rename.rs
index 14744869..5919badf 100644
--- a/core/tests/behavior/rename.rs
+++ b/core/tests/behavior/rename.rs
@@ -29,30 +29,27 @@ use super::utils::*;
 macro_rules! behavior_rename_test {
     ($service:ident, $($(#[$meta:meta])* $test:ident),*,) => {
         paste::item! {
-            mod [<services_ $service:lower _rename>] {
+            $(
+                #[tokio::test]
                 $(
-                    #[tokio::test]
-                    $(
-                        #[$meta]
-                    )*
-                    async fn [< $test >]() -> anyhow::Result<()> {
-                        let op = $crate::utils::init_service::<opendal::services::$service>(true);
-                        match op {
-                            Some(op) if op.info().can_read()
-                              && op.info().can_write()
-                              && op.info().can_rename() => $crate::rename::$test(op).await,
-                            Some(_) => {
-                                log::warn!("service {} doesn't support rename, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            },
-                            None => {
-                                log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            }
+                    #[$meta]
+                )*
+                async fn [<rename_ $test >]() -> anyhow::Result<()> {
+                    match OPERATOR.as_ref() {
+                        Some(op) if op.info().can_read()
+                            && op.info().can_write()
+                            && op.info().can_rename() => $crate::rename::$test(op.clone()).await,
+                        Some(_) => {
+                            log::warn!("service {} doesn't support rename, ignored", opendal::Scheme::$service);
+                            Ok(())
+                        },
+                        None => {
+                            log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
+                            Ok(())
                         }
                     }
-                )*
-            }
+                }
+            )*
         }
     };
 }
diff --git a/core/tests/behavior/write.rs b/core/tests/behavior/write.rs
index 10082b57..2f8a0c87 100644
--- a/core/tests/behavior/write.rs
+++ b/core/tests/behavior/write.rs
@@ -36,28 +36,25 @@ use super::utils::*;
 macro_rules! behavior_write_test {
     ($service:ident, $($(#[$meta:meta])* $test:ident),*,) => {
         paste::item! {
-            mod [<services_ $service:lower _write>] {
+            $(
+                #[tokio::test]
                 $(
-                    #[tokio::test]
-                    $(
-                        #[$meta]
-                    )*
-                    async fn [< $test >]() -> anyhow::Result<()> {
-                        let op = $crate::utils::init_service::<opendal::services::$service>(true);
-                        match op {
-                            Some(op) if op.info().can_read() && op.info().can_write() => $crate::write::$test(op).await,
-                            Some(_) => {
-                                log::warn!("service {} doesn't support write, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            },
-                            None => {
-                                log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
-                                Ok(())
-                            }
+                    #[$meta]
+                )*
+                async fn [<write_ $test >]() -> anyhow::Result<()> {
+                    match OPERATOR.as_ref() {
+                        Some(op) if op.info().can_read() && op.info().can_write() => $crate::write::$test(op.clone()).await,
+                        Some(_) => {
+                            log::warn!("service {} doesn't support write, ignored", opendal::Scheme::$service);
+                            Ok(())
+                        },
+                        None => {
+                            log::warn!("service {} not initiated, ignored", opendal::Scheme::$service);
+                            Ok(())
                         }
                     }
-                )*
-            }
+                }
+            )*
         }
     };
 }