userver: userver/utest/assert_macros.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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
47testing::Matcher<const std::string&> MakeHasSubstrMatcher(std::string_view expected);
48
49} // namespace utest::impl
50
51USERVER_NAMESPACE_END
52
53/// @cond
54// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
55#define IMPL_UTEST_ASSERT_THROW(statement, exception_type, message_substring, failure_macro)
56 if (const auto message_impl_utest = USERVER_NAMESPACE::utest::impl::AssertThrow(
57 [&] { statement; },
58 #statement,
59 &USERVER_NAMESPACE::utest::impl::IsSubtype<exception_type>,
60 typeid(exception_type),
61 message_substring
62 );
63 !message_impl_utest.empty())
64 failure_macro(message_impl_utest.c_str())
65
66// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
67#define IMPL_UTEST_ASSERT_NO_THROW(statement, failure_macro)
68 if (const auto message_impl_utest = USERVER_NAMESPACE::utest::impl::AssertNoThrow([&] { statement; }, #statement);
69 !message_impl_utest.empty())
70 failure_macro(message_impl_utest.c_str())
71/// @endcond
72
73/// @ingroup userver_utest
74///
75/// An equivalent to `EXPECT_THROW` with an additional check for a message
76/// substring
77///
78/// @hideinitializer
79// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
80#define UEXPECT_THROW_MSG(statement, exception_type, message_substring)
81 IMPL_UTEST_ASSERT_THROW(statement, exception_type, message_substring, GTEST_NONFATAL_FAILURE_)
82
83/// @ingroup userver_utest
84///
85/// An equivalent to `ASSERT_THROW` with an additional check for a message
86/// substring
87///
88/// @hideinitializer
89// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
90#define UASSERT_THROW_MSG(statement, exception_type, message_substring)
91 IMPL_UTEST_ASSERT_THROW(statement, exception_type, message_substring, GTEST_FATAL_FAILURE_)
92
93/// @ingroup userver_utest
94///
95/// An equivalent to `EXPECT_THROW` with better diagnostics
96///
97/// @hideinitializer
98// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
99#define UEXPECT_THROW(statement, exception_type)
100 IMPL_UTEST_ASSERT_THROW(statement, exception_type, "", GTEST_NONFATAL_FAILURE_)
101
102/// @ingroup userver_utest
103///
104/// An equivalent to `ASSERT_THROW` with better diagnostics
105///
106/// @hideinitializer
107// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
108#define UASSERT_THROW(statement, exception_type)
109 IMPL_UTEST_ASSERT_THROW(statement, exception_type, "", GTEST_FATAL_FAILURE_)
110
111/// @ingroup userver_utest
112///
113/// An equivalent to `EXPECT_NO_THROW` with better diagnostics
114///
115/// @hideinitializer
116// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
117#define UEXPECT_NO_THROW(statement) IMPL_UTEST_ASSERT_NO_THROW(statement, GTEST_NONFATAL_FAILURE_)
118
119/// @ingroup userver_utest
120///
121/// An equivalent to `EXPECT_THROW` with better diagnostics
122///
123/// @hideinitializer
124// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
125#define UASSERT_NO_THROW(statement) IMPL_UTEST_ASSERT_NO_THROW(statement, GTEST_FATAL_FAILURE_)
126
127/// @cond
128#ifdef NDEBUG
129// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
130#define EXPECT_UINVARIANT_FAILURE_MSG(statement, message_substring)
131 UEXPECT_THROW_MSG(statement, USERVER_NAMESPACE::utils::InvariantError, message_substring)
132#else
133// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
134#define EXPECT_UINVARIANT_FAILURE_MSG(statement, message_substring)
135 UEXPECT_DEATH(statement, USERVER_NAMESPACE::utest::impl::MakeHasSubstrMatcher(message_substring))
136#endif
137/// @endcond
138
139/// @ingroup userver_utest
140///
141/// Test that a UINVARIANT check triggers
142///
143/// @hideinitializer
144// NOLINTNEXTLINE (cppcoreguidelines-macro-usage)
145#define EXPECT_UINVARIANT_FAILURE(statement) EXPECT_UINVARIANT_FAILURE_MSG(statement, "")