@micro-os-plus/micro-test-plus 3.3.1 → 4.0.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 (53) hide show
  1. package/CHANGELOG.md +330 -2
  2. package/CMakeLists.txt +79 -23
  3. package/README.md +1 -1
  4. package/config/xcdl-build.json +11 -4
  5. package/include/micro-os-plus/micro-test-plus/deferred-reporter.h +292 -0
  6. package/include/micro-os-plus/micro-test-plus/detail.h +462 -1076
  7. package/include/micro-os-plus/micro-test-plus/exceptions.h +126 -0
  8. package/include/micro-os-plus/micro-test-plus/function-comparators.h +10 -7
  9. package/include/micro-os-plus/micro-test-plus/inlines/{details-inlines.h → deferred-reporter-inlines.h} +49 -22
  10. package/include/micro-os-plus/micro-test-plus/inlines/function-comparators-inlines.h +67 -4
  11. package/include/micro-os-plus/micro-test-plus/inlines/literals-inlines.h +3 -6
  12. package/include/micro-os-plus/micro-test-plus/inlines/math-inlines.h +21 -15
  13. package/include/micro-os-plus/micro-test-plus/inlines/reflection-inlines.h +35 -17
  14. package/include/micro-os-plus/micro-test-plus/inlines/{test-reporter-inlines.h → reporter-inlines.h} +176 -106
  15. package/include/micro-os-plus/micro-test-plus/inlines/{test-suite-inlines.h → runner-inlines.h} +41 -43
  16. package/include/micro-os-plus/micro-test-plus/inlines/test-inlines.h +369 -0
  17. package/include/micro-os-plus/micro-test-plus/inlines/utility-inlines.h +126 -0
  18. package/include/micro-os-plus/micro-test-plus/literals.h +4 -3
  19. package/include/micro-os-plus/micro-test-plus/math.h +9 -6
  20. package/include/micro-os-plus/micro-test-plus/operators.h +38 -44
  21. package/include/micro-os-plus/micro-test-plus/reflection.h +15 -4
  22. package/include/micro-os-plus/micro-test-plus/{test-reporter-basic.h → reporter-human.h} +72 -72
  23. package/include/micro-os-plus/micro-test-plus/{test-reporter-tap.h → reporter-tap.h} +69 -69
  24. package/include/micro-os-plus/micro-test-plus/{test-reporter.h → reporter.h} +296 -200
  25. package/include/micro-os-plus/micro-test-plus/runner-totals.h +264 -0
  26. package/include/micro-os-plus/micro-test-plus/runner.h +453 -0
  27. package/include/micro-os-plus/micro-test-plus/test.h +1069 -0
  28. package/include/micro-os-plus/micro-test-plus/timings.h +366 -0
  29. package/include/micro-os-plus/micro-test-plus/type-traits.h +239 -545
  30. package/include/micro-os-plus/micro-test-plus/utility.h +135 -0
  31. package/include/micro-os-plus/micro-test-plus.h +25 -228
  32. package/meson.build +10 -6
  33. package/package.json +1 -1
  34. package/src/deferred-reporter.cpp +118 -0
  35. package/src/reflection.cpp +95 -0
  36. package/src/reporter-human.cpp +822 -0
  37. package/src/reporter-tap.cpp +782 -0
  38. package/src/reporter.cpp +676 -0
  39. package/src/runner-totals.cpp +95 -0
  40. package/src/runner.cpp +563 -0
  41. package/src/test.cpp +496 -0
  42. package/src/timings.cpp +209 -0
  43. package/src/utility.cpp +163 -0
  44. package/.cmake-format.yaml +0 -11
  45. package/include/micro-os-plus/micro-test-plus/inlines/micro-test-plus-inlines.h +0 -313
  46. package/include/micro-os-plus/micro-test-plus/test-runner.h +0 -281
  47. package/include/micro-os-plus/micro-test-plus/test-suite.h +0 -492
  48. package/src/micro-test-plus.cpp +0 -316
  49. package/src/test-reporter-basic.cpp +0 -466
  50. package/src/test-reporter-tap.cpp +0 -530
  51. package/src/test-reporter.cpp +0 -399
  52. package/src/test-runner.cpp +0 -311
  53. package/src/test-suite.cpp +0 -304
@@ -34,7 +34,7 @@
34
34
  * and extensibility, enabling professional and readable test reports suitable
35
35
  * for embedded and general C++ development.
36
36
  *
37
- * All definitions reside within the `micro_os_plus::micro_test_plus::detail`
37
+ * All definitions reside within the `micro_os_plus::micro_test_plus`
38
38
  * namespace, ensuring clear separation from user code and minimising the risk
39
39
  * of naming conflicts.
40
40
  *
@@ -55,7 +55,7 @@
55
55
 
56
56
  // ----------------------------------------------------------------------------
57
57
 
58
- #include <stdio.h>
58
+ #include <cstdio>
59
59
  #include <cstring>
60
60
 
61
61
  // ----------------------------------------------------------------------------
@@ -69,17 +69,71 @@
69
69
  #endif
70
70
  #endif
71
71
 
72
+ // ============================================================================
73
+
72
74
  namespace micro_os_plus::micro_test_plus
73
75
  {
74
76
  // --------------------------------------------------------------------------
75
77
 
78
+ #if defined(__GNUC__)
79
+ #pragma GCC diagnostic push
80
+ #if defined(__clang__)
81
+ #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
82
+ #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
83
+ #endif
84
+ #endif
85
+ template <class T>
86
+ void
87
+ reporter::append_number_ (std::string& buffer, const T v)
88
+ {
89
+ char buf[32];
90
+ if constexpr (std::is_same_v<T, long double>)
91
+ {
92
+ #if defined(_WIN32) \
93
+ || (defined(__SIZEOF_LONG_DOUBLE__) \
94
+ && __SIZEOF_LONG_DOUBLE__ == __SIZEOF_DOUBLE__)
95
+ // On Windows (all toolchains: MinGW, Clang, MSVC), the C runtime
96
+ // does not handle the %Lg printf specifier correctly for 80-bit
97
+ // long double, producing garbage output. On platforms where long
98
+ // double has the same width as double (ARM, RISC-V), the cast is
99
+ // lossless. In both cases, cast to double and use std::to_chars.
100
+ const auto [ptr, ec]
101
+ = std::to_chars (buf, buf + sizeof (buf), static_cast<double> (v));
102
+ if (ec == std::errc{})
103
+ buffer.append (buf, ptr);
104
+ #else
105
+ // On x86-64 Linux/macOS with 80-bit extended-precision long double,
106
+ // std::to_chars for long double may be unavailable (e.g., with lld).
107
+ // Use snprintf as a portable fallback; %Lg is supported correctly
108
+ // by glibc and libc++ on these platforms.
109
+ snprintf (buf, sizeof (buf), "%Lg", v);
110
+ buffer.append (buf);
111
+ #endif
112
+ }
113
+ else
114
+ {
115
+ const auto [ptr, ec] = std::to_chars (buf, buf + sizeof (buf), v);
116
+ if (ec == std::errc{})
117
+ buffer.append (buf, ptr);
118
+ }
119
+ }
120
+ #if defined(__GNUC__)
121
+ #pragma GCC diagnostic pop
122
+ #endif
123
+
124
+ // --------------------------------------------------------------------------
125
+
76
126
  /**
77
127
  * @details
78
- * This operator overload enables the `test_reporter` to output pointer
79
- * values in a consistent and readable hexadecimal format.
128
+ * This operator overload enables the `reporter` to output pointer
129
+ * values in a consistent and readable format.
130
+ *
131
+ * Null pointers are always rendered as the string `"nullptr"`,
132
+ * regardless of the platform, avoiding platform-specific behaviour
133
+ * such as `"(nil)"` on Linux/glibc or `"0x0"` on macOS.
80
134
  *
81
- * The pointer is formatted as a string using `snprintf` with the `%p` format
82
- * specifier, ensuring portability across platforms. The resulting string is
135
+ * Non-null pointers are formatted as a hexadecimal address using
136
+ * `snprintf` with the `%p` format specifier. The resulting string is
83
137
  * appended to the internal output buffer, allowing pointer values to be
84
138
  * included in test reports and diagnostics.
85
139
  *
@@ -88,37 +142,59 @@ namespace micro_os_plus::micro_test_plus
88
142
  * pointer-related test cases.
89
143
  */
90
144
  template <typename T>
91
- test_reporter&
92
- test_reporter::operator<< (T* v)
145
+ reporter&
146
+ reporter::operator<< (T* v)
93
147
  {
148
+ if (v == nullptr)
149
+ {
150
+ // Explicitly render null pointers as "0x0" to avoid platform-specific
151
+ // representations such as "(nil)" on Linux/glibc.
152
+ buffer_.append ("0x0");
153
+ return *this;
154
+ }
155
+ #if defined(__GNUC__)
156
+ #pragma GCC diagnostic push
157
+ #if defined(__clang__)
158
+ #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
159
+ #endif
160
+ #endif
94
161
  char buff[20];
95
162
  snprintf (buff, sizeof (buff), "%p", reinterpret_cast<void*> (v));
96
- out_.append (buff);
163
+ buffer_.append (buff);
164
+ #if defined(__GNUC__)
165
+ #pragma GCC diagnostic pop
166
+ #endif
97
167
 
98
168
  return *this;
99
169
  }
100
170
 
101
- #if 0
102
- /**
103
- * @details
104
- * This operator overload enables the `test_reporter` to output any type that is supported by the `detail::get` mechanism, ensuring consistent formatting and extensibility.
105
- *
106
- * By delegating to `detail::get`, the operator allows for custom formatting and extraction of values, supporting a wide range of types including user-defined and framework-specific types. The resulting value is then forwarded to the appropriate output handler, ensuring seamless integration into test reports and diagnostics.
107
- *
108
- * This approach promotes flexibility and maintainability, allowing new types to be supported with minimal changes to the reporting infrastructure.
109
- */
110
- template <class T>
111
- test_reporter&
112
- test_reporter::operator<< (const T& t)
171
+ /**
172
+ * @details
173
+ * This operator overload enables the `reporter` to output any type that is
174
+ * supported by the `detail::get` mechanism, ensuring consistent formatting
175
+ * and extensibility.
176
+ *
177
+ * By delegating to `detail::get`, the operator allows for custom formatting
178
+ * and extraction of values, supporting a wide range of types including
179
+ * user-defined and framework-specific types. The resulting value is then
180
+ * forwarded to the appropriate output handler, ensuring seamless integration
181
+ * into test reports and diagnostics.
182
+ *
183
+ * This approach promotes flexibility and maintainability, allowing new types
184
+ * to be supported with minimal changes to the reporting infrastructure.
185
+ */
186
+ template <class T>
187
+ requires type_traits::is_op<T>
188
+ reporter&
189
+ reporter::operator<< (const T& t)
113
190
  {
114
191
  *this << detail::get (t);
115
192
  return *this;
116
193
  }
117
- #endif
118
194
 
119
195
  /**
120
196
  * @details
121
- * This operator overload enables the `test_reporter` to output
197
+ * This operator overload enables the `reporter` to output
122
198
  * strongly-typed integral values in a clear and consistent decimal format.
123
199
  *
124
200
  * The value is converted to a string using `std::to_string` after being cast
@@ -131,16 +207,16 @@ namespace micro_os_plus::micro_test_plus
131
207
  * facilitating debugging.
132
208
  */
133
209
  template <class T>
134
- test_reporter&
135
- test_reporter::operator<< (const type_traits::genuine_integral_value<T>& v)
210
+ reporter&
211
+ reporter::operator<< (const type_traits::genuine_integral_value<T>& v)
136
212
  {
137
- out_.append (std::to_string (static_cast<long long> (v.get ())));
213
+ append_number_ (buffer_, static_cast<long long> (v.get ()));
138
214
  return *this;
139
215
  }
140
216
 
141
217
  /**
142
218
  * @details
143
- * This operator overload enables the `test_reporter` to output container
219
+ * This operator overload enables the `reporter` to output container
144
220
  * types in a structured and readable format.
145
221
  *
146
222
  * The contents of the container are enclosed in curly braces and each
@@ -152,11 +228,10 @@ namespace micro_os_plus::micro_test_plus
152
228
  * contents, making it easier to interpret test results and debug issues
153
229
  * involving collections of values.
154
230
  */
155
- template <class T,
156
- type_traits::requires_t<type_traits::is_container_v<T>
157
- and not type_traits::has_npos_v<T>>>
158
- test_reporter&
159
- test_reporter::operator<< (T&& t)
231
+ template <class T>
232
+ requires (type_traits::container_like<T> and not type_traits::has_npos<T>)
233
+ reporter&
234
+ reporter::operator<< (const T& t)
160
235
  {
161
236
  *this << '{';
162
237
  auto first = true;
@@ -171,7 +246,7 @@ namespace micro_os_plus::micro_test_plus
171
246
 
172
247
  /**
173
248
  * @details
174
- * This operator overload enables the `test_reporter` to output equality
249
+ * This operator overload enables the `reporter` to output equality
175
250
  * comparison expressions in a clear and expressive format.
176
251
  *
177
252
  * The left-hand side and right-hand side values are formatted and separated
@@ -181,16 +256,16 @@ namespace micro_os_plus::micro_test_plus
181
256
  * equality assertions and facilitates efficient debugging of test failures.
182
257
  */
183
258
  template <class Lhs_T, class Rhs_T>
184
- test_reporter&
185
- test_reporter::operator<< (const detail::eq_<Lhs_T, Rhs_T>& op)
259
+ reporter&
260
+ reporter::operator<< (const detail::eq_<Lhs_T, Rhs_T>& op)
186
261
  {
187
- return (*this << color (op) << op.lhs () << " == " << op.rhs ()
188
- << colors_.none);
262
+ return (*this << colour_ (op) << op.lhs () << " == " << op.rhs ()
263
+ << colours_.none);
189
264
  }
190
265
 
191
266
  /**
192
267
  * @details
193
- * This operator overload enables the `test_reporter` to output inequality
268
+ * This operator overload enables the `reporter` to output inequality
194
269
  * comparison expressions in a clear and expressive format.
195
270
  *
196
271
  * The left-hand side and right-hand side values are formatted and separated
@@ -201,16 +276,16 @@ namespace micro_os_plus::micro_test_plus
201
276
  * failures.
202
277
  */
203
278
  template <class Lhs_T, class Rhs_T>
204
- test_reporter&
205
- test_reporter::operator<< (const detail::ne_<Lhs_T, Rhs_T>& op)
279
+ reporter&
280
+ reporter::operator<< (const detail::ne_<Lhs_T, Rhs_T>& op)
206
281
  {
207
- return (*this << color (op) << op.lhs () << " != " << op.rhs ()
208
- << colors_.none);
282
+ return (*this << colour_ (op) << op.lhs () << " != " << op.rhs ()
283
+ << colours_.none);
209
284
  }
210
285
 
211
286
  /**
212
287
  * @details
213
- * This operator overload enables the `test_reporter` to output greater-than
288
+ * This operator overload enables the `reporter` to output greater-than
214
289
  * comparison expressions in a clear and expressive format.
215
290
  *
216
291
  * The left-hand side and right-hand side values are formatted and separated
@@ -221,16 +296,16 @@ namespace micro_os_plus::micro_test_plus
221
296
  * failures.
222
297
  */
223
298
  template <class Lhs_T, class Rhs_T>
224
- test_reporter&
225
- test_reporter::operator<< (const detail::gt_<Lhs_T, Rhs_T>& op)
299
+ reporter&
300
+ reporter::operator<< (const detail::gt_<Lhs_T, Rhs_T>& op)
226
301
  {
227
- return (*this << color (op) << op.lhs () << " > " << op.rhs ()
228
- << colors_.none);
302
+ return (*this << colour_ (op) << op.lhs () << " > " << op.rhs ()
303
+ << colours_.none);
229
304
  }
230
305
 
231
306
  /**
232
307
  * @details
233
- * This operator overload enables the `test_reporter` to output
308
+ * This operator overload enables the `reporter` to output
234
309
  * greater-than-or-equal-to comparison expressions in a clear and expressive
235
310
  * format.
236
311
  *
@@ -242,16 +317,16 @@ namespace micro_os_plus::micro_test_plus
242
317
  * efficient debugging of test failures.
243
318
  */
244
319
  template <class Lhs_T, class Rhs_T>
245
- test_reporter&
246
- test_reporter::operator<< (const detail::ge_<Lhs_T, Rhs_T>& op)
320
+ reporter&
321
+ reporter::operator<< (const detail::ge_<Lhs_T, Rhs_T>& op)
247
322
  {
248
- return (*this << color (op) << op.lhs () << " >= " << op.rhs ()
249
- << colors_.none);
323
+ return (*this << colour_ (op) << op.lhs () << " >= " << op.rhs ()
324
+ << colours_.none);
250
325
  }
251
326
 
252
327
  /**
253
328
  * @details
254
- * This operator overload enables the `test_reporter` to output less-than
329
+ * This operator overload enables the `reporter` to output less-than
255
330
  * comparison expressions in a clear and expressive format.
256
331
  *
257
332
  * The left-hand side and right-hand side values are formatted and separated
@@ -261,16 +336,16 @@ namespace micro_os_plus::micro_test_plus
261
336
  * less-than assertions and facilitates efficient debugging of test failures.
262
337
  */
263
338
  template <class Lhs_T, class Rhs_T>
264
- test_reporter&
265
- test_reporter::operator<< (const detail::lt_<Rhs_T, Lhs_T>& op)
339
+ reporter&
340
+ reporter::operator<< (const detail::lt_<Rhs_T, Lhs_T>& op)
266
341
  {
267
- return (*this << color (op) << op.lhs () << " < " << op.rhs ()
268
- << colors_.none);
342
+ return (*this << colour_ (op) << op.lhs () << " < " << op.rhs ()
343
+ << colours_.none);
269
344
  }
270
345
 
271
346
  /**
272
347
  * @details
273
- * This operator overload enables the `test_reporter` to output
348
+ * This operator overload enables the `reporter` to output
274
349
  * less-than-or-equal-to comparison expressions in a clear and expressive
275
350
  * format.
276
351
  *
@@ -282,16 +357,16 @@ namespace micro_os_plus::micro_test_plus
282
357
  * efficient debugging of test failures.
283
358
  */
284
359
  template <class Lhs_T, class Rhs_T>
285
- test_reporter&
286
- test_reporter::operator<< (const detail::le_<Rhs_T, Lhs_T>& op)
360
+ reporter&
361
+ reporter::operator<< (const detail::le_<Rhs_T, Lhs_T>& op)
287
362
  {
288
- return (*this << color (op) << op.lhs () << " <= " << op.rhs ()
289
- << colors_.none);
363
+ return (*this << colour_ (op) << op.lhs () << " <= " << op.rhs ()
364
+ << colours_.none);
290
365
  }
291
366
 
292
367
  /**
293
368
  * @details
294
- * This operator overload enables the `test_reporter` to output logical
369
+ * This operator overload enables the `reporter` to output logical
295
370
  * conjunction (AND) expressions in a clear and structured format.
296
371
  *
297
372
  * The left-hand side and right-hand side expressions are enclosed in
@@ -302,16 +377,16 @@ namespace micro_os_plus::micro_test_plus
302
377
  * test failures involving compound conditions.
303
378
  */
304
379
  template <class Lhs_T, class Rhs_T>
305
- test_reporter&
306
- test_reporter::operator<< (const detail::and_<Lhs_T, Rhs_T>& op)
380
+ reporter&
381
+ reporter::operator<< (const detail::and_<Lhs_T, Rhs_T>& op)
307
382
  {
308
- return (*this << '(' << op.lhs () << color (op) << " and " << colors_.none
309
- << op.rhs () << ')');
383
+ return (*this << '(' << op.lhs () << colour_ (op) << " and "
384
+ << colours_.none << op.rhs () << ')');
310
385
  }
311
386
 
312
387
  /**
313
388
  * @details
314
- * This operator overload enables the `test_reporter` to output logical
389
+ * This operator overload enables the `reporter` to output logical
315
390
  * disjunction (OR) expressions in a clear and structured format.
316
391
  *
317
392
  * The left-hand side and right-hand side expressions are enclosed in
@@ -322,11 +397,11 @@ namespace micro_os_plus::micro_test_plus
322
397
  * test failures involving compound conditions.
323
398
  */
324
399
  template <class Lhs_T, class Rhs_T>
325
- test_reporter&
326
- test_reporter::operator<< (const detail::or_<Lhs_T, Rhs_T>& op)
400
+ reporter&
401
+ reporter::operator<< (const detail::or_<Lhs_T, Rhs_T>& op)
327
402
  {
328
- return (*this << '(' << op.lhs () << color (op) << " or " << colors_.none
329
- << op.rhs () << ')');
403
+ return (*this << '(' << op.lhs () << colour_ (op) << " or "
404
+ << colours_.none << op.rhs () << ')');
330
405
  }
331
406
 
332
407
  /**
@@ -338,10 +413,10 @@ namespace micro_os_plus::micro_test_plus
338
413
  * diagnostics.
339
414
  */
340
415
  template <class T>
341
- test_reporter&
342
- test_reporter::operator<< (const detail::not_<T>& op)
416
+ reporter&
417
+ reporter::operator<< (const detail::not_<T>& op)
343
418
  {
344
- return (*this << color (op) << "not " << op.value () << colors_.none);
419
+ return (*this << colour_ (op) << "not " << op.operand () << colours_.none);
345
420
  }
346
421
 
347
422
  #if defined(__cpp_exceptions)
@@ -358,12 +433,12 @@ namespace micro_os_plus::micro_test_plus
358
433
  * exception-related test cases.
359
434
  */
360
435
  template <class Expr_T, class Exception_T>
361
- test_reporter&
362
- test_reporter::operator<< (const detail::throws_<Expr_T, Exception_T>& op)
436
+ reporter&
437
+ reporter::operator<< (const detail::throws_<Expr_T, Exception_T>& op)
363
438
  {
364
- return (*this << color (op) << "throws<"
439
+ return (*this << colour_ (op) << "throws<"
365
440
  << reflection::type_name<Exception_T> () << ">"
366
- << colors_.none);
441
+ << colours_.none);
367
442
  }
368
443
 
369
444
  /**
@@ -377,10 +452,10 @@ namespace micro_os_plus::micro_test_plus
377
452
  * improving the readability and professionalism of the test output.
378
453
  */
379
454
  template <class Expr_T>
380
- test_reporter&
381
- test_reporter::operator<< (const detail::throws_<Expr_T, void>& op)
455
+ reporter&
456
+ reporter::operator<< (const detail::throws_<Expr_T, void>& op)
382
457
  {
383
- return (*this << color (op) << "throws" << colors_.none);
458
+ return (*this << colour_ (op) << "throws" << colours_.none);
384
459
  }
385
460
 
386
461
  /**
@@ -394,33 +469,27 @@ namespace micro_os_plus::micro_test_plus
394
469
  * the readability and professionalism of the test output.
395
470
  */
396
471
  template <class Expr_T>
397
- test_reporter&
398
- test_reporter::operator<< (const detail::nothrow_<Expr_T>& op)
472
+ reporter&
473
+ reporter::operator<< (const detail::nothrow_<Expr_T>& op)
399
474
  {
400
- return (*this << color (op) << "nothrow" << colors_.none);
475
+ return (*this << colour_ (op) << "nothrow" << colours_.none);
401
476
  }
402
477
  #endif
403
478
 
404
479
  /**
405
480
  * @details
406
- * This operator overload formats output for expressions that do not throw
407
- * exceptions. It applies colour styling for clarity and ensures a structured
408
- * representation of exception safety.
409
- *
410
- * When invoked, the function outputs a pass prefix, followed by either the
411
- * provided message or, if the message is empty, the evaluated expression
412
- * itself. It then appends a pass suffix to complete the output. This
413
- * approach guarantees that successful test outcomes are presented in a clear
414
- * and consistent manner, enhancing the readability and professionalism of
415
- * test reports.
481
+ * Outputs a pass prefix, followed by either the provided message or, if
482
+ * the message is empty, the evaluated expression itself. A pass suffix is
483
+ * then appended to complete the output, ensuring that successful test
484
+ * outcomes are presented in a clear and consistent manner.
416
485
  */
417
486
  template <class Expr_T>
418
487
  void
419
- test_reporter::pass (Expr_T& expr, std::string& message)
488
+ reporter::pass (Expr_T& expr, std::string& message, subtest& subtest)
420
489
  {
421
- current_test_suite->current_test_case.index++;
490
+ // current_test_suite->current_test_case.index++;
422
491
 
423
- output_pass_prefix_ (message);
492
+ output_pass_prefix_ (message, subtest);
424
493
 
425
494
  if (message.empty ())
426
495
  {
@@ -428,7 +497,7 @@ namespace micro_os_plus::micro_test_plus
428
497
  *this << expr;
429
498
  }
430
499
 
431
- output_pass_suffix_ ();
500
+ output_pass_suffix_ (subtest);
432
501
  }
433
502
 
434
503
  /**
@@ -442,20 +511,21 @@ namespace micro_os_plus::micro_test_plus
442
511
  */
443
512
  template <class Expr_T>
444
513
  void
445
- test_reporter::fail (Expr_T& expr, bool abort, std::string& message,
446
- const reflection::source_location& location)
514
+ reporter::fail (Expr_T& expr, bool abort, std::string& message,
515
+ const reflection::source_location& location,
516
+ subtest& subtest)
447
517
  {
448
- current_test_suite->current_test_case.index++;
518
+ // current_test_suite->current_test_case.index++;
449
519
 
450
- const bool hasExpression = type_traits::is_op_v<Expr_T>;
451
- output_fail_prefix_ (message, hasExpression, location);
520
+ const bool hasExpression = type_traits::is_op<Expr_T>;
521
+ output_fail_prefix_ (message, hasExpression, location, subtest);
452
522
 
453
- if constexpr (type_traits::is_op_v<Expr_T>)
523
+ if constexpr (type_traits::is_op<Expr_T>)
454
524
  {
455
525
  *this << expr;
456
526
  }
457
527
 
458
- output_fail_suffix_ (location, abort);
528
+ output_fail_suffix_ (location, abort, subtest);
459
529
  }
460
530
 
461
531
  // --------------------------------------------------------------------------
@@ -18,33 +18,26 @@
18
18
  /**
19
19
  * @file
20
20
  * @brief C++ header file with inline implementations for the µTest++ test
21
- * suite.
21
+ * runner.
22
22
  *
23
23
  * @details
24
- * This header provides the inline implementations for the test suite
25
- * facilities used within the µTest++ framework. It defines the logic for
26
- * constructing and registering test suites, including the binding of callable
27
- * objects and their arguments for flexible test suite definitions.
24
+ * This header provides the inline template implementation for
25
+ * `runner::suite()`, the method used to create and register a named test
26
+ * suite with a `runner` instance. The method constructs a `suite` object
27
+ * on the heap (wrapped in `std::unique_ptr`), transfers ownership to the
28
+ * runner via `register_suite_()`, and the newly created suite runs
29
+ * immediately as part of the registration process.
28
30
  *
29
- * The implementation ensures that each test suite is automatically registered
30
- * with the global test runner upon construction, enabling automated discovery
31
- * and execution of test suites. The use of `std::bind` allows for versatile
32
- * test suite initialisation with arbitrary callable types and arguments.
33
- *
34
- * All definitions reside within the `micro_os_plus::micro_test_plus`
35
- * namespace, maintaining a clear separation from user code and minimising the
36
- * risk of naming conflicts.
37
- *
38
- * The header files are organised within the
39
- * `include/micro-os-plus/micro-test-plus` folder to maintain a structured and
40
- * modular codebase.
31
+ * The implementation is separated into this inline header so that the
32
+ * template definition is visible at every call site without cluttering the
33
+ * main `runner.h` declaration file.
41
34
  *
42
35
  * This file is intended solely for internal use within the framework and
43
36
  * should not be included directly by user code.
44
37
  */
45
38
 
46
- #ifndef MICRO_TEST_PLUS_TEST_SUITE_INLINES_H_
47
- #define MICRO_TEST_PLUS_TEST_SUITE_INLINES_H_
39
+ #ifndef MICRO_TEST_PLUS_TEST_RUNNER_INLINES_H_
40
+ #define MICRO_TEST_PLUS_TEST_RUNNER_INLINES_H_
48
41
 
49
42
  // ----------------------------------------------------------------------------
50
43
 
@@ -52,49 +45,54 @@
52
45
 
53
46
  // ----------------------------------------------------------------------------
54
47
 
55
- #include <stdio.h>
56
- #include <cstring>
57
- // #include "test-runner.h"
58
-
59
- // ----------------------------------------------------------------------------
60
-
61
48
  #if defined(__GNUC__)
62
49
  #pragma GCC diagnostic push
63
50
  #pragma GCC diagnostic ignored "-Waggregate-return"
64
51
  #if defined(__clang__)
65
52
  #pragma clang diagnostic ignored "-Wc++98-compat"
66
53
  #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
54
+ #else // GCC only
55
+ #pragma GCC diagnostic ignored "-Wredundant-tags"
67
56
  #endif
68
57
  #endif
69
58
 
59
+ // ============================================================================
60
+
70
61
  namespace micro_os_plus::micro_test_plus
71
62
  {
72
63
  // --------------------------------------------------------------------------
73
64
 
74
- extern test_runner runner;
75
-
76
- // --------------------------------------------------------------------------
77
-
78
65
  /**
79
66
  * @details
80
- * This constructor initialises a test suite by binding the provided callable
81
- * and its arguments, and registers the suite with the test runner.
82
- *
83
- * The callable is bound using `std::bind`, allowing for flexible test suite
84
- * definitions with arbitrary arguments. Upon construction, the test suite is
85
- * automatically registered with the global runner for execution.
67
+ * Constructs a `suite` object on the heap, binding the callable and any
68
+ * additional arguments, then transfers ownership to the runner via
69
+ * `register_suite_()`. The suite runs immediately as part of the
70
+ * registration process.
86
71
  */
87
72
  template <typename Callable_T, typename... Args_T>
88
- test_suite::test_suite (const char* name, Callable_T&& callable,
89
- Args_T&&... arguments)
90
- : test_suite_base{ name },
91
- callable_{ std::bind (callable, arguments...) }
73
+ void
74
+ runner::suite (const char* name, Callable_T&& callable,
75
+ Args_T&&... arguments)
92
76
  {
93
- #if defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
94
- printf ("%s\n", __PRETTY_FUNCTION__);
77
+ #if defined(MICRO_OS_PLUS_TRACE) \
78
+ && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
79
+ #if defined(__GNUC__)
80
+ #pragma GCC diagnostic push
81
+ #if defined(__clang__)
82
+ #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
83
+ #endif
84
+ #endif
85
+ trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name);
86
+ #if defined(__GNUC__)
87
+ #pragma GCC diagnostic pop
88
+ #endif
95
89
  #endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
96
90
 
97
- runner.register_test_suite (this);
91
+ auto child_suite = std::make_unique<class suite> (
92
+ name, *this, std::forward<Callable_T> (callable),
93
+ std::forward<Args_T> (arguments)...);
94
+
95
+ register_suite_ (std::move (child_suite));
98
96
  }
99
97
 
100
98
  // --------------------------------------------------------------------------
@@ -110,6 +108,6 @@ namespace micro_os_plus::micro_test_plus
110
108
 
111
109
  // ----------------------------------------------------------------------------
112
110
 
113
- #endif // MICRO_TEST_PLUS_TEST_SUITE_INLINES_H_
111
+ #endif // MICRO_TEST_PLUS_TEST_RUNNER_INLINES_H_
114
112
 
115
113
  // ----------------------------------------------------------------------------