44#ifndef MICRO_OS_PLUS_MICRO_TEST_PLUS_INLINES_TEST_INLINES_H_
45#define MICRO_OS_PLUS_MICRO_TEST_PLUS_INLINES_TEST_INLINES_H_
49#if defined(__cplusplus)
57#if __has_include("micro-os-plus/diag/trace.h")
58#include "micro-os-plus/diag/trace.h"
68#pragma GCC diagnostic push
70#pragma GCC diagnostic ignored "-Waggregate-return"
71#pragma GCC diagnostic ignored "-Wformat"
72#pragma GCC diagnostic ignored "-Wformat-extra-args"
73#pragma GCC diagnostic ignored "-Wpadded"
75#pragma clang diagnostic ignored "-Wunknown-warning-option"
76#pragma clang diagnostic ignored "-Wc++98-compat"
77#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
78#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
80#pragma GCC diagnostic ignored "-Wredundant-tags"
97 template <
typename Po
inter_T>
98 requires (std::is_same_v<Pointer_T, const char*>
99 or std::is_same_v<Pointer_T, char*>
100 or std::is_null_pointer_v<Pointer_T>)
103 :
name_{
name !=
nullptr ?
name :
"" }, location_{ location }
115 template <std::
size_t N>
118 :
name_{ std::string_view{
name, N }.substr (
119 0, std::string_view{
name, N }.find (
'\0')) },
171 return name_.c_str ();
210#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_DEPRECATED_ENABLED)
290 template <
typename Callable_T,
typename... Args_T>
293 suite& parent_suite,
size_t nesting_depth,
294 Callable_T&& callable,
295 Args_T&&... arguments)
299 if constexpr (
sizeof...(arguments) == 0
300 && !std::is_function_v<
301 std::remove_reference_t<Callable_T>>)
316 std::forward<Callable_T> (callable),
317 std::forward<Args_T> (arguments)...);
342 template <
typename Self_T,
typename Callable_T,
typename... Args_T>
346 if constexpr (
sizeof...(arguments) == 0)
348 return std::forward<Callable_T> (callable);
353 std::decay_t<Args_T>...>{
354 std::forward<Callable_T> (callable),
355 std::forward<Args_T> (arguments)...
367 template <
typename Self_T,
typename Callable_T,
typename... Args_T>
368 template <
typename C,
typename... A>
369 requires (
sizeof...(A) > 0)
371 C&& callable, A&&... arguments)
372 :
callable_ (std::forward<C> (callable)),
381 template <
typename Self_T,
typename Callable_T,
typename... Args_T>
385 invoke (self, std::index_sequence_for<Args_T...>{});
396 template <
typename Self_T,
typename Callable_T,
typename... Args_T>
397 template <std::size_t... Is>
400 Self_T& self, std::index_sequence<Is...>)
402 if constexpr (std::is_member_pointer_v<Callable_T>)
420 template <
typename Callable_T,
typename... Args_T>
424 if constexpr (std::is_invocable_v<std::decay_t<Callable_T>&,
suite&,
425 std::decay_t<Args_T>&...>)
428 "the body of a test case takes a test_case& as its "
429 "first parameter, not a suite&");
434 "the body of a test case takes a test_case& as its "
435 "first parameter, followed by the additional "
436 "arguments passed to test ()");
446 template <
typename Callable_T,
typename... Args_T>
450 if constexpr (not std::is_copy_constructible_v<std::decay_t<Callable_T>>
451 or not(std::is_copy_constructible_v<std::decay_t<Args_T>>
455 "the body of a suite and its additional arguments "
456 "must be copyable, since the suite runs later");
458 else if constexpr (std::is_invocable_v<std::decay_t<Callable_T>&,
460 std::decay_t<Args_T>&...>)
463 "the body of a suite takes a suite& as its first "
464 "parameter, not a test_case&");
469 "the body of a suite takes a suite& as its first "
470 "parameter, followed by the additional arguments");
479 template <
typename Self_T>
480 template <
typename Callable_T>
481 requires (!std::is_same_v<std::remove_cv_t<Callable_T>,
482 callable_ref<Self_T>>)
485 static_cast<const volatile void*
> (std::addressof (callable))) },
486 invoke_{ &invoke_callable<Callable_T> }
494 template <
typename Self_T>
512 template <
typename Self_T>
513 template <
typename Callable_T>
517 if constexpr (std::is_member_pointer_v<Callable_T>)
519 std::invoke (*
static_cast<Callable_T*
> (callable), self);
523 (*
static_cast<Callable_T*
> (callable)) (self);
547#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
561 template <
typename Callable_T,
typename... Args_T>
565 Args_T&&... arguments)
567#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
568 trace::printf (
"%s '%s'\n", __PRETTY_FUNCTION__,
name.
name ());
578 std::forward<Callable_T> (callable),
579 std::forward<Args_T> (arguments)...);
582#if !defined(__DOXYGEN__)
588 template <
typename Callable_T,
typename... Args_T>
592 [[maybe_unused]] Callable_T&& callable,
593 [[maybe_unused]] Args_T&&... arguments)
608 return running !=
nullptr && running !=
this;
620 template <
class Expr_T>
635 return std::move (result);
638#if !defined(__DOXYGEN__)
645 template <
class Expr_T>
655 "expect() does not take a wrapper of a bool, whose "
656 "condition tests the wrapper, not the value; write "
657 "has_value () or != nullptr, or use eq ()");
661 static_assert (extension::checkable<Expr_T>,
662 "expect() takes a Boolean condition or a comparison, "
663 "such as eq (); a value of this type is neither");
665 return std::move (result);
680 template <
class Expr_T>
696 return std::move (result);
699#if !defined(__DOXYGEN__)
707 template <
class Expr_T>
717 "require() does not take a wrapper of a bool, whose "
718 "condition tests the wrapper, not the value; write "
719 "has_value () or != nullptr, or use eq ()");
723 static_assert (extension::checkable<Expr_T>,
724 "require() takes a Boolean condition or a comparison, "
725 "such as eq (); a value of this type is neither");
727 return std::move (result);
731#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_DEPRECATED_ENABLED)
732#if !defined(__DOXYGEN__)
742 template <
class Expr_T>
751 return std::move (result);
759 template <
class Expr_T>
769 return std::move (result);
780 template <
class Expr_T>
786 return require (expr, sl, std::move (result));
829#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
830 trace::printf (
"%s '%s'\n", __PRETTY_FUNCTION__,
name_);
839#if defined(__cpp_exceptions)
850 catch (
const std::exception& e)
891 template <
typename Callable_T,
typename... Args_T>
893 Callable_T&& callable, Args_T&&... arguments)
896 std::forward<Callable_T> (callable),
897 std::forward<Args_T> (arguments)...) },
902#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
909#pragma GCC diagnostic push
911#if defined(__clang__)
912#pragma clang diagnostic ignored "-Wdocumentation"
965 template <
typename Callable_T,
typename... Args_T>
969 Args_T&&... arguments)
971#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
972 trace::printf (
"%s '%s'\n", __PRETTY_FUNCTION__,
name.
name ());
981 running->test (
name, std::forward<Callable_T> (callable),
982 std::forward<Args_T> (arguments)...);
992 std::forward<Args_T> (arguments)...);
995#if !defined(__DOXYGEN__)
1001 template <
typename Callable_T,
typename... Args_T>
1005 [[maybe_unused]] Callable_T&& callable,
1006 [[maybe_unused]] Args_T&&... arguments)
1027 template <
class Self_T,
class Values_T,
class Callable_T>
1030 Callable_T& callable)
1032 std::size_t position = 0;
1035 = [&self, &name, &callable, &position] (
const auto&
value)
1039 std::string text{ name.
name () };
1042 std::remove_cvref_t<
decltype (
value)>>)
1056 [&callable, &
value] (
auto& test_self)
1058 if constexpr (std::is_member_pointer_v<
1059 std::remove_cvref_t<Callable_T>>)
1061 std::invoke (callable, test_self,
value);
1065 callable (test_self,
value);
1072 for (
const auto&
value : values)
1079 std::apply ([&run_one] (
const auto&... elements)
1080 { (run_one (elements), ...); }, values);
1090 template <
typename Values_T,
typename Callable_T>
1095 Callable_T&& callable)
1105 template <
typename T,
typename Callable_T>
1108 std::initializer_list<T> values, Callable_T&& callable)
1118 template <
typename Values_T,
typename Callable_T>
1123 Callable_T&& callable)
1133 template <
typename T,
typename Callable_T>
1136 Callable_T&& callable)
1141#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_DEPRECATED_ENABLED)
1177 template <
typename Callable_T,
typename... Args_T>
1181 Callable_T&& callable, Args_T&&... arguments)
1183 std::forward<Callable_T> (callable),
1184 std::forward<Args_T> (arguments)... }
1186#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
1188 __PRETTY_FUNCTION__, name_, own_index_);
1194#if !defined(__DOXYGEN__)
1202 template <
typename Callable_T,
typename... Args_T>
1203 requires (!detail::static_suite_body<Callable_T, Args_T...>
1204 && !detail::suite_body<Callable_T, Args_T...>)
1206 [[maybe_unused]] Callable_T&& callable,
1207 [[maybe_unused]] Args_T&&... arguments)
1208 : suite{ std::move (name), test_runner, [] (suite&)
noexcept {} }
1214#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_DEPRECATED_ENABLED)
1226 template <
typename Callable_T,
typename... Args_T>
1229 Callable_T&& callable, Args_T&&... arguments)
1230 :
suite{ std::move (name), test_runner,
1231 [stored_callable = std::forward<Callable_T> (callable)] (
1232 suite& self,
auto&... stored_arguments)
mutable
1234 stored_callable (
static_cast<static_suite&
> (self), stored_arguments...);
1236 std::forward<Args_T> (arguments)... }
1238#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
1240 __PRETTY_FUNCTION__, name_, own_index_);
1252#if defined(__GNUC__)
1253#pragma GCC diagnostic pop
1254#pragma GCC diagnostic pop
C++ header file with declarations for the µTest++ check result.
Aggregated check and test case counters for a node in the test tree.
Function object that holds a callable and the additional arguments it is invoked with.
constexpr bound_callable(C &&callable, A &&... arguments)
Constructs the function object from a callable and the arguments.
void operator()(Self_T &self)
Invokes the stored callable.
std::tuple< Args_T... > arguments_
The stored arguments.
void invoke(Self_T &self, std::index_sequence< Is... >)
Invokes the stored callable with the stored arguments, unpacked by their indices.
Callable_T callable_
The stored callable.
Non-owning reference to a callable invoked with a Self_T& argument.
void operator()(Self_T &self) const
Invokes the referred callable.
callable_ref(Callable_T &callable) noexcept
Constructs a reference to a callable.
void * callable_
The address of the referred callable.
void(*) invoke_(void *callable, Self_T &self)
The function that invokes the referred callable.
static void invoke_callable(void *callable, Self_T &self)
Invokes a callable of a given type, from its address.
The result of one check, reported when destroyed.
void init(const Expr_T &expr, check_kind kind, const reflection::source_location &location, test_case &test_case, expression_formatter &expression, bool writes_passed)
Initialises the result with the check of an expression.
Abstract base class for the reporters that display test results, including operand values for failure...
virtual void end_test_case(const test_case &test_case)=0
Marks the end of a test case.
virtual void begin_test_case(const test_case &test_case)=0
Marks the beginning of a test case.
runner & test_runner(void) const noexcept
Returns the test runner that owns this test runnable.
size_t next_test_point_number(void) noexcept
Advances to the next child test point, and returns its number.
void after_test_case_create(class test_case &test_case, suite &suite)
Counts a newly constructed child test case and executes it immediately.
class test_case * running_test_case(void) const noexcept
Returns the innermost test case being run by the owning runner, if any.
bool accepts_test_case(const suite &target, const located_name &name)
Checks whether a test case can be created on a suite.
size_t own_index_
The test index, counting from 1.
const char * name(void) const noexcept
Returns the node name.
void create_test_case(const located_name &name, suite &parent_suite, size_t nesting_depth, Callable_T &&callable, Args_T &&... arguments)
Creates a child test case, and runs it.
size_t current_subtest_index(void) const noexcept
Deprecated number of the most recent child test point.
class reporter & test_reporter(void) const noexcept
Returns the test reporter associated with this test runnable.
counters totals_
Totals for the node.
size_t own_index(void) const noexcept
Deprecated positional index of this node within its parent.
runnable_base(const char *name, runner &test_runner, size_t own_index)
Constructs a runnable_base with a name, runner, and index.
const counters & totals(void) const noexcept
Returns the totals of the node.
const char * name_
The node name.
bool is_aborted(void) const noexcept
Checks whether the test execution was aborted by the owning runner.
size_t children_subtests_count(void) const noexcept
Deprecated number of direct child test cases of this node.
runner & runner_
Reference to the test runner that owns this object.
size_t test_point_number_
The number of the most recent child test point.
bool has_running_test_case_of(const suite &target) const noexcept
Checks whether the innermost running test case belongs to a suite.
size_t child_test_cases_count_
The number of direct child test cases.
Measures the elapsed time of an operation.
A name of a suite or of a test case, with the location where it was given.
reflection::source_location location_
The location where the name was given.
std::string name_
The copy of the name.
const char * name(void) const noexcept
Returns the name.
located_name(Pointer_T name, const reflection::source_location &location=reflection::source_location::current())
Constructs the name from a C string, capturing the location of the caller.
const reflection::source_location & location(void) const noexcept
Returns the location where the name was given.
Local implementation of source location information for diagnostics.
The test runner for the µTest++ framework.
A test suite designed for static (namespace-scope) registration with a runner.
static_suite(located_name name, runner &test_runner, Callable_T &&callable, Args_T &&... arguments)
Constructs a static suite, and links it into the list of suites.
A named, runnable test suite registered with the test runner.
const detail::stopwatch & timings(void) const noexcept
Deprecated access to the timings of the suite.
void test(const located_name &name, Callable_T &&callable, Args_T &&... arguments)
Adds a test case to the suite, and runs it.
void test_each(const located_name &name, Values_T &&values, Callable_T &&callable)
Adds a test case to the suite for each value of a range or a tuple, and runs them.
friend class micro_test_plus::runner
The runner, which creates and runs the suites.
located_name located_name_
The name of the suite, with the location where it was given.
detail::stopwatch stopwatch_
Stopwatch of this suite.
suite(located_name &&name, runner &test_runner, Callable_T &&callable, Args_T &&... arguments)
Constructs a suite with a name, runner, and callable body.
std::function< void(suite &)> callable_
Callable storing the suite body and any bound arguments.
friend class static_suite
The static suite, which registers itself.
A named, runnable test case that lives inside a suite.
void fail_unexpected_exception(const char *what)
Reports an exception that escaped the test case body as a failed check.
size_t nesting_depth_
The nesting depth of this test case within the suite.
suite & parent_suite_
Reference to the parent suite that owns this test case.
void test_each(const located_name &name, Values_T &&values, Callable_T &&callable)
Adds a nested test case for each value of a range or a tuple, and runs them.
friend class detail::runnable_base
The base of the nodes, which creates the test cases.
test_case(const located_name &name, runner &test_runner, suite &parent_suite, size_t own_index, size_t nesting_depth, detail::callable_ref< test_case > body)
Constructs a test case with a name, runner, parent suite, index, nesting depth, and body.
friend class micro_test_plus::runner
The runner, which reports the rejected calls as failed checks of the running test case.
bool is_misdirected(void) const noexcept
Tells whether another test case is running.
const located_name & located_name_
The name and the location of the call to test() that created this test case.
detail::check_result && report_misdirected(detail::check_kind kind, const reflection::source_location &sl, detail::check_result &&result)
Reports a check on this test case as a failure of the running one.
void test(const located_name &name, Callable_T &&callable, Args_T &&... arguments)
Adds a nested test case to this test case, and runs it.
detail::callable_ref< test_case > callable_
Reference to the test case body, with any bound arguments.
void report_misdirected_test(const located_name &name)
Reports a nested test case started on this test case as a failure of the running one.
void run(void) override
Executes the test case body by invoking the referred callable.
detail::check_result && assume(const Expr_T &expr, const reflection::source_location &sl=reflection::source_location::current(), detail::check_result &&result=detail::check_result{})
Deprecated name of require().
size_t nesting_depth(void) const noexcept
Returns the nesting depth of this test case.
Concept satisfied by the wrappers of a bool, whose condition is ambiguous.
Concept satisfied when a type was accepted by expect() and require() before the exclusion of the susp...
The body of a static suite written for v5.0.1, whose first parameter is a static_suite& reference.
Concept satisfied by a callable object that can be the body of a suite.
Concept satisfied by a callable object that can be the body of a test case.
Concept satisfied when T is a range of values for test_each().
Concept satisfied when T is a tuple of values for test_each().
Concept satisfied by a value that expect() and require() do not accept.
Concept satisfied when a type can be used as a test expression in expect() or require().
Concept satisfied when a type can be appended to the message of a check result via operator<<.
C++ header file with declarations for the µTest++ internals.
#define MICRO_OS_PLUS_MICRO_TEST_PLUS_PRI_SIZE
Portable printf() conversion for the size_t values.
detail::check_result && expect(const Expr_T &expr, const reflection::source_location &sl=reflection::source_location::current(), detail::check_result &&result=detail::check_result{})
Evaluates a condition and reports the result.
detail::check_result && require(const Expr_T &expr, const reflection::source_location &sl=reflection::source_location::current(), detail::check_result &&result=detail::check_result{})
Checks a condition and, if false, stops the test case.
Internal implementation details for the µTest++ framework.
@ requirement
A check created by require().
@ expectation
A check created by expect().
void test_each_value(Self_T &self, const located_name &name, Values_T &&values, Callable_T &callable)
Adds and runs a test case for each value.
constexpr bool dependent_false_v
A value that is always false, but depends on the template arguments.
auto bind_callable(Callable_T &&callable, Args_T &&... arguments)
Creates the function object that holds the body of a test case or suite.
constexpr void reject_test_body(void) noexcept
Stops the compilation with a message that tells what the body of a test case takes.
constexpr void reject_suite_body(void) noexcept
Stops the compilation with a message that tells what the body of a suite takes.
void escape_control_characters(std::string &name)
Escapes the control characters of a name.
Primary namespace for the µTest++ testing framework.
C++ header file with declarations for the µTest++ test reporter.
The exception thrown to stop a test case after a failed require().
static void append(std::string &text, const T &value)
Appends a value to a text, in the plain mode of the formatter.
Struct template representing a generic value, accessible via a getter.