micro-test-plus 4.1.1
µ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 __has_include(<micro-os-plus/project-config.h>)
47#include <micro-os-plus/project-config.h>
48#elif __has_include(<micro-os-plus/config.h>)
49#pragma message \
50 "micro-os-plus/config.h is deprecated, rename to micro-os-plus/project-config.h and include it instead of micro-os-plus/config.h"
51#include <micro-os-plus/config.h>
52#endif // __has_include(<micro-os-plus/project-config.h>)
53
54#if __has_include(<micro-os-plus/micro-test-plus-defines.h>)
55#include <micro-os-plus/micro-test-plus-defines.h>
56#endif // __has_include(<micro-os-plus/micro-test-plus-defines.h>)
57
58#if defined(MICRO_OS_PLUS_TRACE)
59#include <micro-os-plus/diag/trace.h>
60#endif // MICRO_OS_PLUS_TRACE
61
64
65// ----------------------------------------------------------------------------
66
67#if defined(__GNUC__)
68#if defined(__clang__)
69#pragma clang diagnostic ignored "-Wunknown-warning-option"
70#pragma clang diagnostic ignored "-Wc++98-compat"
71#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
72#else // GCC only
73#pragma GCC diagnostic ignored "-Wredundant-tags"
74#pragma GCC diagnostic ignored "-Wsuggest-final-types"
75#pragma GCC diagnostic ignored "-Wsuggest-final-methods"
76#endif
77#endif
78
79// ============================================================================
80
82{
83 namespace detail
84 {
85 // ========================================================================
86
94 {
95#if defined(MICRO_OS_PLUS_TRACE) \
96 && defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
97#if defined(__GNUC__)
98#pragma GCC diagnostic push
99#if defined(__clang__)
100#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
101#endif
102#endif
103 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name);
104#if defined(__GNUC__)
105#pragma GCC diagnostic pop
106#endif
107#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
108 }
109
117 {
118#if defined(MICRO_OS_PLUS_TRACE) \
119 && defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
120#if defined(__GNUC__)
121#pragma GCC diagnostic push
122#if defined(__clang__)
123#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
124#endif
125#endif
126 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
127#if defined(__GNUC__)
128#pragma GCC diagnostic pop
129#endif
130#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
131 }
132
133 // ========================================================================
134
146 size_t own_index)
148 {
149#if defined(MICRO_OS_PLUS_TRACE) \
150 && defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
151#if defined(__GNUC__)
152#pragma GCC diagnostic push
153#if defined(__clang__)
154#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
155#endif
156#endif
157 trace::printf ("%s '%s' %zu\n", __PRETTY_FUNCTION__, name, own_index_);
158#if defined(__GNUC__)
159#pragma GCC diagnostic pop
160#endif
161#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
162 }
163
172 {
173#if defined(MICRO_OS_PLUS_TRACE) \
174 && defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
175#if defined(__GNUC__)
176#pragma GCC diagnostic push
177#if defined(__clang__)
178#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
179#endif
180#endif
181 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
182#if defined(__GNUC__)
183#pragma GCC diagnostic pop
184#endif
185#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
186
187 // children_subtests_ holds unique_ptrs; destroyed automatically.
188 }
189
195 [[nodiscard]] reporter&
196 runnable_base::reporter (void) const noexcept
197 {
198 return runner_.reporter ();
199 }
200
207 [[noreturn]] void
209 {
210 runner_.abort (sl);
211 }
212
223 void
225 std::unique_ptr<class subtest> child_test, suite& suite)
226 {
227 // Transfer ownership into the vector.
228 children_subtests_.push_back (std::move (child_test));
229
230 // Run the child test case immediately.
231 class subtest& subtest = *children_subtests_.back ();
232 subtest.run ();
233
234 // This test executed one more subtest.
235#if defined(MICRO_OS_PLUS_TRACE) \
236 && defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
237#if defined(__GNUC__)
238#pragma GCC diagnostic push
239#if defined(__clang__)
240#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
241#endif
242#endif
243 trace::printf ("%s subtest '%s' executed one more subtest\n",
244 __PRETTY_FUNCTION__, name ());
245#if defined(__GNUC__)
246#pragma GCC diagnostic pop
247#endif
248#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
250 // Do not accumulate the totals from the child test into the current test
251 // totals, each subtest shows only its counters.
252
253#if defined(MICRO_OS_PLUS_TRACE) \
254 && defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
255#if defined(__GNUC__)
256#pragma GCC diagnostic push
257#if defined(__clang__)
258#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
259#endif
260#endif
261 trace::printf ("%s suite '%s' totals\n", __PRETTY_FUNCTION__,
262 suite.name ());
263#if defined(__GNUC__)
264#pragma GCC diagnostic pop
265#endif
266#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
267
268 // Accumulate the totals from the child test into the suite totals.
269 suite.totals () += subtest.totals ();
270 }
271 } // namespace detail
272
273 // ==========================================================================
274
285 {
286#if defined(MICRO_OS_PLUS_TRACE) \
287 && defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
288#if defined(__GNUC__)
289#pragma GCC diagnostic push
290#if defined(__clang__)
291#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
292#endif
293#endif
294 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
295#if defined(__GNUC__)
296#pragma GCC diagnostic pop
297#endif
298#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
299 }
300
306 void
308 {
309#if defined(MICRO_OS_PLUS_TRACE) \
310 && defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
311#if defined(__GNUC__)
312#pragma GCC diagnostic push
313#if defined(__clang__)
314#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
315#endif
316#endif
317 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
318#if defined(__GNUC__)
319#pragma GCC diagnostic pop
320#endif
321#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
322
323 class reporter& reporter = this->reporter ();
324
325 // For now, subtests do not record the time.
326 // this->timings.timestamp_begin ();
327 reporter.begin_subtest (*this);
328
329 // Invoke the callable, passing the self reference followed by the variadic
330 // arguments.
331 callable_ (*this);
332
333 // this->timings.timestamp_end ();
334 reporter.end_subtest (*this);
335 }
336
337 // ==========================================================================
338
346 {
347#if defined(MICRO_OS_PLUS_TRACE) \
348 && defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
349#if defined(__GNUC__)
350#pragma GCC diagnostic push
351#if defined(__clang__)
352#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
353#endif
354#endif
355 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
356#if defined(__GNUC__)
357#pragma GCC diagnostic pop
358#endif
359#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
360 }
361
367 void
370#if defined(MICRO_OS_PLUS_TRACE) \
371 && defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
372#if defined(__GNUC__)
373#pragma GCC diagnostic push
374#if defined(__clang__)
375#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
376#endif
377#endif
378 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
379#if defined(__GNUC__)
380#pragma GCC diagnostic pop
381#endif
382#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
383
384 class reporter& reporter = this->reporter ();
385
386 this->timings ().timestamp_begin ();
387 reporter.begin_suite (*this);
388
389 // Invoke the callable, passing the self reference followed by the variadic
390 // arguments.
391 callable_ (*this);
392
393 this->timings ().timestamp_end ();
394 reporter.end_suite (*this);
395 }
396
397 // ==========================================================================
398
407 : suite{ name, runner, [] (suite&) noexcept {} }
408 {
409#if defined(MICRO_OS_PLUS_TRACE) \
410 && defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
411#if defined(__GNUC__)
412#pragma GCC diagnostic push
413#if defined(__clang__)
414#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
415#endif
416#endif
417 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name);
418#if defined(__GNUC__)
419#pragma GCC diagnostic pop
420#endif
421#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
422
423 own_index (1);
424 }
425
433 {
434#if defined(MICRO_OS_PLUS_TRACE) \
435 && defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
436#if defined(__GNUC__)
437#pragma GCC diagnostic push
438#if defined(__clang__)
439#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
440#endif
441#endif
442 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
443#if defined(__GNUC__)
444#pragma GCC diagnostic pop
445#endif
446#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
447 }
448
449 // ==========================================================================
450
458 {
459#if defined(MICRO_OS_PLUS_TRACE) \
460 && defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
461#if defined(__GNUC__)
462#pragma GCC diagnostic push
463#if defined(__clang__)
464#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
465#endif
466#endif
467 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
468#if defined(__GNUC__)
469#pragma GCC diagnostic pop
470#endif
471#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
472 }
473
481 void
483 {
484#if defined(MICRO_OS_PLUS_TRACE) \
485 && defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
486#if defined(__GNUC__)
487#pragma GCC diagnostic push
488#if defined(__clang__)
489#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
490#endif
491#endif
492 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
493#if defined(__GNUC__)
494#pragma GCC diagnostic pop
495#endif
496#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
497
498 class reporter& reporter = this->reporter ();
499
500 this->timings ().timestamp_begin ();
501 reporter.begin_suite (*this);
502
503 static_callable_ (*this);
504
505 this->timings ().timestamp_end ();
506 reporter.end_suite (*this);
507 }
508
509 // --------------------------------------------------------------------------
510} // namespace micro_os_plus::micro_test_plus
511
512// ----------------------------------------------------------------------------
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:145
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:224
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:196
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:171
void abort(const reflection::source_location &sl=reflection::source_location::current())
Aborts test execution via the owning runner.
Definition test.cpp:208
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:116
runner_totals & totals() noexcept
Gets the totals for the test.
test_node(const char *name)
Constructs a test node.
Definition test.cpp:93
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:110
void timestamp_end(void) noexcept
Records the end timestamp using the current system clock.
Definition timings.cpp:143
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:482
virtual ~static_suite() override
Virtual destructor.
Definition test.cpp:457
A named, runnable test case that lives inside a suite.
Definition test.h:542
virtual ~subtest() override
Virtual destructor.
Definition test.cpp:284
virtual void run(void) override
Executes the subtest body by invoking the stored callable.
Definition test.cpp:307
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:368
detail::timestamps & timings() noexcept
Gets the timings for this suite.
virtual ~suite() override
Virtual destructor.
Definition test.cpp:345
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:406
virtual ~top_suite() override
Virtual destructor.
Definition test.cpp:432
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.