]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/test: add interruptible future unit test
authorXuehan Xu <xxhdx1985126@gmail.com>
Tue, 20 Oct 2020 10:19:11 +0000 (18:19 +0800)
committerXuehan Xu <xxhdx1985126@gmail.com>
Sun, 7 Mar 2021 06:24:51 +0000 (14:24 +0800)
Signed-off-by: Xuehan Xu <xxhdx1985126@gmail.com>
src/test/crimson/CMakeLists.txt
src/test/crimson/test_interruptible_future.cc [new file with mode: 0644]

index bc624ce672ed5556d78b36fefeb391ddde6a8f67..b5120cd87efe505a5470b92aefdebc55ecf564a3 100644 (file)
@@ -72,6 +72,14 @@ add_executable(unittest-fixed-kv-node-layout
   test_fixed_kv_node_layout.cc)
 add_ceph_unittest(unittest-fixed-kv-node-layout)
 
+add_executable(unittest_interruptible_future
+  test_interruptible_future.cc
+  gtest_seastar.cc)
+add_ceph_unittest(unittest_interruptible_future)
+target_link_libraries(
+  unittest_interruptible_future
+  crimson-common)
+
 add_subdirectory(seastore)
 
 add_library(crimson-gtest STATIC
diff --git a/src/test/crimson/test_interruptible_future.cc b/src/test/crimson/test_interruptible_future.cc
new file mode 100644 (file)
index 0000000..0dbf2a5
--- /dev/null
@@ -0,0 +1,167 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include <seastar/core/sleep.hh>
+
+#include "test/crimson/gtest_seastar.h"
+
+#include "crimson/common/interruptible_future.h"
+#include "crimson/common/log.h"
+
+class test_interruption : public std::exception
+{};
+
+class TestInterruptCondition {
+public:
+  TestInterruptCondition(bool interrupt)
+    : interrupt(interrupt) {}
+
+  template <typename T>
+  std::pair<bool, std::optional<T>> may_interrupt() {
+    if (interrupt)
+      return std::pair<bool, std::optional<T>>(
+         true, seastar::futurize<T>::make_exception_future(test_interruption()));
+    else
+      return std::pair<bool, std::optional<T>>(false, std::optional<T>());
+  }
+
+  template <typename T>
+  static constexpr bool is_interruption_v = std::is_same_v<T, test_interruption>;
+
+  bool is_interruption(std::exception_ptr& eptr) {
+    if (*eptr.__cxa_exception_type() == typeid(test_interruption))
+      return true;
+    return false;
+  }
+private:
+  bool interrupt = false;
+};
+
+TEST_F(seastar_test_suite_t, basic)
+{
+  using interruptor =
+    ::crimson::interruptible::interruptor<TestInterruptCondition>;
+  run_async([this] {
+    interruptor::with_interruption(
+      [] {
+       ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+       return interruptor::make_interruptible(seastar::now())
+       .then_interruptible([] {
+         ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+       }).then_interruptible([] {
+         ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+         return ::crimson::errorator<::crimson::ct_error::enoent>::make_ready_future<>();
+       }).safe_then_interruptible([] {
+         ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+         return seastar::now();
+       }, ::crimson::errorator<::crimson::ct_error::enoent>::all_same_way([] {
+         ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+         })
+       );
+      }, [](std::exception_ptr) {}, false).get0();
+
+    interruptor::with_interruption(
+      [] {
+       ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+       return interruptor::make_interruptible(seastar::now())
+       .then_interruptible([] {
+         ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+       });
+      }, [](std::exception_ptr) {
+       ceph_assert(!::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+       return seastar::now();
+      }, true).get0();
+
+
+  });
+}
+
+TEST_F(seastar_test_suite_t, loops)
+{
+  using interruptor =
+    ::crimson::interruptible::interruptor<TestInterruptCondition>;
+  std::cout << "testing interruptible loops" << std::endl;
+  run_async([this] {
+    std::cout << "beginning" << std::endl;
+    interruptor::with_interruption(
+      [] {
+       std::cout << "interruptiion enabled" << std::endl;
+       ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+       return interruptor::make_interruptible(seastar::now())
+       .then_interruptible([] {
+         std::cout << "test seastar future do_for_each" << std::endl;
+         std::vector<int> vec = {1, 2};
+         return seastar::do_with(std::move(vec), [](auto& vec) {
+           return interruptor::do_for_each(std::begin(vec), std::end(vec), [](int) {
+             ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+             return seastar::now();
+           });
+         });
+       }).then_interruptible([] {
+         std::cout << "test interruptible seastar future do_for_each" << std::endl;
+         std::vector<int> vec = {1, 2};
+         return seastar::do_with(std::move(vec), [](auto& vec) {
+           return interruptor::do_for_each(std::begin(vec), std::end(vec), [](int) {
+             ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+             return interruptor::make_interruptible(seastar::now());
+           });
+         });
+       }).then_interruptible([] {
+         std::cout << "test seastar future repeat" << std::endl;
+         return interruptor::repeat([] {
+           ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+           return interruptor::make_interruptible(
+               seastar::make_ready_future<
+                 seastar::stop_iteration>(
+                   seastar::stop_iteration::yes));
+         });
+       }).then_interruptible([] {
+         std::cout << "test interruptible seastar future repeat" << std::endl;
+         return interruptor::repeat([] {
+           ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+           return seastar::make_ready_future<
+                   seastar::stop_iteration>(
+                     seastar::stop_iteration::yes);
+         });
+       }).then_interruptible([] {
+         std::cout << "test interruptible errorated future do_for_each" << std::endl;
+         std::vector<int> vec = {1, 2};
+         return seastar::do_with(std::move(vec), [](auto& vec) {
+           using namespace std::chrono_literals;
+           return interruptor::make_interruptible(seastar::now()).then_interruptible([&vec] {
+             return interruptor::do_for_each(std::begin(vec), std::end(vec), [](int) {
+               ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+               return interruptor::make_interruptible(
+                 ::crimson::errorator<::crimson::ct_error::enoent>::make_ready_future<>());
+             }).safe_then_interruptible([] {
+               ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+               return seastar::now();
+             }, ::crimson::errorator<::crimson::ct_error::enoent>::all_same_way([] {
+               ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+             }));
+           });
+         });
+       }).then_interruptible([] {
+         std::cout << "test errorated future do_for_each" << std::endl;
+         std::vector<int> vec = {1, 2};
+         return seastar::do_with(std::move(vec), [](auto& vec) {
+           using namespace std::chrono_literals;
+           return interruptor::make_interruptible(seastar::now()).then_interruptible([&vec] {
+             return interruptor::do_for_each(std::begin(vec), std::end(vec), [](int) {
+               ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+               return ::crimson::errorator<::crimson::ct_error::enoent>::make_ready_future<>();
+             }).safe_then_interruptible([] {
+               ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+               return seastar::now();
+             }, ::crimson::errorator<::crimson::ct_error::enoent>::all_same_way([] {
+               ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+             }));
+           });
+         });
+       }).then_interruptible([] {
+         ceph_assert(::crimson::interruptible::interrupt_cond<TestInterruptCondition>);
+         return seastar::now();
+       });
+      }, [](std::exception_ptr) {}, false).get0();
+  });
+}