Skip to main content

reporter.cpp File

C++ source file with implementations for the µTest++ test reporter methods. More...

Included Headers

Namespaces Index

namespacemicro_os_plus

The primary namespace for the µOS++ framework. More...

namespacemicro_test_plus

Primary namespace for the µTest++ testing framework. More...

Functions Index

reporter &endl (reporter &stream)

Output stream manipulator for ending a line in test reports. More...

Description

C++ source file with implementations for the µTest++ test reporter methods.

This source file contains the core implementations for the test reporting facilities of the µTest++ framework. It provides lifecycle and utility behaviour for reporters, including command-line option parsing, output-file handling, informational banner emission, buffering helpers, stream operators, and pass/fail dispatch to reporter-specific prefix/ suffix hooks.

Concrete formatting behaviour is implemented by derived reporters (reporter_human and reporter_tap).

All definitions reside within the micro_os_plus::micro_test_plus namespace, ensuring clear separation from user code and minimising the risk of naming conflicts.

This file must be included when building the µTest++ library.

Functions

endl()

reporter & micro_os_plus::micro_test_plus::endl (reporter & stream)

Output stream manipulator for ending a line in test reports.

Parameters
stream

Reference to the reporter instance.

Returns

Reference to the same reporter instance, enabling chaining of output operations.

The endl function inserts a newline character into the specified reporter stream and flushes its output buffer. This operation ensures that each test output line is clearly separated and immediately visible, facilitating the readability and clarity of test results across all test cases and folders within the µTest++ framework.

Definition at line 187 of file reporter.cpp.

187 endl (reporter& stream)
188 {
189 stream.endline ();
190 return stream;
191 }

Reference micro_os_plus::micro_test_plus::reporter::endline.

Referenced by micro_os_plus::micro_test_plus::reporter_tap::output_fail_prefix_, micro_os_plus::micro_test_plus::reporter_human::output_fail_suffix_, micro_os_plus::micro_test_plus::reporter_tap::output_fail_suffix_, micro_os_plus::micro_test_plus::reporter_human::output_pass_suffix_ and micro_os_plus::micro_test_plus::reporter_tap::output_pass_suffix_.

File Listing

The file content with the documentation metadata removed is:

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 Software License,
13 * which can be obtained from https://www.boost.org/LICENSE_1_0.txt.
14 */
15
16// ----------------------------------------------------------------------------
17
40
41// ----------------------------------------------------------------------------
42
44
45#if __has_include("micro-os-plus/diag/trace.h")
46#include "micro-os-plus/diag/trace.h"
47#endif // __has_include("micro-os-plus/diag/trace.h")
48
49// ----------------------------------------------------------------------------
50
51#if defined(__GNUC__)
52#pragma GCC diagnostic ignored "-Waggregate-return"
53#if defined(__clang__)
54#pragma clang diagnostic ignored "-Wunknown-warning-option"
55#pragma clang diagnostic ignored "-Wc++98-compat"
56#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
57#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
58#endif // defined(__clang__)
59#endif // defined(__GNUC__)
60
61// =============================================================================
62
63#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_ENABLED)
64
65// ----------------------------------------------------------------------------
66
68{
69 // --------------------------------------------------------------------------
70
80 reporter::reporter (std::unique_ptr<std::vector<std::string_view>> argvs)
81 {
82#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
83 trace::printf ("%s\n", __PRETTY_FUNCTION__);
84#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
85
86 std::string_view output_file_sv{};
87
88 argvs_ = std::move (argvs);
89
90 static constexpr std::string_view output_file_prefix{ "--output-file=" };
91 if (argvs_)
92 {
93 const auto& args = *argvs_;
94 for (size_t i = 0; i < args.size (); ++i)
95 {
96 if (args[i] == "--verbose")
97 {
99 }
100 else if (args[i] == "--quiet")
101 {
103 }
104 else if (args[i] == "--silent")
105 {
107 }
108 else if (args[i].starts_with (output_file_prefix))
109 {
110 output_file_sv = args[i].substr (output_file_prefix.size ());
111 }
112 else if (args[i]
113 == output_file_prefix.substr (
114 0, output_file_prefix.size () - 1))
115 {
116 if (i + 1 < args.size ())
117 {
118 output_file_sv = args[++i];
119 }
120 else
121 {
122 fprintf (stderr, "error: --output-file option requires a "
123 "file path argument\n");
124 exit (1);
125 }
126 }
127 }
128 }
129
130 if (!output_file_sv.empty ())
131 {
132 // .data() is safe: all string_views are views into argv[]
133 // entries, which are null-terminated C strings.
134 output_file_ = fopen (output_file_sv.data (), "w");
135 if (output_file_ == nullptr)
136 {
137 fprintf (stderr, "error: Failed to open output file '%.*s'\n",
138 static_cast<int> (output_file_sv.size ()),
139 output_file_sv.data ());
140 exit (1);
141 }
142 // The original string is zero terminated, so we can safely use .data()
143 // here.
144 output_file_path_ = output_file_sv.data ();
145 }
146
147 // Pre-allocate buffer to reduce dynamic allocations.
148 buffer_.reserve (128);
149 }
150
159 {
160#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED)
161 trace::printf ("%s\n", __PRETTY_FUNCTION__);
162#endif // MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_CONSTRUCTORS_ENABLED
163
164 if (output_file_ != nullptr)
165 {
166 fflush (output_file_);
167 fclose (output_file_);
168
169 printf ("Test output written to '%s'.\n", output_file_path_);
170
171 output_file_ = nullptr;
172 output_file_path_ = nullptr;
173 }
174 }
175
176 // --------------------------------------------------------------------------
177
187 endl (reporter& stream)
188 {
189 stream.endline ();
190 return stream;
191 }
192
201 void
203 {
204 buffer_.append ("\n");
205 flush ();
206 }
207
217 void
219 {
220 // Pass only the string, do not add an `\n` here.
221 printf ("%s", buffer_.c_str ());
222 }
223
230 void
232 {
233 // Pass only the string, do not add an `\n` here.
234 if (output_file_ != nullptr)
235 {
236 fprintf (output_file_, "%s", buffer_.c_str ());
237 }
238 }
239
250 void
252 {
253 if (argvs_ && !argvs_->empty ())
254 {
255 const auto& args = *argvs_;
256 std::string line;
257 line.reserve (256);
258 line.append (get_comment_prefix ());
259 line.append ("Running: ");
260
261 // Append only the file name part of argv[0].
262 const std::string_view arg0 = args[0];
263 const auto sep = arg0.rfind ('/');
264 line.append ((sep != std::string_view::npos) ? arg0.substr (sep + 1)
265 : arg0);
266
267 for (size_t i = 1; i < args.size (); ++i)
268 {
269 line.append (" ");
270 line.append (args[i]);
271 }
272 line.append ("\n");
273
274 if (output_file_ != nullptr)
275 fprintf (output_file_, "%s", line.c_str ());
276
277#if !(defined(MICRO_OS_PLUS_STARTUP_ENABLED) \
278 && defined(MICRO_OS_PLUS_DIAG_TRACE_ENABLED))
281 printf ("%s", line.c_str ());
282#endif // !defined(MICRO_OS_PLUS_STARTUP_ENABLED)
283 }
284
285 {
286 // Build the "Built with ..." line. For the output file the compiler
287 // version is omitted; for stdout it is appended via __VERSION__.
288 std::string line;
289 line.reserve (256);
290 line.append (get_comment_prefix ());
291 line.append ("Built with ");
292#if defined(__clang__)
293 line.append ("clang " __VERSION__);
294#elif defined(__GNUC__)
295 line.append ("GCC " __VERSION__);
296#elif defined(_MSC_VER)
297 line.append ("MSVC");
298 char msvc_ver[16];
299 snprintf (msvc_ver, sizeof (msvc_ver), " - %d", _MSC_VER);
300 line.append (msvc_ver);
301#else
302 line.append ("an unknown compiler");
303#endif // defined(__clang__)
304#if !(defined(__APPLE__) || defined(__linux__) || defined(__unix__) \
305 || defined(WIN32))
306 // This is relevant only on bare-metal.
307#if defined(__ARM_PCS_VFP) || defined(__ARM_FP)
308 line.append (", with FP");
309#else
310 line.append (", no FP");
311#endif // defined(__ARM_PCS_VFP) || defined(__ARM_FP)
312#endif // !(defined(__APPLE__) || defined(__linux__) || defined(__unix__) || defined(WIN32))
313#if defined(__EXCEPTIONS)
314 line.append (", with exceptions");
315#else
316 line.append (", no exceptions");
317#endif // defined(__EXCEPTIONS)
318#if defined(MICRO_OS_PLUS_DEBUG_ENABLED)
319 line.append (", with MICRO_OS_PLUS_DEBUG_ENABLED");
320#endif // defined(MICRO_OS_PLUS_DEBUG_ENABLED)
321#if defined(MICRO_OS_PLUS_DIAG_TRACE_ENABLED)
322 line.append (", with MICRO_OS_PLUS_DIAG_TRACE_ENABLED");
323#endif // defined(MICRO_OS_PLUS_DIAG_TRACE_ENABLED)
324
325 if (output_file_ != nullptr)
326 {
327 fprintf (output_file_, "%s\n", line.c_str ());
328 }
329
330#if !(defined(MICRO_OS_PLUS_STARTUP_ENABLED) \
331 && defined(MICRO_OS_PLUS_DIAG_TRACE_ENABLED))
333 {
334 printf ("%s\n", line.c_str ());
335 }
336#endif // !defined(MICRO_OS_PLUS_STARTUP_ENABLED)
337 }
338 }
339
347 void
349 {
350 fflush (stdout);
351 if (output_file_ != nullptr)
352 {
353 fflush (output_file_);
354 }
355 }
356
357 // --------------------------------------------------------------------------
358
370 {
371 // Call the endl function.
372 (*func) (*this);
373 return *this;
374 }
375
385 reporter::operator<<(std::string_view sv)
386 {
387 buffer_.append (sv);
388 return *this;
389 }
390
400 {
401 buffer_.append (1, c);
402 return *this;
403 }
404
414 reporter::operator<<(const char* s)
415 {
416 buffer_.append (s);
417 return *this;
418 }
419
426 void
427 reporter::pass (std::string& message, const std::string& expression,
429 {
431
432 if (message.empty ())
433 {
434 *this << expression;
435 }
436
438 }
439
445 void
446 reporter::fail (bool abort, std::string& message,
447 const std::string& expression, bool has_expression,
448 const reflection::source_location& location,
450 {
451 output_fail_prefix_ (message, has_expression, location, subtest);
452
453 if (has_expression)
454 {
455 *this << expression;
456 }
457
458 output_fail_suffix_ (location, abort, subtest);
459 }
460
461 // --------------------------------------------------------------------------
462} // namespace micro_os_plus::micro_test_plus
463
464// ----------------------------------------------------------------------------
465
466#endif // defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_ENABLED)
467
468// ----------------------------------------------------------------------------

Generated via doxygen2docusaurus 2.2.2 by Doxygen 1.17.0.