@micro-os-plus/micro-test-plus 3.3.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +330 -2
- package/CMakeLists.txt +79 -23
- package/README.md +1 -1
- package/config/xcdl-build.json +11 -4
- package/include/micro-os-plus/micro-test-plus/deferred-reporter.h +292 -0
- package/include/micro-os-plus/micro-test-plus/detail.h +462 -1076
- package/include/micro-os-plus/micro-test-plus/exceptions.h +126 -0
- package/include/micro-os-plus/micro-test-plus/function-comparators.h +10 -7
- package/include/micro-os-plus/micro-test-plus/inlines/{details-inlines.h → deferred-reporter-inlines.h} +49 -22
- package/include/micro-os-plus/micro-test-plus/inlines/function-comparators-inlines.h +67 -4
- package/include/micro-os-plus/micro-test-plus/inlines/literals-inlines.h +3 -6
- package/include/micro-os-plus/micro-test-plus/inlines/math-inlines.h +21 -15
- package/include/micro-os-plus/micro-test-plus/inlines/reflection-inlines.h +35 -17
- package/include/micro-os-plus/micro-test-plus/inlines/{test-reporter-inlines.h → reporter-inlines.h} +176 -106
- package/include/micro-os-plus/micro-test-plus/inlines/{test-suite-inlines.h → runner-inlines.h} +41 -43
- package/include/micro-os-plus/micro-test-plus/inlines/test-inlines.h +369 -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 +4 -3
- package/include/micro-os-plus/micro-test-plus/math.h +9 -6
- package/include/micro-os-plus/micro-test-plus/operators.h +38 -44
- package/include/micro-os-plus/micro-test-plus/reflection.h +15 -4
- package/include/micro-os-plus/micro-test-plus/{test-reporter-basic.h → reporter-human.h} +72 -72
- package/include/micro-os-plus/micro-test-plus/{test-reporter-tap.h → reporter-tap.h} +69 -69
- package/include/micro-os-plus/micro-test-plus/{test-reporter.h → reporter.h} +296 -200
- package/include/micro-os-plus/micro-test-plus/runner-totals.h +264 -0
- package/include/micro-os-plus/micro-test-plus/runner.h +453 -0
- package/include/micro-os-plus/micro-test-plus/test.h +1069 -0
- package/include/micro-os-plus/micro-test-plus/timings.h +366 -0
- package/include/micro-os-plus/micro-test-plus/type-traits.h +239 -545
- package/include/micro-os-plus/micro-test-plus/utility.h +135 -0
- package/include/micro-os-plus/micro-test-plus.h +25 -228
- package/meson.build +10 -6
- package/package.json +1 -1
- package/src/deferred-reporter.cpp +118 -0
- package/src/reflection.cpp +95 -0
- package/src/reporter-human.cpp +822 -0
- package/src/reporter-tap.cpp +782 -0
- package/src/reporter.cpp +676 -0
- package/src/runner-totals.cpp +95 -0
- package/src/runner.cpp +563 -0
- package/src/test.cpp +496 -0
- package/src/timings.cpp +209 -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/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,95 @@
|
|
|
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++ source file with implementations for the µTest++ runner
|
|
21
|
+
* totals methods.
|
|
22
|
+
*
|
|
23
|
+
* @details
|
|
24
|
+
* This source file contains the implementation of the
|
|
25
|
+
* `runner_totals::operator+=` method, which aggregates test result
|
|
26
|
+
* counters from one `runner_totals` instance into another. It
|
|
27
|
+
* accumulates successful checks, failed checks, and executed subtests.
|
|
28
|
+
*
|
|
29
|
+
* All definitions reside within the
|
|
30
|
+
* `micro_os_plus::micro_test_plus` namespace.
|
|
31
|
+
*
|
|
32
|
+
* This file must be included when building the µTest++ library.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
// ----------------------------------------------------------------------------
|
|
36
|
+
|
|
37
|
+
#if defined(MICRO_OS_PLUS_INCLUDE_CONFIG_H)
|
|
38
|
+
#include <micro-os-plus/config.h>
|
|
39
|
+
#endif // MICRO_OS_PLUS_INCLUDE_CONFIG_H
|
|
40
|
+
|
|
41
|
+
#include <micro-os-plus/micro-test-plus.h>
|
|
42
|
+
#include <micro-os-plus/diag/trace.h>
|
|
43
|
+
|
|
44
|
+
// ----------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
#if defined(__GNUC__)
|
|
47
|
+
#if defined(__clang__)
|
|
48
|
+
#pragma clang diagnostic ignored "-Wc++98-compat"
|
|
49
|
+
#pragma clang diagnostic ignored "-Wpre-c++17-compat"
|
|
50
|
+
#endif
|
|
51
|
+
#endif
|
|
52
|
+
|
|
53
|
+
// ============================================================================
|
|
54
|
+
|
|
55
|
+
namespace micro_os_plus::micro_test_plus
|
|
56
|
+
{
|
|
57
|
+
// ===========================================================================
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @details
|
|
61
|
+
* Adds the successful check count, failed check count, and executed
|
|
62
|
+
* subtest count of @p other to the corresponding members of this
|
|
63
|
+
* instance. Returns a reference to `*this` to support chaining.
|
|
64
|
+
* When tracing is enabled, the updated totals are output for
|
|
65
|
+
* diagnostic purposes.
|
|
66
|
+
*/
|
|
67
|
+
runner_totals&
|
|
68
|
+
runner_totals::operator+= (const runner_totals& other) noexcept
|
|
69
|
+
{
|
|
70
|
+
successful_checks_ += other.successful_checks ();
|
|
71
|
+
failed_checks_ += other.failed_checks ();
|
|
72
|
+
executed_subtests_ += other.executed_subtests ();
|
|
73
|
+
|
|
74
|
+
#if defined(MICRO_OS_PLUS_TRACE) \
|
|
75
|
+
&& defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
|
|
76
|
+
#if defined(__GNUC__)
|
|
77
|
+
#pragma GCC diagnostic push
|
|
78
|
+
#if defined(__clang__)
|
|
79
|
+
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
|
|
80
|
+
#endif
|
|
81
|
+
#endif
|
|
82
|
+
trace::printf ("%s -> +%zu -%zu in xs%zu\n", __PRETTY_FUNCTION__,
|
|
83
|
+
successful_checks_, failed_checks_, executed_subtests_);
|
|
84
|
+
#if defined(__GNUC__)
|
|
85
|
+
#pragma GCC diagnostic pop
|
|
86
|
+
#endif
|
|
87
|
+
#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
|
|
88
|
+
|
|
89
|
+
return *this;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// --------------------------------------------------------------------------
|
|
93
|
+
} // namespace micro_os_plus::micro_test_plus
|
|
94
|
+
|
|
95
|
+
// ----------------------------------------------------------------------------
|
package/src/runner.cpp
ADDED
|
@@ -0,0 +1,563 @@
|
|
|
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++ source file with implementations for the µTest++ test runner
|
|
21
|
+
* methods.
|
|
22
|
+
*
|
|
23
|
+
* @details
|
|
24
|
+
* This source file contains the core implementations for the test runner
|
|
25
|
+
* facilities of the µTest++ framework. It provides the logic for initialising
|
|
26
|
+
* the test environment, registering and managing test suites, handling
|
|
27
|
+
* command-line arguments, orchestrating test execution, and determining the
|
|
28
|
+
* overall test result. The implementation supports automated discovery and
|
|
29
|
+
* execution of test suites, flexible verbosity control, and robust mechanisms
|
|
30
|
+
* for aborting test execution in critical scenarios.
|
|
31
|
+
*
|
|
32
|
+
* All definitions reside within the `micro_os_plus::micro_test_plus`
|
|
33
|
+
* namespace, ensuring clear separation from user code and minimising the risk
|
|
34
|
+
* of naming conflicts.
|
|
35
|
+
*
|
|
36
|
+
* This file must be included when building the µTest++ library.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
// ----------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
#if defined(MICRO_OS_PLUS_INCLUDE_CONFIG_H)
|
|
42
|
+
#include <micro-os-plus/config.h>
|
|
43
|
+
#endif // MICRO_OS_PLUS_INCLUDE_CONFIG_H
|
|
44
|
+
|
|
45
|
+
#include <micro-os-plus/micro-test-plus.h>
|
|
46
|
+
#include <micro-os-plus/diag/trace.h>
|
|
47
|
+
#include <algorithm>
|
|
48
|
+
|
|
49
|
+
// ----------------------------------------------------------------------------
|
|
50
|
+
|
|
51
|
+
#if defined(__GNUC__)
|
|
52
|
+
#pragma GCC diagnostic ignored "-Waggregate-return"
|
|
53
|
+
#if defined(__clang__)
|
|
54
|
+
#pragma clang diagnostic ignored "-Wc++98-compat"
|
|
55
|
+
#pragma clang diagnostic ignored "-Wc++98-c++11-c++14-compat"
|
|
56
|
+
#pragma clang diagnostic ignored "-Wpre-c++17-compat"
|
|
57
|
+
#endif
|
|
58
|
+
#endif
|
|
59
|
+
|
|
60
|
+
// ============================================================================
|
|
61
|
+
|
|
62
|
+
namespace micro_os_plus::micro_test_plus
|
|
63
|
+
{
|
|
64
|
+
// --------------------------------------------------------------------------
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @details
|
|
68
|
+
* The constructor initialises a new instance of the `test_runner` class,
|
|
69
|
+
* preparing the test runner for managing test suites and cases within the
|
|
70
|
+
* µTest++ framework. If tracing is enabled, it outputs the function
|
|
71
|
+
* signature for diagnostic purposes. This setup ensures the test runner is
|
|
72
|
+
* ready to coordinate the registration, execution, and reporting of tests
|
|
73
|
+
* across all test cases and folders.
|
|
74
|
+
*/
|
|
75
|
+
runner::runner (const char* top_suite_name)
|
|
76
|
+
: test_node{ "runner" }, top_suite_{ top_suite_name, *this }
|
|
77
|
+
{
|
|
78
|
+
#if defined(MICRO_OS_PLUS_TRACE) \
|
|
79
|
+
&& defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
|
|
80
|
+
#if defined(__GNUC__)
|
|
81
|
+
#pragma GCC diagnostic push
|
|
82
|
+
#if defined(__clang__)
|
|
83
|
+
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
|
|
84
|
+
#endif
|
|
85
|
+
#endif
|
|
86
|
+
trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name ());
|
|
87
|
+
#if defined(__GNUC__)
|
|
88
|
+
#pragma GCC diagnostic pop
|
|
89
|
+
#endif
|
|
90
|
+
#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @details
|
|
95
|
+
* The `reporter_` unique pointer is released automatically. If tracing
|
|
96
|
+
* is enabled, the function signature is output for diagnostic purposes.
|
|
97
|
+
*/
|
|
98
|
+
runner::~runner ()
|
|
99
|
+
{
|
|
100
|
+
#if defined(MICRO_OS_PLUS_TRACE) \
|
|
101
|
+
&& defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
|
|
102
|
+
trace::printf ("%s\n", __PRETTY_FUNCTION__);
|
|
103
|
+
#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
|
|
104
|
+
|
|
105
|
+
// reporter_ is a unique_ptr; destroyed automatically.
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
#if defined(__GNUC__)
|
|
109
|
+
#pragma GCC diagnostic push
|
|
110
|
+
#if defined(__clang__)
|
|
111
|
+
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
|
|
112
|
+
#endif
|
|
113
|
+
#endif
|
|
114
|
+
/**
|
|
115
|
+
* @details
|
|
116
|
+
* This method initialises the test runner by capturing the command-line
|
|
117
|
+
* arguments and the default test suite name, configuring the framework for
|
|
118
|
+
* subsequent test execution. It parses the arguments to determine the
|
|
119
|
+
* desired verbosity level (normal, verbose, quiet, or silent) and applies
|
|
120
|
+
* this setting to the test reporter. The method also outputs build and
|
|
121
|
+
* environment information when appropriate, aiding diagnostics and
|
|
122
|
+
* transparency. Finally, it creates and registers the default test suite,
|
|
123
|
+
* preparing the framework to manage and execute all test cases and suites
|
|
124
|
+
* across the project’s folders.
|
|
125
|
+
*/
|
|
126
|
+
suite&
|
|
127
|
+
runner::initialise (int argc, char* argv[])
|
|
128
|
+
{
|
|
129
|
+
#if defined(MICRO_OS_PLUS_TRACE) \
|
|
130
|
+
&& defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
|
|
131
|
+
trace::printf ("%s\n", __PRETTY_FUNCTION__);
|
|
132
|
+
#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
|
|
133
|
+
|
|
134
|
+
#if !(defined(MICRO_OS_PLUS_INCLUDE_STARTUP) && defined(MICRO_OS_PLUS_TRACE))
|
|
135
|
+
#if defined(MICRO_OS_PLUS_DEBUG)
|
|
136
|
+
trace::printf ("argv[");
|
|
137
|
+
for (int i = 0; i < argc; ++i)
|
|
138
|
+
{
|
|
139
|
+
if (i > 0)
|
|
140
|
+
{
|
|
141
|
+
trace::printf (", ");
|
|
142
|
+
}
|
|
143
|
+
trace::printf ("'%s'", argv[i]);
|
|
144
|
+
}
|
|
145
|
+
trace::puts ("]");
|
|
146
|
+
#endif // defined(MICRO_OS_PLUS_DEBUG)
|
|
147
|
+
#endif // !defined(MICRO_OS_PLUS_INCLUDE_STARTUP)
|
|
148
|
+
|
|
149
|
+
std::vector<std::string_view> argvs (argv, argv + argc);
|
|
150
|
+
|
|
151
|
+
std::string_view reporter_name{ "tap" };
|
|
152
|
+
static constexpr std::string_view reporter_prefix{ "--reporter=" };
|
|
153
|
+
for (size_t i = 0; i < argvs.size (); ++i)
|
|
154
|
+
{
|
|
155
|
+
if (argvs[i].starts_with (reporter_prefix))
|
|
156
|
+
{
|
|
157
|
+
reporter_name = argvs[i].substr (reporter_prefix.size ());
|
|
158
|
+
}
|
|
159
|
+
else if (argvs[i]
|
|
160
|
+
== reporter_prefix.substr (0, reporter_prefix.size () - 1))
|
|
161
|
+
{
|
|
162
|
+
if (i + 1 < argvs.size ())
|
|
163
|
+
{
|
|
164
|
+
reporter_name = argvs[++i];
|
|
165
|
+
}
|
|
166
|
+
else
|
|
167
|
+
{
|
|
168
|
+
fprintf (stderr, "error: --reporter option requires a "
|
|
169
|
+
"reporter name argument\n");
|
|
170
|
+
exit (1);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Initialise and configure the reporter.
|
|
176
|
+
if (reporter_name == "human")
|
|
177
|
+
{
|
|
178
|
+
reporter_ = std::make_unique<reporter_human> (
|
|
179
|
+
std::make_unique<std::vector<std::string_view>> (
|
|
180
|
+
std::move (argvs)));
|
|
181
|
+
}
|
|
182
|
+
else if (reporter_name == "tap")
|
|
183
|
+
{
|
|
184
|
+
reporter_ = std::make_unique<reporter_tap> (
|
|
185
|
+
std::make_unique<std::vector<std::string_view>> (
|
|
186
|
+
std::move (argvs)));
|
|
187
|
+
}
|
|
188
|
+
else
|
|
189
|
+
{
|
|
190
|
+
fprintf (stderr, "error: unknown reporter '%.*s'\n",
|
|
191
|
+
static_cast<int> (reporter_name.size ()),
|
|
192
|
+
reporter_name.data ());
|
|
193
|
+
exit (1);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// ------------------------------------------------------------------------
|
|
197
|
+
|
|
198
|
+
timings_.timestamp_begin ();
|
|
199
|
+
reporter_->begin_session (*this);
|
|
200
|
+
|
|
201
|
+
top_suite_.timings ().timestamp_begin ();
|
|
202
|
+
reporter_->begin_suite (top_suite_);
|
|
203
|
+
|
|
204
|
+
return top_suite_;
|
|
205
|
+
}
|
|
206
|
+
#if defined(__GNUC__)
|
|
207
|
+
#pragma GCC diagnostic pop
|
|
208
|
+
#endif
|
|
209
|
+
|
|
210
|
+
// --------------------------------------------------------------------------
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @details
|
|
214
|
+
* Takes ownership of the supplied `suite` unique pointer and appends
|
|
215
|
+
* it to the internal `children_suites_` vector, deferring execution
|
|
216
|
+
* until `run_suites_()` is called. If tracing is enabled, the suite
|
|
217
|
+
* name is logged for diagnostic purposes.
|
|
218
|
+
*/
|
|
219
|
+
void
|
|
220
|
+
runner::register_suite_ (std::unique_ptr<class suite> suite)
|
|
221
|
+
{
|
|
222
|
+
#if defined(MICRO_OS_PLUS_TRACE) \
|
|
223
|
+
&& defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
|
|
224
|
+
#if defined(__GNUC__)
|
|
225
|
+
#pragma GCC diagnostic push
|
|
226
|
+
#if defined(__clang__)
|
|
227
|
+
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
|
|
228
|
+
#endif
|
|
229
|
+
#endif
|
|
230
|
+
trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, suite->name ());
|
|
231
|
+
#if defined(__GNUC__)
|
|
232
|
+
#pragma GCC diagnostic pop
|
|
233
|
+
#endif
|
|
234
|
+
#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
|
|
235
|
+
|
|
236
|
+
children_suites_.push_back (std::move (suite));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* @details
|
|
241
|
+
* Sorts `children_suites_` alphabetically by suite name using a
|
|
242
|
+
* selection sort on `unique_ptr::swap`, avoiding the
|
|
243
|
+
* `-Waggregate-return` diagnostic that `std::sort` would trigger on
|
|
244
|
+
* unique-pointer iterators. Each suite is assigned a 1-based index
|
|
245
|
+
* offset by the top-suite index, executed via `suite::run()`, and its
|
|
246
|
+
* totals are accumulated into the runner totals. The executed-subtest
|
|
247
|
+
* counter is not incremented; suites are not counted as subtests.
|
|
248
|
+
*/
|
|
249
|
+
void
|
|
250
|
+
runner::run_suites_ (void)
|
|
251
|
+
{
|
|
252
|
+
// Use selection sort with unique_ptr::swap (returns void) to avoid
|
|
253
|
+
// std::sort triggering -Waggregate-return via std::move_backward,
|
|
254
|
+
// which returns a class-type iterator when operating on unique_ptr
|
|
255
|
+
// elements.
|
|
256
|
+
const size_t n = children_suites_.size ();
|
|
257
|
+
for (size_t i = 0; i < n; ++i)
|
|
258
|
+
{
|
|
259
|
+
size_t min_idx = i;
|
|
260
|
+
for (size_t j = i + 1; j < n; ++j)
|
|
261
|
+
{
|
|
262
|
+
if (std::string_view{ children_suites_[j]->name () }
|
|
263
|
+
< std::string_view{ children_suites_[min_idx]->name () })
|
|
264
|
+
min_idx = j;
|
|
265
|
+
}
|
|
266
|
+
if (min_idx != i)
|
|
267
|
+
children_suites_[i].swap (children_suites_[min_idx]);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
for (size_t i = 0; i < n; ++i)
|
|
271
|
+
{
|
|
272
|
+
auto* suite_ptr = children_suites_[i].get ();
|
|
273
|
+
|
|
274
|
+
// +1 for 1-based index, +1 for top suite
|
|
275
|
+
suite_ptr->own_index (i + 1 + 1);
|
|
276
|
+
|
|
277
|
+
// Run the child suite immediately.
|
|
278
|
+
suite_ptr->run ();
|
|
279
|
+
|
|
280
|
+
// Accumulate the totals from the static suite into the runner
|
|
281
|
+
// totals.
|
|
282
|
+
// DO NOT increment executed_subtests here.
|
|
283
|
+
totals_ += suite_ptr->totals ();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* @details
|
|
289
|
+
* Finalises the top suite by recording its end timestamp and notifying
|
|
290
|
+
* the reporter, then accumulates its totals into the runner totals.
|
|
291
|
+
* Subsequently invokes `run_suites_()` to sort, execute, and
|
|
292
|
+
* accumulate all registered child suites. Finally, records the session
|
|
293
|
+
* end timestamp, notifies the reporter, and returns `0` if all checks
|
|
294
|
+
* passed or `1` otherwise.
|
|
295
|
+
*/
|
|
296
|
+
int
|
|
297
|
+
runner::exit_code (void)
|
|
298
|
+
{
|
|
299
|
+
#if defined(MICRO_OS_PLUS_TRACE) \
|
|
300
|
+
&& defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
|
|
301
|
+
trace::printf ("%s\n", __PRETTY_FUNCTION__);
|
|
302
|
+
#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
|
|
303
|
+
|
|
304
|
+
if (reporter_ == nullptr)
|
|
305
|
+
{
|
|
306
|
+
fprintf (stderr, "error: test runner not initialised\n");
|
|
307
|
+
return 1;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
top_suite_.timings ().timestamp_end ();
|
|
311
|
+
reporter_->end_suite (top_suite_);
|
|
312
|
+
totals_ += top_suite_.totals ();
|
|
313
|
+
|
|
314
|
+
run_suites_ ();
|
|
315
|
+
|
|
316
|
+
timings_.timestamp_end ();
|
|
317
|
+
reporter_->end_session (*this);
|
|
318
|
+
|
|
319
|
+
const int result = totals_.was_successful () ? 0 : 1;
|
|
320
|
+
|
|
321
|
+
#if defined(MICRO_OS_PLUS_TRACE) \
|
|
322
|
+
&& defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
|
|
323
|
+
#if defined(__GNUC__)
|
|
324
|
+
#pragma GCC diagnostic push
|
|
325
|
+
#if defined(__clang__)
|
|
326
|
+
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
|
|
327
|
+
#endif
|
|
328
|
+
#endif
|
|
329
|
+
trace::printf ("%s -> %d\n", __PRETTY_FUNCTION__, result);
|
|
330
|
+
#if defined(__GNUC__)
|
|
331
|
+
#pragma GCC diagnostic pop
|
|
332
|
+
#endif
|
|
333
|
+
#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
|
|
334
|
+
|
|
335
|
+
return result;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* @details
|
|
340
|
+
* This method immediately terminates the process by invoking the standard C
|
|
341
|
+
* library `abort()` function. It is used to halt test execution in critical
|
|
342
|
+
* failure scenarios, ensuring that no further tests are run and that the
|
|
343
|
+
* cause of the failure can be promptly investigated. This approach provides
|
|
344
|
+
* a robust mechanism for enforcing strict test outcomes across all test
|
|
345
|
+
* cases and folders.
|
|
346
|
+
*/
|
|
347
|
+
void
|
|
348
|
+
runner::abort (const reflection::source_location& sl)
|
|
349
|
+
{
|
|
350
|
+
#if defined(MICRO_OS_PLUS_TRACE) \
|
|
351
|
+
&& defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
|
|
352
|
+
trace::printf ("%s\n", __PRETTY_FUNCTION__);
|
|
353
|
+
#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
|
|
354
|
+
|
|
355
|
+
#if defined(__GNUC__)
|
|
356
|
+
#pragma GCC diagnostic push
|
|
357
|
+
#if defined(__clang__)
|
|
358
|
+
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
|
|
359
|
+
#endif
|
|
360
|
+
#endif
|
|
361
|
+
fprintf (stderr, "\nerror: test execution aborted at %s:%u\n",
|
|
362
|
+
reflection::short_name (sl.file_name ()), sl.line ());
|
|
363
|
+
#if defined(__GNUC__)
|
|
364
|
+
#pragma GCC diagnostic pop
|
|
365
|
+
#endif
|
|
366
|
+
|
|
367
|
+
::abort ();
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* @details
|
|
372
|
+
* Returns the number of registered child suites plus one, accounting
|
|
373
|
+
* for the top suite.
|
|
374
|
+
*/
|
|
375
|
+
size_t
|
|
376
|
+
runner::suites_count (void) const noexcept
|
|
377
|
+
{
|
|
378
|
+
return children_suites_.size () + 1;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* @details
|
|
383
|
+
* For the base `runner`, the total suite count equals `suites_count()`,
|
|
384
|
+
* as there are no additional static suites.
|
|
385
|
+
*/
|
|
386
|
+
size_t
|
|
387
|
+
runner::total_suites_count (void) const noexcept
|
|
388
|
+
{
|
|
389
|
+
return suites_count ();
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// ==========================================================================
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* @details
|
|
396
|
+
* Delegates construction to the `runner` base class with the given
|
|
397
|
+
* @p top_suite_name. If tracing is enabled, the function signature
|
|
398
|
+
* and suite name are output for diagnostic purposes.
|
|
399
|
+
*/
|
|
400
|
+
static_runner::static_runner (const char* top_suite_name)
|
|
401
|
+
: runner{ top_suite_name }
|
|
402
|
+
{
|
|
403
|
+
#if defined(MICRO_OS_PLUS_TRACE) \
|
|
404
|
+
&& defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
|
|
405
|
+
#if defined(__GNUC__)
|
|
406
|
+
#pragma GCC diagnostic push
|
|
407
|
+
#if defined(__clang__)
|
|
408
|
+
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
|
|
409
|
+
#endif
|
|
410
|
+
#endif
|
|
411
|
+
trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name ());
|
|
412
|
+
#if defined(__GNUC__)
|
|
413
|
+
#pragma GCC diagnostic pop
|
|
414
|
+
#endif
|
|
415
|
+
#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* @details
|
|
420
|
+
* If `static_children_suites_` is non-null, the dynamically allocated
|
|
421
|
+
* vector of raw pointers is deleted and the pointer is reset to
|
|
422
|
+
* `nullptr`. The pointed-to `static_suite` objects are not deleted,
|
|
423
|
+
* as they are static storage-duration objects. If tracing is enabled,
|
|
424
|
+
* the function signature is output for diagnostic purposes.
|
|
425
|
+
*/
|
|
426
|
+
static_runner::~static_runner ()
|
|
427
|
+
{
|
|
428
|
+
#if defined(MICRO_OS_PLUS_TRACE) \
|
|
429
|
+
&& defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
|
|
430
|
+
trace::printf ("%s\n", __PRETTY_FUNCTION__);
|
|
431
|
+
#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
|
|
432
|
+
|
|
433
|
+
if (static_children_suites_ != nullptr)
|
|
434
|
+
{
|
|
435
|
+
// The tests are static, so we do not delete them, but we need to
|
|
436
|
+
// delete the array of pointers.
|
|
437
|
+
delete static_children_suites_;
|
|
438
|
+
static_children_suites_ = nullptr;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* @details
|
|
444
|
+
* Returns the number of elements in `static_children_suites_`, or
|
|
445
|
+
* zero if the vector has not been allocated yet.
|
|
446
|
+
*/
|
|
447
|
+
size_t
|
|
448
|
+
static_runner::static_suites_count (void) const noexcept
|
|
449
|
+
{
|
|
450
|
+
return static_children_suites_ != nullptr
|
|
451
|
+
? static_children_suites_->size ()
|
|
452
|
+
: 0;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* @details
|
|
457
|
+
* Returns the combined count of dynamically registered suites (from
|
|
458
|
+
* the base `runner`) and statically registered suites.
|
|
459
|
+
*/
|
|
460
|
+
size_t
|
|
461
|
+
static_runner::total_suites_count (void) const noexcept
|
|
462
|
+
{
|
|
463
|
+
return suites_count () + static_suites_count ();
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* @details
|
|
468
|
+
* First invokes `runner::run_suites_()` to execute all dynamically
|
|
469
|
+
* registered child suites. If `static_children_suites_` is non-null,
|
|
470
|
+
* its contents are sorted alphabetically by suite name using selection
|
|
471
|
+
* sort on raw pointers, each suite is assigned a 1-based index offset
|
|
472
|
+
* by the dynamic suite count, executed via `suite::run()`, and its
|
|
473
|
+
* totals are accumulated into the runner totals.
|
|
474
|
+
*/
|
|
475
|
+
void
|
|
476
|
+
static_runner::run_suites_ (void)
|
|
477
|
+
{
|
|
478
|
+
#if defined(MICRO_OS_PLUS_TRACE) \
|
|
479
|
+
&& defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
|
|
480
|
+
trace::printf ("%s\n", __PRETTY_FUNCTION__);
|
|
481
|
+
#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
|
|
482
|
+
|
|
483
|
+
runner::run_suites_ ();
|
|
484
|
+
|
|
485
|
+
if (static_children_suites_ != nullptr)
|
|
486
|
+
{
|
|
487
|
+
// Use selection sort with std::swap on raw pointers (returns void)
|
|
488
|
+
// to avoid std::sort triggering -Waggregate-return via
|
|
489
|
+
// std::move_backward returning a class-type iterator.
|
|
490
|
+
const size_t n = static_children_suites_->size ();
|
|
491
|
+
auto& suites = *static_children_suites_;
|
|
492
|
+
for (size_t i = 0; i < n; ++i)
|
|
493
|
+
{
|
|
494
|
+
size_t min_idx = i;
|
|
495
|
+
for (size_t j = i + 1; j < n; ++j)
|
|
496
|
+
{
|
|
497
|
+
if (std::string_view{ suites[j]->name () }
|
|
498
|
+
< std::string_view{ suites[min_idx]->name () })
|
|
499
|
+
min_idx = j;
|
|
500
|
+
}
|
|
501
|
+
if (min_idx != i)
|
|
502
|
+
std::swap (suites[i], suites[min_idx]);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
for (size_t i = 0; i < n; ++i)
|
|
506
|
+
{
|
|
507
|
+
auto* suite_ptr = suites[i];
|
|
508
|
+
|
|
509
|
+
suite_ptr->own_index (i + 1 + suites_count ());
|
|
510
|
+
|
|
511
|
+
// Run the child suite immediately.
|
|
512
|
+
suite_ptr->run ();
|
|
513
|
+
|
|
514
|
+
// Accumulate the totals from the static suite into the runner
|
|
515
|
+
// totals.
|
|
516
|
+
// DO NOT increment executed_subtests here.
|
|
517
|
+
totals_ += suite_ptr->totals ();
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* @details
|
|
524
|
+
* If `runner.static_children_suites_` is null, a new
|
|
525
|
+
* `std::vector<static_suite*>` is heap-allocated and assigned to it.
|
|
526
|
+
* The address of @p suite is then appended to the vector. This method
|
|
527
|
+
* is intended to be called from the constructor of `static_suite`,
|
|
528
|
+
* before test execution begins.
|
|
529
|
+
*/
|
|
530
|
+
void
|
|
531
|
+
static_runner::register_static_suite (static_runner& runner,
|
|
532
|
+
static_suite& suite)
|
|
533
|
+
{
|
|
534
|
+
#if defined(MICRO_OS_PLUS_TRACE) \
|
|
535
|
+
&& defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
|
|
536
|
+
#if defined(__GNUC__)
|
|
537
|
+
#pragma GCC diagnostic push
|
|
538
|
+
#if defined(__clang__)
|
|
539
|
+
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
|
|
540
|
+
#endif
|
|
541
|
+
#endif
|
|
542
|
+
trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, suite.name ());
|
|
543
|
+
#if defined(__GNUC__)
|
|
544
|
+
#pragma GCC diagnostic pop
|
|
545
|
+
#endif
|
|
546
|
+
#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
|
|
547
|
+
|
|
548
|
+
if (runner.static_children_suites_ == nullptr)
|
|
549
|
+
{
|
|
550
|
+
#if defined(MICRO_OS_PLUS_TRACE) \
|
|
551
|
+
&& defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
|
|
552
|
+
trace::printf ("%s new static_children_suites_ array\n",
|
|
553
|
+
__PRETTY_FUNCTION__);
|
|
554
|
+
#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
|
|
555
|
+
runner.static_children_suites_ = new std::vector<static_suite*>;
|
|
556
|
+
}
|
|
557
|
+
runner.static_children_suites_->push_back (&suite);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// --------------------------------------------------------------------------
|
|
561
|
+
} // namespace micro_os_plus::micro_test_plus
|
|
562
|
+
|
|
563
|
+
// ----------------------------------------------------------------------------
|