@micro-os-plus/micro-test-plus 3.3.1 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/CHANGELOG.md +412 -2
  2. package/CMakeLists.txt +134 -28
  3. package/README.md +3 -2
  4. package/config/xcdl-build.json +11 -4
  5. package/include/micro-os-plus/micro-test-plus/README.md +6 -0
  6. package/include/micro-os-plus/micro-test-plus/deferred-reporter.h +267 -0
  7. package/include/micro-os-plus/micro-test-plus/detail.h +272 -1425
  8. package/include/micro-os-plus/micro-test-plus/exceptions.h +125 -0
  9. package/include/micro-os-plus/micro-test-plus/expression-formatter.h +669 -0
  10. package/include/micro-os-plus/micro-test-plus/function-comparators.h +15 -7
  11. package/include/micro-os-plus/micro-test-plus/inlines/{details-inlines.h → deferred-reporter-inlines.h} +66 -44
  12. package/include/micro-os-plus/micro-test-plus/inlines/detail-inlines.h +711 -0
  13. package/include/micro-os-plus/micro-test-plus/inlines/exceptions-inline.h +137 -0
  14. package/include/micro-os-plus/micro-test-plus/inlines/{test-reporter-inlines.h → expression-formatter-inlines.h} +232 -198
  15. package/include/micro-os-plus/micro-test-plus/inlines/function-comparators-inlines.h +24 -20
  16. package/include/micro-os-plus/micro-test-plus/inlines/literals-inlines.h +50 -31
  17. package/include/micro-os-plus/micro-test-plus/inlines/math-inlines.h +25 -19
  18. package/include/micro-os-plus/micro-test-plus/inlines/operators-inlines.h +275 -0
  19. package/include/micro-os-plus/micro-test-plus/inlines/reflection-inlines.h +39 -21
  20. package/include/micro-os-plus/micro-test-plus/inlines/reporter-inlines.h +205 -0
  21. package/include/micro-os-plus/micro-test-plus/inlines/runner-inlines.h +151 -0
  22. package/include/micro-os-plus/micro-test-plus/inlines/runner-totals-inlines.h +152 -0
  23. package/include/micro-os-plus/micro-test-plus/inlines/test-inlines.h +555 -0
  24. package/include/micro-os-plus/micro-test-plus/inlines/timings-inlines.h +120 -0
  25. package/include/micro-os-plus/micro-test-plus/inlines/type-traits-inlines.h +231 -0
  26. package/include/micro-os-plus/micro-test-plus/inlines/utility-inlines.h +126 -0
  27. package/include/micro-os-plus/micro-test-plus/literals.h +12 -17
  28. package/include/micro-os-plus/micro-test-plus/math.h +14 -6
  29. package/include/micro-os-plus/micro-test-plus/operators.h +53 -209
  30. package/include/micro-os-plus/micro-test-plus/reflection.h +8 -4
  31. package/include/micro-os-plus/micro-test-plus/{test-reporter-basic.h → reporter-human.h} +80 -74
  32. package/include/micro-os-plus/micro-test-plus/{test-reporter-tap.h → reporter-tap.h} +77 -71
  33. package/include/micro-os-plus/micro-test-plus/reporter.h +619 -0
  34. package/include/micro-os-plus/micro-test-plus/runner-totals.h +250 -0
  35. package/include/micro-os-plus/micro-test-plus/runner.h +472 -0
  36. package/include/micro-os-plus/micro-test-plus/test.h +1013 -0
  37. package/include/micro-os-plus/micro-test-plus/timings.h +363 -0
  38. package/include/micro-os-plus/micro-test-plus/type-traits.h +223 -577
  39. package/include/micro-os-plus/micro-test-plus/utility.h +136 -0
  40. package/include/micro-os-plus/micro-test-plus.h +42 -236
  41. package/meson.build +11 -6
  42. package/package.json +11 -3
  43. package/src/deferred-reporter.cpp +137 -0
  44. package/src/expression-formatter.cpp +289 -0
  45. package/src/reflection.cpp +97 -0
  46. package/src/reporter-human.cpp +816 -0
  47. package/src/reporter-tap.cpp +772 -0
  48. package/src/reporter.cpp +481 -0
  49. package/src/runner-totals.cpp +98 -0
  50. package/src/runner.cpp +669 -0
  51. package/src/test.cpp +503 -0
  52. package/src/timings.cpp +210 -0
  53. package/src/utility.cpp +163 -0
  54. package/.cmake-format.yaml +0 -11
  55. package/include/micro-os-plus/micro-test-plus/inlines/micro-test-plus-inlines.h +0 -313
  56. package/include/micro-os-plus/micro-test-plus/inlines/test-suite-inlines.h +0 -115
  57. package/include/micro-os-plus/micro-test-plus/test-reporter.h +0 -846
  58. package/include/micro-os-plus/micro-test-plus/test-runner.h +0 -281
  59. package/include/micro-os-plus/micro-test-plus/test-suite.h +0 -492
  60. package/src/micro-test-plus.cpp +0 -316
  61. package/src/test-reporter-basic.cpp +0 -466
  62. package/src/test-reporter-tap.cpp +0 -530
  63. package/src/test-reporter.cpp +0 -399
  64. package/src/test-runner.cpp +0 -311
  65. package/src/test-suite.cpp +0 -304
@@ -1,530 +0,0 @@
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.0 Software License,
13
- * which can be obtained from https://www.boost.org/LICENSE_1_0.txt.
14
- */
15
-
16
- // ----------------------------------------------------------------------------
17
-
18
- /**
19
- * @file
20
- * @brief C++ source file with implementations for the µTest++ TAP test
21
- * reporter methods.
22
- *
23
- * @details
24
- * This source file contains the implementations for `test_reporter_tap`,
25
- * a concrete implementation of the `test_reporter` abstract interface that
26
- * formats test results according to the Test Anything Protocol (TAP).
27
- *
28
- * All definitions reside within the `micro_os_plus::micro_test_plus`
29
- * namespace, ensuring clear separation from user code and minimising the risk
30
- * of naming conflicts.
31
- *
32
- * This file must be included when building the µTest++ library.
33
- */
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
-
41
- #include <micro-os-plus/micro-test-plus.h>
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
-
54
- namespace micro_os_plus::micro_test_plus
55
- {
56
- // --------------------------------------------------------------------------
57
-
58
- /**
59
- * @details
60
- * This method outputs the prefix for a passing test result, applying the
61
- * appropriate colour formatting and symbols to clearly indicate success. If
62
- * the output occurs within a test case, additional indentation is applied
63
- * for readability. The prefix includes a tick symbol (`✓`) and, if provided,
64
- * an associated message. Colour formatting is reset after the prefix to
65
- * maintain consistent output style across all test cases and folders.
66
- *
67
- * The prefix/suffix methods help shorten the code
68
- * generated by the template methods.
69
- */
70
- void
71
- test_reporter_tap::output_pass_prefix_ (std::string& message)
72
- {
73
- if (is_in_test_case_)
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
-
86
- /**
87
- * @details
88
- * The `endl` function acts as a stream manipulator for the `test_reporter`,
89
- * inserting a line ending into the output buffer and flushing the current
90
- * content if necessary. This ensures that test report output is clearly
91
- * separated and formatted, improving readability and professionalism in the
92
- * presentation of test results.
93
- *
94
- * Using `endl` in conjunction with the `test_reporter` output operators
95
- * provides a familiar and convenient mechanism for managing line breaks,
96
- * similar to standard C++ stream manipulators.
97
- *
98
- * The prefix/suffix methods help shorten the code
99
- * generated by the template methods.
100
- */
101
- void
102
- test_reporter_tap::output_pass_suffix_ (void)
103
- {
104
- *this << endl;
105
-
106
- flush ();
107
- }
108
-
109
- /**
110
- * @details
111
- * This method outputs the prefix for a failing test result, applying the
112
- * appropriate colour formatting and symbols to clearly indicate failure. If
113
- * the output occurs within a test case, additional indentation is applied
114
- * for readability. The prefix includes a cross symbol (`✗`), an optional
115
- * message, and the label "FAILED". The source location is appended in
116
- * parentheses, showing the file or folder name and line number where the
117
- * failure occurred. Colour formatting is reset after the prefix to maintain
118
- * consistent output style across all test cases and folders.
119
- */
120
- void
121
- test_reporter_tap::output_fail_prefix_ (
122
- std::string& message, [[maybe_unused]] const bool hasExpression,
123
- [[maybe_unused]] const reflection::source_location& location)
124
- {
125
- if (is_in_test_case_)
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
-
147
- /**
148
- * @details
149
- * This method outputs the suffix for a failing test result by closing the
150
- * location information, appending an "aborted..." message if the test was
151
- * aborted, and then adding a newline to the test output. The output stream
152
- * is flushed to ensure immediate visibility. This approach guarantees that
153
- * failure results are clearly separated, promptly reported, and easily
154
- * distinguishable across all test cases and folders.
155
- */
156
- void
157
- test_reporter_tap::output_fail_suffix_ (
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: "
170
- << type_traits::genuine_integral_value<unsigned int>{ location
171
- .line () }
172
- << endl;
173
-
174
- *this << " ..." << endl;
175
-
176
- flush ();
177
- }
178
-
179
- /**
180
- * @details
181
- * This method appends a newline character to the internal output buffer of
182
- * the `test_reporter` and immediately flushes the stream. This ensures that
183
- * each line of test output is clearly separated and promptly displayed,
184
- * enhancing the readability and organisation of test results across all test
185
- * cases and folders.
186
- */
187
- void
188
- test_reporter_tap::endline (void)
189
- {
190
- out_.append ("\n");
191
- flush ();
192
- }
193
-
194
- /**
195
- * @details
196
- * This method flushes the output buffer of the `test_reporter` by
197
- * synchronising it with the standard output stream. This guarantees that all
198
- * pending test output is immediately written and visible, ensuring prompt
199
- * and reliable reporting of test results across all test cases and folders.
200
- */
201
- void
202
- test_reporter_tap::flush (void)
203
- {
204
- fflush (stdout); // Sync STDOUT.
205
- }
206
-
207
- /**
208
- * @details
209
- * This method marks the beginning of a test case, setting the internal state
210
- * to indicate that test output is now within a test case context. If there
211
- * is pending output and the verbosity level is set to verbose, it ensures
212
- * that output is properly separated and displayed, adding an empty line if
213
- * necessary. The output buffer is cleared and the stream is flushed to
214
- * guarantee that all previous output is visible before the new test case
215
- * begins. This approach enhances the clarity and organisation of test
216
- * results across all test cases and folders.
217
- */
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
- {
225
- if (add_empty_line)
226
- {
227
- printf ("\n");
228
- }
229
- output ();
230
- add_empty_line = true;
231
- }
232
-
233
- out_.clear ();
234
-
235
- flush ();
236
- }
237
-
238
- /**
239
- * @details
240
- * This method marks the end of a test case, summarising its outcome and
241
- * outputting the results with appropriate formatting and colour coding. If
242
- * any checks have failed, a failure message is displayed, including the
243
- * number of successful and failed checks. For passing test cases, a success
244
- * message is shown with the total number of checks. The output is adjusted
245
- * according to the verbosity level, and additional spacing is managed for
246
- * clarity. The output buffer is cleared and the stream is flushed to ensure
247
- * all results are immediately visible, supporting clear and organised
248
- * reporting across all test cases and folders.
249
- */
250
- void
251
- test_reporter_tap::end_test_case ([[maybe_unused]] const char* name)
252
- {
253
- if (verbosity == verbosity::normal || verbosity == verbosity::verbose)
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
- {
284
- if (add_empty_line)
285
- {
286
- printf ("\n");
287
- }
288
- if (verbosity == verbosity::verbose)
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
-
336
- /**
337
- * @details
338
- * This method marks the beginning of a test suite, ensuring that output is
339
- * properly separated and clearly presented. If there is pending output, the
340
- * stream is flushed and an empty line is added for clarity. For silent or
341
- * quiet verbosity levels, output is suppressed. Otherwise, a message
342
- * indicating the start of the test suite is displayed. This approach
343
- * enhances the organisation and readability of test results across all test
344
- * cases and folders.
345
- */
346
- void
347
- test_reporter_tap::begin_test_suite (const char* name)
348
- {
349
- if (add_empty_line)
350
- {
351
- flush ();
352
- printf ("\n");
353
- }
354
-
355
- if (verbosity == verbosity::silent || verbosity == verbosity::quiet)
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
-
371
- /**
372
- * @details
373
- * This method marks the end of a test suite, summarising the overall results
374
- * and presenting them with appropriate formatting and colour coding. If the
375
- * suite contains test cases and the verbosity is not set to quiet, an empty
376
- * line is added for clarity. For suites with no failed checks and at least
377
- * one successful check, a success message is displayed, including the number
378
- * of checks and test cases. Otherwise, a failure message is shown, detailing
379
- * the number of successful and failed checks, as well as the total number of
380
- * test cases. The output is immediately flushed to ensure prompt and
381
- * organised reporting across all test cases and folders.
382
- */
383
- void
384
- test_reporter_tap::end_test_suite (test_suite_base& suite)
385
- {
386
- if (verbosity == verbosity::silent)
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
411
- if (verbosity != verbosity::quiet)
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
436
- if (verbosity != verbosity::quiet)
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
- {
462
- if (verbosity != verbosity::silent)
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
474
- test_reporter_tap::end_test (test_runner& runner)
475
- {
476
- if (verbosity != verbosity::silent)
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
-
511
- /**
512
- * @details
513
- * This method writes the contents of the internal output buffer to the
514
- * standard output stream without appending a newline character. After
515
- * outputting the buffer, it is cleared to prepare for subsequent output.
516
- * This approach ensures that test results are presented promptly and
517
- * efficiently, supporting clear and organised reporting across all test
518
- * cases and folders.
519
- */
520
- void
521
- test_reporter_tap::output (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
- // ----------------------------------------------------------------------------