@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,555 @@
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
+ * suite.
22
+ *
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.
28
+ *
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.
41
+ *
42
+ * This file is intended solely for internal use within the framework and
43
+ * should not be included directly by user code.
44
+ */
45
+
46
+ #ifndef MICRO_TEST_PLUS_TEST_INLINES_H_
47
+ #define MICRO_TEST_PLUS_TEST_INLINES_H_
48
+
49
+ // ----------------------------------------------------------------------------
50
+
51
+ #ifdef __cplusplus
52
+
53
+ // ----------------------------------------------------------------------------
54
+
55
+ #include <cstdio>
56
+ #include <cstring>
57
+
58
+ #if defined(MICRO_OS_PLUS_TRACE)
59
+ #include <micro-os-plus/diag/trace.h>
60
+ #endif // MICRO_OS_PLUS_TRACE
61
+
62
+ #include "micro-os-plus/micro-test-plus/deferred-reporter.h"
63
+ #include "micro-os-plus/micro-test-plus/reporter.h"
64
+
65
+ // ----------------------------------------------------------------------------
66
+
67
+ #if defined(__GNUC__)
68
+ #pragma GCC diagnostic push
69
+ #pragma GCC diagnostic ignored "-Waggregate-return"
70
+ #if defined(__clang__)
71
+ #pragma clang diagnostic ignored "-Wc++98-compat"
72
+ #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
73
+ #else // GCC only
74
+ #pragma GCC diagnostic ignored "-Wredundant-tags"
75
+ #endif
76
+ #endif
77
+
78
+ // ============================================================================
79
+
80
+ namespace micro_os_plus::micro_test_plus
81
+ {
82
+ namespace detail
83
+ {
84
+ // ========================================================================
85
+
86
+ /**
87
+ * @details
88
+ * Returns a pointer to the null-terminated name stored in `name_`.
89
+ */
90
+ inline const char*
91
+ test_node::name (void) const noexcept
92
+ {
93
+ return name_;
94
+ }
95
+
96
+ /**
97
+ * @details
98
+ * Returns a reference to the `runner_totals` member.
99
+ */
100
+ inline runner_totals&
101
+ test_node::totals () noexcept
102
+ {
103
+ return totals_;
104
+ }
105
+
106
+ /**
107
+ * @details
108
+ * Returns a const reference to the `runner_totals` member.
109
+ */
110
+ inline const runner_totals&
111
+ test_node::totals () const noexcept
112
+ {
113
+ return totals_;
114
+ }
115
+
116
+ // ========================================================================
117
+
118
+ /**
119
+ * @details
120
+ * Returns the one-based positional index of this object within its parent.
121
+ */
122
+ inline size_t
123
+ runnable_base::own_index () const noexcept
124
+ {
125
+ return own_index_;
126
+ }
127
+
128
+ /**
129
+ * @details
130
+ * Sets the positional index of this object within its parent.
131
+ */
132
+ inline void
133
+ runnable_base::own_index (size_t index) noexcept
134
+ {
135
+ own_index_ = index;
136
+ }
137
+
138
+ /**
139
+ * @details
140
+ * Returns the sequential index of the most recently created child subtest.
141
+ */
142
+ inline size_t
143
+ runnable_base::current_subtest_index () const noexcept
144
+ {
145
+ return current_subtest_index_;
146
+ }
147
+
148
+ /**
149
+ * @details
150
+ * Each call to `test()` invokes this method before constructing the new
151
+ * `subtest`, so the index values form a strictly increasing, one-based
152
+ * sequence.
153
+ */
154
+ inline size_t
155
+ runnable_base::increment_subtest_index () noexcept
156
+ {
157
+ return ++current_subtest_index_;
158
+ }
159
+
160
+ /**
161
+ * @details
162
+ * Returns the number of child subtests owned by this node.
163
+ */
164
+ inline size_t
165
+ runnable_base::children_subtests_count (void) const noexcept
166
+ {
167
+ return children_subtests_.size ();
168
+ }
169
+
170
+ /**
171
+ * @details
172
+ * Returns a reference to the owning test runner.
173
+ */
174
+ inline class runner&
175
+ runnable_base::runner (void) const noexcept
176
+ {
177
+ return runner_;
178
+ }
179
+
180
+ // ========================================================================
181
+
182
+ /**
183
+ * @details
184
+ * Binds the callable and its arguments into the stored `callable_`
185
+ * function object. When `run()` is called, the stored function is invoked
186
+ * with a reference to the derived `Self_T` instance as its first argument,
187
+ * followed by the bound arguments.
188
+ */
189
+ template <typename Self_T>
190
+ template <typename Callable_T, typename... Args_T>
191
+ runnable<Self_T>::runnable (const char* name, class runner& runner,
192
+ size_t own_index, Callable_T&& callable,
193
+ Args_T&&... arguments)
194
+ : runnable_base{ name, runner, own_index }
195
+ {
196
+ // When there are no extra arguments the callable already has the
197
+ // signature void(Self_T&), so store it directly. Only use std::bind when
198
+ // additional arguments must be pre-bound, to avoid triggering a GCC ARM
199
+ // bug in
200
+ // __is_nothrow_invocable<_Bind<...>, Self_T&> (GCC 15.2.1).
201
+ if constexpr (sizeof...(arguments) == 0)
202
+ {
203
+ callable_ = std::forward<Callable_T> (callable);
204
+ }
205
+ else
206
+ {
207
+ callable_ = std::bind (std::forward<Callable_T> (callable),
208
+ std::placeholders::_1,
209
+ std::forward<Args_T> (arguments)...);
210
+ }
211
+
212
+ #if defined(MICRO_OS_PLUS_TRACE) \
213
+ && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
214
+ #if defined(__GNUC__)
215
+ #pragma GCC diagnostic push
216
+ #if defined(__clang__)
217
+ #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
218
+ #endif
219
+ #endif
220
+ trace::printf ("%s '%s' %zu\n", __PRETTY_FUNCTION__, name, own_index_);
221
+ #if defined(__GNUC__)
222
+ #pragma GCC diagnostic pop
223
+ #endif
224
+ #endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
225
+ }
226
+
227
+ /**
228
+ * @details
229
+ * No-op in production builds. When tracing is enabled via
230
+ * `MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS`, emits a trace
231
+ * message identifying the instance being destroyed.
232
+ */
233
+ template <typename Self_T>
234
+ runnable<Self_T>::~runnable ()
235
+ {
236
+ #if defined(MICRO_OS_PLUS_TRACE) \
237
+ && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
238
+ #if defined(__GNUC__)
239
+ #pragma GCC diagnostic push
240
+ #if defined(__clang__)
241
+ #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
242
+ #endif
243
+ #endif
244
+ trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
245
+ #if defined(__GNUC__)
246
+ #pragma GCC diagnostic pop
247
+ #endif
248
+ #endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
249
+ }
250
+
251
+ // ------------------------------------------------------------------------
252
+ } // namespace detail
253
+
254
+ // ==========================================================================
255
+
256
+ /**
257
+ * @details
258
+ * Delegates to `runnable`, which binds the callable with
259
+ * its arguments.
260
+ */
261
+ template <typename Callable_T, typename... Args_T>
262
+ subtest::subtest (const char* name, class runner& runner,
263
+ suite& parent_suite, size_t own_index,
264
+ size_t nesting_depth, Callable_T&& callable,
265
+ Args_T&&... arguments)
266
+ : runnable<subtest>{ name, runner, own_index,
267
+ std::forward<Callable_T> (callable),
268
+ std::forward<Args_T> (arguments)... },
269
+ parent_suite_{ parent_suite }, nesting_depth_{ nesting_depth }
270
+ {
271
+ #if defined(MICRO_OS_PLUS_TRACE) \
272
+ && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
273
+ #if defined(__GNUC__)
274
+ #pragma GCC diagnostic push
275
+ #if defined(__clang__)
276
+ #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
277
+ #endif
278
+ #endif
279
+ trace::printf ("%s '%s' %zu %zu\n", __PRETTY_FUNCTION__, name, own_index_,
280
+ nesting_depth_);
281
+ #if defined(__GNUC__)
282
+ #pragma GCC diagnostic pop
283
+ #endif
284
+ #endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
285
+ }
286
+
287
+ /**
288
+ * @details
289
+ * Allocates a child `subtest` on the heap, incrementing the subtest index
290
+ * and deepening the nesting level by one relative to this subtest's depth,
291
+ * then transfers ownership to the framework via `after_subtest_create_()`.
292
+ */
293
+ template <typename Callable_T, typename... Args_T>
294
+ void
295
+ subtest::test (const char* name, Callable_T&& callable,
296
+ Args_T&&... arguments)
297
+ {
298
+ #if defined(MICRO_OS_PLUS_TRACE) \
299
+ && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
300
+ #if defined(__GNUC__)
301
+ #pragma GCC diagnostic push
302
+ #if defined(__clang__)
303
+ #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
304
+ #endif
305
+ #endif
306
+ trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name);
307
+ #if defined(__GNUC__)
308
+ #pragma GCC diagnostic pop
309
+ #endif
310
+ #endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
311
+
312
+ size_t own_index = increment_subtest_index ();
313
+ auto child_subtest = std::make_unique<subtest> (
314
+ name, runner (), parent_suite_, own_index, nesting_depth_ + 1,
315
+ std::forward<Callable_T> (callable),
316
+ std::forward<Args_T> (arguments)...);
317
+
318
+ after_subtest_create_ (std::move (child_subtest), parent_suite_);
319
+ }
320
+
321
+ /**
322
+ * @details
323
+ * Constructs and returns a `deferred_reporter<Expr_T>` with `abort = false`.
324
+ * The reporter evaluates the condition and records a pass or fail when
325
+ * it is destroyed at the end of the expression statement.
326
+ */
327
+ template <class Expr_T>
328
+ requires type_traits::checkable<Expr_T>
329
+ auto
330
+ subtest::expect (const Expr_T& expr, const reflection::source_location& sl)
331
+ {
332
+ return detail::deferred_reporter{ expr, false, sl, *this,
333
+ reporter ().expression () };
334
+ }
335
+
336
+ /**
337
+ * @details
338
+ * Constructs and returns a `deferred_reporter<Expr_T>` with `abort = true`.
339
+ * The reporter evaluates the condition, records a pass or fail when it is
340
+ * destroyed, and aborts execution if the condition is false.
341
+ */
342
+ template <class Expr_T>
343
+ requires type_traits::checkable<Expr_T>
344
+ auto
345
+ subtest::assume (const Expr_T& expr, const reflection::source_location& sl)
346
+ {
347
+ return detail::deferred_reporter{ expr, true, sl, *this,
348
+ reporter ().expression () };
349
+ }
350
+
351
+ /**
352
+ * @details
353
+ * Top-level subtests (direct children of a `suite`) have depth 1.
354
+ * Each additional level of nesting increments the depth by 1.
355
+ */
356
+ inline size_t
357
+ subtest::nesting_depth () const noexcept
358
+ {
359
+ return nesting_depth_;
360
+ }
361
+
362
+ // ==========================================================================
363
+
364
+ /**
365
+ * @details
366
+ * Delegates to `runnable`, which binds the callable with
367
+ * its arguments. After construction, the suite is registered with the
368
+ * static test runner.
369
+ */
370
+ template <typename Callable_T, typename... Args_T>
371
+ suite::suite (const char* name, class runner& runner, Callable_T&& callable,
372
+ Args_T&&... arguments)
373
+ : runnable<suite>{ name, runner, 0, std::forward<Callable_T> (callable),
374
+ std::forward<Args_T> (arguments)... }
375
+ {
376
+ #if defined(MICRO_OS_PLUS_TRACE) \
377
+ && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
378
+ #if defined(__GNUC__)
379
+ #pragma GCC diagnostic push
380
+ #if defined(__clang__)
381
+ #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
382
+ #endif
383
+ #endif
384
+ trace::printf ("%s '%s' %zu\n", __PRETTY_FUNCTION__, name, own_index_);
385
+ #if defined(__GNUC__)
386
+ #pragma GCC diagnostic pop
387
+ #endif
388
+ #endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
389
+ }
390
+
391
+ #if defined(__GNUC__)
392
+ #pragma GCC diagnostic push
393
+ #if defined(__clang__)
394
+ #pragma clang diagnostic ignored "-Wdocumentation"
395
+ #endif
396
+ #endif
397
+ /**
398
+ * @details
399
+ * The `test` function template registers and executes a test case
400
+ * within the µTest++ framework. It accepts a descriptive name, a callable
401
+ * object (such as a lambda or function pointer), and an optional list of
402
+ * arguments to be passed to the callable. The test case is reported using
403
+ * the provided name, and its execution is managed by the framework's test
404
+ * runner.
405
+ *
406
+ * Each test case typically involves evaluating a logical expression, such as
407
+ * comparing a computed result to an expected value. For C++ projects, it is
408
+ * also possible to verify whether evaluating an expression throws
409
+ * exceptions. Each test either succeeds or fails, and for expectations, the
410
+ * test runner maintains counts of successful and failed checks.
411
+ *
412
+ * This function template enables flexible and expressive test case
413
+ * definitions, supporting both parameterised and non-parameterised tests. It
414
+ * is typically invoked at global scope or within test suite definitions to
415
+ * ensure automatic registration and execution.
416
+ *
417
+ * A test case is characterised by a name, a function that performs the
418
+ * checks, and optionally, arguments to be passed to that function. The
419
+ * implementation of `test` invokes the provided function with the given
420
+ * arguments and reports the results to the test runner.
421
+ *
422
+ * @par Example
423
+ *
424
+ * @code{.cpp}
425
+ * namespace mt = micro_os_plus::micro_test_plus;
426
+ *
427
+ * ts.test ("Check answer with comparator", [] (auto& t) {
428
+ * t.expect (mt::eq (compute_answer (), 42)) << "answer is 42";
429
+ * });
430
+ * @endcode
431
+ */
432
+ #if defined(__GNUC__)
433
+ #pragma GCC diagnostic pop
434
+ #endif
435
+ template <typename Callable_T, typename... Args_T>
436
+ void
437
+ suite::test (const char* name, Callable_T&& callable, Args_T&&... arguments)
438
+ {
439
+ #if defined(MICRO_OS_PLUS_TRACE) \
440
+ && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
441
+ #if defined(__GNUC__)
442
+ #pragma GCC diagnostic push
443
+ #if defined(__clang__)
444
+ #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
445
+ #endif
446
+ #endif
447
+ trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name);
448
+ #if defined(__GNUC__)
449
+ #pragma GCC diagnostic pop
450
+ #endif
451
+ #endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
452
+
453
+ size_t own_index = increment_subtest_index ();
454
+ auto child_subtest
455
+ = std::make_unique<subtest> (name, runner (), *this, own_index, 1,
456
+ std::forward<Callable_T> (callable),
457
+ std::forward<Args_T> (arguments)...);
458
+
459
+ after_subtest_create_ (std::move (child_subtest), *this);
460
+ }
461
+
462
+ /**
463
+ * @details
464
+ * Returns a reference to the `timestamps` member.
465
+ */
466
+ inline detail::timestamps&
467
+ suite::timings () noexcept
468
+ {
469
+ return timings_;
470
+ }
471
+
472
+ /**
473
+ * @details
474
+ * Returns a const reference to the `timestamps` member.
475
+ */
476
+ inline const detail::timestamps&
477
+ suite::timings () const noexcept
478
+ {
479
+ return timings_;
480
+ }
481
+
482
+ // ==========================================================================
483
+
484
+ /**
485
+ * @details
486
+ * Sets the name of the top-level suite.
487
+ *
488
+ * Used internally by the runner to set the name of the top suite after
489
+ * initialisation.
490
+ */
491
+ inline void
492
+ top_suite::name (const char* new_name) noexcept
493
+ {
494
+ name_ = new_name;
495
+ }
496
+
497
+ // ==========================================================================
498
+
499
+ /**
500
+ * @details
501
+ * Delegates to `runnable`, which binds the callable with
502
+ * its arguments. After construction, the suite is registered with the
503
+ * static test runner.
504
+ */
505
+ template <typename Callable_T, typename... Args_T>
506
+ static_suite::static_suite (const char* name, static_runner& runner,
507
+ Callable_T&& callable, Args_T&&... arguments)
508
+ // The nullptr passed to the base constructor is an optimisation to save
509
+ // some space, since this callble is not used by the static runner.
510
+ : suite{ name, detail::to_runner (runner), nullptr }
511
+ {
512
+ if constexpr (sizeof...(arguments) == 0)
513
+ {
514
+ static_callable_ = std::forward<Callable_T> (callable);
515
+ }
516
+ else
517
+ {
518
+ static_callable_ = std::bind (std::forward<Callable_T> (callable),
519
+ std::placeholders::_1,
520
+ std::forward<Args_T> (arguments)...);
521
+ }
522
+
523
+ #if defined(MICRO_OS_PLUS_TRACE) \
524
+ && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
525
+ #if defined(__GNUC__)
526
+ #pragma GCC diagnostic push
527
+ #if defined(__clang__)
528
+ #pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
529
+ #endif
530
+ #endif
531
+ trace::printf ("%s '%s' %zu\n", __PRETTY_FUNCTION__, name, own_index_);
532
+ #if defined(__GNUC__)
533
+ #pragma GCC diagnostic pop
534
+ #endif
535
+ #endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
536
+
537
+ detail::register_static_suite (runner, *this);
538
+ }
539
+
540
+ // --------------------------------------------------------------------------
541
+ } // namespace micro_os_plus::micro_test_plus
542
+
543
+ #if defined(__GNUC__)
544
+ #pragma GCC diagnostic pop
545
+ #endif
546
+
547
+ // ----------------------------------------------------------------------------
548
+
549
+ #endif // __cplusplus
550
+
551
+ // ----------------------------------------------------------------------------
552
+
553
+ #endif // MICRO_TEST_PLUS_TEST_INLINES_H_
554
+
555
+ // ----------------------------------------------------------------------------
@@ -0,0 +1,120 @@
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
+
12
+ // ----------------------------------------------------------------------------
13
+
14
+ /**
15
+ * @file
16
+ * @brief C++ header file with inline implementations for the µTest++
17
+ * timing utilities.
18
+ *
19
+ * @details
20
+ * This header provides the inline method bodies for the `timestamp` and
21
+ * `timestamps` classes, separated from the class declarations in
22
+ * `timings.h` to enforce the project convention that declarations reside
23
+ * in headers and implementations reside in inline files.
24
+ *
25
+ * All definitions reside within the `micro_os_plus::micro_test_plus`
26
+ * namespace, ensuring clear separation from user code and minimising
27
+ * the risk of naming conflicts.
28
+ */
29
+
30
+ #ifndef MICRO_TEST_PLUS_TIMINGS_INLINES_H_
31
+ #define MICRO_TEST_PLUS_TIMINGS_INLINES_H_
32
+
33
+ // ----------------------------------------------------------------------------
34
+
35
+ #ifdef __cplusplus
36
+
37
+ // ----------------------------------------------------------------------------
38
+
39
+ #if defined(__GNUC__)
40
+ #pragma GCC diagnostic push
41
+ #if defined(__clang__)
42
+ #pragma clang diagnostic ignored "-Wc++98-compat"
43
+ #pragma clang diagnostic ignored "-Wpre-c++17-compat"
44
+ #endif
45
+ #endif
46
+
47
+ // ============================================================================
48
+
49
+ namespace micro_os_plus::micro_test_plus::detail
50
+ {
51
+ // ==========================================================================
52
+
53
+ /**
54
+ * @details
55
+ * Stores the supplied `timespec` value in the `value_` member.
56
+ */
57
+ inline timestamp::timestamp (const timespec& ts) noexcept : value_{ ts }
58
+ {
59
+ }
60
+
61
+ /**
62
+ * @details
63
+ * Returns a mutable reference to the `value_` member.
64
+ */
65
+ inline timespec&
66
+ timestamp::value () noexcept
67
+ {
68
+ return value_;
69
+ }
70
+
71
+ /**
72
+ * @details
73
+ * Returns a const reference to the `value_` member.
74
+ */
75
+ inline const timespec&
76
+ timestamp::value () const noexcept
77
+ {
78
+ return value_;
79
+ }
80
+
81
+ // ==========================================================================
82
+
83
+ /**
84
+ * @details
85
+ * Returns `true` when `begin_time_` holds a value, i.e. when
86
+ * `timestamp_begin()` has previously been called.
87
+ */
88
+ inline bool
89
+ timestamps::has_begin () const noexcept
90
+ {
91
+ return begin_time_.has_value ();
92
+ }
93
+
94
+ /**
95
+ * @details
96
+ * Returns `true` when `end_time_` holds a value, i.e. when
97
+ * `timestamp_end()` has previously been called.
98
+ */
99
+ inline bool
100
+ timestamps::has_end () const noexcept
101
+ {
102
+ return end_time_.has_value ();
103
+ }
104
+
105
+ // --------------------------------------------------------------------------
106
+ } // namespace micro_os_plus::micro_test_plus::detail
107
+
108
+ #if defined(__GNUC__)
109
+ #pragma GCC diagnostic pop
110
+ #endif
111
+
112
+ // ----------------------------------------------------------------------------
113
+
114
+ #endif // __cplusplus
115
+
116
+ // ----------------------------------------------------------------------------
117
+
118
+ #endif // MICRO_TEST_PLUS_TIMINGS_INLINES_H_
119
+
120
+ // ----------------------------------------------------------------------------