@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.
- package/CHANGELOG.md +412 -2
- package/CMakeLists.txt +134 -28
- package/README.md +3 -2
- package/config/xcdl-build.json +11 -4
- package/include/micro-os-plus/micro-test-plus/README.md +6 -0
- package/include/micro-os-plus/micro-test-plus/deferred-reporter.h +267 -0
- package/include/micro-os-plus/micro-test-plus/detail.h +272 -1425
- package/include/micro-os-plus/micro-test-plus/exceptions.h +125 -0
- package/include/micro-os-plus/micro-test-plus/expression-formatter.h +669 -0
- package/include/micro-os-plus/micro-test-plus/function-comparators.h +15 -7
- package/include/micro-os-plus/micro-test-plus/inlines/{details-inlines.h → deferred-reporter-inlines.h} +66 -44
- package/include/micro-os-plus/micro-test-plus/inlines/detail-inlines.h +711 -0
- package/include/micro-os-plus/micro-test-plus/inlines/exceptions-inline.h +137 -0
- package/include/micro-os-plus/micro-test-plus/inlines/{test-reporter-inlines.h → expression-formatter-inlines.h} +232 -198
- package/include/micro-os-plus/micro-test-plus/inlines/function-comparators-inlines.h +24 -20
- package/include/micro-os-plus/micro-test-plus/inlines/literals-inlines.h +50 -31
- package/include/micro-os-plus/micro-test-plus/inlines/math-inlines.h +25 -19
- package/include/micro-os-plus/micro-test-plus/inlines/operators-inlines.h +275 -0
- package/include/micro-os-plus/micro-test-plus/inlines/reflection-inlines.h +39 -21
- package/include/micro-os-plus/micro-test-plus/inlines/reporter-inlines.h +205 -0
- package/include/micro-os-plus/micro-test-plus/inlines/runner-inlines.h +151 -0
- package/include/micro-os-plus/micro-test-plus/inlines/runner-totals-inlines.h +152 -0
- package/include/micro-os-plus/micro-test-plus/inlines/test-inlines.h +555 -0
- package/include/micro-os-plus/micro-test-plus/inlines/timings-inlines.h +120 -0
- package/include/micro-os-plus/micro-test-plus/inlines/type-traits-inlines.h +231 -0
- package/include/micro-os-plus/micro-test-plus/inlines/utility-inlines.h +126 -0
- package/include/micro-os-plus/micro-test-plus/literals.h +12 -17
- package/include/micro-os-plus/micro-test-plus/math.h +14 -6
- package/include/micro-os-plus/micro-test-plus/operators.h +53 -209
- package/include/micro-os-plus/micro-test-plus/reflection.h +8 -4
- package/include/micro-os-plus/micro-test-plus/{test-reporter-basic.h → reporter-human.h} +80 -74
- package/include/micro-os-plus/micro-test-plus/{test-reporter-tap.h → reporter-tap.h} +77 -71
- package/include/micro-os-plus/micro-test-plus/reporter.h +619 -0
- package/include/micro-os-plus/micro-test-plus/runner-totals.h +250 -0
- package/include/micro-os-plus/micro-test-plus/runner.h +472 -0
- package/include/micro-os-plus/micro-test-plus/test.h +1013 -0
- package/include/micro-os-plus/micro-test-plus/timings.h +363 -0
- package/include/micro-os-plus/micro-test-plus/type-traits.h +223 -577
- package/include/micro-os-plus/micro-test-plus/utility.h +136 -0
- package/include/micro-os-plus/micro-test-plus.h +42 -236
- package/meson.build +11 -6
- package/package.json +11 -3
- package/src/deferred-reporter.cpp +137 -0
- package/src/expression-formatter.cpp +289 -0
- package/src/reflection.cpp +97 -0
- package/src/reporter-human.cpp +816 -0
- package/src/reporter-tap.cpp +772 -0
- package/src/reporter.cpp +481 -0
- package/src/runner-totals.cpp +98 -0
- package/src/runner.cpp +669 -0
- package/src/test.cpp +503 -0
- package/src/timings.cpp +210 -0
- package/src/utility.cpp +163 -0
- package/.cmake-format.yaml +0 -11
- package/include/micro-os-plus/micro-test-plus/inlines/micro-test-plus-inlines.h +0 -313
- package/include/micro-os-plus/micro-test-plus/inlines/test-suite-inlines.h +0 -115
- package/include/micro-os-plus/micro-test-plus/test-reporter.h +0 -846
- package/include/micro-os-plus/micro-test-plus/test-runner.h +0 -281
- package/include/micro-os-plus/micro-test-plus/test-suite.h +0 -492
- package/src/micro-test-plus.cpp +0 -316
- package/src/test-reporter-basic.cpp +0 -466
- package/src/test-reporter-tap.cpp +0 -530
- package/src/test-reporter.cpp +0 -399
- package/src/test-runner.cpp +0 -311
- 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
|
+
// ----------------------------------------------------------------------------
|