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 206 of file reporter.cpp.

206 endl (reporter& stream)
207 {
208 stream.endline ();
209 return stream;
210 }

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
43#if defined(MICRO_OS_PLUS_INCLUDE_CONFIG_H)
44#include <micro-os-plus/config.h>
45#endif // MICRO_OS_PLUS_INCLUDE_CONFIG_H
46
47#if defined(MICRO_OS_PLUS_TRACE)
48#include <micro-os-plus/diag/trace.h>
49#endif // MICRO_OS_PLUS_TRACE
50
52
53// ----------------------------------------------------------------------------
54
55#if defined(__GNUC__)
56#pragma GCC diagnostic ignored "-Waggregate-return"
57#if defined(__clang__)
58#pragma clang diagnostic ignored "-Wunknown-warning-option"
59#pragma clang diagnostic ignored "-Wc++98-compat"
60#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
61#endif
62#endif
63
64// =============================================================================
65
67{
68 // --------------------------------------------------------------------------
69
79 reporter::reporter (std::unique_ptr<std::vector<std::string_view>> argvs)
80 {
81#if defined(MICRO_OS_PLUS_TRACE) \
82 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
83 trace::printf ("%s\n", __PRETTY_FUNCTION__);
84#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
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#if defined(__GNUC__)
138#pragma GCC diagnostic push
139#if defined(__clang__)
140#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
141#endif
142#endif
143 fprintf (stderr, "error: Failed to open output file '%.*s'\n",
144 static_cast<int> (output_file_sv.size ()),
145 output_file_sv.data ());
146#if defined(__GNUC__)
147#pragma GCC diagnostic pop
148#endif
149 exit (1);
150 }
151 // The original string is zero terminated, so we can safely use .data()
152 // here.
153 output_file_path_ = output_file_sv.data ();
154 }
155
156 // Pre-allocate buffer to reduce dynamic allocations.
157 buffer_.reserve (128);
158 }
159
168 {
169#if defined(MICRO_OS_PLUS_TRACE) \
170 && defined(MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS)
171 trace::printf ("%s\n", __PRETTY_FUNCTION__);
172#endif // MICRO_OS_PLUS_TRACE_MICRO_TEST_PLUS_CONSTRUCTORS
173
174 if (output_file_ != nullptr)
175 {
176 fflush (output_file_);
177 fclose (output_file_);
178
179#if defined(__GNUC__)
180#pragma GCC diagnostic push
181#if defined(__clang__)
182#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
183#endif
184#endif
185 printf ("Test output written to '%s'.\n", output_file_path_);
186#if defined(__GNUC__)
187#pragma GCC diagnostic pop
188#endif
189
190 output_file_ = nullptr;
191 output_file_path_ = nullptr;
192 }
193 }
194
195 // --------------------------------------------------------------------------
196
206 endl (reporter& stream)
207 {
208 stream.endline ();
209 return stream;
210 }
211
220 void
222 {
223 buffer_.append ("\n");
224 flush ();
225 }
226
236 void
238 {
239 // Pass only the string, do not add an `\n` here.
240 printf ("%s", buffer_.c_str ());
241 }
242
249 void
251 {
252 // Pass only the string, do not add an `\n` here.
253 if (output_file_ != nullptr)
254 {
255 fprintf (output_file_, "%s", buffer_.c_str ());
256 }
257 }
258
269 void
271 {
272 if (argvs_ && !argvs_->empty ())
273 {
274 const auto& args = *argvs_;
275 std::string line;
276 line.reserve (256);
277 line.append (get_comment_prefix ());
278 line.append ("Running: ");
279
280 // Append only the file name part of argv[0].
281 const std::string_view arg0 = args[0];
282 const auto sep = arg0.rfind ('/');
283 line.append ((sep != std::string_view::npos) ? arg0.substr (sep + 1)
284 : arg0);
285
286 for (size_t i = 1; i < args.size (); ++i)
287 {
288 line.append (" ");
289 line.append (args[i]);
290 }
291 line.append ("\n");
292
293 if (output_file_ != nullptr)
294 fprintf (output_file_, "%s", line.c_str ());
295
296#if !(defined(MICRO_OS_PLUS_INCLUDE_STARTUP) && defined(MICRO_OS_PLUS_TRACE))
299 printf ("%s", line.c_str ());
300#endif // !defined(MICRO_OS_PLUS_INCLUDE_STARTUP)
301 }
302
303 {
304 // Build the "Built with ..." line. For the output file the compiler
305 // version is omitted; for stdout it is appended via __VERSION__.
306 std::string line;
307 line.reserve (256);
308 line.append (get_comment_prefix ());
309 line.append ("Built with ");
310#if defined(__clang__)
311 line.append ("clang " __VERSION__);
312#elif defined(__GNUC__)
313 line.append ("GCC " __VERSION__);
314#elif defined(_MSC_VER)
315 line.append ("MSVC");
316 char msvc_ver[16];
317 snprintf (msvc_ver, sizeof (msvc_ver), " - %d", _MSC_VER);
318 line.append (msvc_ver);
319#else
320 line.append ("an unknown compiler");
321#endif
322#if !(defined(__APPLE__) || defined(__linux__) || defined(__unix__) \
323 || defined(WIN32))
324 // This is relevant only on bare-metal.
325#if defined(__ARM_PCS_VFP) || defined(__ARM_FP)
326 line.append (", with FP");
327#else
328 line.append (", no FP");
329#endif
330#endif
331#if defined(__EXCEPTIONS)
332 line.append (", with exceptions");
333#else
334 line.append (", no exceptions");
335#endif
336#if defined(MICRO_OS_PLUS_DEBUG)
337 line.append (", with MICRO_OS_PLUS_DEBUG");
338#endif
339#if defined(MICRO_OS_PLUS_TRACE)
340 line.append (", with MICRO_OS_PLUS_TRACE");
341#endif
342
343 if (output_file_ != nullptr)
344 {
345 fprintf (output_file_, "%s\n", line.c_str ());
346 }
347
348#if !(defined(MICRO_OS_PLUS_INCLUDE_STARTUP) && defined(MICRO_OS_PLUS_TRACE))
350 {
351 printf ("%s\n", line.c_str ());
352 }
353#endif // !defined(MICRO_OS_PLUS_INCLUDE_STARTUP)
354 }
355 }
356
364 void
366 {
367 fflush (stdout);
368 if (output_file_ != nullptr)
369 {
370 fflush (output_file_);
371 }
372 }
373
374 // --------------------------------------------------------------------------
375
387 {
388 // Call the endl function.
389 (*func) (*this);
390 return *this;
391 }
392
402 reporter::operator<<(std::string_view sv)
403 {
404 buffer_.append (sv);
405 return *this;
406 }
407
417 {
418 buffer_.append (1, c);
419 return *this;
420 }
421
431 reporter::operator<<(const char* s)
432 {
433 buffer_.append (s);
434 return *this;
435 }
436
443 void
444 reporter::pass (std::string& message, const std::string& expression,
446 {
448
449 if (message.empty ())
450 {
451 *this << expression;
452 }
453
455 }
456
462 void
463 reporter::fail (bool abort, std::string& message,
464 const std::string& expression, bool has_expression,
465 const reflection::source_location& location,
467 {
468 output_fail_prefix_ (message, has_expression, location, subtest);
469
470 if (has_expression)
471 {
472 *this << expression;
473 }
474
475 output_fail_suffix_ (location, abort, subtest);
476 }
477
478 // --------------------------------------------------------------------------
479} // namespace micro_os_plus::micro_test_plus
480
481// ----------------------------------------------------------------------------

Generated via doxygen2docusaurus 2.2.0 by Doxygen 1.17.0.