mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 16:56:44 +08:00
Add error handling testing
This commit is contained in:
parent
60c73a1a48
commit
4d964b0fe2
@ -42,6 +42,13 @@
|
|||||||
#define ASSERT_ASYNC_COMPLETION(CONTINUABLE) \
|
#define ASSERT_ASYNC_COMPLETION(CONTINUABLE) \
|
||||||
cti::detail::testing::assert_async_completion(CONTINUABLE);
|
cti::detail::testing::assert_async_completion(CONTINUABLE);
|
||||||
|
|
||||||
|
/// Asserts that the final callback of the given continuable was called
|
||||||
|
/// with any exceptional result.
|
||||||
|
///
|
||||||
|
/// \since version 2.0.0
|
||||||
|
#define ASSERT_ASYNC_EXCEPTION_COMPLETION(CONTINUABLE) \
|
||||||
|
cti::detail::testing::assert_async_exception_completion(CONTINUABLE);
|
||||||
|
|
||||||
/// Asserts that the final callback of the given continuable is never called
|
/// Asserts that the final callback of the given continuable is never called
|
||||||
/// with any result.
|
/// with any result.
|
||||||
///
|
///
|
||||||
@ -85,6 +92,18 @@
|
|||||||
#define ASSERT_ASYNC_BINARY_VALIDATION(VALIDATOR, ...) \
|
#define ASSERT_ASYNC_BINARY_VALIDATION(VALIDATOR, ...) \
|
||||||
cti::detail::testing::assert_async_binary_validation(VALIDATOR, __VA_ARGS__);
|
cti::detail::testing::assert_async_binary_validation(VALIDATOR, __VA_ARGS__);
|
||||||
|
|
||||||
|
/// Asserts that the continuation was resolved through an error and forwards
|
||||||
|
/// it's error result to the given validator which can then do assertions on the
|
||||||
|
/// error result.
|
||||||
|
///
|
||||||
|
/// \note This macro is mainly present for building other assertions
|
||||||
|
/// relying on custom validation logic.
|
||||||
|
///
|
||||||
|
/// \since version 2.0.0
|
||||||
|
#define ASSERT_ASYNC_BINARY_EXCEPTION_VALIDATION(VALIDATOR, ...) \
|
||||||
|
cti::detail::testing::assert_async_binary_exception_validation(VALIDATOR, \
|
||||||
|
__VA_ARGS__);
|
||||||
|
|
||||||
/// Expects that the continuable is finished with the given result
|
/// Expects that the continuable is finished with the given result
|
||||||
///
|
///
|
||||||
/// ```cpp
|
/// ```cpp
|
||||||
@ -99,6 +118,13 @@
|
|||||||
ASSERT_ASYNC_BINARY_VALIDATION(cti::detail::testing::expecting_eq_check(), \
|
ASSERT_ASYNC_BINARY_VALIDATION(cti::detail::testing::expecting_eq_check(), \
|
||||||
__VA_ARGS__)
|
__VA_ARGS__)
|
||||||
|
|
||||||
|
/// Asserts that the continuable is finished with the given exception
|
||||||
|
///
|
||||||
|
/// \since version 2.0.0
|
||||||
|
#define EXPECT_ASYNC_EXCEPTION_RESULT(...) \
|
||||||
|
ASSERT_ASYNC_BINARY_EXCEPTION_VALIDATION( \
|
||||||
|
cti::detail::testing::expecting_eq_check(), __VA_ARGS__)
|
||||||
|
|
||||||
/// Asserts that the continuable is finished with the given result
|
/// Asserts that the continuable is finished with the given result
|
||||||
///
|
///
|
||||||
/// ```cpp
|
/// ```cpp
|
||||||
@ -130,11 +156,11 @@
|
|||||||
cti::detail::testing::assert_async_types( \
|
cti::detail::testing::assert_async_types( \
|
||||||
CONTINUABLE, cti::detail::traits::identity<__VA_ARGS__>{})
|
CONTINUABLE, cti::detail::traits::identity<__VA_ARGS__>{})
|
||||||
|
|
||||||
/// Asserts that the continuable is finished with the given error
|
/// Asserts that the continuable is finished with the given exception
|
||||||
/// TODO
|
///
|
||||||
/// \since version 2.0.0
|
/// \since version 2.0.0
|
||||||
#define ASSERT_ASYNC_ERROR(...) \
|
#define ASSERT_ASYNC_EXCEPTION_RESULT(...) \
|
||||||
ASSERT_ASYNC_BINARY_VALIDATION(cti::detail::testing::asserting_eq_check(), \
|
ASSERT_ASYNC_BINARY_EXCEPTION_VALIDATION( \
|
||||||
__VA_ARGS__)
|
cti::detail::testing::asserting_eq_check(), __VA_ARGS__)
|
||||||
|
|
||||||
#endif // CONTINUABLE_TESTING_HPP_INCLUDED__
|
#endif // CONTINUABLE_TESTING_HPP_INCLUDED__
|
||||||
|
|||||||
@ -31,9 +31,15 @@
|
|||||||
#ifndef CONTINUABLE_DETAIL_TESTING_HPP_INCLUDED__
|
#ifndef CONTINUABLE_DETAIL_TESTING_HPP_INCLUDED__
|
||||||
#define CONTINUABLE_DETAIL_TESTING_HPP_INCLUDED__
|
#define CONTINUABLE_DETAIL_TESTING_HPP_INCLUDED__
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include <continuable/continuable-base.hpp>
|
#include <continuable/detail/api.hpp>
|
||||||
|
#include <continuable/detail/traits.hpp>
|
||||||
|
#include <continuable/detail/types.hpp>
|
||||||
|
#include <continuable/detail/util.hpp>
|
||||||
|
|
||||||
namespace cti {
|
namespace cti {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -41,25 +47,54 @@ namespace testing {
|
|||||||
template <typename C>
|
template <typename C>
|
||||||
void assert_async_completion(C&& continuable) {
|
void assert_async_completion(C&& continuable) {
|
||||||
auto called = std::make_shared<bool>(false);
|
auto called = std::make_shared<bool>(false);
|
||||||
std::forward<C>(continuable).then([called](auto&&... args) {
|
std::forward<C>(continuable)
|
||||||
ASSERT_FALSE(*called);
|
.then([called](auto&&... args) {
|
||||||
*called = true;
|
ASSERT_FALSE(*called);
|
||||||
|
*called = true;
|
||||||
|
|
||||||
// Workaround for our known GCC bug.
|
// Workaround for our known GCC bug.
|
||||||
util::unused(std::forward<decltype(args)>(args)...);
|
util::unused(std::forward<decltype(args)>(args)...);
|
||||||
});
|
})
|
||||||
|
.fail([](cti::error_type /*error*/) {
|
||||||
|
// ...
|
||||||
|
FAIL();
|
||||||
|
});
|
||||||
|
|
||||||
|
ASSERT_TRUE(*called);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename C>
|
||||||
|
void assert_async_exception_completion(C&& continuable) {
|
||||||
|
auto called = std::make_shared<bool>(false);
|
||||||
|
std::forward<C>(continuable)
|
||||||
|
.then([](auto&&... args) {
|
||||||
|
// Workaround for our known GCC bug.
|
||||||
|
util::unused(std::forward<decltype(args)>(args)...);
|
||||||
|
|
||||||
|
// ...
|
||||||
|
FAIL();
|
||||||
|
})
|
||||||
|
.fail([called](cti::error_type /*error*/) {
|
||||||
|
ASSERT_FALSE(*called);
|
||||||
|
*called = true;
|
||||||
|
});
|
||||||
|
|
||||||
ASSERT_TRUE(*called);
|
ASSERT_TRUE(*called);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename C>
|
template <typename C>
|
||||||
void assert_async_never_completed(C&& continuable) {
|
void assert_async_never_completed(C&& continuable) {
|
||||||
std::forward<C>(continuable).then([](auto&&... args) {
|
std::forward<C>(continuable)
|
||||||
// Workaround for our known GCC bug.
|
.then([](auto&&... args) {
|
||||||
util::unused(std::forward<decltype(args)>(args)...);
|
// Workaround for our known GCC bug.
|
||||||
|
util::unused(std::forward<decltype(args)>(args)...);
|
||||||
|
|
||||||
FAIL();
|
FAIL();
|
||||||
});
|
})
|
||||||
|
.fail([](cti::error_type /*error*/) {
|
||||||
|
// ...
|
||||||
|
FAIL();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename C, typename V>
|
template <typename C, typename V>
|
||||||
@ -94,6 +129,43 @@ void assert_async_binary_validation(V&& validator, C&& continuable,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expects that the continuable is finished with the given arguments
|
||||||
|
template <typename V, typename C, typename Args>
|
||||||
|
void assert_async_binary_exception_validation(V&& validator, C&& continuable,
|
||||||
|
Args&& expected) {
|
||||||
|
auto called = std::make_shared<bool>(false);
|
||||||
|
std::forward<C>(continuable)
|
||||||
|
.then([](auto&&... args) {
|
||||||
|
// Workaround for our known GCC bug.
|
||||||
|
util::unused(std::forward<decltype(args)>(args)...);
|
||||||
|
|
||||||
|
// ...
|
||||||
|
FAIL();
|
||||||
|
})
|
||||||
|
.fail([
|
||||||
|
called, validator = std::forward<decltype(validator)>(validator),
|
||||||
|
expected = std::forward<decltype(expected)>(expected)
|
||||||
|
](types::error_type error) {
|
||||||
|
ASSERT_FALSE(*called);
|
||||||
|
*called = true;
|
||||||
|
|
||||||
|
#if !defined(CONTINUABLE_WITH_CUSTOM_ERROR_TYPE) && \
|
||||||
|
!defined(CONTINUABLE_WITH_NO_EXCEPTIONS)
|
||||||
|
try {
|
||||||
|
std::rethrow_exception(error);
|
||||||
|
} catch (std::decay_t<decltype(expected)> const& exception) {
|
||||||
|
validator(exception, expected);
|
||||||
|
} catch (...) {
|
||||||
|
FAIL();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
validator(error, expected);
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
|
ASSERT_TRUE(*called);
|
||||||
|
}
|
||||||
|
|
||||||
inline auto expecting_eq_check() {
|
inline auto expecting_eq_check() {
|
||||||
return [](auto&& expected, auto&& actual) {
|
return [](auto&& expected, auto&& actual) {
|
||||||
EXPECT_EQ(std::forward<decltype(expected)>(expected),
|
EXPECT_EQ(std::forward<decltype(expected)>(expected),
|
||||||
|
|||||||
@ -32,6 +32,7 @@
|
|||||||
#define CONTINUABLE_DETAIL_TRAITS_HPP_INCLUDED__
|
#define CONTINUABLE_DETAIL_TRAITS_HPP_INCLUDED__
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <initializer_list>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -347,8 +348,8 @@ constexpr void static_for_each_in(Sequenceable&& sequenceable,
|
|||||||
unpack(
|
unpack(
|
||||||
std::forward<Sequenceable>(sequenceable), [&](auto&&... entries) mutable {
|
std::forward<Sequenceable>(sequenceable), [&](auto&&... entries) mutable {
|
||||||
// Apply the consume function to every entry inside the pack
|
// Apply the consume function to every entry inside the pack
|
||||||
(void)std::initializer_list<int>{0,
|
(void)std::initializer_list<int>{
|
||||||
((void)handler(std::forward<decltype(entries)>(entries)), 0)...};
|
0, ((void)handler(std::forward<decltype(entries)>(entries)), 0)...};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
#ifndef CONTINUABLE_DETAIL_UTIL_HPP_INCLUDED__
|
#ifndef CONTINUABLE_DETAIL_UTIL_HPP_INCLUDED__
|
||||||
#define CONTINUABLE_DETAIL_UTIL_HPP_INCLUDED__
|
#define CONTINUABLE_DETAIL_UTIL_HPP_INCLUDED__
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -45,14 +46,7 @@ namespace detail {
|
|||||||
namespace util {
|
namespace util {
|
||||||
/// Helper to trick compilers about that a parameter pack is used
|
/// Helper to trick compilers about that a parameter pack is used
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
void unused(T&&... args) {
|
void unused(T&&...) {
|
||||||
auto use = [](auto&& type) mutable {
|
|
||||||
(void)type;
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
auto deduce = {0, use(std::forward<decltype(args)>(args))...};
|
|
||||||
(void)deduce;
|
|
||||||
(void)use;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|||||||
@ -21,10 +21,53 @@
|
|||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <continuable/detail/features.hpp>
|
||||||
|
|
||||||
#include "test-continuable.hpp"
|
#include "test-continuable.hpp"
|
||||||
|
|
||||||
TYPED_TEST(single_dimension_tests, are_using_errors) {
|
#if !defined(CONTINUABLE_WITH_NO_EXCEPTIONS)
|
||||||
/*ASSERT_ASYNC_ERROR(this->supply().then([] {
|
struct test_exception : std::exception {
|
||||||
return; // void
|
explicit test_exception() {
|
||||||
}));*/
|
}
|
||||||
|
|
||||||
|
bool operator==(test_exception const&) const noexcept {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto get_test_exception_proto() {
|
||||||
|
return test_exception{};
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto supply_test_exception() {
|
||||||
|
try {
|
||||||
|
throw get_test_exception_proto();
|
||||||
|
} catch (...) {
|
||||||
|
return std::current_exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
struct my_error_category : std::error_category {
|
||||||
|
const char* name() const override noexcept {return "generic name"}
|
||||||
|
|
||||||
|
std::string message(int) const override {
|
||||||
|
return "generic"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto get_test_exception_proto() {
|
||||||
|
static const my_error_category cat;
|
||||||
|
return std::error_condition(123, cat);
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto supply_test_exception() {
|
||||||
|
return get_test_exception_proto();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TYPED_TEST(single_dimension_tests, are_using_errors) {
|
||||||
|
ASSERT_ASYNC_EXCEPTION_COMPLETION(
|
||||||
|
this->supply_exception(supply_test_exception()));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,57 +24,15 @@
|
|||||||
#ifndef TEST_CONTINUABLE_HPP__
|
#ifndef TEST_CONTINUABLE_HPP__
|
||||||
#define TEST_CONTINUABLE_HPP__
|
#define TEST_CONTINUABLE_HPP__
|
||||||
|
|
||||||
#if UNIT_TEST_STEP >= 3
|
|
||||||
#define THIRD_PARTY_TESTS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef THIRD_PARTY_TESTS
|
|
||||||
// #if _MSC_VER
|
|
||||||
// #pragma warning(push, 0)
|
|
||||||
// #endif
|
|
||||||
#endif // THIRD_PARTY_TESTS
|
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "continuable/continuable-base.hpp"
|
#include <gtest/gtest.h>
|
||||||
#include "continuable/continuable-testing.hpp"
|
|
||||||
#include "continuable/continuable.hpp"
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#ifdef THIRD_PARTY_TESTS
|
#include <continuable/continuable-base.hpp>
|
||||||
|
#include <continuable/continuable-testing.hpp>
|
||||||
#include "cxx_function/cxx_function.hpp"
|
#include <continuable/continuable.hpp>
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using cxx_function_fn = cxx_function::function<T>;
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
using cxx_trait_of =
|
|
||||||
cti::continuable_trait<cxx_function_fn, cxx_function_fn, Args...>;
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
using cxx_continuable = typename cxx_trait_of<Args...>::continuable;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using cxx_function_unique_fn = cxx_function::unique_function<T>;
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
using unique_cxx_trait_of =
|
|
||||||
cti::continuable_trait<cxx_function_unique_fn, cxx_function_unique_fn,
|
|
||||||
Args...>;
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
using cxx_unique_continuable =
|
|
||||||
typename unique_cxx_trait_of<Args...>::continuable;
|
|
||||||
#endif // THIRD_PARTY_TESTS
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
using std_trait_of =
|
|
||||||
cti::continuable_trait<std::function, std::function, Args...>;
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
using std_continuable = typename std_trait_of<Args...>::continuable;
|
|
||||||
|
|
||||||
using cti::detail::traits::identity;
|
using cti::detail::traits::identity;
|
||||||
|
|
||||||
@ -96,6 +54,13 @@ auto supplier_of(Args&&... args) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Arg>
|
||||||
|
auto exception_supplier_of(Arg&& arg) {
|
||||||
|
return [arg = std::forward<Arg>(arg)](auto&& promise) mutable {
|
||||||
|
promise.set_exception(std::move(arg));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Provider>
|
template <typename Provider>
|
||||||
class continuation_provider : public ::testing::Test, public Provider {
|
class continuation_provider : public ::testing::Test, public Provider {
|
||||||
public:
|
public:
|
||||||
@ -115,6 +80,15 @@ public:
|
|||||||
return this->make(arg_types, hint_types,
|
return this->make(arg_types, hint_types,
|
||||||
supplier_of(std::forward<Args>(args)...));
|
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,
|
||||||
|
exception_supplier_of(std::forward<Arg>(arg)));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline auto empty_caller() {
|
inline auto empty_caller() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user