micro-test-plus 4.1.0
µTest++ Testing Framework
Loading...
Searching...
No Matches
test.cpp
Go to the documentation of this file.
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
43
44// ----------------------------------------------------------------------------
45
46#if defined(MICRO_OS_PLUS_INCLUDE_CONFIG_H)
47#include <micro-os-plus/config.h>
48#endif // MICRO_OS_PLUS_INCLUDE_CONFIG_H
49
50#if defined(MICRO_OS_PLUS_TRACE)
51#include <micro-os-plus/diag/trace.h>
52#endif // MICRO_OS_PLUS_TRACE
53
56
57// ----------------------------------------------------------------------------
58
59#if defined(__GNUC__)
60#if defined(__clang__)
61#pragma clang diagnostic ignored "-Wc++98-compat"
62#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
63#else // GCC only
64#pragma GCC diagnostic ignored "-Wredundant-tags"
65#pragma GCC diagnostic ignored "-Wsuggest-final-types"
66#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
67#endif
68#endif
69
70// ============================================================================
71
73{
74 namespace detail
75 {
76 // ========================================================================
77
85 {
86#if defined(MICRO_OS_PLUS_TRACE) \
87 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
88#if defined(__GNUC__)
89#pragma GCC diagnostic push
90#if defined(__clang__)
91#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
92#endif
93#endif
94 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name);
95#if defined(__GNUC__)
96#pragma GCC diagnostic pop
97#endif
98#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
99 }
100
108 {
109#if defined(MICRO_OS_PLUS_TRACE) \
110 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
111#if defined(__GNUC__)
112#pragma GCC diagnostic push
113#if defined(__clang__)
114#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
115#endif
116#endif
117 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
118#if defined(__GNUC__)
119#pragma GCC diagnostic pop
120#endif
121#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
122 }
123
124 // ========================================================================
125
137 size_t own_index)
139 {
140#if defined(MICRO_OS_PLUS_TRACE) \
141 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
142#if defined(__GNUC__)
143#pragma GCC diagnostic push
144#if defined(__clang__)
145#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
146#endif
147#endif
148 trace::printf ("%s '%s' %zu\n", __PRETTY_FUNCTION__, name, own_index_);
149#if defined(__GNUC__)
150#pragma GCC diagnostic pop
151#endif
152#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
153 }
154
163 {
164#if defined(MICRO_OS_PLUS_TRACE) \
165 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
166#if defined(__GNUC__)
167#pragma GCC diagnostic push
168#if defined(__clang__)
169#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
170#endif
171#endif
172 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
173#if defined(__GNUC__)
174#pragma GCC diagnostic pop
175#endif
176#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
177
178 // children_subtests_ holds unique_ptrs; destroyed automatically.
179 }
180
186 [[nodiscard]] reporter&
187 runnable_base::reporter (void) const noexcept
188 {
189 return runner_.reporter ();
190 }
191
198 [[noreturn]] void
200 {
201 runner_.abort (sl);
202 }
203
214 void
216 std::unique_ptr<class subtest> child_test, suite& suite)
217 {
218 // Transfer ownership into the vector.
219 children_subtests_.push_back (std::move (child_test));
220
221 // Run the child test case immediately.
222 class subtest& subtest = *children_subtests_.back ();
223 subtest.run ();
224
225 // This test executed one more subtest.
226#if defined(MICRO_OS_PLUS_TRACE) \
227 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
228#if defined(__GNUC__)
229#pragma GCC diagnostic push
230#if defined(__clang__)
231#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
232#endif
233#endif
234 trace::printf ("%s subtest '%s' executed one more subtest\n",
235 __PRETTY_FUNCTION__, name ());
236#if defined(__GNUC__)
237#pragma GCC diagnostic pop
238#endif
239#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
241 // Do not accumulate the totals from the child test into the current test
242 // totals, each subtest shows only its counters.
243
244#if defined(MICRO_OS_PLUS_TRACE) \
245 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
246#if defined(__GNUC__)
247#pragma GCC diagnostic push
248#if defined(__clang__)
249#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
250#endif
251#endif
252 trace::printf ("%s suite '%s' totals\n", __PRETTY_FUNCTION__,
253 suite.name ());
254#if defined(__GNUC__)
255#pragma GCC diagnostic pop
256#endif
257#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
258
259 // Accumulate the totals from the child test into the suite totals.
260 suite.totals () += subtest.totals ();
261 }
262 } // namespace detail
263
264 // ==========================================================================
265
276 {
277#if defined(MICRO_OS_PLUS_TRACE) \
278 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
279#if defined(__GNUC__)
280#pragma GCC diagnostic push
281#if defined(__clang__)
282#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
283#endif
284#endif
285 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
286#if defined(__GNUC__)
287#pragma GCC diagnostic pop
288#endif
289#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
290 }
291
297 void
299 {
300#if defined(MICRO_OS_PLUS_TRACE) \
301 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
302#if defined(__GNUC__)
303#pragma GCC diagnostic push
304#if defined(__clang__)
305#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
306#endif
307#endif
308 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
309#if defined(__GNUC__)
310#pragma GCC diagnostic pop
311#endif
312#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
313
314 class reporter& reporter = this->reporter ();
315
316 // For now, subtests do not record the time.
317 // this->timings.timestamp_begin ();
318 reporter.begin_subtest (*this);
319
320 // Invoke the callable, passing the self reference followed by the variadic
321 // arguments.
322 callable_ (*this);
323
324 // this->timings.timestamp_end ();
325 reporter.end_subtest (*this);
326 }
327
328 // ==========================================================================
329
337 {
338#if defined(MICRO_OS_PLUS_TRACE) \
339 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
340#if defined(__GNUC__)
341#pragma GCC diagnostic push
342#if defined(__clang__)
343#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
344#endif
345#endif
346 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
347#if defined(__GNUC__)
348#pragma GCC diagnostic pop
349#endif
350#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
351 }
352
358 void
360 {
361#if defined(MICRO_OS_PLUS_TRACE) \
362 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
363#if defined(__GNUC__)
364#pragma GCC diagnostic push
365#if defined(__clang__)
366#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
367#endif
368#endif
369 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
370#if defined(__GNUC__)
371#pragma GCC diagnostic pop
372#endif
373#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
374
375 class reporter& reporter = this->reporter ();
376
377 this->timings ().timestamp_begin ();
378 reporter.begin_suite (*this);
379
380 // Invoke the callable, passing the self reference followed by the variadic
381 // arguments.
382 callable_ (*this);
383
384 this->timings ().timestamp_end ();
385 reporter.end_suite (*this);
386 }
387
388 // ==========================================================================
389
394 * runner itself. If tracing is enabled, the name is output for
395 * diagnostic purposes.
396 */
398 : suite{ name, runner, [] (suite&) noexcept {} }
399 {
400#if defined(MICRO_OS_PLUS_TRACE) \
401 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
402#if defined(__GNUC__)
403#pragma GCC diagnostic push
404#if defined(__clang__)
405#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
406#endif
407#endif
408 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name);
409#if defined(__GNUC__)
410#pragma GCC diagnostic pop
411#endif
412#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
413
414 own_index (1);
415 }
416
424 {
425#if defined(MICRO_OS_PLUS_TRACE) \
426 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
427#if defined(__GNUC__)
428#pragma GCC diagnostic push
429#if defined(__clang__)
430#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
431#endif
432#endif
433 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
434#if defined(__GNUC__)
435#pragma GCC diagnostic pop
436#endif
437#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
438 }
439
440 // ==========================================================================
441
449 {
450#if defined(MICRO_OS_PLUS_TRACE) \
451 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
452#if defined(__GNUC__)
453#pragma GCC diagnostic push
454#if defined(__clang__)
455#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
456#endif
457#endif
458 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
459#if defined(__GNUC__)
460#pragma GCC diagnostic pop
461#endif
462#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
463 }
464
472 void
474 {
475#if defined(MICRO_OS_PLUS_TRACE) \
476 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS)
477#if defined(__GNUC__)
478#pragma GCC diagnostic push
479#if defined(__clang__)
480#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
481#endif
482#endif
483 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
484#if defined(__GNUC__)
485#pragma GCC diagnostic pop
486#endif
487#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS
488
489 class reporter& reporter = this->reporter ();
490
491 this->timings ().timestamp_begin ();
492 reporter.begin_suite (*this);
493
494 static_callable_ (*this);
495
496 this->timings ().timestamp_end ();
497 reporter.end_suite (*this);
498 }
499
500 // --------------------------------------------------------------------------
501} // namespace micro_os_plus::micro_test_plus
502
503// ----------------------------------------------------------------------------
class runner & runner(void) const noexcept
Gets the test runner associated with this test runnable.
runnable_base(const char *name, runner &runner, size_t own_index)
Constructs a runnable_base with a name, runner, and index.
Definition test.cpp:136
void after_subtest_create_(std::unique_ptr< subtest > child_test, suite &suite)
Registers a newly constructed child subtest and executes it immediately.
Definition test.cpp:215
size_t own_index_
The test index, counting from 1.
Definition test.h:406
size_t own_index() const noexcept
Returns the positional index of this object within its parent.
class reporter & reporter(void) const noexcept
Gets the test reporter associated with this test runnable.
Definition test.cpp:187
class runner & runner_
Reference to the test runner that owns this object.
Definition test.h:401
virtual ~runnable_base() override
Virtual destructor.
Definition test.cpp:162
void abort(const reflection::source_location &sl=reflection::source_location::current())
Aborts test execution via the owning runner.
Definition test.cpp:199
std::vector< std::unique_ptr< subtest > > children_subtests_
Owning collection of direct child subtests.
Definition test.h:427
void increment_executed_subtests(size_t count=1) noexcept
Increments the executed-subtests counter.
const char * name(void) const noexcept
Gets the node name.
virtual ~test_node()
Virtual destructor for the test_node class.
Definition test.cpp:107
runner_totals & totals() noexcept
Gets the totals for the test.
test_node(const char *name)
Constructs a test node.
Definition test.cpp:84
const char * name_
The test node name.
Definition test.h:224
void timestamp_begin(void) noexcept
Records the begin timestamp using the current system clock.
Definition timings.cpp:102
void timestamp_end(void) noexcept
Records the end timestamp using the current system clock.
Definition timings.cpp:135
Local implementation of source location information for diagnostics.
Definition reflection.h:138
Reporter to display test results, including operand values and types for failures.
Definition reporter.h:186
virtual void begin_subtest(subtest &subtest)=0
Mark the beginning of a subtest.
virtual void begin_suite(suite &suite)=0
Mark the beginning of a test suite.
virtual void end_suite(suite &suite)=0
Mark the end of a test suite.
The test runner for the µTest++ framework.
Definition runner.h:111
std::function< void(static_suite &)> static_callable_
Callable storing the static suite body and any bound arguments. Invoked with a reference to the concr...
Definition test.h:990
virtual void run(void) override
Executes the static suite body using the stored static callable.
Definition test.cpp:473
virtual ~static_suite() override
Virtual destructor.
Definition test.cpp:448
A named, runnable test case that lives inside a suite.
Definition test.h:542
virtual ~subtest() override
Virtual destructor.
Definition test.cpp:275
virtual void run(void) override
Executes the subtest body by invoking the stored callable.
Definition test.cpp:298
A named, runnable test suite registered with the test runner.
Definition test.h:714
suite(const char *name, class runner &runner, Callable_T &&callable, Args_T &&... arguments)
Constructs a suite with a name, runner, and callable body.
virtual void run(void) override
Executes the suite body by invoking the stored callable.
Definition test.cpp:359
detail::timestamps & timings() noexcept
Gets the timings for this suite.
virtual ~suite() override
Virtual destructor.
Definition test.cpp:336
void name(const char *new_name) noexcept
Sets the name of the top-level suite.
top_suite(const char *name, class runner &runner)
Constructs the top-level suite with a name and runner reference.
Definition test.cpp:397
virtual ~top_suite() override
Virtual destructor.
Definition test.cpp:423
Internal implementation details for the µTest++ framework.
Primary namespace for the µTest++ testing framework.
C++ header file with declarations for the µTest++ test runner.
C++ header file with declarations for the µTest++ test suite.