diff options
author | Abseil Team <absl-team@google.com> | 2023-11-27 13:31:59 -0800 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-11-27 13:32:49 -0800 |
commit | 76bb2afb8b522d24496ad1c757a49784fbfa2e42 (patch) | |
tree | dfc624e5c005a86b9a7680926625b1aaf881cd43 | |
parent | b10fad38c4026a29ea6561ab15fc4818170d1c10 (diff) | |
download | googletest-76bb2afb8b522d24496ad1c757a49784fbfa2e42.tar.gz |
Implement `testing::Rethrow` to throw exceptions more easily via `std::exception_ptr`
We avoid overloading or specializing `testing::Throw` as this is fundamentally a different operation than throwing the object.
However, we disable the corresponding overload of `testing::Throw` to prevent likely mistakes in the usage.
Fixes: #4412
PiperOrigin-RevId: 585745469
Change-Id: I03bb585427ce51983d914e88f2bf65a13545c920
-rw-r--r-- | googlemock/include/gmock/gmock-actions.h | 24 | ||||
-rw-r--r-- | googlemock/test/gmock_link_test.h | 9 |
2 files changed, 30 insertions, 3 deletions
diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h index f20258bc..fab99933 100644 --- a/googlemock/include/gmock/gmock-actions.h +++ b/googlemock/include/gmock/gmock-actions.h @@ -135,6 +135,7 @@ #endif #include <algorithm> +#include <exception> #include <functional> #include <memory> #include <string> @@ -1746,6 +1747,13 @@ struct ThrowAction { return [copy](Args...) -> R { throw copy; }; } }; +struct RethrowAction { + std::exception_ptr exception; + template <typename R, typename... Args> + operator Action<R(Args...)>() const { // NOLINT + return [ex = exception](Args...) -> R { std::rethrow_exception(ex); }; + } +}; #endif // GTEST_HAS_EXCEPTIONS } // namespace internal @@ -2062,13 +2070,23 @@ internal::ReturnPointeeAction<Ptr> ReturnPointee(Ptr pointer) { return {pointer}; } -// Action Throw(exception) can be used in a mock function of any type -// to throw the given exception. Any copyable value can be thrown. #if GTEST_HAS_EXCEPTIONS +// Action Throw(exception) can be used in a mock function of any type +// to throw the given exception. Any copyable value can be thrown, +// except for std::exception_ptr, which is likely a mistake if +// thrown directly. template <typename T> -internal::ThrowAction<typename std::decay<T>::type> Throw(T&& exception) { +typename std::enable_if< + !std::is_base_of<std::exception_ptr, typename std::decay<T>::type>::value, + internal::ThrowAction<typename std::decay<T>::type>>::type +Throw(T&& exception) { return {std::forward<T>(exception)}; } +// Action Rethrow(exception_ptr) can be used in a mock function of any type +// to rethrow any exception_ptr. Note that the same object is thrown each time. +inline internal::RethrowAction Rethrow(std::exception_ptr exception) { + return {std::move(exception)}; +} #endif // GTEST_HAS_EXCEPTIONS namespace internal { diff --git a/googlemock/test/gmock_link_test.h b/googlemock/test/gmock_link_test.h index db11c2d2..cf0a985b 100644 --- a/googlemock/test/gmock_link_test.h +++ b/googlemock/test/gmock_link_test.h @@ -187,6 +187,7 @@ using testing::SetErrnoAndReturn; #if GTEST_HAS_EXCEPTIONS using testing::Throw; +using testing::Rethrow; #endif using testing::ContainsRegex; @@ -416,6 +417,14 @@ TEST(LinkTest, TestThrow) { EXPECT_CALL(mock, VoidFromString(_)).WillOnce(Throw(42)); EXPECT_THROW(mock.VoidFromString(nullptr), int); } +// Tests the linkage of the Rethrow action. +TEST(LinkTest, TestRethrow) { + Mock mock; + + EXPECT_CALL(mock, VoidFromString(_)) + .WillOnce(Rethrow(std::make_exception_ptr(42))); + EXPECT_THROW(mock.VoidFromString(nullptr), int); +} #endif // GTEST_HAS_EXCEPTIONS // The ACTION*() macros trigger warning C4100 (unreferenced formal |