Add the unit tests for the failure handlers recovering and rethrowing

This commit is contained in:
Denis Blank 2018-11-26 03:02:49 +01:00
parent afe1a3298e
commit c5663bf1ad
5 changed files with 98 additions and 58 deletions

View File

@ -899,17 +899,20 @@ constexpr auto make_exceptional_continuable(Exception&& exception) {
template <typename... Args>
auto recover(Args&&... args) {
return make_expected(std::forward<Args>(args)...);
return make_result(std::forward<Args>(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

View File

@ -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

View File

@ -409,7 +409,7 @@ struct result_handler_base<handle_results::yes, Base,
}
};
inline auto make_error_invoker(
inline auto make_exception_invoker(
std::integral_constant<handle_errors, handle_errors::plain>) noexcept {
return [](auto&& callback, exception_t&& error) {
// Errors are not partial invoked
@ -417,7 +417,7 @@ inline auto make_error_invoker(
std::forward<decltype(callback)>(callback)(std::move(error));
};
}
inline auto make_error_invoker(
inline auto make_exception_invoker(
std::integral_constant<handle_errors, handle_errors::forward>) noexcept {
return [](auto&& callback, exception_t&& error) {
// Errors are not partial invoked
@ -432,7 +432,7 @@ template <handle_errors HandleErrors /* = plain or forward*/, typename Base>
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<handle_errors, HandleErrors>{});
// Invoke the error handler
@ -578,7 +578,6 @@ constexpr auto
next_hint_of(std::integral_constant<handle_results, handle_results::no>,
traits::identity<T> /*callback*/,
hints::signature_hint_tag<Args...> current) {
// TODO
return current;
}

View File

@ -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<decltype(canaries)>(canaries)...);
return recover(std::forward<decltype(canaries)>(canaries)...);
}));
EXPECT_ASYNC_RESULT(
this->supply(CANARY).then([](auto&&... canaries) -> result<int> {
//
return make_result(std::forward<decltype(canaries)>(canaries)...);
return recover(std::forward<decltype(canaries)>(canaries)...);
}),
CANARY);
@ -44,7 +44,7 @@ TYPED_TEST(single_dimension_tests, multipath_result_is_forwardable) {
this->supply(1, CANARY, 3)
.then([](auto&&... canaries) -> result<int, int, int> {
//
return make_result(std::forward<decltype(canaries)>(canaries)...);
return recover(std::forward<decltype(canaries)>(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<int> {
//
return make_result(CANARY);
}),
CANARY);
EXPECT_ASYNC_RESULT(
this->supply_exception(supply_test_exception(), identity<int>{})
.fail([](exception_t) -> result<int> {
//
return recover(CANARY);
}),
CANARY);
EXPECT_ASYNC_RESULT(this->supply_exception(supply_test_exception())
.fail([](exception_t) -> result<int, int, int> {
//
return make_result(1, CANARY, 3);
}),
1, CANARY, 3);*/
EXPECT_ASYNC_RESULT(
this->supply_exception(supply_test_exception(), identity<int, int, int>{})
.fail([](exception_t) -> result<int, int, int> {
//
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<int>{})
.fail([](exception_t exception) -> exceptional_result {
//
return rethrow(exception);
}));
ASSERT_ASYNC_EXCEPTION_COMPLETION(
this->supply_exception(supply_test_exception(), identity<int>{})
.fail([](exception_t exception) -> result<int> {
//
return rethrow(exception);
}));
}
TYPED_TEST(single_dimension_tests, multipath_exception_is_cancelable) {
// TODO
ASSERT_ASYNC_INCOMPLETION(
this->supply_exception(supply_test_exception(), identity<int>{})
.fail([](exception_t) -> empty_result {
//
return cancel();
})
.fail([] {
//
FAIL();
}));
ASSERT_ASYNC_INCOMPLETION(
this->supply_exception(supply_test_exception(), identity<int>{})
.fail([](exception_t) -> result<int> {
//
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);
}

View File

@ -48,7 +48,7 @@ auto to_hint(identity<Args...> hint) {
template <typename... Args>
auto supplier_of(Args&&... args) {
return [values = std::make_tuple(std::forward<Args>(args)...)](
auto&& promise) mutable {
auto&& promise) mutable {
cti::detail::traits::unpack(
[&](auto&&... passed) {
promise.set_value(std::forward<decltype(passed)>(passed)...);
@ -84,12 +84,9 @@ public:
supplier_of(std::forward<Args>(args)...));
}
template <typename Arg>
auto supply_exception(Arg&& arg) {
identity<> arg_types;
auto hint_types = to_hint(arg_types);
return this->make(arg_types, hint_types,
template <typename Arg, typename Hint = identity<>>
auto supply_exception(Arg&& arg, Hint hint = {}) {
return this->make(hint, to_hint(hint),
exception_supplier_of(std::forward<Arg>(arg)));
}
};
@ -112,12 +109,12 @@ struct provide_copyable {
struct provide_unique {
template <typename... Args, typename... Hint, typename T>
auto make(identity<Args...>, identity<Hint...>, T&& callback) {
return cti::make_continuable<Hint...>([
callback = std::forward<T>(callback), guard = std::make_unique<int>(0)
](auto&&... args) mutable {
(void)(*guard);
return std::move(callback)(std::forward<decltype(args)>(args)...);
});
return cti::make_continuable<Hint...>(
[callback = std::forward<T>(callback),
guard = std::make_unique<int>(0)](auto&&... args) mutable {
(void)(*guard);
return std::move(callback)(std::forward<decltype(args)>(args)...);
});
}
};