micro-test-plus 5.0.0
µTest++ Testing Framework
Loading...
Searching...
No Matches
test-inlines.h
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
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#include <micro-os-plus/diag/trace.h>
59
62
63// ----------------------------------------------------------------------------
64
65#if defined(__GNUC__)
66#pragma GCC diagnostic push
67#pragma GCC diagnostic ignored "-Waggregate-return"
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#endif
75#endif
76
77// ============================================================================
78
80{
81 namespace detail
82 {
83 // ========================================================================
84
89 inline const char*
90 test_node::name (void) const noexcept
91 {
92 return name_;
93 }
94
99 inline runner_totals&
101 {
102 return totals_;
103 }
104
109 inline const runner_totals&
110 test_node::totals () const noexcept
111 {
112 return totals_;
113 }
114
115 // ========================================================================
116
121 inline size_t
122 runnable_base::own_index () const noexcept
123 {
124 return own_index_;
125 }
126
131 inline void
132 runnable_base::own_index (size_t index) noexcept
133 {
134 own_index_ = index;
135 }
136
141 inline size_t
143 {
145 }
146
153 inline size_t
158
163 inline size_t
165 {
166 return children_subtests_.size ();
167 }
168
173 inline class runner&
174 runnable_base::runner (void) const noexcept
175 {
176 return runner_;
177 }
178
179 // ========================================================================
180
188 template <typename Self_T>
189 template <typename Callable_T, typename... Args_T>
191 size_t own_index, Callable_T&& callable,
192 Args_T&&... arguments)
195 // When there are no extra arguments the callable already has the
196 // signature void(Self_T&), so store it directly. Only use std::bind when
197 // additional arguments must be pre-bound, to avoid triggering a GCC ARM
198 // bug in
199 // __is_nothrow_invocable<_Bind<...>, Self_T&> (GCC 15.2.1).
200 if constexpr (sizeof...(arguments) == 0)
201 {
202 callable_ = std::forward<Callable_T> (callable);
203 }
204 else
206 callable_ = std::bind (std::forward<Callable_T> (callable),
207 std::placeholders::_1,
208 std::forward<Args_T> (arguments)...);
209 }
210
211#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
212#if defined(__GNUC__)
213#pragma GCC diagnostic push
214#if defined(__clang__)
215#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
216#endif
217#endif
218 trace::printf ("%s '%s' %zu\n", __PRETTY_FUNCTION__, name, own_index_);
219#if defined(__GNUC__)
220#pragma GCC diagnostic pop
221#endif
222#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
223 }
224
231 template <typename Self_T>
233 {
234#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
235#if defined(__GNUC__)
236#pragma GCC diagnostic push
237#if defined(__clang__)
238#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
239#endif
240#endif
241 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name_);
242#if defined(__GNUC__)
243#pragma GCC diagnostic pop
244#endif
245#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
246 }
247
248 // ------------------------------------------------------------------------
249 } // namespace detail
250
251 // ==========================================================================
252
258 template <typename Callable_T, typename... Args_T>
259 subtest::subtest (const char* name, class runner& runner,
260 suite& parent_suite, size_t own_index,
261 size_t nesting_depth, Callable_T&& callable,
262 Args_T&&... arguments)
264 std::forward<Callable_T> (callable),
265 std::forward<Args_T> (arguments)... },
266 parent_suite_{ parent_suite }, nesting_depth_{ nesting_depth }
267 {
268#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
269#if defined(__GNUC__)
270#pragma GCC diagnostic push
271#if defined(__clang__)
272#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
273#endif
274#endif
275 trace::printf ("%s '%s' %zu %zu\n", __PRETTY_FUNCTION__, name, own_index_,
276 nesting_depth_);
277#if defined(__GNUC__)
278#pragma GCC diagnostic pop
279#endif
280#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
281 }
282
289 template <typename Callable_T, typename... Args_T>
290 void
291 subtest::test (const char* name, Callable_T&& callable,
292 Args_T&&... arguments)
293 {
294#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
295#if defined(__GNUC__)
296#pragma GCC diagnostic push
297#if defined(__clang__)
298#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
299#endif
300#endif
301 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name);
302#if defined(__GNUC__)
303#pragma GCC diagnostic pop
304#endif
305#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
306
308 auto child_subtest = std::make_unique<subtest> (
310 std::forward<Callable_T> (callable),
311 std::forward<Args_T> (arguments)...);
312
313 after_subtest_create_ (std::move (child_subtest), parent_suite_);
314 }
315
319 * The reporter evaluates the condition and records a pass or fail when
320 * it is destroyed at the end of the expression statement.
321 */
322 template <class Expr_T>
324 auto
325 subtest::expect (const Expr_T& expr, const reflection::source_location& sl)
326 {
327 return detail::deferred_reporter{ expr, false, sl, *this,
328 reporter ().expression () };
330
337 template <class Expr_T>
339 auto
340 subtest::assume (const Expr_T& expr, const reflection::source_location& sl)
341 {
342 return detail::deferred_reporter{ expr, true, sl, *this,
343 reporter ().expression () };
344 }
345
349 * Each additional level of nesting increments the depth by 1.
350 */
351 inline size_t
352 subtest::nesting_depth () const noexcept
353 {
354 return nesting_depth_;
355 }
356
357 // ==========================================================================
358
365 template <typename Callable_T, typename... Args_T>
366 suite::suite (const char* name, class runner& runner, Callable_T&& callable,
367 Args_T&&... arguments)
368 : runnable<suite>{ name, runner, 0, std::forward<Callable_T> (callable),
369 std::forward<Args_T> (arguments)... }
370 {
371#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_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' %zu\n", __PRETTY_FUNCTION__, name, own_index_);
379#if defined(__GNUC__)
380#pragma GCC diagnostic pop
381#endif
382#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
383 }
384
385#if defined(__GNUC__)
386#pragma GCC diagnostic push
387#if defined(__clang__)
388#pragma clang diagnostic ignored "-Wdocumentation"
389#endif
390#endif
426#if defined(__GNUC__)
427#pragma GCC diagnostic pop
428#endif
429 template <typename Callable_T, typename... Args_T>
430 void
431 suite::test (const char* name, Callable_T&& callable, Args_T&&... arguments)
432 {
433#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
434#if defined(__GNUC__)
435#pragma GCC diagnostic push
436#if defined(__clang__)
437#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
438#endif
439#endif
440 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, name);
441#if defined(__GNUC__)
442#pragma GCC diagnostic pop
443#endif
444#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
445
447 auto child_subtest
448 = std::make_unique<subtest> (name, runner (), *this, own_index, 1,
449 std::forward<Callable_T> (callable),
450 std::forward<Args_T> (arguments)...);
451
452 after_subtest_create_ (std::move (child_subtest), *this);
453 }
454
459 inline detail::timestamps&
460 suite::timings () noexcept
461 {
462 return timings_;
463 }
464
469 inline const detail::timestamps&
470 suite::timings () const noexcept
471 {
472 return timings_;
473 }
474
475 // ==========================================================================
476
484 inline void
485 top_suite::name (const char* new_name) noexcept
486 {
487 name_ = new_name;
488 }
489
490 // ==========================================================================
491
498 template <typename Callable_T, typename... Args_T>
500 Callable_T&& callable, Args_T&&... arguments)
501 // The nullptr passed to the base constructor is an optimisation to save
502 // some space, since this callble is not used by the static runner.
503 : suite{ name, detail::to_runner (runner), nullptr }
504 {
505 if constexpr (sizeof...(arguments) == 0)
506 {
507 static_callable_ = std::forward<Callable_T> (callable);
508 }
509 else
510 {
511 static_callable_ = std::bind (std::forward<Callable_T> (callable),
512 std::placeholders::_1,
513 std::forward<Args_T> (arguments)...);
514 }
515
516#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
517#if defined(__GNUC__)
518#pragma GCC diagnostic push
519#if defined(__clang__)
520#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
521#endif
522#endif
523 trace::printf ("%s '%s' %zu\n", __PRETTY_FUNCTION__, name, own_index_);
524#if defined(__GNUC__)
525#pragma GCC diagnostic pop
526#endif
527#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
528
530 }
531
532 // --------------------------------------------------------------------------
533} // namespace micro_os_plus::micro_test_plus
534
535#if defined(__GNUC__)
536#pragma GCC diagnostic pop
537#endif
538
539// ----------------------------------------------------------------------------
540
541#endif // __cplusplus
542
543// ----------------------------------------------------------------------------
544
545#endif // MICRO_TEST_PLUS_TEST_INLINES_H_
546
547// ----------------------------------------------------------------------------
Deferred reporter class for a specific expression.
class runner & runner(void) const noexcept
Gets the test runner associated with this test runnable.
size_t current_subtest_index() const noexcept
Returns the index of the most recently created child subtest.
runnable_base(const char *name, runner &runner, size_t own_index)
Constructs a runnable_base with a name, runner, and index.
Definition test.cpp:141
void after_subtest_create_(std::unique_ptr< subtest > child_test, suite &suite)
Definition test.cpp:218
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.
size_t current_subtest_index_
The subtest index, counting from 1.
Definition test.h:417
class reporter & reporter(void) const noexcept
Definition test.cpp:190
size_t children_subtests_count(void) const noexcept
Returns the number of direct child subtests owned by this node.
class runner & runner_
Reference to the test runner that owns this object.
Definition test.h:401
size_t increment_subtest_index() noexcept
Increments and returns the child subtest sequential index.
std::vector< std::unique_ptr< subtest > > children_subtests_
Owning collection of direct child subtests.
Definition test.h:427
runnable(const char *name, class runner &runner, size_t own_index, Callable_T &&callable, Args_T &&... arguments)
Class template constructor.
virtual ~runnable() override
Virtual destructor.
Aggregated pass/fail/subtest counters for a node in the test tree.
const char * name(void) const noexcept
Gets the node name.
runner_totals totals_
Totals for the test node, including nested cases.
Definition test.h:229
runner_totals & totals() noexcept
Gets the totals for the test.
const char * name_
The test node name.
Definition test.h:224
A begin/end timestamp pair used to measure elapsed time.
Definition timings.h:205
Local implementation of source location information for diagnostics.
Definition reflection.h:138
detail::expression_formatter & expression()
Provides access to the expression formatter for this reporter.
The test runner for the µTest++ framework.
Definition runner.h:111
A runner variant that also manages statically-registered test suites.
Definition runner.h:345
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
static_suite(const char *name, static_runner &runner, Callable_T &&callable, Args_T &&... arguments)
Class template constructor for static_suite.
suite & parent_suite_
Reference to the parent suite that owns this subtest.
Definition test.h:683
void test(const char *name, Callable_T &&callable, Args_T &&... arguments)
Adds a test case to the suite.
subtest(const char *name, class runner &runner, suite &parent_suite, size_t own_index, size_t nesting_depth, Callable_T &&callable, Args_T &&... arguments)
Constructs a subtest with a name, runner, parent suite, index, nesting depth, and callable.
size_t nesting_depth_
The nesting depth of this subtest within the suite.
Definition test.h:688
size_t nesting_depth() const noexcept
Returns the nesting depth of this subtest.
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.
detail::timestamps timings_
Timing measurements for this suite's execution.
Definition test.h:818
detail::timestamps & timings() noexcept
Gets the timings for this suite.
void test(const char *name, Callable_T &&callable, Args_T &&... arguments)
Adds a test case to the suite.
const char * name(void) const noexcept
Gets the node name.
C++20 concept satisfied when a type can be used as a test expression in expect() or assume().
C++ header file with declarations for the µTest++ deferred reporter.
auto assume(const Expr_T &expr, const reflection::source_location &sl=reflection::source_location::current())
Check a condition and, if false, abort test execution.
auto expect(const Expr_T &expr, const reflection::source_location &sl=reflection::source_location::current())
Evaluate a generic condition and report the results.
Internal implementation details for the µTest++ framework.
void register_static_suite(static_runner &static_runner_ref, static_suite &static_suite_ref)
Registers a static suite with a static runner.
Definition runner.cpp:100
Primary namespace for the µTest++ testing framework.
C++ header file with declarations for the µTest++ test reporter.