micro-test-plus 4.1.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#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#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
81{
82 namespace detail
83 {
84 // ========================================================================
85
90 inline const char*
91 test_node::name (void) const noexcept
92 {
93 return name_;
94 }
95
100 inline runner_totals&
102 {
103 return totals_;
104 }
105
110 inline const runner_totals&
111 test_node::totals () const noexcept
112 {
113 return totals_;
114 }
115
116 // ========================================================================
117
122 inline size_t
123 runnable_base::own_index () const noexcept
124 {
125 return own_index_;
126 }
127
132 inline void
133 runnable_base::own_index (size_t index) noexcept
134 {
135 own_index_ = index;
136 }
137
142 inline size_t
144 {
146 }
147
154 inline size_t
159
164 inline size_t
166 {
167 return children_subtests_.size ();
168 }
169
174 inline class runner&
175 runnable_base::runner (void) const noexcept
176 {
177 return runner_;
178 }
179
180 // ========================================================================
181
189 template <typename Self_T>
190 template <typename Callable_T, typename... Args_T>
192 size_t own_index, Callable_T&& callable,
193 Args_T&&... arguments)
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
233 template <typename Self_T>
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
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)
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
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
313 auto child_subtest = std::make_unique<subtest> (
315 std::forward<Callable_T> (callable),
316 std::forward<Args_T> (arguments)...);
317
318 after_subtest_create_ (std::move (child_subtest), parent_suite_);
320
327 template <class 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
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>
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 () };
350
356 inline size_t
357 subtest::nesting_depth () const noexcept
358 {
359 return nesting_depth_;
360 }
361
362 // ==========================================================================
363
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
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
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);
461
466 inline detail::timestamps&
467 suite::timings () noexcept
468 {
469 return timings_;
470 }
471
476 inline const detail::timestamps&
477 suite::timings () const noexcept
478 {
479 return timings_;
480 }
481
482 // ==========================================================================
483
490 */
491 inline void
492 top_suite::name (const char* new_name) noexcept
493 {
494 name_ = new_name;
495 }
496
497 // ==========================================================================
498
505 template <typename Callable_T, typename... Args_T>
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
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// ----------------------------------------------------------------------------
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:136
void after_subtest_create_(std::unique_ptr< subtest > child_test, suite &suite)
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.
size_t current_subtest_index_
The subtest index, counting from 1.
Definition test.h:417
class reporter & reporter(void) const noexcept
Definition test.cpp:187
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.
void name(const char *new_name) noexcept
Sets the name of the top-level suite.
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:93
Primary namespace for the µTest++ testing framework.
C++ header file with declarations for the µTest++ test reporter.