Skip to main content

test-reporter-tap.cpp File

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

Included Headers

#include <micro-os-plus/micro-test-plus.h> #include <time.h>

Namespaces Index

namespacemicro_os_plus

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

namespacemicro_test_plus

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

Description

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

This source file contains the implementations for test_reporter_tap, a concrete implementation of the test_reporter abstract interface that formats test results according to the Test Anything Protocol (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.

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
34
35// ----------------------------------------------------------------------------
36
37#if defined(MICRO_OS_PLUS_INCLUDE_CONFIG_H)
38#include <micro-os-plus/config.h>
39#endif // MICRO_OS_PLUS_INCLUDE_CONFIG_H
40
42
43#include <time.h>
44
45// ----------------------------------------------------------------------------
46
47#pragma GCC diagnostic ignored "-Waggregate-return"
48#if defined(__clang__)
49#pragma clang diagnostic ignored "-Wunknown-warning-option"
50#pragma clang diagnostic ignored "-Wc++98-compat"
51#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
52#endif
53
55{
56 // --------------------------------------------------------------------------
57
70 void
72 {
74 {
75 *this << " ";
76 }
77 *this << "ok "
78 << static_cast<int> (current_test_suite->current_test_case.index)
79 << " - ";
80 if (!message.empty ())
81 {
82 *this << message.c_str ();
83 }
84 }
85
101 void
103 {
104 *this << endl;
105
106 flush ();
107 }
108
120 void
122 std::string& message, [[maybe_unused]] const bool hasExpression,
123 [[maybe_unused]] const reflection::source_location& location)
124 {
126 {
127 *this << " ";
128 }
129 *this << "not ok "
130 << static_cast<int> (current_test_suite->current_test_case.index);
131
132 if (!message.empty ())
133 {
134 *this << " - " << message.c_str ();
135 *this << " ";
136 }
137 *this << endl;
138
139 *this << " ---";
140 if (hasExpression)
141 {
142 *this << endl;
143 *this << " expect: ";
144 }
145 }
146
156 void
158 const reflection::source_location& location, bool abort)
159 {
160 if (abort)
161 {
162 *this << " aborted...";
163 }
164 *this << endl;
165 *this << " at:" << endl;
166
167 *this << " filename: "
168 << reflection::short_name (location.file_name ()) << endl;
169 *this << " line: "
171 .line () }
172 << endl;
173
174 *this << " ..." << endl;
175
176 flush ();
177 }
178
187 void
189 {
190 out_.append ("\n");
191 flush ();
192 }
193
201 void
203 {
204 fflush (stdout); // Sync STDOUT.
205 }
206
218 void
219 test_reporter_tap::begin_test_case ([[maybe_unused]] const char* name)
220 {
221 is_in_test_case_ = true;
222
223 if (!out_.empty () && (verbosity == verbosity::verbose))
224 {
226 {
227 printf ("\n");
228 }
229 output ();
230 add_empty_line = true;
231 }
232
233 out_.clear ();
234
235 flush ();
236 }
237
250 void
251 test_reporter_tap::end_test_case ([[maybe_unused]] const char* name)
252 {
254 {
255 if (current_test_suite->current_test_case.failed_checks > 0)
256 {
257 if (true /* add_empty_line */)
258 {
259 printf ("\n");
260 }
261#pragma GCC diagnostic push
262#if defined(__clang__)
263#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
264#endif
265 printf (" # Subtest: %s - test case started\n", name);
266 output ();
267 printf (" 1..%zu\n",
268 current_test_suite->current_test_case.index);
269 printf (" not ok %zu - %s # { test case FAILED, %zu check%s "
270 "passed, %zu failed }\n",
271 current_test_suite->test_cases_count (), name,
272 current_test_suite->current_test_case.successful_checks,
273 current_test_suite->current_test_case.successful_checks
274 == 1
275 ? ""
276 : "s",
277 current_test_suite->current_test_case.failed_checks);
278
279#pragma GCC diagnostic pop
280 add_empty_line = true;
281 }
282 else
283 {
285 {
286 printf ("\n");
287 }
289 {
290#pragma GCC diagnostic push
291#if defined(__clang__)
292#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
293#endif
294 printf (" # Subtest: %s - test case\n", name);
295 output ();
296 printf (" 1..%zu\n",
297 current_test_suite->current_test_case.index);
298 printf (
299 " ok %zu - %s # { test case passed, %zu check%s }\n",
300 current_test_suite->test_cases_count (), name,
301 current_test_suite->current_test_case.successful_checks,
302 current_test_suite->current_test_case.successful_checks
303 == 1
304 ? ""
305 : "s");
306#pragma GCC diagnostic pop
307 add_empty_line = true;
308 }
309 else
310 {
311#pragma GCC diagnostic push
312#if defined(__clang__)
313#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
314#endif
315 printf (
316 " ok %zu - %s # { test case passed, %zu check%s }\n",
317 current_test_suite->test_cases_count (), name,
318 current_test_suite->current_test_case.successful_checks,
319 current_test_suite->current_test_case.successful_checks
320 == 1
321 ? ""
322 : "s");
323#pragma GCC diagnostic pop
324
325 add_empty_line = false;
326 }
327 }
328 }
329
330 out_.clear ();
331 flush ();
332
333 is_in_test_case_ = false;
334 }
335
346 void
348 {
350 {
351 flush ();
352 printf ("\n");
353 }
354
356 {
357 add_empty_line = false;
358 return;
359 }
360
361#pragma GCC diagnostic push
362#if defined(__clang__)
363#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
364#endif
365 printf ("# Subtest: %s - test suite\n", name);
366#pragma GCC diagnostic pop
367
368 add_empty_line = false;
369 }
370
383 void
385 {
387 {
388 return;
389 }
390
391#if defined(_WIN32) || defined(CLOCK_MONOTONIC)
392 long milliseconds = 0;
393 long microseconds = 0;
394 suite.compute_elapsed_time (suite.begin_time, suite.end_time, milliseconds,
395 microseconds);
396#endif
397
398 if (suite.test_cases_count () > 0 && verbosity != verbosity::quiet)
399 {
400 // printf ("\n");
401 add_empty_line = true;
402 }
403
404 // Also fail if none passed.
405 if (suite.failed_checks () == 0 && suite.successful_checks () != 0)
406 {
407#pragma GCC diagnostic push
408#if defined(__clang__)
409#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
410#endif
412 {
413 printf (" 1..%zu\n", suite.test_cases_count ());
414 }
415 printf ("ok %zu - %s # { test suite passed, %zu check%s in %zu test "
416 "case%s",
417 suite.index, suite.name (), suite.successful_checks (),
418 suite.successful_checks () == 1 ? "" : "s",
419 suite.test_cases_count (),
420 suite.test_cases_count () == 1 ? "" : "s");
421#if defined(_WIN32) || defined(CLOCK_MONOTONIC)
422 if (milliseconds > 0 || microseconds > 0)
423 {
424 printf (", time: %ld.%03ld ms", milliseconds, microseconds);
425 }
426#endif
427 printf (" }\n");
428#pragma GCC diagnostic pop
429 }
430 else
431 {
432#pragma GCC diagnostic push
433#if defined(__clang__)
434#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
435#endif
437 {
438 printf (" 1..%zu\n", suite.test_cases_count ());
439 }
440 printf ("not ok %zu - %s # { test suite FAILED, %zu check%s passed, "
441 "%zu failed, in %zu test case%s",
442 suite.index, suite.name (), suite.successful_checks (),
443 suite.successful_checks () == 1 ? "" : "s",
444 suite.failed_checks (), suite.test_cases_count (),
445 suite.test_cases_count () == 1 ? "" : "s");
446#if defined(_WIN32) || defined(CLOCK_MONOTONIC)
447 if (milliseconds > 0 || microseconds > 0)
448 {
449 printf (", time: %ld.%03ld ms", milliseconds, microseconds);
450 }
451#endif
452 printf (" }\n");
453#pragma GCC diagnostic pop
454 }
455
456 flush ();
457 }
458
459 void
460 test_reporter_tap::begin_test (size_t test_suites_count)
461 {
463 {
464 printf ("\nTAP version 14\n");
465 printf ("1..%zu\n", test_suites_count ? test_suites_count : 1);
466 flush ();
467 }
468 add_empty_line = false;
469 }
470
471#pragma GCC diagnostic push
472#pragma GCC diagnostic ignored "-Wshadow"
473 void
475 {
477 {
478#if defined(_WIN32) || defined(CLOCK_MONOTONIC)
479 long milliseconds = 0;
480 long microseconds = 0;
481 runner.default_test_suite->compute_elapsed_time (
482 runner.begin_time, runner.end_time, milliseconds, microseconds);
483#endif
484
485#pragma GCC diagnostic push
486#if defined(__clang__)
487#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
488#endif
489 printf ("\n# { total: %zu check%s passed, %zu failed, in %zu test "
490 "case%s, %zu test suite%s",
491 runner.totals.successful_checks,
492 runner.totals.successful_checks == 1 ? "" : "s",
493 runner.totals.failed_checks, runner.totals.test_cases_count,
494 runner.totals.test_cases_count == 1 ? "" : "s",
495 runner.test_suites_count (),
496 runner.test_suites_count () == 1 ? "" : "s");
497
498#if defined(_WIN32) || defined(CLOCK_MONOTONIC)
499 if (milliseconds > 0 || microseconds > 0)
500 {
501 printf (", time: %ld.%03ld ms", milliseconds, microseconds);
502 }
503#endif
504 printf (" }\n");
505#pragma GCC diagnostic pop
506 flush ();
507 }
508 }
509#pragma GCC diagnostic pop
510
520 void
522 {
523 printf ("%s", out_.c_str ()); // No `\n` here.
524 out_.clear ();
525 }
526
527 // --------------------------------------------------------------------------
528} // namespace micro_os_plus::micro_test_plus
529
530// ----------------------------------------------------------------------------

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.14.0.