@micro-os-plus/micro-test-plus 3.3.1 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/CHANGELOG.md +412 -2
  2. package/CMakeLists.txt +134 -28
  3. package/README.md +3 -2
  4. package/config/xcdl-build.json +11 -4
  5. package/include/micro-os-plus/micro-test-plus/README.md +6 -0
  6. package/include/micro-os-plus/micro-test-plus/deferred-reporter.h +267 -0
  7. package/include/micro-os-plus/micro-test-plus/detail.h +272 -1425
  8. package/include/micro-os-plus/micro-test-plus/exceptions.h +125 -0
  9. package/include/micro-os-plus/micro-test-plus/expression-formatter.h +669 -0
  10. package/include/micro-os-plus/micro-test-plus/function-comparators.h +15 -7
  11. package/include/micro-os-plus/micro-test-plus/inlines/{details-inlines.h → deferred-reporter-inlines.h} +66 -44
  12. package/include/micro-os-plus/micro-test-plus/inlines/detail-inlines.h +711 -0
  13. package/include/micro-os-plus/micro-test-plus/inlines/exceptions-inline.h +137 -0
  14. package/include/micro-os-plus/micro-test-plus/inlines/{test-reporter-inlines.h → expression-formatter-inlines.h} +232 -198
  15. package/include/micro-os-plus/micro-test-plus/inlines/function-comparators-inlines.h +24 -20
  16. package/include/micro-os-plus/micro-test-plus/inlines/literals-inlines.h +50 -31
  17. package/include/micro-os-plus/micro-test-plus/inlines/math-inlines.h +25 -19
  18. package/include/micro-os-plus/micro-test-plus/inlines/operators-inlines.h +275 -0
  19. package/include/micro-os-plus/micro-test-plus/inlines/reflection-inlines.h +39 -21
  20. package/include/micro-os-plus/micro-test-plus/inlines/reporter-inlines.h +205 -0
  21. package/include/micro-os-plus/micro-test-plus/inlines/runner-inlines.h +151 -0
  22. package/include/micro-os-plus/micro-test-plus/inlines/runner-totals-inlines.h +152 -0
  23. package/include/micro-os-plus/micro-test-plus/inlines/test-inlines.h +555 -0
  24. package/include/micro-os-plus/micro-test-plus/inlines/timings-inlines.h +120 -0
  25. package/include/micro-os-plus/micro-test-plus/inlines/type-traits-inlines.h +231 -0
  26. package/include/micro-os-plus/micro-test-plus/inlines/utility-inlines.h +126 -0
  27. package/include/micro-os-plus/micro-test-plus/literals.h +12 -17
  28. package/include/micro-os-plus/micro-test-plus/math.h +14 -6
  29. package/include/micro-os-plus/micro-test-plus/operators.h +53 -209
  30. package/include/micro-os-plus/micro-test-plus/reflection.h +8 -4
  31. package/include/micro-os-plus/micro-test-plus/{test-reporter-basic.h → reporter-human.h} +80 -74
  32. package/include/micro-os-plus/micro-test-plus/{test-reporter-tap.h → reporter-tap.h} +77 -71
  33. package/include/micro-os-plus/micro-test-plus/reporter.h +619 -0
  34. package/include/micro-os-plus/micro-test-plus/runner-totals.h +250 -0
  35. package/include/micro-os-plus/micro-test-plus/runner.h +472 -0
  36. package/include/micro-os-plus/micro-test-plus/test.h +1013 -0
  37. package/include/micro-os-plus/micro-test-plus/timings.h +363 -0
  38. package/include/micro-os-plus/micro-test-plus/type-traits.h +223 -577
  39. package/include/micro-os-plus/micro-test-plus/utility.h +136 -0
  40. package/include/micro-os-plus/micro-test-plus.h +42 -236
  41. package/meson.build +11 -6
  42. package/package.json +11 -3
  43. package/src/deferred-reporter.cpp +137 -0
  44. package/src/expression-formatter.cpp +289 -0
  45. package/src/reflection.cpp +97 -0
  46. package/src/reporter-human.cpp +816 -0
  47. package/src/reporter-tap.cpp +772 -0
  48. package/src/reporter.cpp +481 -0
  49. package/src/runner-totals.cpp +98 -0
  50. package/src/runner.cpp +669 -0
  51. package/src/test.cpp +503 -0
  52. package/src/timings.cpp +210 -0
  53. package/src/utility.cpp +163 -0
  54. package/.cmake-format.yaml +0 -11
  55. package/include/micro-os-plus/micro-test-plus/inlines/micro-test-plus-inlines.h +0 -313
  56. package/include/micro-os-plus/micro-test-plus/inlines/test-suite-inlines.h +0 -115
  57. package/include/micro-os-plus/micro-test-plus/test-reporter.h +0 -846
  58. package/include/micro-os-plus/micro-test-plus/test-runner.h +0 -281
  59. package/include/micro-os-plus/micro-test-plus/test-suite.h +0 -492
  60. package/src/micro-test-plus.cpp +0 -316
  61. package/src/test-reporter-basic.cpp +0 -466
  62. package/src/test-reporter-tap.cpp +0 -530
  63. package/src/test-reporter.cpp +0 -399
  64. package/src/test-runner.cpp +0 -311
  65. package/src/test-suite.cpp +0 -304
@@ -0,0 +1,275 @@
1
+ /*
2
+ * This file is part of the µOS++ project (https://micro-os-plus.github.io/).
3
+ * Copyright (c) 2021-2026 Liviu Ionescu. All rights reserved.
4
+ *
5
+ * Permission to use, copy, modify, and/or distribute this software for any
6
+ * purpose is hereby granted, under the terms of the MIT license.
7
+ *
8
+ * If a copy of the license was not distributed with this file, it can be
9
+ * obtained from https://opensource.org/licenses/mit.
10
+ *
11
+ * Major parts of the code are inspired from v1.1.8 of the Boost UT project,
12
+ * released under the terms of the Boost Version 1.0 Software License,
13
+ * which can be obtained from https://www.boost.org/LICENSE_1_0.txt.
14
+ */
15
+
16
+ // ----------------------------------------------------------------------------
17
+
18
+ /**
19
+ * @file
20
+ * @brief C++ header file with inline implementations for the µTest++
21
+ * operator overloads.
22
+ *
23
+ * @details
24
+ * This header provides the inline implementations for all operator overloads
25
+ * declared in `operators.h`. Each operator constructs and returns the
26
+ * appropriate comparator or logical object from the `detail` namespace.
27
+ *
28
+ * Separating the implementations from the declarations keeps `operators.h`
29
+ * concise and focused on the interface, whilst grouping all operator bodies
30
+ * here for maintainability.
31
+ *
32
+ * All definitions reside within the
33
+ * `micro_os_plus::micro_test_plus::operators` namespace, ensuring clear
34
+ * separation from user code and minimising the risk of naming conflicts.
35
+ *
36
+ * This file is intended solely for internal use within the framework and
37
+ * should not be included directly by user code.
38
+ */
39
+
40
+ #ifndef MICRO_TEST_PLUS_OPERATORS_INLINES_H_
41
+ #define MICRO_TEST_PLUS_OPERATORS_INLINES_H_
42
+
43
+ // ----------------------------------------------------------------------------
44
+
45
+ #ifdef __cplusplus
46
+
47
+ // ----------------------------------------------------------------------------
48
+
49
+ #include "micro-os-plus/micro-test-plus/detail.h"
50
+
51
+ // ----------------------------------------------------------------------------
52
+
53
+ #if defined(__GNUC__)
54
+ #pragma GCC diagnostic push
55
+ #pragma GCC diagnostic ignored "-Waggregate-return"
56
+ #if defined(__clang__)
57
+ #pragma clang diagnostic ignored "-Wc++98-compat"
58
+ #endif
59
+ #endif
60
+
61
+ // ============================================================================
62
+
63
+ namespace micro_os_plus::micro_test_plus
64
+ {
65
+ namespace operators
66
+ {
67
+ // ========================================================================
68
+
69
+ /**
70
+ * @details
71
+ * Constructs an `eq_` comparator object from the two `string_view`
72
+ * operands and returns it. The comparator evaluates to `true` if the
73
+ * string views are equal.
74
+ */
75
+ constexpr auto
76
+ operator== (std::string_view lhs, std::string_view rhs)
77
+ {
78
+ return detail::eq_{ lhs, rhs };
79
+ }
80
+
81
+ /**
82
+ * @details
83
+ * Constructs an `ne_` comparator object from the two `string_view`
84
+ * operands and returns it. The comparator evaluates to `true` if the
85
+ * string views are not equal.
86
+ */
87
+ constexpr auto
88
+ operator!= (std::string_view lhs, std::string_view rhs)
89
+ {
90
+ return detail::ne_{ lhs, rhs };
91
+ }
92
+
93
+ /**
94
+ * @details
95
+ * Constructs an `eq_` comparator object from the two container
96
+ * operands and returns it. The comparator evaluates to `true` if the
97
+ * containers are equal in content and order.
98
+ *
99
+ * The operator is enabled only for types recognised as containers by the
100
+ * framework's type traits.
101
+ */
102
+ template <class Lhs_T, class Rhs_T>
103
+ requires (type_traits::container_like<Lhs_T>
104
+ and type_traits::container_like<Rhs_T>)
105
+ constexpr auto
106
+ operator== (const Lhs_T& lhs, const Rhs_T& rhs)
107
+ {
108
+ return detail::eq_{ lhs, rhs };
109
+ }
110
+
111
+ /**
112
+ * @details
113
+ * Constructs an `ne_` comparator object from the two container
114
+ * operands and returns it. The comparator evaluates to `true` if the
115
+ * containers are not equal in content or order.
116
+ *
117
+ * The operator is enabled only for types recognised as containers by the
118
+ * framework's type traits.
119
+ */
120
+ template <class Lhs_T, class Rhs_T>
121
+ requires (type_traits::container_like<Lhs_T>
122
+ and type_traits::container_like<Rhs_T>)
123
+ constexpr auto
124
+ operator!= (const Lhs_T& lhs, const Rhs_T& rhs)
125
+ {
126
+ return detail::ne_{ lhs, rhs };
127
+ }
128
+
129
+ /**
130
+ * @details
131
+ * Constructs an `eq_` comparator object from the two operands and
132
+ * returns it. The comparator evaluates to `true` if the operands are
133
+ * equal. At least one operand must derive from the local `op` base.
134
+ */
135
+ template <class Lhs_T, class Rhs_T>
136
+ requires type_traits::any_op<Lhs_T, Rhs_T>
137
+ constexpr auto
138
+ operator== (const Lhs_T& lhs, const Rhs_T& rhs)
139
+ {
140
+ return detail::eq_{ lhs, rhs };
141
+ }
142
+
143
+ /**
144
+ * @details
145
+ * Constructs an `ne_` comparator object from the two operands and
146
+ * returns it. The comparator evaluates to `true` if the operands are
147
+ * not equal. At least one operand must derive from the local `op` base.
148
+ */
149
+ template <class Lhs_T, class Rhs_T>
150
+ requires type_traits::any_op<Lhs_T, Rhs_T>
151
+ constexpr auto
152
+ operator!= (const Lhs_T& lhs, const Rhs_T& rhs)
153
+ {
154
+ return detail::ne_{ lhs, rhs };
155
+ }
156
+
157
+ /**
158
+ * @details
159
+ * Constructs a `gt_` comparator object from the two operands and
160
+ * returns it. The comparator evaluates to `true` if `lhs` is greater
161
+ * than `rhs`. At least one operand must derive from the local `op` base.
162
+ */
163
+ template <class Lhs_T, class Rhs_T>
164
+ requires type_traits::any_op<Lhs_T, Rhs_T>
165
+ constexpr auto
166
+ operator> (const Lhs_T& lhs, const Rhs_T& rhs)
167
+ {
168
+ return detail::gt_{ lhs, rhs };
169
+ }
170
+
171
+ /**
172
+ * @details
173
+ * Constructs a `ge_` comparator object from the two operands and
174
+ * returns it. The comparator evaluates to `true` if `lhs` is greater
175
+ * than or equal to `rhs`. At least one operand must derive from the
176
+ * local `op` base.
177
+ */
178
+ template <class Lhs_T, class Rhs_T>
179
+ requires type_traits::any_op<Lhs_T, Rhs_T>
180
+ constexpr auto
181
+ operator>= (const Lhs_T& lhs, const Rhs_T& rhs)
182
+ {
183
+ return detail::ge_{ lhs, rhs };
184
+ }
185
+
186
+ /**
187
+ * @details
188
+ * Constructs an `lt_` comparator object from the two operands and
189
+ * returns it. The comparator evaluates to `true` if `lhs` is less
190
+ * than `rhs`. At least one operand must derive from the local `op` base.
191
+ */
192
+ template <class Lhs_T, class Rhs_T>
193
+ requires type_traits::any_op<Lhs_T, Rhs_T>
194
+ constexpr auto
195
+ operator< (const Lhs_T& lhs, const Rhs_T& rhs)
196
+ {
197
+ return detail::lt_{ lhs, rhs };
198
+ }
199
+
200
+ /**
201
+ * @details
202
+ * Constructs an `le_` comparator object from the two operands and
203
+ * returns it. The comparator evaluates to `true` if `lhs` is less than
204
+ * or equal to `rhs`. At least one operand must derive from the local
205
+ * `op` base.
206
+ */
207
+ template <class Lhs_T, class Rhs_T>
208
+ requires type_traits::any_op<Lhs_T, Rhs_T>
209
+ constexpr auto
210
+ operator<= (const Lhs_T& lhs, const Rhs_T& rhs)
211
+ {
212
+ return detail::le_{ lhs, rhs };
213
+ }
214
+
215
+ /**
216
+ * @details
217
+ * Constructs an `and_` logical conjunction object from the two operands
218
+ * and returns it. The object evaluates to `true` if both operands are
219
+ * true. At least one operand must derive from the local `op` base.
220
+ */
221
+ template <class Lhs_T, class Rhs_T>
222
+ requires type_traits::any_op<Lhs_T, Rhs_T>
223
+ constexpr auto
224
+ operator and (const Lhs_T& lhs, const Rhs_T& rhs)
225
+ {
226
+ return detail::and_{ lhs, rhs };
227
+ }
228
+
229
+ /**
230
+ * @details
231
+ * Constructs an `or_` logical disjunction object from the two operands
232
+ * and returns it. The object evaluates to `true` if at least one operand
233
+ * is true. At least one operand must derive from the local `op` base.
234
+ */
235
+ template <class Lhs_T, class Rhs_T>
236
+ requires type_traits::any_op<Lhs_T, Rhs_T>
237
+ constexpr auto
238
+ operator or (const Lhs_T& lhs, const Rhs_T& rhs)
239
+ {
240
+ return detail::or_{ lhs, rhs };
241
+ }
242
+
243
+ /**
244
+ * @details
245
+ * Constructs a `not_` logical negator object from the operand and
246
+ * returns it. The object evaluates to `true` if the operand is false.
247
+ * The operand must derive from the local `op` base.
248
+ */
249
+ template <class T>
250
+ requires type_traits::is_op<T>
251
+ constexpr auto
252
+ operator not(const T& t)
253
+ {
254
+ return detail::not_{ t };
255
+ }
256
+
257
+ // ------------------------------------------------------------------------
258
+ } // namespace operators
259
+
260
+ // --------------------------------------------------------------------------
261
+ } // namespace micro_os_plus::micro_test_plus
262
+
263
+ #if defined(__GNUC__)
264
+ #pragma GCC diagnostic pop
265
+ #endif
266
+
267
+ // ----------------------------------------------------------------------------
268
+
269
+ #endif // __cplusplus
270
+
271
+ // ----------------------------------------------------------------------------
272
+
273
+ #endif // MICRO_TEST_PLUS_OPERATORS_INLINES_H_
274
+
275
+ // ----------------------------------------------------------------------------
@@ -56,8 +56,6 @@
56
56
 
57
57
  #include <cstdint>
58
58
 
59
- // #include "type-traits.h"
60
-
61
59
  // ----------------------------------------------------------------------------
62
60
 
63
61
  #if defined(__GNUC__)
@@ -69,6 +67,8 @@
69
67
  #endif
70
68
  #endif
71
69
 
70
+ // ============================================================================
71
+
72
72
  namespace micro_os_plus::micro_test_plus
73
73
  {
74
74
  // --------------------------------------------------------------------------
@@ -87,7 +87,7 @@ namespace micro_os_plus::micro_test_plus
87
87
  * If supported by the compiler, uses built-in macros to capture this
88
88
  * information; otherwise, defaults to `"unknown"` and zero.
89
89
  */
90
- [[nodiscard]] constexpr source_location
90
+ constexpr source_location
91
91
  source_location::current (const char* file, unsigned int line) noexcept
92
92
  {
93
93
  source_location sl{};
@@ -98,9 +98,10 @@ namespace micro_os_plus::micro_test_plus
98
98
 
99
99
  /**
100
100
  * @details
101
- * ... TBD
101
+ * Returns the file name captured at the time this `source_location`
102
+ * instance was created.
102
103
  */
103
- [[nodiscard]] constexpr auto
104
+ constexpr auto
104
105
  source_location::file_name (void) const noexcept
105
106
  {
106
107
  return file_;
@@ -108,9 +109,10 @@ namespace micro_os_plus::micro_test_plus
108
109
 
109
110
  /**
110
111
  * @details
111
- * ... TBD
112
+ * Returns the line number captured at the time this `source_location`
113
+ * instance was created.
112
114
  */
113
- [[nodiscard]] constexpr auto
115
+ constexpr auto
114
116
  source_location::line (void) const noexcept
115
117
  {
116
118
  return line_;
@@ -124,29 +126,45 @@ namespace micro_os_plus::micro_test_plus
124
126
  * `__PRETTY_FUNCTION__` macro to extract a concise type name for the
125
127
  * template parameter \c T.
126
128
  *
127
- * The implementation is compiler-dependent and may require adjustment for
128
- * different toolchains. It is primarily intended for internal use within
129
- * the µTest++ framework to support improved diagnostics and reporting.
129
+ * Rather than relying on fixed character offsets (which are fragile across
130
+ * compiler versions and namespace changes), the implementation searches
131
+ * for well-known marker characters in the function signature string:
132
+ *
133
+ * - Clang formats the signature as `"... [T = <typename>]"`, so the type
134
+ * name lies between the last `'['` (skipping `"[T = "`) and the last
135
+ * `']'`.
136
+ * - GCC formats the signature as `"... [with T = <typename>]"`, so the
137
+ * type name lies between the last `'='` (skipping the trailing space)
138
+ * and the last `']'`.
139
+ *
140
+ * This approach is resilient to namespace renaming, namespace nesting
141
+ * changes, and compiler format updates.
130
142
  */
131
143
  template <class T>
132
- [[nodiscard]] constexpr auto
144
+ constexpr auto
133
145
  type_name (void) -> std::string_view
134
146
  {
147
+ const std::string_view sv = __PRETTY_FUNCTION__;
135
148
  #if defined(__clang__)
136
- #pragma GCC diagnostic push
137
- #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
138
- // printf("|%s|%zu|\n", __PRETTY_FUNCTION__, sizeof
139
- // (__PRETTY_FUNCTION__)); printf("|%s|\n", &__PRETTY_FUNCTION__[78]);
140
- return { &__PRETTY_FUNCTION__[78], sizeof (__PRETTY_FUNCTION__) - 80 };
141
- #pragma GCC diagnostic pop
149
+ // Clang: "... [T = <typename>]"
150
+ // rfind('[') locates the opening bracket of "[T = ...]".
151
+ const auto start = sv.rfind ('[') + 5; // skip "[T = "
152
+ const auto end = sv.rfind (']');
142
153
  #elif defined(__GNUC__)
143
- // printf("|%s|%zu|\n", __PRETTY_FUNCTION__, sizeof
144
- // (__PRETTY_FUNCTION__)); printf("|%s|\n", &__PRETTY_FUNCTION__[93]);
145
- return { &__PRETTY_FUNCTION__[93], sizeof (__PRETTY_FUNCTION__) - 144 };
154
+ // GCC: "... [with T = <typename>]" or, on some versions,
155
+ // "... [with T = <typename>; std::string_view = ...]"
156
+ // Search for "T = " explicitly to avoid landing on a later '='.
157
+ const auto t_eq = sv.find ("T = ");
158
+ const auto start = t_eq + 4; // skip "T = "
159
+ const auto semi = sv.find (';', start);
160
+ const auto end
161
+ = (semi != std::string_view::npos) ? semi : sv.rfind (']');
146
162
  #else
163
+ // Note: MSVC uses __FUNCSIG__ instead of __PRETTY_FUNCTION__.
164
+ // MSVC is not a supported target for this framework.
147
165
  #error "Unsupported compiler"
148
- return "Unsupported compiler";
149
166
  #endif
167
+ return sv.substr (start, end - start);
150
168
  }
151
169
 
152
170
  // ------------------------------------------------------------------------
@@ -0,0 +1,205 @@
1
+ /*
2
+ * This file is part of the µOS++ project (https://micro-os-plus.github.io/).
3
+ * Copyright (c) 2021-2026 Liviu Ionescu. All rights reserved.
4
+ *
5
+ * Permission to use, copy, modify, and/or distribute this software for any
6
+ * purpose is hereby granted, under the terms of the MIT license.
7
+ *
8
+ * If a copy of the license was not distributed with this file, it can be
9
+ * obtained from https://opensource.org/licenses/mit.
10
+ *
11
+ * Major parts of the code are inspired from v1.1.8 of the Boost UT project,
12
+ * released under the terms of the Boost Version 1.0 Software License,
13
+ * which can be obtained from https://www.boost.org/LICENSE_1_0.txt.
14
+ */
15
+
16
+ // ----------------------------------------------------------------------------
17
+
18
+ /**
19
+ * @file
20
+ * @brief C++ header file with inline implementations for the µTest++ test
21
+ * reporter.
22
+ *
23
+ * @details
24
+ * This header provides the inline implementations for the test reporting
25
+ * facilities used within the µTest++ framework. It defines the logic for
26
+ * formatting and outputting test results, including operator overloads for
27
+ * various value types, containers, and comparison expressions, as well as
28
+ * structured output for logical and exception-related assertions.
29
+ *
30
+ * The implementations ensure that test outcomes are presented in a clear,
31
+ * consistent, and expressive manner, supporting both value and pointer
32
+ * semantics, and providing detailed diagnostics for both successful and failed
33
+ * test cases. Special attention is given to formatting, colour highlighting,
34
+ * and extensibility, enabling professional and readable test reports suitable
35
+ * for embedded and general C++ development.
36
+ *
37
+ * All definitions reside within the `micro_os_plus::micro_test_plus`
38
+ * namespace, ensuring clear separation from user code and minimising the risk
39
+ * of naming conflicts.
40
+ *
41
+ * The header files are organised within the
42
+ * `include/micro-os-plus/micro-test-plus` folder to maintain a structured and
43
+ * modular codebase.
44
+ *
45
+ * This file is intended solely for internal use within the framework and
46
+ * should not be included directly by user code.
47
+ */
48
+
49
+ #ifndef MICRO_TEST_PLUS_TEST_REPORTER_INLINES_H_
50
+ #define MICRO_TEST_PLUS_TEST_REPORTER_INLINES_H_
51
+
52
+ // ----------------------------------------------------------------------------
53
+
54
+ #ifdef __cplusplus
55
+
56
+ // ----------------------------------------------------------------------------
57
+
58
+ #include <cstdio>
59
+ #include <cstring>
60
+
61
+ // ----------------------------------------------------------------------------
62
+
63
+ #if defined(__GNUC__)
64
+ #pragma GCC diagnostic push
65
+ #pragma GCC diagnostic ignored "-Waggregate-return"
66
+ #if defined(__clang__)
67
+ #pragma clang diagnostic ignored "-Wc++98-compat"
68
+ #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
69
+ #endif
70
+ #endif
71
+
72
+ // ============================================================================
73
+
74
+ namespace micro_os_plus::micro_test_plus
75
+ {
76
+ // --------------------------------------------------------------------------
77
+
78
+ inline detail::indent_t
79
+ indent (size_t level)
80
+ {
81
+ return { level };
82
+ }
83
+
84
+ // ==========================================================================
85
+
86
+ /**
87
+ * @details
88
+ * Returns the verbosity level stored in `verbosity_`.
89
+ */
90
+ inline auto
91
+ reporter::verbosity () const -> micro_test_plus::verbosity
92
+ {
93
+ return verbosity_;
94
+ }
95
+
96
+ /**
97
+ * @details
98
+ * Returns a reference to the `expression_formatter` instance used by the
99
+ * reporter for formatting expressions in test reports. This allows the
100
+ * reporter to delegate the formatting of complex expressions to the
101
+ * `expression_formatter`, which provides a consistent and extensible way to
102
+ * convert various types of values and expressions into their string
103
+ * representations for output in test reports.
104
+ */
105
+ inline detail::expression_formatter&
106
+ reporter::expression ()
107
+ {
108
+ return expression_;
109
+ }
110
+
111
+ /**
112
+ * @details
113
+ * Returns the ANSI colour code for pass or fail, depending on the boolean
114
+ * condition provided.
115
+ */
116
+ inline auto
117
+ reporter::colour_ (const bool cond) const
118
+ {
119
+ return cond ? colours_.pass : colours_.fail;
120
+ }
121
+
122
+ // --------------------------------------------------------------------------
123
+
124
+ /**
125
+ * @details
126
+ * This operator overload enables the `reporter` to output pointer
127
+ * values in a consistent and readable format.
128
+ *
129
+ * Null pointers are always rendered as the string `"nullptr"`,
130
+ * regardless of the platform, avoiding platform-specific behaviour
131
+ * such as `"(nil)"` on Linux/glibc or `"0x0"` on macOS.
132
+ *
133
+ * Non-null pointers are formatted as a hexadecimal address using
134
+ * `snprintf` with the `%p` format specifier. The resulting string is
135
+ * appended to the internal output buffer, allowing pointer values to be
136
+ * included in test reports and diagnostics.
137
+ *
138
+ * This approach provides clear and unambiguous representation of pointer
139
+ * addresses, which is particularly useful for debugging and verifying
140
+ * pointer-related test cases.
141
+ */
142
+ template <typename T>
143
+ reporter&
144
+ reporter::operator<< (T* v)
145
+ {
146
+ if (v == nullptr)
147
+ {
148
+ // Explicitly render null pointers as "0x0" to avoid platform-specific
149
+ // representations such as "(nil)" on Linux/glibc.
150
+ buffer_.append ("0x0");
151
+ return *this;
152
+ }
153
+ #if defined(__GNUC__)
154
+ #pragma GCC diagnostic push
155
+ #if defined(__clang__)
156
+ #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
157
+ #endif
158
+ #endif
159
+ char buff[20];
160
+ snprintf (buff, sizeof (buff), "%p", reinterpret_cast<void*> (v));
161
+ buffer_.append (buff);
162
+ #if defined(__GNUC__)
163
+ #pragma GCC diagnostic pop
164
+ #endif
165
+
166
+ return *this;
167
+ }
168
+
169
+ /**
170
+ * @details
171
+ * This template operator overload allows the `reporter` to output values of
172
+ * any arithmetic type (integral or floating-point) in a consistent and
173
+ * readable format. The value is formatted using the `append_number_` helper
174
+ * function, which handles the conversion to a string representation with
175
+ * appropriate type suffixes where applicable (e.g., "f" for float, "l" for
176
+ * long double). This enables numeric values to be included in test reports
177
+ * and diagnostics in a clear and unambiguous manner, supporting the
178
+ * verification of test cases that involve arithmetic expressions and
179
+ * comparisons.
180
+ */
181
+ template <class T>
182
+ requires std::is_arithmetic_v<T>
183
+ reporter&
184
+ reporter::operator<< (T v)
185
+ {
186
+ detail::append_number_ (buffer_, v);
187
+ return *this;
188
+ }
189
+
190
+ // --------------------------------------------------------------------------
191
+ } // namespace micro_os_plus::micro_test_plus
192
+
193
+ #if defined(__GNUC__)
194
+ #pragma GCC diagnostic pop
195
+ #endif
196
+
197
+ // ----------------------------------------------------------------------------
198
+
199
+ #endif // __cplusplus
200
+
201
+ // ----------------------------------------------------------------------------
202
+
203
+ #endif // MICRO_TEST_PLUS_TEST_REPORTER_INLINES_H_
204
+
205
+ // ----------------------------------------------------------------------------