userver: userver/utest/assert_macros.hpp Source File
Loading...
Searching...
No Matches
assert_macros.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utest/assert_macros.hpp
4/// @brief Extensions to the gtest macros for printing and testing exceptions
5/// that could work even without coroutine environment.
6/// @ingroup userver_universal
7
8#include <exception>
9#include <functional>
10#include <string>
11#include <string_view>
12#include <type_traits>
13#include <typeinfo>
14
15#include <gtest/gtest.h>
16
17#include <userver/utest/death_tests.hpp>
18#include <userver/utils/invariant_error.hpp>
19
20USERVER_NAMESPACE_BEGIN
21
22namespace utest::impl {
23
24template <typename ExceptionType>
25bool IsSubtype(const std::exception& ex) noexcept {
26 static_assert(
27 std::is_base_of_v<std::exception, ExceptionType>,
28 "Exception types not inherited from std::exception are not supported"
29 );
30 if constexpr (std::is_same_v<ExceptionType, std::exception>) {
31 return true;
32 } else {
33 return dynamic_cast<const ExceptionType*>(&ex) != nullptr;
34 }
35}
36
37std::string AssertThrow(
38 std::function<void()> statement,
39 std::string_view statement_text,
40 std::function<bool(const std::exception&)> type_checker,
41 const std::type_info& expected_type,
42 std::string_view message_substring
43);
44
45std::string AssertNoThrow(std::function<void()> statement, std::string_view statement_text);
46
47} // namespace utest::impl
48
49USERVER_NAMESPACE_END
50
51/// @cond
52// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
53#define IMPL_UTEST_ASSERT_THROW(statement, exception_type, message_substring, failure_macro)
54 if (const auto message_impl_utest = USERVER_NAMESPACE::utest::impl::AssertThrow(
55 [&] { statement; },
56 #statement,
57 &USERVER_NAMESPACE::utest::impl::IsSubtype<exception_type>,
58 typeid(exception_type),
59 message_substring
60 );
61 !message_impl_utest.empty())
62 failure_macro(message_impl_utest.c_str())
63
64// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
65#define IMPL_UTEST_ASSERT_NO_THROW(statement, failure_macro)
66 if (const auto message_impl_utest = USERVER_NAMESPACE::utest::impl::AssertNoThrow([&] { statement; }, #statement);
67 !message_impl_utest.empty())
68 failure_macro(message_impl_utest.c_str())
69/// @endcond
70
71/// @ingroup userver_utest
72///
73/// An equivalent to `EXPECT_THROW` with an additional check for a message
74/// substring
75///
76/// @hideinitializer
77// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
78#define UEXPECT_THROW_MSG(statement, exception_type, message_substring)
79 IMPL_UTEST_ASSERT_THROW(statement, exception_type, message_substring, GTEST_NONFATAL_FAILURE_)
80
81/// @ingroup userver_utest
82///
83/// An equivalent to `ASSERT_THROW` with an additional check for a message
84/// substring
85///
86/// @hideinitializer
87// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
88#define UASSERT_THROW_MSG(statement, exception_type, message_substring)
89 IMPL_UTEST_ASSERT_THROW(statement, exception_type, message_substring, GTEST_FATAL_FAILURE_)
90
91/// @ingroup userver_utest
92///
93/// An equivalent to `EXPECT_THROW` with better diagnostics
94///
95/// @hideinitializer
96// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
97#define UEXPECT_THROW(statement, exception_type)
98 IMPL_UTEST_ASSERT_THROW(statement, exception_type, "", GTEST_NONFATAL_FAILURE_)
99
100/// @ingroup userver_utest
101///
102/// An equivalent to `ASSERT_THROW` with better diagnostics
103///
104/// @hideinitializer
105// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
106#define UASSERT_THROW(statement, exception_type)
107 IMPL_UTEST_ASSERT_THROW(statement, exception_type, "", GTEST_FATAL_FAILURE_)
108
109/// @ingroup userver_utest
110///
111/// An equivalent to `EXPECT_NO_THROW` with better diagnostics
112///
113/// @hideinitializer
114// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
115#define UEXPECT_NO_THROW(statement) IMPL_UTEST_ASSERT_NO_THROW(statement, GTEST_NONFATAL_FAILURE_)
116
117/// @ingroup userver_utest
118///
119/// An equivalent to `EXPECT_THROW` with better diagnostics
120///
121/// @hideinitializer
122// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
123#define UASSERT_NO_THROW(statement) IMPL_UTEST_ASSERT_NO_THROW(statement, GTEST_FATAL_FAILURE_)
124
125/// @cond
126#ifdef NDEBUG
127// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
128#define EXPECT_UINVARIANT_FAILURE_MSG(statement, message_substring)
129 UEXPECT_THROW_MSG(statement, USERVER_NAMESPACE::utils::InvariantError, message_substring)
130#else
131// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
132#define EXPECT_UINVARIANT_FAILURE_MSG(statement, message_substring) UEXPECT_DEATH(statement, message_substring)
133#endif
134/// @endcond
135
136/// @ingroup userver_utest
137///
138/// Test that a UINVARIANT check triggers
139///
140/// @hideinitializer
141// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
142#define EXPECT_UINVARIANT_FAILURE(statement) EXPECT_UINVARIANT_FAILURE_MSG(statement, "")