micro-test-plus 6.0.0
µTest++ Testing Framework
Loading...
Searching...
No Matches
runner.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
12// ----------------------------------------------------------------------------
13
34
35// ----------------------------------------------------------------------------
36
41
42#if __has_include("micro-os-plus/diag/trace.h")
43#include "micro-os-plus/diag/trace.h"
44#endif // __has_include("micro-os-plus/diag/trace.h")
45
46#include <cstdio>
47#include <cstring>
48#include <string>
49
50// ----------------------------------------------------------------------------
51
52#if defined(__GNUC__)
53#pragma GCC diagnostic ignored "-Waggregate-return"
54#if defined(__clang__)
55#pragma clang diagnostic ignored "-Wunknown-warning-option"
56#pragma clang diagnostic ignored "-Wc++98-compat"
57#pragma clang diagnostic ignored "-Wc++98-c++11-c++14-compat"
58#pragma clang diagnostic ignored "-Wpre-c++17-compat"
59#pragma clang diagnostic ignored "-Wc++20-compat"
60#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
61#endif // defined(__clang__)
62#endif // defined(__GNUC__)
63
64// ============================================================================
65
66#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_ENABLED)
67
68// ----------------------------------------------------------------------------
69
71{
72 // --------------------------------------------------------------------------
73
86 namespace
87 {
95 constexpr const char* help_options
96 = "Options:\n"
97 " --help, -h\n"
98 " --verbose | --quiet | --silent\n"
99 " --list-tests, --list\n"
100 " --reporter=human|tap\n"
101 " --output-file=<path>\n"
102 " --colour[=always|never|auto], --color[=...]\n"
103 " --use-colour=yes|no|auto, --use-color=...\n"
104 " --filter=<pattern>\n"
105 " Run only the matching names; repeat the option for each\n"
106 " nesting level: the first pattern applies to the suite\n"
107 " names, the second to the test case names, and each\n"
108 " further one to the nested test cases. The patterns use\n"
109 " '*' and '?', and '|' separates alternatives.\n";
110 } // namespace
111
112 // --------------------------------------------------------------------------
113
120 runner::runner (void) : top_suite_{ "", *this }
121 {
122#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
123 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, top_suite_.name ());
124#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
125 }
126
127#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_DEPRECATED_ENABLED)
134 // Deprecated since 4.1.0; use runner() and add_top_suite().
135 runner::runner (const char* top_suite_name)
136 : top_suite_{ top_suite_name, *this }
137 {
138#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
139 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, top_suite_.name ());
140#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
141 }
142#endif // defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_DEPRECATED_ENABLED)
143
150 {
151#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
152 trace::printf ("%s\n", __PRETTY_FUNCTION__);
153#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
154
155 for (runner** slot = &started_first_; *slot != nullptr;
156 slot = &(*slot)->started_next_)
157 {
158 if (*slot == this)
159 {
160 *slot = started_next_;
161 break;
162 }
163 }
164
165 // reporter_ is a unique_ptr; destroyed automatically.
166 }
167
168#if defined(__GNUC__)
169#pragma GCC diagnostic push
170
171#if defined(__clang__)
172#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
173#endif // defined(__clang__)
174#endif // defined(__GNUC__)
175
176#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_DEPRECATED_ENABLED)
186 // Deprecated since 6.0.0; use initialise (argc, argv) and
187 // add_top_suite().
188 suite&
189 runner::initialise (int argc, char* argv[], const char* top_suite_name)
190 {
192 {
193 return top_suite_;
194 }
195
196 initialise (argc, argv);
197
198 return add_top_suite (top_suite_name != nullptr ? top_suite_name : "");
199 }
200#endif // defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_DEPRECATED_ENABLED)
201
215 void
216 runner::initialise (int argc, char* argv[])
217 {
218#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
219 trace::printf ("%s\n", __PRETTY_FUNCTION__);
220
221#if !(defined(MICRO_OS_PLUS_STARTUP_ENABLED) \
222 && defined(MICRO_OS_PLUS_DIAG_TRACE_ENABLED))
223#if defined(MICRO_OS_PLUS_DEBUG_ENABLED)
224 trace::printf ("argv[");
225 for (int i = 0; i < argc; ++i)
226 {
227 if (i > 0)
228 {
229 trace::printf (", ");
230 }
231 trace::printf ("'%s'", argv[i]);
232 }
233 trace::puts ("]");
234#endif // defined(MICRO_OS_PLUS_DEBUG_ENABLED)
235#endif // !defined(MICRO_OS_PLUS_STARTUP_ENABLED)
236#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
237
239 {
241 return;
242 }
243
244 initialise (runner_options{ argc, argv });
245 }
246
272 void
274 {
275#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
276 trace::printf ("%s\n", __PRETTY_FUNCTION__);
277#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
278
279 if (aborted_)
280 {
281 fprintf (stderr, "error: test execution aborted\n");
282 return;
283 }
284
286 {
287 reject_call ("test runner already initialised");
288 return;
289 }
290
291 // Move the vectors, since their copy assignment uses std::copy, which
292 // triggers -Waggregate-return in the standard library headers on some
293 // targets.
294 options_ = std::move (options);
295
296 // With errors in the options, do not proceed: the errors are written on
297 // the console and in the output file, if any, which is truncated, so
298 // that it never keeps the results of an earlier run; no test is run, and
299 // `run_suites()` returns 2. The same for `--help`, which writes the
300 // usage instead of the errors, only on the console, and `run_suites()`
301 // returns 0. A reporter is still created, since the suites and the test
302 // cases refer to it.
304 {
305 runner_options console_options{ options_ };
306 if (!options_.has_errors ())
307 {
308 console_options.output_file_path.clear ();
309 }
310 if (console_options.selected_reporter == reporter_kind::human)
311 {
313 = std::make_unique<detail::reporter_human> (console_options);
314 }
315 else
316 {
318 = std::make_unique<detail::reporter_tap> (console_options);
319 }
320
321 for (const std::string& error : options_.errors ())
322 {
323 fprintf (stderr, "error: %s\n", error.c_str ());
324 reporter_->write_line (
326 reporter_->error_prefix (), error.c_str ());
327 }
329 {
332 "%sUse --help to list the options.\n",
333 reporter_->comment_prefix ());
334 }
335 if (options_.help && !options_.has_errors ())
336 {
337 // Requested, so written also with the silent verbosity.
338 const char* program = options_.arguments ().empty ()
339 ? "<program>"
341 options_.arguments ()[0].c_str ());
342 reporter_->write_line (true,
343 "Usage: %s [options] [--] "
344 "[arguments]\n%s",
345 program, help_options);
346 }
347 reporter_->flush_streams ();
348
349 exit_code_ = options_.has_errors () ? 2 : 0;
351 return;
352 }
353
354 // Initialise and configure the reporter; it keeps its own copy of the
355 // verbosity, taken from the same options.
357 {
358 reporter_ = std::make_unique<detail::reporter_human> (options_);
359 }
360 else
361 {
362 reporter_ = std::make_unique<detail::reporter_tap> (options_);
363 }
364
365 // If the output file cannot be opened, do not run the tests either.
366 if (reporter_->has_output_file_error ())
367 {
369 "%sfailed to open output file '%s'\n",
370 reporter_->error_prefix (),
371 options_.output_file_path.c_str ());
372 reporter_->flush_streams ();
373
374 exit_code_ = 2;
376 return;
377 }
378
379 // ------------------------------------------------------------------------
380
381 // When listing, the session is not reported; only the header of the
382 // list is written, and the test cases are listed as they are created.
384 {
385 reporter_->write_line (true, "%s\n",
387 ? "All available test cases:"
388 : "Matching test cases:");
390 return;
391 }
392
393 stopwatch_.start ();
394 reporter_->begin_session (*this);
395
397 }
398
419 suite&
420 runner::add_top_suite (const located_name& top_suite_name)
421 {
422 const std::string_view requested_name{ top_suite_name.name () };
423
424#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
425 trace::printf ("%s\n", __PRETTY_FUNCTION__);
426#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
427
428 if (aborted_)
429 {
430 fprintf (stderr, "error: test execution aborted\n");
431 return top_suite_;
432 }
433
435 {
437 }
438
440 {
441 return top_suite_;
442 }
443
444 if (has_top_suite_)
445 {
446 reject_call ("top suite already added", &top_suite_name.location ());
447 return top_suite_;
448 }
449
450 if (!requested_name.empty ())
451 {
452 // If provided by this call, use it, possibly override the
453 // deprecated constructor.
454 top_suite_.located_name_ = top_suite_name;
456 }
457 else if (strlen (top_suite_.name ()) == 0)
458 {
459 // If not provided by the constructor or by this call, try to extract a
460 // name from argv[0], which is commonly the executable name. If that
461 // fails, use a default name.
462 if (!options_.arguments ().empty ())
463 {
464 std::string_view top_suite_name_view{ utility::extract_file_name (
465 options_.arguments ()[0].c_str ()) };
466
467 const auto dot_pos = top_suite_name_view.rfind ('.');
468 if (dot_pos != std::string_view::npos)
469 {
470 top_suite_name_view = top_suite_name_view.substr (0, dot_pos);
471 }
472
474 = located_name{ top_suite_name_view,
475 top_suite_name.location () };
476 }
477 else
478 {
480 = located_name{ "default suite", top_suite_name.location () };
481 }
483 }
484
485 // Named first, so that the rejection names it.
487 {
488 reject_suite (top_suite_.name (), top_suite_name.location ());
489 return top_suite_;
490 }
491
492 has_top_suite_ = true;
493
494 // The top suite runs until run_suites() is called; its test cases
495 // are accepted only meanwhile.
497
498 // When listing, the top suite is not reported; its test cases are
499 // listed as they are created.
500 if (!options_.list_tests)
501 {
503 reporter_->begin_suite (top_suite_);
504 }
505
506 return top_suite_;
507 }
508
513 suite&
515 {
516 return add_top_suite (located_name{ "" });
517 }
518
519#if defined(__GNUC__)
520#pragma GCC diagnostic pop
521#endif // defined(__GNUC__)
522
529 bool
530 runner::is_selected (const char* name, size_t level) const
531 {
532 if (level >= options_.filter_patterns.size ())
533 {
534 return true;
535 }
536
537 std::string_view alternatives{ options_.filter_patterns[level] };
538 while (true)
539 {
540 const size_t separator = alternatives.find ('|');
541 if (utility::is_match (name, alternatives.substr (0, separator)))
542 {
543 return true;
544 }
545 if (separator == std::string_view::npos)
546 {
547 return false;
548 }
549 alternatives.remove_prefix (separator + 1);
550 }
551 }
552
553 // --------------------------------------------------------------------------
554
562 void
564 const test_case& test_case)
565 {
566 if (&suite != listed_suite_)
567 {
570 reporter_->write_line (true, " %s\n", suite.name ());
571 }
572
574 reporter_->write_line (true, " %s\n", test_case.name ());
575 }
576
577 // --------------------------------------------------------------------------
578
598 void
599 runner::register_suite (std::unique_ptr<micro_test_plus::suite> suite)
600 {
601#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
602 trace::printf ("%s '%s'\n", __PRETTY_FUNCTION__, suite->name ());
603#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
604
606 {
607 // Nothing runs in a declined session; the suite is discarded.
608 return;
609 }
610
613 {
614 reject_suite (suite->name (), suite->located_name_.location ());
615 return;
616 }
617
618 children_suites_.push_back (std::move (suite));
619 children_suites_.back ()->link ();
620 }
621
627 void
629 const reflection::source_location& location)
630 {
631 std::string message{ "suite '" };
632 message.append (name);
633 message.append ("' added after run_suites() started, rejected");
634
635 reject_call (message, &location);
636 }
637
659 void
660 runner::reject_call (const std::string& message,
661 const reflection::source_location* location)
662 {
663 fprintf (stderr, "error: %s\n", message.c_str ());
664 mark_rejected ();
665
667 || aborted_)
668 {
669 return;
670 }
671
673 {
675 "%serror: %s\n", reporter_->comment_prefix (),
676 message.c_str ());
677 reporter_->flush_streams ();
678 return;
679 }
680
681 if (running_test_case_ != nullptr)
682 {
684 message, location != nullptr
685 ? *location
687 return;
688 }
689
690 if (running_suite_ != nullptr)
691 {
693 reporter_->fail_suite (message, *running_suite_);
695 return;
696 }
697
699 "%serror: %s\n", reporter_->comment_prefix (),
700 message.c_str ());
701 reporter_->flush_streams ();
702 }
703
710 void
711 runner::mark_rejected (void) noexcept
712 {
713 has_rejected_calls_ = true;
715 {
716 exit_code_ = 1;
717 }
718 }
719
727 void
730 {
731 for (const runner* started = started_first_; started != nullptr;
732 started = started->started_next_)
733 {
734 if (started == &test_runner)
735 {
736 test_runner.reject_suite (suite.name (),
737 suite.located_name_.location ());
738 return;
739 }
740 }
741
742 suite.link ();
743 }
744
750 constinit runner* runner::started_first_ = nullptr;
751
777 void
779 {
780 // The top suite, if added, has index 1.
781 size_t own_index = has_top_suite_ ? 1 : 0;
782 for (micro_test_plus::suite* suite_ptr = suite::first_;
783 suite_ptr != nullptr; suite_ptr = suite_ptr->next_)
784 {
785 // Skip the suites run by other runners.
786 if (&suite_ptr->test_runner () != this)
787 {
788 continue;
789 }
790
791 suite_ptr->own_index_ = ++own_index;
792
793 if (!is_selected (suite_ptr->name (), 0))
794 {
796 if (!options_.list_tests)
797 {
798 reporter_->skip_suite (*suite_ptr);
799 }
800 continue;
801 }
802
803 suite_ptr->run ();
804
805 // Accumulate the totals from the child suite into the runner
806 // totals.
807 // DO NOT increment executed_test_cases here.
808 totals_ += suite_ptr->totals ();
809 }
810 }
811
839 int
841 {
842#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
843 trace::printf ("%s\n", __PRETTY_FUNCTION__);
844#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
845
846 if (aborted_)
847 {
848 fprintf (stderr, "error: test execution aborted\n");
849 return 1;
850 }
851
854 {
855 // The session has ended; do not run the suites again.
856 return exit_code_;
857 }
858
860 {
861 fprintf (stderr, "error: test runner already running\n");
862 return 1;
863 }
864
866 {
868 }
869
871 running_suite_ = nullptr;
873 started_first_ = this;
874
875 // When listing, the suites run only to create their test cases, which
876 // are listed, and the number of listed test cases ends the list.
878 {
880
881 const size_t test_cases = listed_test_cases_count_;
882 const size_t suites = listed_suites_count_;
883 reporter_->write_line (
884 true,
887 " test suite%s\n",
888 test_cases, (test_cases == 1) ? "" : "s", suites,
889 (suites == 1) ? "" : "s");
890
891 // As for a run, filters that select no test case are an error.
892 const bool listed_nothing = total_suites_count () != 0
893 && !options_.filter_patterns.empty ()
895 if (listed_nothing)
896 {
897 fprintf (stderr, "error: the filters selected no test case\n");
898 reporter_->write_line (
900 "%serror: the filters selected no test case\n",
901 reporter_->comment_prefix ());
902 }
903 reporter_->flush_streams ();
904
905 if (listed_nothing || has_option_errors ())
906 {
907 exit_code_ = 2;
908 }
909 else
910 {
912 }
914 return exit_code_;
915 }
916
917 if (has_top_suite_)
918 {
920 reporter_->end_suite (top_suite_);
922 }
923
925
926 // A session without suites runs nothing; report it.
927 const bool has_no_suites = (total_suites_count () == 0);
928 if (has_no_suites)
929 {
930 fprintf (stderr, "error: no test suites\n");
932 "%serror: no test suites\n",
933 reporter_->comment_prefix ());
934 }
935
936 // A filter that selects no test case disables the tests; report it.
937 const bool selected_nothing = !has_no_suites
938 && !options_.filter_patterns.empty ()
939 && totals_.executed_test_cases () == 0;
940 if (selected_nothing)
941 {
942 fprintf (stderr, "error: the filters selected no test case\n");
944 "%serror: the filters selected no test case\n",
945 reporter_->comment_prefix ());
946 }
947
948 stopwatch_.stop ();
949 reporter_->end_session (*this);
950
951 if (selected_nothing || has_option_errors ())
952 {
953 exit_code_ = 2;
954 }
955 else
956 {
958 = (totals_.passed () && !has_rejected_calls_ && !has_no_suites)
959 ? 0
960 : 1;
961 }
963
964#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
965 trace::printf ("%s -> %d\n", __PRETTY_FUNCTION__, exit_code_);
966#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
967
968 return exit_code_;
969 }
970
971#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_DEPRECATED_ENABLED)
977 // Deprecated since 6.0.0; use run_suites().
978 int
980 {
981 return run_suites ();
982 }
983#endif // defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_DEPRECATED_ENABLED)
984
992 {
994 abort_handler_ = handler;
995 return previous;
996 }
997
1003 void
1005 {
1006 abort (sl, false);
1007 }
1008
1028 void
1029 runner::abort (const reflection::source_location& sl, bool is_requirement)
1030 {
1031#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
1032 trace::printf ("%s\n", __PRETTY_FUNCTION__);
1033#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
1034
1035 if (!aborted_)
1036 {
1037 aborted_ = true;
1038
1041 {
1042 reporter_->abort_session (sl, is_requirement);
1043 }
1044 else
1045 {
1046 // The type of `line()` depends on the toolchain
1047 // (`uint_least32_t` for `std::source_location`); widen it
1048 // implicitly, without a cast that would be useless on some
1049 // platforms.
1050 const unsigned long line = sl.line ();
1051 fprintf (stderr, "error: test execution aborted at %s:%lu\n",
1053 }
1054 }
1055
1056 fflush (stdout);
1057 fflush (stderr);
1058
1059 if (abort_handler_ != nullptr)
1060 {
1061 abort_handler_ (sl);
1062 }
1063
1064 ::abort ();
1065 }
1066
1072 size_t
1073 runner::added_suites_count (void) const noexcept
1074 {
1075 return children_suites_.size ();
1076 }
1077
1078#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_DEPRECATED_ENABLED)
1084 // Deprecated since 6.0.0; the name is that of the top suite.
1085 const char*
1086 runner::name (void) const noexcept
1087 {
1088 return "runner";
1089 }
1090
1096 // Deprecated since 6.0.0; use added_suites_count() or total_suites_count().
1097 size_t
1098 runner::suites_count (void) const noexcept
1099 {
1100 return added_suites_count () + 1;
1101 }
1102#endif // defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_DEPRECATED_ENABLED)
1103
1110 size_t
1111 runner::static_suites_count (void) const noexcept
1112 {
1113 size_t count = 0;
1114 for (const micro_test_plus::suite* suite_ptr = suite::first_;
1115 suite_ptr != nullptr; suite_ptr = suite_ptr->next_)
1116 {
1117 if (&suite_ptr->test_runner () == this)
1118 {
1119 ++count;
1120 }
1121 }
1122 return count - children_suites_.size ();
1123 }
1124
1130 size_t
1131 runner::total_suites_count (void) const noexcept
1132 {
1133 return (has_top_suite_ ? 1u : 0u) + added_suites_count ()
1135 }
1136
1141 size_t
1142 runner::skipped_suites_count (void) const noexcept
1143 {
1144 return skipped_suites_count_;
1145 }
1146
1147 // --------------------------------------------------------------------------
1148} // namespace micro_os_plus::micro_test_plus
1149
1150// ----------------------------------------------------------------------------
1151
1152#endif // defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_ENABLED)
1153
1154// ----------------------------------------------------------------------------
bool passed(void) const noexcept
Checks whether all executed checks and test cases were successful.
size_t executed_test_cases(void) const noexcept
Returns the number of test cases that were executed.
void increment_failed_checks(size_t count=1) noexcept
Increments the failed-checks counter.
size_t next_test_point_number(void) noexcept
Advances to the next child test point, and returns its number.
const char * name(void) const noexcept
Returns the node name.
const counters & totals(void) const noexcept
Returns the totals of the node.
void stop(void) noexcept
Records the stop time, from the system clock.
void start(void) noexcept
Records the start time, from the system clock.
Definition stopwatch.cpp:87
A name of a suite or of a test case, with the location where it was given.
Definition test.h:177
const char * name(void) const noexcept
Returns the name.
const reflection::source_location & location(void) const noexcept
Returns the location where the name was given.
Local implementation of source location information for diagnostics.
Definition reflection.h:143
constexpr auto file_name(void) const noexcept
Returns the file name associated with this source location.
constexpr auto line(void) const noexcept
Returns the line number associated with this source location.
The configuration of a test session, and its command-line parser.
bool has_unknown_option(void) const noexcept
Checks whether an unknown option was found while parsing the command line.
bool help
Whether to display the usage and the list of the options, instead of running the tests.
const std::vector< std::string > & errors(void) const noexcept
Returns the errors found while parsing the command line.
bool has_errors(void) const noexcept
Checks whether errors were found while parsing the command line.
std::vector< std::string > filter_patterns
The patterns that select the suites and the test cases to run, one per nesting level.
std::string output_file_path
Path of the optional output file.
const std::vector< std::string > & arguments(void) const noexcept
Returns the complete command line, including argv[0], if any.
bool list_tests
Whether the test cases are listed instead of run.
reporter_kind selected_reporter
The reporter that displays the results.
micro_test_plus::verbosity verbosity_level
The level of detail of the console output.
The test runner for the µTest++ framework.
Definition runner.h:187
void reject_suite(const char *name, const reflection::source_location &location)
Rejects a suite constructed after run_suites() has started.
Definition runner.cpp:628
class suite * running_suite_
The suite whose body is running, if any.
Definition runner.h:1409
counters totals_
Totals of the test session.
Definition runner.h:1294
void run_child_suites(void)
Runs all registered test suites.
Definition runner.cpp:778
void list_test_case(const class suite &suite, const class test_case &test_case)
Lists a test case, instead of running it.
Definition runner.cpp:563
abort_handler_t abort_handler_
The function called by abort(), if not null.
Definition runner.h:1373
bool has_option_errors(void) const noexcept
Checks whether an option error was found by initialise().
detail::stopwatch stopwatch_
Stopwatch of this runner.
Definition runner.h:1285
static void link_static_suite(runner &test_runner, class suite &suite) noexcept
Inserts a static suite into the list of suites, or reject it.
Definition runner.cpp:728
int exit_code_
The exit code computed by run_suites().
Definition runner.h:1354
void register_suite(std::unique_ptr< class suite > suite)
Registers a test suite with the runner.
Definition runner.cpp:599
void suite(std::string_view name, Callable_T &&callable, Args_T &&... arguments)
Deprecated name of add_suite().
runner * started_next_
The next runner in the list of the started runners.
Definition runner.h:1152
bool is_selected(const char *name, size_t level) const
Checks whether a suite or a test case is selected by the filter pattern of its nesting level.
Definition runner.cpp:530
size_t skipped_suites_count(void) const noexcept
Returns the count of the test suites skipped by the filter.
Definition runner.cpp:1142
class suite & initialise(int argc, char *argv[], const char *top_suite_name)
Deprecated initialisation with the command-line arguments, which also adds the top suite.
Definition runner.cpp:189
bool has_top_suite_
Whether the top suite was added to the session.
Definition runner.h:1252
void mark_rejected(void) noexcept
Records that a call was rejected.
Definition runner.cpp:711
runner(void)
Constructor for the runner class.
Definition runner.cpp:120
const char * name(void) const noexcept
Deprecated name of the runner.
Definition runner.cpp:1086
static runner * started_first_
The head of the list of the runners that have started.
Definition runner.h:1144
std::unique_ptr< detail::reporter > reporter_
Owning pointer to the test reporter used for outputting test results.
Definition runner.h:1275
size_t static_suites_count(void) const noexcept
Returns the count of static test suites.
Definition runner.cpp:1111
void reject_call(const std::string &message, const reflection::source_location *location=nullptr)
Reports a rejected call, and records it.
Definition runner.cpp:660
size_t suites_count(void) const noexcept
Deprecated count of the test suites added with add_suite(), plus the top suite.
Definition runner.cpp:1098
int run_suites(void)
Runs the registered suites, ends the session, and returns the exit code.
Definition runner.cpp:840
session_state session_state_
The current state of the test session.
Definition runner.h:1345
abort_handler_t set_abort_handler(abort_handler_t handler) noexcept
Sets the function called when test execution is aborted.
Definition runner.cpp:991
class suite & add_top_suite(const located_name &top_suite_name)
Adds the top suite and returns it.
Definition runner.cpp:420
void abort(const reflection::source_location &sl=reflection::source_location::current())
Aborts test execution immediately.
Definition runner.cpp:1004
int exit_code(void)
Deprecated name of run_suites().
Definition runner.cpp:979
size_t listed_test_cases_count_
The number of listed test cases.
Definition runner.h:1427
class top_suite top_suite_
The top suite, whose body is the code of main().
Definition runner.h:1243
size_t added_suites_count(void) const noexcept
Returns the count of the test suites added with add_suite().
Definition runner.cpp:1073
bool has_rejected_calls_
Whether a call was rejected.
Definition runner.h:1365
class suite & add_top_suite(void)
Adds the top suite, without a name, and returns it.
Definition runner.cpp:514
void(*)(const reflection::source_location &sl) abort_handler_t
The type of the function called when test execution is aborted.
Definition runner.h:670
std::vector< std::unique_ptr< class suite > > children_suites_
Owning collection of dynamically registered child suites.
Definition runner.h:1263
size_t total_suites_count(void) const noexcept
Returns the count of all the test suites.
Definition runner.cpp:1131
size_t listed_suites_count_
The number of suites with listed test cases.
Definition runner.h:1436
runner_options options_
The options of the test session.
Definition runner.h:1306
test_case * running_test_case_
The innermost test case being run, if any.
Definition runner.h:1397
bool aborted_
Whether the test execution was aborted.
Definition runner.h:1386
size_t skipped_suites_count_
The number of suites skipped by the filter.
Definition runner.h:1315
~runner()
Destructor for the runner class.
Definition runner.cpp:149
const class suite * listed_suite_
The suite whose name was listed last, if any.
Definition runner.h:1418
A named, runnable test suite registered with the test runner.
Definition test.h:2059
static suite * first_
The first suite in the list of suites.
Definition test.h:2475
suite * next_
The next suite in the list of suites.
Definition test.h:2463
located_name located_name_
The name of the suite, with the location where it was given.
Definition test.h:2453
detail::stopwatch stopwatch_
Stopwatch of this suite.
Definition test.h:2441
A named, runnable test case that lives inside a suite.
Definition test.h:1362
void report_rejected_test(const std::string &message, const reflection::source_location &location)
Reports a rejected call as a failed check of this test case.
Definition test.cpp:493
const located_name & located_name_
The name and the location of the call to test() that created this test case.
Definition test.h:1998
#define MICRO_OS_PLUS_MICRO_TEST_PLUS_PRI_SIZE
Portable printf() conversion for the size_t values.
Definition detail.h:102
const char * extract_file_name(const char *path) noexcept
Extracts the file name component from a full path.
Definition utility.cpp:95
bool is_match(std::string_view input, std::string_view pattern)
Checks whether a string matches a pattern with * and ? wildcards.
Definition utility.cpp:147
constexpr const char * help_options
The text displayed by --help, after the usage line.
Definition runner.cpp:96
Primary namespace for the µTest++ testing framework.
C++ header file with declarations for the µTest++ human-readable reporter.
C++ header file with declarations for the µTest++ TAP test reporter.
C++ header file with declarations for the µTest++ test runner.
C++ header file with declarations for the µTest++ utility helpers.