From ca747f57f9fb618e7b122714c44aa87525ec290e Mon Sep 17 00:00:00 2001 From: Xuehan Xu Date: Tue, 20 Oct 2020 18:19:11 +0800 Subject: [PATCH] crimson/test: add interruptible future unit test Signed-off-by: Xuehan Xu --- src/test/crimson/CMakeLists.txt | 8 + src/test/crimson/test_interruptible_future.cc | 167 ++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 src/test/crimson/test_interruptible_future.cc diff --git a/src/test/crimson/CMakeLists.txt b/src/test/crimson/CMakeLists.txt index bc624ce672e..b5120cd87ef 100644 --- a/src/test/crimson/CMakeLists.txt +++ b/src/test/crimson/CMakeLists.txt @@ -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 index 00000000000..0dbf2a5368a --- /dev/null +++ b/src/test/crimson/test_interruptible_future.cc @@ -0,0 +1,167 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include + +#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 + std::pair> may_interrupt() { + if (interrupt) + return std::pair>( + true, seastar::futurize::make_exception_future(test_interruption())); + else + return std::pair>(false, std::optional()); + } + + template + static constexpr bool is_interruption_v = std::is_same_v; + + 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; + run_async([this] { + interruptor::with_interruption( + [] { + ceph_assert(::crimson::interruptible::interrupt_cond); + return interruptor::make_interruptible(seastar::now()) + .then_interruptible([] { + ceph_assert(::crimson::interruptible::interrupt_cond); + }).then_interruptible([] { + ceph_assert(::crimson::interruptible::interrupt_cond); + return ::crimson::errorator<::crimson::ct_error::enoent>::make_ready_future<>(); + }).safe_then_interruptible([] { + ceph_assert(::crimson::interruptible::interrupt_cond); + return seastar::now(); + }, ::crimson::errorator<::crimson::ct_error::enoent>::all_same_way([] { + ceph_assert(::crimson::interruptible::interrupt_cond); + }) + ); + }, [](std::exception_ptr) {}, false).get0(); + + interruptor::with_interruption( + [] { + ceph_assert(::crimson::interruptible::interrupt_cond); + return interruptor::make_interruptible(seastar::now()) + .then_interruptible([] { + ceph_assert(::crimson::interruptible::interrupt_cond); + }); + }, [](std::exception_ptr) { + ceph_assert(!::crimson::interruptible::interrupt_cond); + return seastar::now(); + }, true).get0(); + + + }); +} + +TEST_F(seastar_test_suite_t, loops) +{ + using interruptor = + ::crimson::interruptible::interruptor; + 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); + return interruptor::make_interruptible(seastar::now()) + .then_interruptible([] { + std::cout << "test seastar future do_for_each" << std::endl; + std::vector 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); + return seastar::now(); + }); + }); + }).then_interruptible([] { + std::cout << "test interruptible seastar future do_for_each" << std::endl; + std::vector 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); + 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); + 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); + 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 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); + return interruptor::make_interruptible( + ::crimson::errorator<::crimson::ct_error::enoent>::make_ready_future<>()); + }).safe_then_interruptible([] { + ceph_assert(::crimson::interruptible::interrupt_cond); + return seastar::now(); + }, ::crimson::errorator<::crimson::ct_error::enoent>::all_same_way([] { + ceph_assert(::crimson::interruptible::interrupt_cond); + })); + }); + }); + }).then_interruptible([] { + std::cout << "test errorated future do_for_each" << std::endl; + std::vector 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); + return ::crimson::errorator<::crimson::ct_error::enoent>::make_ready_future<>(); + }).safe_then_interruptible([] { + ceph_assert(::crimson::interruptible::interrupt_cond); + return seastar::now(); + }, ::crimson::errorator<::crimson::ct_error::enoent>::all_same_way([] { + ceph_assert(::crimson::interruptible::interrupt_cond); + })); + }); + }); + }).then_interruptible([] { + ceph_assert(::crimson::interruptible::interrupt_cond); + return seastar::now(); + }); + }, [](std::exception_ptr) {}, false).get0(); + }); +} -- 2.39.5