@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,1013 @@
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 declarations for the µTest++ test suite.
21
+ *
22
+ * @details
23
+ * This header provides the declarations for the test suite facilities used
24
+ * within the µTest++ framework. It defines the interfaces for constructing,
25
+ * registering, and managing test suites and their associated test cases. The
26
+ * core classes, `test_node` and `suite`, offer mechanisms for
27
+ * tracking test case execution, managing counters for successful and failed
28
+ * checks, and supporting automated registration and discovery of test suites.
29
+ *
30
+ * The design ensures that test suites are non-copyable and non-movable,
31
+ * maintaining unique ownership and consistent state. Flexible support for
32
+ * callable objects enables a wide range of test suite definitions,
33
+ * facilitating expressive and maintainable test organisation across embedded
34
+ * and general C++ projects.
35
+ *
36
+ * All definitions reside within the `micro_os_plus::micro_test_plus`
37
+ * namespace, ensuring clear separation from user code and minimising the risk
38
+ * of naming conflicts.
39
+ *
40
+ * The header files are organised within the
41
+ * `include/micro-os-plus/micro-test-plus` folder to maintain a structured and
42
+ * modular codebase.
43
+ *
44
+ * This file is intended solely for internal use within the framework and
45
+ * should not be included directly by user code.
46
+ */
47
+
48
+ #ifndef MICRO_TEST_PLUS_TEST_H_
49
+ #define MICRO_TEST_PLUS_TEST_H_
50
+
51
+ // ----------------------------------------------------------------------------
52
+
53
+ #ifdef __cplusplus
54
+
55
+ // ----------------------------------------------------------------------------
56
+
57
+ #include <functional>
58
+ #include <memory>
59
+
60
+ #include "runner-totals.h"
61
+ #include "type-traits.h"
62
+ #include "timings.h"
63
+ #include "reflection.h"
64
+
65
+ // ----------------------------------------------------------------------------
66
+
67
+ #if defined(__GNUC__)
68
+ #pragma GCC diagnostic push
69
+ #pragma GCC diagnostic ignored "-Wpadded"
70
+ #if defined(__clang__)
71
+ #pragma clang diagnostic ignored "-Wc++98-compat"
72
+ #else // GCC only
73
+ #pragma GCC diagnostic ignored "-Wsuggest-final-types"
74
+ #pragma GCC diagnostic ignored "-Wsuggest-final-methods"
75
+ #pragma GCC diagnostic ignored "-Wredundant-tags"
76
+ #endif
77
+ #endif
78
+
79
+ // =============================================================================
80
+
81
+ namespace micro_os_plus::micro_test_plus
82
+ {
83
+ // --------------------------------------------------------------------------
84
+
85
+ class runner;
86
+ class static_runner;
87
+ class reporter;
88
+ class runner_totals;
89
+ class subtest;
90
+ class suite;
91
+ class static_suite;
92
+
93
+ namespace detail
94
+ {
95
+ // ========================================================================
96
+
97
+ /**
98
+ * @brief Converts a `static_runner` reference to a `runner` reference.
99
+ *
100
+ * @details
101
+ * This declaration breaks the include-order cycle between `test` and
102
+ * `runner` headers. The definition is provided in a translation unit where
103
+ * both types are complete, so the conversion remains type-safe.
104
+ *
105
+ * @param static_runner_ref The source `static_runner` reference.
106
+ * @return The same object viewed as its `runner` base.
107
+ */
108
+ runner&
109
+ to_runner (static_runner& static_runner_ref) noexcept;
110
+
111
+ /**
112
+ * @brief Registers a static suite with a static runner.
113
+ *
114
+ * @details
115
+ * This declaration allows `test-inlines.h` to request registration
116
+ * without requiring the complete `static_runner` type in that header.
117
+ *
118
+ * @param static_runner_ref The destination static runner.
119
+ * @param static_suite_ref The static suite to register.
120
+ */
121
+ void
122
+ register_static_suite (static_runner& static_runner_ref,
123
+ static_suite& static_suite_ref);
124
+
125
+ /**
126
+ * @brief Base class for runners and runable tests.
127
+ *
128
+ * @details
129
+ * The `test_node` class provides the foundational interface for
130
+ * managing test within the µTest++ framework. It maintains counters
131
+ * for successful and failed checks, tracks test cases, and offers methods
132
+ * for marking the commencement and completion of test cases and suites.
133
+ *
134
+ * This class ensures consistent state management and reporting for all
135
+ * derived classes. It also provides utility methods for querying the
136
+ * node's name, the number of successful and failed checks, the number of
137
+ * test cases, and the overall result of the node.
138
+ *
139
+ * All members and methods are defined within the
140
+ * `micro_os_plus::micro_test_plus` namespace, ensuring clear separation
141
+ * from user code and minimising the risk of naming conflicts.
142
+ *
143
+ * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
144
+ */
145
+ class test_node
146
+ {
147
+ public:
148
+ /**
149
+ * @brief Constructs a test node.
150
+ *
151
+ * @param [in] name The test node name.
152
+ */
153
+ test_node (const char* name);
154
+
155
+ /**
156
+ * @brief Deleted copy constructor to prevent copying.
157
+ */
158
+ test_node (const test_node&) = delete;
159
+
160
+ /**
161
+ * @brief Deleted move constructor to prevent moving.
162
+ */
163
+ test_node (test_node&&) = delete;
164
+
165
+ /**
166
+ * @brief Deleted copy assignment operator to prevent copying.
167
+ */
168
+ test_node&
169
+ operator= (const test_node&)
170
+ = delete;
171
+
172
+ /**
173
+ * @brief Deleted move assignment operator to prevent moving.
174
+ */
175
+ test_node&
176
+ operator= (test_node&&)
177
+ = delete;
178
+
179
+ /**
180
+ * @brief Virtual destructor for the test_node class.
181
+ */
182
+ virtual ~test_node ();
183
+
184
+ // ----------------------------------------------------------------------
185
+
186
+ /**
187
+ * @brief Gets the node name.
188
+ *
189
+ * @par Parameters
190
+ * None.
191
+ * @return A pointer to the null-terminated test node name.
192
+ */
193
+ [[nodiscard]] const char*
194
+ name (void) const noexcept;
195
+
196
+ public:
197
+ /**
198
+ * @brief Gets the totals for the test.
199
+ *
200
+ * @par Parameters
201
+ * None.
202
+ * @return A reference to the runner_totals instance.
203
+ */
204
+ [[nodiscard]] runner_totals&
205
+ totals () noexcept;
206
+
207
+ /**
208
+ * @brief Gets the totals for the test (const overload).
209
+ *
210
+ * @par Parameters
211
+ * None.
212
+ * @return A const reference to the runner_totals instance.
213
+ */
214
+ [[nodiscard]] const runner_totals&
215
+ totals () const noexcept;
216
+
217
+ protected:
218
+ /**
219
+ * @brief The test node name.
220
+ *
221
+ * @note Derived classes may access this member directly in
222
+ * addition to the public `name()` getter.
223
+ */
224
+ const char* name_;
225
+
226
+ /**
227
+ * @brief Totals for the test node, including nested cases.
228
+ */
229
+ runner_totals totals_;
230
+ };
231
+
232
+ // ========================================================================
233
+
234
+ /**
235
+ * @brief Non-template base for all runnable objects (suites and subtests).
236
+ *
237
+ * @details
238
+ * `runnable_base` extends `test_node` with the state that is shared by
239
+ * every runnable object but does not depend on the CRTP self-type:
240
+ * - a reference to the owning `runner`,
241
+ * - the object's own index within its parent container,
242
+ * - a sequential subtest index used when creating nested subtests, and
243
+ * - an owning vector of child `subtest` instances.
244
+ *
245
+ * Concrete runnable classes (`suite`, `subtest`) derive from
246
+ * `runnable<Self_T>` which in turn derives from `runnable_base`.
247
+ *
248
+ * The class is non-copyable and non-movable to preserve unique ownership
249
+ * and consistent state throughout the test session.
250
+ *
251
+ * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
252
+ */
253
+ class runnable_base : public test_node
254
+ {
255
+ public:
256
+ /**
257
+ * @brief Constructs a `runnable_base` with a name, runner, and index.
258
+ *
259
+ * @param name The name used in reports.
260
+ * @param runner The test runner managing this object.
261
+ * @param own_index The positional index of this object within its
262
+ * parent.
263
+ */
264
+ runnable_base (const char* name, runner& runner, size_t own_index);
265
+
266
+ /**
267
+ * @brief Deleted copy constructor to prevent copying.
268
+ */
269
+ runnable_base (const runnable_base&) = delete;
270
+
271
+ /**
272
+ * @brief Deleted move constructor to prevent moving.
273
+ */
274
+ runnable_base (runnable_base&&) = delete;
275
+
276
+ /**
277
+ * @brief Deleted copy assignment operator to prevent copying.
278
+ */
279
+ runnable_base&
280
+ operator= (const runnable_base&)
281
+ = delete;
282
+
283
+ /**
284
+ * @brief Deleted move assignment operator to prevent moving.
285
+ */
286
+ runnable_base&
287
+ operator= (runnable_base&&)
288
+ = delete;
289
+
290
+ /**
291
+ * @brief Virtual destructor.
292
+ */
293
+ virtual ~runnable_base () override;
294
+
295
+ // ----------------------------------------------------------------------
296
+
297
+ /**
298
+ * @brief Returns the positional index of this object within its parent.
299
+ *
300
+ * @par Parameters
301
+ * None.
302
+ * @return The one-based own index.
303
+ */
304
+ [[nodiscard]] size_t
305
+ own_index () const noexcept;
306
+
307
+ /**
308
+ * @brief Sets the positional index of this object within its parent.
309
+ *
310
+ * @note This overload follows the same-name getter/setter pattern
311
+ * used throughout the framework: the getter is the `const` overload
312
+ * and the setter is the non-`const` single-argument overload.
313
+ *
314
+ * @param index The new index value.
315
+ * @par Returns
316
+ * Nothing.
317
+ */
318
+ void
319
+ own_index (size_t index) noexcept;
320
+
321
+ /**
322
+ * @brief Returns the index of the most recently created child subtest.
323
+ *
324
+ * @par Parameters
325
+ * None.
326
+ * @return The current child subtest sequential index.
327
+ */
328
+ [[nodiscard]] size_t
329
+ current_subtest_index () const noexcept;
330
+
331
+ /**
332
+ * @brief Increments and returns the child subtest sequential index.
333
+ *
334
+ * @par Parameters
335
+ * None.
336
+ * @return The new index value after incrementing.
337
+ */
338
+ size_t
339
+ increment_subtest_index () noexcept;
340
+
341
+ /**
342
+ * @brief Returns the number of direct child subtests owned by this node.
343
+ *
344
+ * @par Parameters
345
+ * None.
346
+ * @return The number of child subtests.
347
+ */
348
+ [[nodiscard]] size_t
349
+ children_subtests_count (void) const noexcept;
350
+
351
+ /**
352
+ * @brief Gets the test reporter associated with this test runnable.
353
+ *
354
+ * @par Parameters
355
+ * None.
356
+ * @return A reference to the test reporter.
357
+ */
358
+ [[nodiscard]] class reporter&
359
+ reporter (void) const noexcept;
360
+
361
+ /**
362
+ * @brief Aborts test execution via the owning runner.
363
+ *
364
+ * @param sl The source location from which the abort is triggered.
365
+ * @par Returns
366
+ * Does not return.
367
+ */
368
+ [[noreturn]] void
369
+ abort (const reflection::source_location& sl
370
+ = reflection::source_location::current ());
371
+
372
+ /**
373
+ * @brief Gets the test runner associated with this test runnable.
374
+ *
375
+ * @par Parameters
376
+ * None.
377
+ * @return A reference to the test runner.
378
+ */
379
+ [[nodiscard]] class runner&
380
+ runner (void) const noexcept;
381
+
382
+ protected:
383
+ /**
384
+ * @brief Registers a newly constructed child subtest and executes it
385
+ * immediately.
386
+ *
387
+ * @param child_test Owning pointer to the newly created `subtest`.
388
+ * @param suite The parent `suite` to which execution results are
389
+ * reported.
390
+ * @par Returns
391
+ * Nothing.
392
+ */
393
+ void
394
+ after_subtest_create_ (std::unique_ptr<subtest> child_test,
395
+ suite& suite);
396
+
397
+ protected:
398
+ /**
399
+ * @brief Reference to the test runner that owns this object.
400
+ */
401
+ class runner& runner_;
402
+
403
+ /**
404
+ * @brief The test index, counting from 1.
405
+ */
406
+ size_t own_index_;
407
+
408
+ /**
409
+ * @brief The subtest index, counting from 1.
410
+ *
411
+ * @details
412
+ * This index is used for reporting and tracking the execution order of
413
+ * subtests within a suite, especially when nested subtests are
414
+ * involved. It is incremented for each subtest created, allowing for
415
+ * clear identification of subtests in reports and diagnostics.
416
+ */
417
+ size_t current_subtest_index_ = 0;
418
+
419
+ /**
420
+ * @brief Owning collection of direct child subtests.
421
+ *
422
+ * @details
423
+ * Each call to `test()` appends a new `subtest` to this vector and
424
+ * runs it immediately. The vector retains ownership for the lifetime of
425
+ * the parent runnable.
426
+ */
427
+ std::vector<std::unique_ptr<subtest>> children_subtests_;
428
+ };
429
+
430
+ // ========================================================================
431
+
432
+ /**
433
+ * @brief CRTP base class factoring out callable storage, rule-of-five, and
434
+ * `run()` logic shared by `subtest` and `suite`.
435
+ *
436
+ * @tparam Self_T The concrete derived class type (CRTP pattern). The
437
+ * stored callable receives a `Self_T&` reference when the test is
438
+ * executed.
439
+ *
440
+ * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
441
+ */
442
+ template <typename Self_T>
443
+ class runnable : public detail::runnable_base
444
+ {
445
+ public:
446
+ /**
447
+ * @brief Class template constructor.
448
+ *
449
+ * @tparam Callable_T The callable type.
450
+ * @tparam Args_T The additional argument types.
451
+ *
452
+ * @param [in] name The test name, used in reports.
453
+ * @param [in] runner The test runner managing this test.
454
+ * @param [in] own_index The test index within the runner.
455
+ * @param [in] callable The callable invoked when the test runs.
456
+ * @param [in] arguments Additional arguments forwarded to the callable
457
+ * after the leading `Self_T&` reference.
458
+ */
459
+ template <typename Callable_T, typename... Args_T>
460
+ runnable (const char* name, class runner& runner, size_t own_index,
461
+ Callable_T&& callable, Args_T&&... arguments);
462
+
463
+ /**
464
+ * @brief Deleted copy constructor to prevent copying.
465
+ */
466
+ runnable (const runnable&) = delete;
467
+
468
+ /**
469
+ * @brief Deleted move constructor to prevent moving.
470
+ */
471
+ runnable (runnable&&) = delete;
472
+
473
+ /**
474
+ * @brief Deleted copy assignment operator to prevent copying.
475
+ */
476
+ runnable&
477
+ operator= (const runnable&)
478
+ = delete;
479
+
480
+ /**
481
+ * @brief Deleted move assignment operator to prevent moving.
482
+ */
483
+ runnable&
484
+ operator= (runnable&&)
485
+ = delete;
486
+
487
+ /**
488
+ * @brief Virtual destructor.
489
+ */
490
+ virtual ~runnable () override;
491
+
492
+ // ----------------------------------------------------------------------
493
+
494
+ /**
495
+ * @brief Runs the test function by invoking the stored callable with the
496
+ * derived self instance.
497
+ *
498
+ * @par Parameters
499
+ * None.
500
+ * @par Returns
501
+ * Nothing.
502
+ */
503
+ virtual void
504
+ run (void)
505
+ = 0;
506
+
507
+ protected:
508
+ /**
509
+ * @brief Callable storing the test body and any bound arguments.
510
+ * Invoked with a reference to the derived `Self_T` instance.
511
+ */
512
+ std::function<void (Self_T&)> callable_;
513
+ };
514
+
515
+ // ------------------------------------------------------------------------
516
+ } // namespace detail
517
+
518
+ // ==========================================================================
519
+
520
+ /**
521
+ * @ingroup micro-test-plus-test-case
522
+ * @brief A named, runnable test case that lives inside a `suite`.
523
+ *
524
+ * @details
525
+ * `subtest` represents a single, named test case or a nested group of
526
+ * checks within a parent `suite` or `subtest`. It is constructed by calling
527
+ * `suite::test()` or `subtest::test()`, both of which create the object,
528
+ * immediately execute its callable body via `run()`, and register the
529
+ * result with the parent node.
530
+ *
531
+ * The body of the subtest is supplied as a callable (typically a lambda)
532
+ * that receives a `subtest&` reference as its first argument. Inside the
533
+ * body, `expect()` and `assume()` are used to evaluate conditions and
534
+ * record the results. Subtests may be nested to an arbitrary depth.
535
+ *
536
+ * The class is non-copyable and non-movable to preserve unique ownership
537
+ * and consistent state throughout the test session.
538
+ *
539
+ * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
540
+ */
541
+ class subtest : public detail::runnable<subtest>
542
+ {
543
+ public:
544
+ /**
545
+ * @brief Constructs a subtest with a name, runner, parent suite, index,
546
+ * nesting depth, and callable.
547
+ *
548
+ * @tparam Callable_T The type of a callable object.
549
+ * @tparam Args_T The types of the callable arguments.
550
+ *
551
+ * @param [in] name The subtest name or description, used in reports.
552
+ * @param [in] runner The test runner managing this subtest.
553
+ * @param [in] parent_suite The suite that owns this subtest.
554
+ * @param [in] own_index The one-based positional index within the parent.
555
+ * @param [in] nesting_depth The depth of nesting; 1 for top-level
556
+ * subtests.
557
+ * @param [in] callable A generic callable object, usually a lambda,
558
+ * invoked when the subtest executes.
559
+ * @param [in] arguments A possibly empty list of arguments forwarded to
560
+ * the callable after the leading `subtest&` reference.
561
+ */
562
+ template <typename Callable_T, typename... Args_T>
563
+ subtest (const char* name, class runner& runner, suite& parent_suite,
564
+ size_t own_index, size_t nesting_depth, Callable_T&& callable,
565
+ Args_T&&... arguments);
566
+
567
+ /**
568
+ * @brief Deleted copy constructor to prevent copying.
569
+ */
570
+ subtest (const subtest&) = delete;
571
+
572
+ /**
573
+ * @brief Deleted move constructor to prevent moving.
574
+ */
575
+ subtest (subtest&&) = delete;
576
+
577
+ /**
578
+ * @brief Deleted copy assignment operator to prevent copying.
579
+ */
580
+ subtest&
581
+ operator= (const subtest&)
582
+ = delete;
583
+
584
+ /**
585
+ * @brief Deleted move assignment operator to prevent moving.
586
+ */
587
+ subtest&
588
+ operator= (subtest&&)
589
+ = delete;
590
+
591
+ /**
592
+ * @brief Virtual destructor.
593
+ */
594
+ virtual ~subtest () override;
595
+
596
+ // ------------------------------------------------------------------------
597
+
598
+ /**
599
+ * @brief Adds a test case to the suite.
600
+ *
601
+ * @tparam Callable_T The type of a callable object.
602
+ * @tparam Args_T The types of the callable arguments.
603
+ *
604
+ * @param [in] name The test case name or description, used in reports.
605
+ * @param [in] callable A generic callable object, usually a lambda,
606
+ * invoked to perform the test.
607
+ * @param [in] arguments A possibly empty list of arguments to be passed to
608
+ * the callable.
609
+ */
610
+ template <typename Callable_T, typename... Args_T>
611
+ void
612
+ test (const char* name, Callable_T&& callable, Args_T&&... arguments);
613
+
614
+ // ------------------------------------------------------------------------
615
+
616
+ /**
617
+ * @ingroup micro-test-plus-expectations
618
+ * @brief Evaluate a generic condition and report the results.
619
+ *
620
+ * @tparam Expr_T The type of the custom expression.
621
+ *
622
+ * @par Constraints
623
+ * Enabled only if `Expr_T` is derived from `detail::op` or
624
+ * is convertible to `bool` (enforced via a C++20 `requires` clause).
625
+ *
626
+ * @param [in] expr Logical expression to evaluate.
627
+ * @param [in] sl Optional source location, defaulting to the current line.
628
+ * @return An output stream to write optional messages.
629
+ */
630
+ template <class Expr_T>
631
+ requires type_traits::checkable<Expr_T>
632
+ auto
633
+ expect (const Expr_T& expr, const reflection::source_location& sl
634
+ = reflection::source_location::current ());
635
+
636
+ /**
637
+ * @ingroup micro-test-plus-assumptions
638
+ * @brief Check a condition and, if false, abort test execution.
639
+ *
640
+ * @tparam Expr_T The type of the custom expression.
641
+ *
642
+ * @par Constraints
643
+ * Enabled only if `Expr_T` is derived from `detail::op` or
644
+ * is convertible to `bool` (enforced via a C++20 `requires` clause).
645
+ *
646
+ * @param [in] expr Logical expression to evaluate.
647
+ * @param [in] sl Optional source location, defaulting to the current line.
648
+ * @return An output stream to write optional messages.
649
+ */
650
+ template <class Expr_T>
651
+ requires type_traits::checkable<Expr_T>
652
+ auto
653
+ assume (const Expr_T& expr, const reflection::source_location& sl
654
+ = reflection::source_location::current ());
655
+
656
+ // ------------------------------------------------------------------------
657
+
658
+ /**
659
+ * @brief Executes the subtest body by invoking the stored callable.
660
+ *
661
+ * @par Parameters
662
+ * None.
663
+ * @par Returns
664
+ * Nothing.
665
+ */
666
+ virtual void
667
+ run (void) override;
668
+
669
+ /**
670
+ * @brief Returns the nesting depth of this subtest.
671
+ *
672
+ * @par Parameters
673
+ * None.
674
+ * @return The nesting depth (1 = top-level).
675
+ */
676
+ [[nodiscard]] size_t
677
+ nesting_depth () const noexcept;
678
+
679
+ protected:
680
+ /**
681
+ * @brief Reference to the parent suite that owns this subtest.
682
+ */
683
+ suite& parent_suite_;
684
+
685
+ /**
686
+ * @brief The nesting depth of this subtest within the suite.
687
+ */
688
+ size_t nesting_depth_;
689
+ };
690
+
691
+ // ==========================================================================
692
+
693
+ /**
694
+ * @ingroup micro-test-plus-test-suites
695
+ * @brief A named, runnable test suite registered with the test runner.
696
+ *
697
+ * @details
698
+ * `suite` represents a top-level named group of related test cases within
699
+ * the µTest++ framework. It is created by calling `runner::suite()`, which
700
+ * constructs the object, stores it in the runner's collection, and runs it
701
+ * immediately. Each suite records its own timing information and propagates
702
+ * its results to the owning `runner`.
703
+ *
704
+ * The body of a suite is supplied as a callable (typically a lambda) that
705
+ * receives a `suite&` reference as its first argument. Inside the body,
706
+ * `suite::test()` is called to create and run individual subtests.
707
+ *
708
+ * The class is non-copyable and non-movable to preserve unique ownership
709
+ * and consistent state throughout the test session.
710
+ *
711
+ * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
712
+ */
713
+ class suite : public detail::runnable<suite>
714
+ {
715
+ public:
716
+ /**
717
+ * @brief Constructs a suite with a name, runner, and callable body.
718
+ *
719
+ * @tparam Callable_T The type of the callable object.
720
+ * @tparam Args_T The types of any additional callable arguments.
721
+ *
722
+ * @param [in] name The suite name or description, used in reports.
723
+ * @param [in] runner The test runner managing this suite.
724
+ * @param [in] callable A generic callable object, usually a lambda,
725
+ * invoked when the suite executes. Its first parameter must be
726
+ * `suite&`.
727
+ * @param [in] arguments A possibly empty list of arguments forwarded to
728
+ * the callable after the leading `suite&` reference.
729
+ */
730
+ template <typename Callable_T, typename... Args_T>
731
+ suite (const char* name, class runner& runner, Callable_T&& callable,
732
+ Args_T&&... arguments);
733
+
734
+ /**
735
+ * @brief Deleted copy constructor to prevent copying.
736
+ */
737
+ suite (const suite&) = delete;
738
+
739
+ /**
740
+ * @brief Deleted move constructor to prevent moving.
741
+ */
742
+ suite (suite&&) = delete;
743
+
744
+ /**
745
+ * @brief Deleted copy assignment operator to prevent copying.
746
+ */
747
+ suite&
748
+ operator= (const suite&)
749
+ = delete;
750
+
751
+ /**
752
+ * @brief Deleted move assignment operator to prevent moving.
753
+ */
754
+ suite&
755
+ operator= (suite&&)
756
+ = delete;
757
+
758
+ /**
759
+ * @brief Virtual destructor.
760
+ */
761
+ virtual ~suite () override;
762
+
763
+ // ------------------------------------------------------------------------
764
+
765
+ /**
766
+ * @brief Adds a test case to the suite.
767
+ *
768
+ * @tparam Callable_T The type of a callable object.
769
+ * @tparam Args_T The types of the callable arguments.
770
+ *
771
+ * @param [in] name The test case name or description, used in reports.
772
+ * @param [in] callable A generic callable object, usually a lambda,
773
+ * invoked to perform the test.
774
+ * @param [in] arguments A possibly empty list of arguments to be passed to
775
+ * the callable.
776
+ */
777
+ template <typename Callable_T, typename... Args_T>
778
+ void
779
+ test (const char* name, Callable_T&& callable, Args_T&&... arguments);
780
+
781
+ // ------------------------------------------------------------------------
782
+
783
+ /**
784
+ * @brief Gets the timings for this suite.
785
+ *
786
+ * @par Parameters
787
+ * None.
788
+ * @return A reference to the timestamps instance.
789
+ */
790
+ [[nodiscard]] detail::timestamps&
791
+ timings () noexcept;
792
+
793
+ /**
794
+ * @brief Gets the timings for this suite (const overload).
795
+ *
796
+ * @par Parameters
797
+ * None.
798
+ * @return A const reference to the timestamps instance.
799
+ */
800
+ [[nodiscard]] const detail::timestamps&
801
+ timings () const noexcept;
802
+
803
+ /**
804
+ * @brief Executes the suite body by invoking the stored callable.
805
+ *
806
+ * @par Parameters
807
+ * None.
808
+ * @par Returns
809
+ * Nothing.
810
+ */
811
+ virtual void
812
+ run (void) override;
813
+
814
+ protected:
815
+ /**
816
+ * @brief Timing measurements for this suite's execution.
817
+ */
818
+ detail::timestamps timings_;
819
+ };
820
+
821
+ // ==========================================================================
822
+
823
+ /**
824
+ * @brief The implicit top-level suite owned by every `runner` instance.
825
+ *
826
+ * @details
827
+ * `top_suite` is a thin specialisation of `suite` used as the implicit
828
+ * root context for the `runner`. It is created by the `runner` constructor
829
+ * and is available to user code via `runner::initialise()`, which returns
830
+ * a reference to it. Unlike regular `suite` objects, `top_suite` is not
831
+ * stored in the runner's child-suite vector; instead it is a direct member
832
+ * of `runner`.
833
+ *
834
+ * Users do not normally construct `top_suite` directly.
835
+ *
836
+ * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
837
+ */
838
+ class top_suite : public suite
839
+ {
840
+ public:
841
+ // Expose the accessor for the suite name from the base test_node class,
842
+ // since the top_suite may need to change its name after construction, and
843
+ // the base class provides the necessary interface for that purpose.
844
+ using detail::test_node::name;
845
+
846
+ /**
847
+ * @brief Constructs the top-level suite with a name and runner reference.
848
+ *
849
+ * @param name The suite name used in reports.
850
+ * @param runner The test runner that owns this suite.
851
+ */
852
+ top_suite (const char* name, class runner& runner);
853
+
854
+ /**
855
+ * @brief Deleted copy constructor to prevent copying.
856
+ */
857
+ top_suite (const top_suite&) = delete;
858
+
859
+ /**
860
+ * @brief Deleted move constructor to prevent moving.
861
+ */
862
+ top_suite (top_suite&&) = delete;
863
+
864
+ /**
865
+ * @brief Deleted copy assignment operator to prevent copying.
866
+ */
867
+ top_suite&
868
+ operator= (const top_suite&)
869
+ = delete;
870
+
871
+ /**
872
+ * @brief Deleted move assignment operator to prevent moving.
873
+ */
874
+ top_suite&
875
+ operator= (top_suite&&)
876
+ = delete;
877
+
878
+ /**
879
+ * @brief Virtual destructor.
880
+ */
881
+ virtual ~top_suite () override;
882
+
883
+ /**
884
+ * @brief Sets the name of the top-level suite.
885
+ *
886
+ * @param [in] new_name The new name for the top-level suite.
887
+ */
888
+ void
889
+ name (const char* new_name) noexcept;
890
+ };
891
+
892
+ // ==========================================================================
893
+
894
+ /**
895
+ * @ingroup micro-test-plus-test-suites
896
+ * @brief A test suite designed for static (namespace-scope) registration
897
+ * with a `static_runner`.
898
+ *
899
+ * @details
900
+ * `static_suite` extends `suite` to support the pattern where test suites
901
+ * are declared as namespace-scope objects and therefore constructed before
902
+ * or after the `static_runner` instance, in unspecified
903
+ * static-initialisation order.
904
+ *
905
+ * Upon construction, the suite automatically registers itself with the
906
+ * supplied `static_runner` by calling
907
+ * `static_runner::register_suite_()`. The runner defers execution of all
908
+ * registered static suites until `static_runner::run_suites_()` is invoked,
909
+ * which typically happens inside the implicit `main()` provided by the
910
+ * framework.
911
+ *
912
+ * In addition to the standard callable body inherited from `suite`, a
913
+ * `static_suite` may carry a second, statically-registered callable stored
914
+ * in `static_callable_`. The overridden `run()` method invokes both bodies
915
+ * in sequence, allowing the suite to integrate both dynamic and static
916
+ * registration patterns.
917
+ *
918
+ * The class is non-copyable and non-movable to preserve unique ownership
919
+ * and consistent state throughout the test session.
920
+ *
921
+ * @headerfile micro-test-plus.h <micro-os-plus/micro-test-plus.h>
922
+ */
923
+ class static_suite : public suite
924
+ {
925
+ public:
926
+ /**
927
+ * @brief Class template constructor for static_suite.
928
+ *
929
+ * @tparam Callable_T The type of a callable object.
930
+ * @tparam Args_T The types of the callable arguments.
931
+ *
932
+ * @param [in] name The test suite name or description, used in reports.
933
+ * @param [in] runner The static test runner managing this suite.
934
+ * @param [in] callable A generic callable object, usually a lambda or
935
+ * function, invoked to perform the test suite.
936
+ * @param [in] arguments A possibly empty list of arguments to be passed to
937
+ * the callable.
938
+ */
939
+ template <typename Callable_T, typename... Args_T>
940
+ static_suite (const char* name, static_runner& runner,
941
+ Callable_T&& callable, Args_T&&... arguments);
942
+
943
+ /**
944
+ * @brief Deleted copy constructor to prevent copying.
945
+ */
946
+ static_suite (const static_suite&) = delete;
947
+
948
+ /**
949
+ * @brief Deleted move constructor to prevent moving.
950
+ */
951
+ static_suite (static_suite&&) = delete;
952
+
953
+ /**
954
+ * @brief Deleted copy assignment operator to prevent copying.
955
+ */
956
+ static_suite&
957
+ operator= (const static_suite&)
958
+ = delete;
959
+
960
+ /**
961
+ * @brief Deleted move assignment operator to prevent moving.
962
+ */
963
+ static_suite&
964
+ operator= (static_suite&&)
965
+ = delete;
966
+
967
+ /**
968
+ * @brief Virtual destructor.
969
+ */
970
+ virtual ~static_suite () override;
971
+
972
+ // ------------------------------------------------------------------------
973
+
974
+ /**
975
+ * @brief Executes the static suite body using the stored static callable.
976
+ *
977
+ * @par Parameters
978
+ * None.
979
+ * @par Returns
980
+ * Nothing.
981
+ */
982
+ virtual void
983
+ run (void) override;
984
+
985
+ protected:
986
+ /**
987
+ * @brief Callable storing the static suite body and any bound arguments.
988
+ * Invoked with a reference to the concrete `static_suite` instance.
989
+ */
990
+ std::function<void (static_suite&)> static_callable_;
991
+ };
992
+
993
+ // --------------------------------------------------------------------------
994
+ } // namespace micro_os_plus::micro_test_plus
995
+
996
+ #if defined(__GNUC__)
997
+ #pragma GCC diagnostic pop
998
+ #endif
999
+
1000
+ // ----------------------------------------------------------------------------
1001
+
1002
+ #endif // __cplusplus
1003
+
1004
+ // ============================================================================
1005
+ // Templates & constexpr implementations.
1006
+
1007
+ #include "inlines/test-inlines.h"
1008
+
1009
+ // ----------------------------------------------------------------------------
1010
+
1011
+ #endif // MICRO_TEST_PLUS_TEST_H_
1012
+
1013
+ // ----------------------------------------------------------------------------