From c5663bf1ad2d720765b0e6e11a65c46ec5efd76e Mon Sep 17 00:00:00 2001 From: Denis Blank Date: Mon, 26 Nov 2018 03:02:49 +0100 Subject: [PATCH] Add the unit tests for the failure handlers recovering and rethrowing --- include/continuable/continuable-base.hpp | 9 +- include/continuable/continuable-result.hpp | 12 -- include/continuable/detail/core/base.hpp | 7 +- .../multi/test-continuable-base-multipath.cpp | 105 +++++++++++++----- test/unit-test/test-continuable.hpp | 23 ++-- 5 files changed, 98 insertions(+), 58 deletions(-) diff --git a/include/continuable/continuable-base.hpp b/include/continuable/continuable-base.hpp index 1af4d18..77f3ebd 100644 --- a/include/continuable/continuable-base.hpp +++ b/include/continuable/continuable-base.hpp @@ -899,17 +899,20 @@ constexpr auto make_exceptional_continuable(Exception&& exception) { template auto recover(Args&&... args) { - return make_expected(std::forward(args)...); + return make_result(std::forward(args)...); } +/// Returns a new exceptional result from the given exception +// NOLINTNEXTLINE(performance-unnecessary-value-param) inline auto rethrow(exception_t exception) { // NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg) - return make_exceptional_result(std::move(exception)); + return exceptional_result{std::move(exception)}; } inline auto cancel() { - return make_empty_result(); + return empty_result{}; } + /// \} } // namespace cti diff --git a/include/continuable/continuable-result.hpp b/include/continuable/continuable-result.hpp index ff146b9..d5699eb 100644 --- a/include/continuable/continuable-result.hpp +++ b/include/continuable/continuable-result.hpp @@ -52,11 +52,6 @@ namespace cti { /// value so the real result gets invalidated when this object is passed to it. struct empty_result {}; -/// Returns a new empty result -inline empty_result make_empty_result() { - return {}; -} - /// A class which is convertible to any result and that definitly holds /// an exception which is then passed to the converted result object. class exceptional_result { @@ -101,13 +96,6 @@ public: } }; -/// Returns a new exceptional result from the given exception -// NOLINTNEXTLINE(performance-unnecessary-value-param) -inline exceptional_result make_exceptional_result(exception_t exception) { - // NOLINTNEXTLINE(hicpp-move-const-arg, performance-move-const-arg) - return exceptional_result{std::move(exception)}; -} - /// The result class can carry the three kinds of results an asynchronous /// operation can return: no result, a value or an exception. /// - *no result*: If the operation didn't finish diff --git a/include/continuable/detail/core/base.hpp b/include/continuable/detail/core/base.hpp index b427716..5af4712 100644 --- a/include/continuable/detail/core/base.hpp +++ b/include/continuable/detail/core/base.hpp @@ -409,7 +409,7 @@ struct result_handler_base) noexcept { return [](auto&& callback, exception_t&& error) { // Errors are not partial invoked @@ -417,7 +417,7 @@ inline auto make_error_invoker( std::forward(callback)(std::move(error)); }; } -inline auto make_error_invoker( +inline auto make_exception_invoker( std::integral_constant) noexcept { return [](auto&& callback, exception_t&& error) { // Errors are not partial invoked @@ -432,7 +432,7 @@ template struct error_handler_base { void operator()(exception_arg_t, exception_t error) && { // Just invoke the error handler, cancel the calling hierarchy after - auto invoker = make_error_invoker( + auto invoker = make_exception_invoker( std::integral_constant{}); // Invoke the error handler @@ -578,7 +578,6 @@ constexpr auto next_hint_of(std::integral_constant, traits::identity /*callback*/, hints::signature_hint_tag current) { - // TODO return current; } diff --git a/test/unit-test/multi/test-continuable-base-multipath.cpp b/test/unit-test/multi/test-continuable-base-multipath.cpp index 210860e..60b7d49 100644 --- a/test/unit-test/multi/test-continuable-base-multipath.cpp +++ b/test/unit-test/multi/test-continuable-base-multipath.cpp @@ -30,13 +30,13 @@ static int const CANARY = 382947; TYPED_TEST(single_dimension_tests, multipath_result_is_forwardable) { EXPECT_ASYNC_RESULT(this->supply().then([](auto&&... canaries) -> result<> { // - return make_result(std::forward(canaries)...); + return recover(std::forward(canaries)...); })); EXPECT_ASYNC_RESULT( this->supply(CANARY).then([](auto&&... canaries) -> result { // - return make_result(std::forward(canaries)...); + return recover(std::forward(canaries)...); }), CANARY); @@ -44,7 +44,7 @@ TYPED_TEST(single_dimension_tests, multipath_result_is_forwardable) { this->supply(1, CANARY, 3) .then([](auto&&... canaries) -> result { // - return make_result(std::forward(canaries)...); + return recover(std::forward(canaries)...); }), 1, CANARY, 3); } @@ -53,53 +53,106 @@ TYPED_TEST(single_dimension_tests, multipath_result_is_throwable) { ASSERT_ASYNC_EXCEPTION_COMPLETION( this->supply().then([]() -> exceptional_result { // - return make_exceptional_result(supply_test_exception()); + return rethrow(supply_test_exception()); })); ASSERT_ASYNC_EXCEPTION_COMPLETION(this->supply().then([]() -> result<> { // - return make_exceptional_result(supply_test_exception()); + return rethrow(supply_test_exception()); })); } TYPED_TEST(single_dimension_tests, multipath_result_is_cancelable) { ASSERT_ASYNC_INCOMPLETION(this->supply().then([]() -> empty_result { // - return make_empty_result(); + return cancel(); })); ASSERT_ASYNC_INCOMPLETION(this->supply().then([]() -> result<> { // - return make_empty_result(); + return cancel(); })); } TYPED_TEST(single_dimension_tests, multipath_exception_is_recoverable) { - /*EXPECT_ASYNC_RESULT(this->supply_exception(supply_test_exception()) - .fail([](exception_t) -> result<> { - // - return make_result(); - })); + EXPECT_ASYNC_RESULT( + this->supply_exception(supply_test_exception(), identity<>{}) + .fail([](exception_t) -> result<> { + // + return recover(); + })); - EXPECT_ASYNC_RESULT(this->supply_exception(supply_test_exception()) - .fail([](exception_t) -> result { - // - return make_result(CANARY); - }), - CANARY); + EXPECT_ASYNC_RESULT( + this->supply_exception(supply_test_exception(), identity{}) + .fail([](exception_t) -> result { + // + return recover(CANARY); + }), + CANARY); - EXPECT_ASYNC_RESULT(this->supply_exception(supply_test_exception()) - .fail([](exception_t) -> result { - // - return make_result(1, CANARY, 3); - }), - 1, CANARY, 3);*/ + EXPECT_ASYNC_RESULT( + this->supply_exception(supply_test_exception(), identity{}) + .fail([](exception_t) -> result { + // + return recover(1, CANARY, 3); + }), + 1, CANARY, 3); } TYPED_TEST(single_dimension_tests, multipath_exception_is_forwardable) { - // TODO + ASSERT_ASYNC_EXCEPTION_COMPLETION( + this->supply_exception(supply_test_exception(), identity{}) + .fail([](exception_t exception) -> exceptional_result { + // + return rethrow(exception); + })); + + ASSERT_ASYNC_EXCEPTION_COMPLETION( + this->supply_exception(supply_test_exception(), identity{}) + .fail([](exception_t exception) -> result { + // + return rethrow(exception); + })); } TYPED_TEST(single_dimension_tests, multipath_exception_is_cancelable) { - // TODO + ASSERT_ASYNC_INCOMPLETION( + this->supply_exception(supply_test_exception(), identity{}) + .fail([](exception_t) -> empty_result { + // + return cancel(); + }) + .fail([] { + // + FAIL(); + })); + + ASSERT_ASYNC_INCOMPLETION( + this->supply_exception(supply_test_exception(), identity{}) + .fail([](exception_t) -> result { + // + return cancel(); + }) + .fail([] { + // + FAIL(); + })); +} + +TYPED_TEST(single_dimension_tests, multipath_exception_is_autocanceled) { + bool caught = false; + ASSERT_ASYNC_INCOMPLETION(this->supply_exception(supply_test_exception()) + .fail([&](exception_t) { + EXPECT_FALSE(caught); + caught = true; + }) + .then([] { + // ... + FAIL(); + }) + .fail([](exception_t) { + // ... + FAIL(); + })); + ASSERT_TRUE(caught); } diff --git a/test/unit-test/test-continuable.hpp b/test/unit-test/test-continuable.hpp index 89f5bdd..afc6dd8 100644 --- a/test/unit-test/test-continuable.hpp +++ b/test/unit-test/test-continuable.hpp @@ -48,7 +48,7 @@ auto to_hint(identity hint) { template auto supplier_of(Args&&... args) { return [values = std::make_tuple(std::forward(args)...)]( - auto&& promise) mutable { + auto&& promise) mutable { cti::detail::traits::unpack( [&](auto&&... passed) { promise.set_value(std::forward(passed)...); @@ -84,12 +84,9 @@ public: supplier_of(std::forward(args)...)); } - template - auto supply_exception(Arg&& arg) { - identity<> arg_types; - auto hint_types = to_hint(arg_types); - - return this->make(arg_types, hint_types, + template > + auto supply_exception(Arg&& arg, Hint hint = {}) { + return this->make(hint, to_hint(hint), exception_supplier_of(std::forward(arg))); } }; @@ -112,12 +109,12 @@ struct provide_copyable { struct provide_unique { template auto make(identity, identity, T&& callback) { - return cti::make_continuable([ - callback = std::forward(callback), guard = std::make_unique(0) - ](auto&&... args) mutable { - (void)(*guard); - return std::move(callback)(std::forward(args)...); - }); + return cti::make_continuable( + [callback = std::forward(callback), + guard = std::make_unique(0)](auto&&... args) mutable { + (void)(*guard); + return std::move(callback)(std::forward(args)...); + }); } };