qxLib
expected_assert.inl
Go to the documentation of this file.
1 /**
2 
3  @file expected_assert.inl
4  @author Khrapov
5  @date 31.10.2026
6  @copyright (c) Nick Khrapov, 2026. All right reserved.
7 
8 **/
9 
10 namespace qx
11 {
12 
13 inline expected_assert_builder::string_matcher::string_matcher(string_view svValue, bool bRegex) : m_Value(svValue)
14 {
15  if (bRegex)
16  m_Regex.emplace(svValue.begin(), svValue.end());
17 }
18 
19 inline bool expected_assert_builder::string_matcher::matches(string_view svValue) const
20 {
21  return m_Regex ? std::regex_search(svValue.begin(), svValue.end(), *m_Regex) : svValue == m_Value;
22 }
23 
24 inline string_view expected_assert_builder::string_matcher::get_pattern() const
25 {
26  return m_Value;
27 }
28 
29 inline bool expected_assert_builder::string_matcher::is_regex() const
30 {
31  return m_Regex.has_value();
32 }
33 
34 inline expected_assert_builder& expected_assert_builder::condition(string_view svCondition, bool bRegex)
35 {
36  m_Condition.emplace(svCondition, bRegex);
37  return *this;
38 }
39 
40 inline expected_assert_builder& expected_assert_builder::category(const qx::category& category)
41 {
42  m_pCategory = &category;
43  return *this;
44 }
45 
46 inline expected_assert_builder& expected_assert_builder::type(assert_type eType)
47 {
48  m_Type = eType;
49  return *this;
50 }
51 
52 inline expected_assert_builder& expected_assert_builder::message(string_view svPattern, bool bRegex)
53 {
54  m_Message.emplace(svPattern, bRegex);
55  return *this;
56 }
57 
58 inline expected_assert_builder& expected_assert_builder::function(string_view svFunction, bool bRegex)
59 {
60  m_Function.emplace(svFunction, bRegex);
61  return *this;
62 }
63 
64 inline expected_assert_builder& expected_assert_builder::file(string_view svFile, bool bRegex)
65 {
66  m_File.emplace(svFile, bRegex);
67  return *this;
68 }
69 
70 inline expected_assert_builder& expected_assert_builder::line(i32 nLine)
71 {
72  m_Line = nLine;
73  return *this;
74 }
75 
76 inline expected_assert_builder& expected_assert_builder::count(size_t nCount)
77 {
78  m_nCount = nCount;
79  return *this;
80 }
81 
82 inline expected_assert expected_assert_builder::build() const
83 {
84  return expected_assert(*this);
85 }
86 
87 inline expected_assert::expected_assert(const expected_assert_builder& builder) : m_Builder(builder)
88 {
89  asserts_manager::get_instance().add_interceptor(
90  this,
91  [this](
92  string_view svCondition,
93  const qx::category& category,
94  assert_type eType,
95  string_view svMessage,
96  string_view svFunction,
97  string_view svFile,
98  i32 nLine)
99  {
100  if (m_Builder.m_Condition && !m_Builder.m_Condition->matches(svCondition))
101  return false;
102 
103  if (m_Builder.m_pCategory && *m_Builder.m_pCategory != category)
104  return false;
105 
106  if (m_Builder.m_Type && eType != *m_Builder.m_Type)
107  return false;
108 
109  if (m_Builder.m_Message && !m_Builder.m_Message->matches(svMessage))
110  return false;
111 
112  if (m_Builder.m_Function && !m_Builder.m_Function->matches(svFunction))
113  return false;
114 
115  if (m_Builder.m_File && !m_Builder.m_File->matches(svFile))
116  return false;
117 
118  if (m_Builder.m_Line && nLine != *m_Builder.m_Line)
119  return false;
120 
121  ++m_nActual;
122  return true;
123  });
124 }
125 
126 inline expected_assert::~expected_assert()
127 {
128  asserts_manager::get_instance().remove_interceptor(this);
129  const size_t nActual = m_nActual.load();
130  if (nActual != m_Builder.m_nCount)
131  {
132  string sDetails;
133  const auto AppendMatcher = [&sDetails](string_view svName, const auto& optMatcher)
134  {
135  if (optMatcher)
136  {
137  sDetails.append_format(
138  QXT("\n {}{}: {}"),
139  svName,
140  optMatcher->is_regex() ? QXT(" (regex)") : QXT(""),
141  optMatcher->get_pattern());
142  }
143  };
144 
145  AppendMatcher(QXT("condition"), m_Builder.m_Condition);
146 
147  if (m_Builder.m_pCategory)
148  sDetails.append_format(QXT("\n category: {}"), m_Builder.m_pCategory->get_name());
149 
150  if (m_Builder.m_Type)
151  sDetails.append_format(QXT("\n type: {}"), *m_Builder.m_Type);
152 
153  AppendMatcher(QXT("message"), m_Builder.m_Message);
154 
155  AppendMatcher(QXT("function"), m_Builder.m_Function);
156 
157  AppendMatcher(QXT("file"), m_Builder.m_File);
158 
159  if (m_Builder.m_Line)
160  sDetails.append_format(QXT("\n line: {}"), *m_Builder.m_Line);
161 
162  ADD_FAILURE() << "Expected " << m_Builder.m_nCount << " matching assertions, got " << nActual
163  << to_cstring(sDetails).c_str();
164  }
165 }
166 
167 } // namespace qx
A category is a class that identifies a particular piece of code. This code can be located in differe...
Definition: category.h:62
constexpr string_view get_name() const noexcept
Get category name.
Definition: category.inl:26
Selects assertion properties and the number of expected occurrences.
Counts assertions matching the criteria selected by expected_assert_builder.
void to_cstring(cstring &out, wstring_view stringView, const std::locale &locale=get_locale())
Convert wstring to cstring.
std::int32_t i32
− 9 223 372 036 854 775 808 .. 9 223 372 036 854 775 807
Definition: typedefs.h:32