@micro-os-plus/micro-test-plus 2.1.1 → 3.0.2

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.
@@ -0,0 +1,423 @@
1
+ /*
2
+ * This file is part of the µOS++ distribution.
3
+ * (https://github.com/micro-os-plus/)
4
+ * Copyright (c) 2021 Liviu Ionescu.
5
+ *
6
+ * Permission to use, copy, modify, and/or distribute this software
7
+ * for any purpose is hereby granted, under the terms of the MIT license.
8
+ *
9
+ * If a copy of the license was not distributed with this file, it can
10
+ * be obtained from <https://opensource.org/licenses/MIT/>.
11
+ *
12
+ * Major parts of the code are inspired from v1.1.8 of the Boost UT project,
13
+ * released under the terms of the Boost Version 1.0 Software License,
14
+ * which can be obtained from <https://www.boost.org/LICENSE_1_0.txt>.
15
+ */
16
+
17
+ // ----------------------------------------------------------------------------
18
+
19
+ #if defined(MICRO_OS_PLUS_INCLUDE_CONFIG_H)
20
+ #include <micro-os-plus/config.h>
21
+ #endif // MICRO_OS_PLUS_INCLUDE_CONFIG_H
22
+
23
+ #include <micro-os-plus/micro-test-plus.h>
24
+
25
+ // ----------------------------------------------------------------------------
26
+
27
+ #pragma GCC diagnostic ignored "-Waggregate-return"
28
+ #if defined(__clang__)
29
+ #pragma clang diagnostic ignored "-Wc++98-compat"
30
+ #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
31
+ #endif
32
+
33
+ namespace micro_os_plus::micro_test_plus
34
+ {
35
+ // --------------------------------------------------------------------------
36
+
37
+ test_reporter&
38
+ endl (test_reporter& stream)
39
+ {
40
+ reporter.endline ();
41
+ return stream;
42
+ }
43
+
44
+ // --------------------------------------------------------------------------
45
+
46
+ void
47
+ test_reporter::output_pass_prefix_ (std::string& message)
48
+ {
49
+ *this << colors_.pass;
50
+ if (is_in_test_case_)
51
+ {
52
+ *this << " ";
53
+ }
54
+ *this << " ✓ ";
55
+ *this << colors_.none;
56
+ if (!message.empty ())
57
+ {
58
+ *this << message.c_str ();
59
+ }
60
+ }
61
+
62
+ void
63
+ test_reporter::output_pass_suffix_ (void)
64
+ {
65
+ *this << endl;
66
+
67
+ flush ();
68
+ }
69
+
70
+ void
71
+ test_reporter::output_fail_prefix_ (
72
+ std::string& message, const reflection::source_location& location)
73
+ {
74
+ *this << colors_.fail;
75
+ if (is_in_test_case_)
76
+ {
77
+ *this << " ";
78
+ }
79
+ *this << " ✗ ";
80
+ *this << colors_.none;
81
+ if (!message.empty ())
82
+ {
83
+ *this << message.c_str ();
84
+ *this << " ";
85
+ }
86
+ *this << colors_.fail << "FAILED" << colors_.none;
87
+ *this << " (" << reflection::short_name (location.file_name ()) << ":"
88
+ << type_traits::genuine_integral_value<int>{ location.line () };
89
+ }
90
+
91
+ void
92
+ test_reporter::output_fail_suffix_ (bool abort)
93
+ {
94
+ *this << ")";
95
+ if (abort)
96
+ {
97
+ *this << " aborted...";
98
+ }
99
+ *this << endl;
100
+
101
+ flush ();
102
+ }
103
+
104
+ test_reporter&
105
+ test_reporter::operator<< (test_reporter& (*func) (test_reporter&))
106
+ {
107
+ // Call the endl function.
108
+ (*func) (*this);
109
+ return *this;
110
+ }
111
+
112
+ void
113
+ test_reporter::endline (void)
114
+ {
115
+ out_.append ("\n");
116
+ flush ();
117
+ }
118
+
119
+ void
120
+ test_reporter::flush (void)
121
+ {
122
+ fflush (stdout); // Sync STDOUT.
123
+ }
124
+
125
+ test_reporter&
126
+ test_reporter::operator<< (std::string_view sv)
127
+ {
128
+ out_.append (sv);
129
+ return *this;
130
+ }
131
+
132
+ test_reporter&
133
+ test_reporter::operator<< (char c)
134
+ {
135
+ out_.append (1, c);
136
+ return *this;
137
+ }
138
+
139
+ test_reporter&
140
+ test_reporter::operator<< (const char* s)
141
+ {
142
+ out_.append (s);
143
+ return *this;
144
+ }
145
+
146
+ test_reporter&
147
+ test_reporter::operator<< (char* s)
148
+ {
149
+ out_.append (s);
150
+ return *this;
151
+ }
152
+
153
+ test_reporter&
154
+ test_reporter::operator<< (bool v)
155
+ {
156
+ out_.append (v ? "true" : "false");
157
+ return *this;
158
+ }
159
+
160
+ test_reporter&
161
+ test_reporter::operator<< (std::nullptr_t)
162
+ {
163
+ out_.append ("nullptr");
164
+ return *this;
165
+ }
166
+
167
+ test_reporter&
168
+ test_reporter::operator<< (signed char c)
169
+ {
170
+ out_.append (std::to_string (c));
171
+ out_.append ("c");
172
+ return *this;
173
+ }
174
+
175
+ test_reporter&
176
+ test_reporter::operator<< (unsigned char c)
177
+ {
178
+ out_.append (std::to_string (static_cast<int> (c)));
179
+ out_.append ("uc");
180
+ return *this;
181
+ }
182
+
183
+ test_reporter&
184
+ test_reporter::operator<< (signed short v)
185
+ {
186
+ out_.append (std::to_string (v));
187
+ out_.append ("s");
188
+ return *this;
189
+ }
190
+
191
+ test_reporter&
192
+ test_reporter::operator<< (unsigned short v)
193
+ {
194
+ out_.append (std::to_string (static_cast<long> (v)));
195
+ out_.append ("us");
196
+ return *this;
197
+ }
198
+
199
+ test_reporter&
200
+ test_reporter::operator<< (signed int v)
201
+ {
202
+ out_.append (std::to_string (v));
203
+ return *this;
204
+ }
205
+
206
+ test_reporter&
207
+ test_reporter::operator<< (unsigned int v)
208
+ {
209
+ out_.append (std::to_string (v));
210
+ out_.append ("u");
211
+ return *this;
212
+ }
213
+
214
+ test_reporter&
215
+ test_reporter::operator<< (signed long v)
216
+ {
217
+ out_.append (std::to_string (v));
218
+ out_.append ("l");
219
+ return *this;
220
+ }
221
+
222
+ test_reporter&
223
+ test_reporter::operator<< (unsigned long v)
224
+ {
225
+ out_.append (std::to_string (v));
226
+ out_.append ("ul");
227
+ return *this;
228
+ }
229
+
230
+ test_reporter&
231
+ test_reporter::operator<< (signed long long v)
232
+ {
233
+ out_.append (std::to_string (v));
234
+ out_.append ("ll");
235
+ return *this;
236
+ }
237
+
238
+ test_reporter&
239
+ test_reporter::operator<< (unsigned long long v)
240
+ {
241
+ out_.append (std::to_string (v));
242
+ out_.append ("ull");
243
+ return *this;
244
+ }
245
+
246
+ test_reporter&
247
+ test_reporter::operator<< (float v)
248
+ {
249
+ out_.append (std::to_string (v));
250
+ out_.append ("f");
251
+ return *this;
252
+ }
253
+
254
+ test_reporter&
255
+ test_reporter::operator<< (double v)
256
+ {
257
+ out_.append (std::to_string (v));
258
+ return *this;
259
+ }
260
+
261
+ test_reporter&
262
+ test_reporter::operator<< (long double v)
263
+ {
264
+ out_.append (std::to_string (v));
265
+ out_.append ("l");
266
+ return *this;
267
+ }
268
+
269
+ void
270
+ test_reporter::begin_test_case ([[maybe_unused]] const char* name)
271
+ {
272
+ is_in_test_case_ = true;
273
+
274
+ if (!out_.empty () && (verbosity == verbosity::verbose))
275
+ {
276
+ if (add_empty_line)
277
+ {
278
+ printf ("\n");
279
+ }
280
+ output ();
281
+ add_empty_line = true;
282
+ }
283
+
284
+ out_.clear ();
285
+
286
+ flush ();
287
+ }
288
+
289
+ void
290
+ test_reporter::end_test_case ([[maybe_unused]] const char* name)
291
+ {
292
+ if (verbosity == verbosity::normal || verbosity == verbosity::verbose)
293
+ {
294
+ if (current_test_suite->current_test_case.failed_checks > 0)
295
+ {
296
+ if (true /* add_empty_line */)
297
+ {
298
+ printf ("\n");
299
+ }
300
+ printf (" • %s - test case started\n", name);
301
+ output ();
302
+ printf (
303
+ " %s✗%s %s - test case %sFAILED%s (%d %s passed, %d "
304
+ "failed)\n",
305
+ colors_.fail, colors_.none, name, colors_.fail, colors_.none,
306
+ current_test_suite->current_test_case.successful_checks,
307
+ current_test_suite->current_test_case.successful_checks == 1
308
+ ? "check"
309
+ : "checks",
310
+ current_test_suite->current_test_case.failed_checks);
311
+ add_empty_line = true;
312
+ }
313
+ else
314
+ {
315
+ if (add_empty_line)
316
+ {
317
+ printf ("\n");
318
+ }
319
+ if (verbosity == verbosity::verbose)
320
+ {
321
+ printf (" • %s - test case started\n", name);
322
+ output ();
323
+ printf (
324
+ " %s✓%s %s - test case passed (%d %s)\n", colors_.pass,
325
+ colors_.none, name,
326
+ current_test_suite->current_test_case.successful_checks,
327
+ current_test_suite->current_test_case.successful_checks
328
+ == 1
329
+ ? "check"
330
+ : "checks");
331
+
332
+ add_empty_line = true;
333
+ }
334
+ else
335
+ {
336
+ printf (
337
+ " %s✓%s %s - test case passed (%d %s)\n", colors_.pass,
338
+ colors_.none, name,
339
+ current_test_suite->current_test_case.successful_checks,
340
+ current_test_suite->current_test_case.successful_checks
341
+ == 1
342
+ ? "check"
343
+ : "checks");
344
+
345
+ add_empty_line = false;
346
+ }
347
+ }
348
+ }
349
+
350
+ out_.clear ();
351
+ flush ();
352
+
353
+ is_in_test_case_ = false;
354
+ }
355
+
356
+ void
357
+ test_reporter::begin_test_suite (const char* name)
358
+ {
359
+ if (add_empty_line)
360
+ {
361
+ flush ();
362
+ printf ("\n");
363
+ }
364
+
365
+ if (verbosity == verbosity::silent || verbosity == verbosity::quiet)
366
+ {
367
+ add_empty_line = false;
368
+ return;
369
+ }
370
+
371
+ printf ("• %s - test suite started\n", name);
372
+
373
+ add_empty_line = true;
374
+ }
375
+
376
+ void
377
+ test_reporter::end_test_suite (test_suite_base& suite)
378
+ {
379
+ if (verbosity == verbosity::silent)
380
+ {
381
+ return;
382
+ }
383
+
384
+ if (suite.test_cases () > 0 && verbosity != verbosity::quiet)
385
+ {
386
+ printf ("\n");
387
+ add_empty_line = true;
388
+ }
389
+
390
+ // Also fail if none passed.
391
+ if (suite.failed_checks () == 0 && suite.successful_checks () != 0)
392
+ {
393
+ printf ("%s✓%s %s - test suite passed (%d %s in %d test %s)\n",
394
+ colors_.pass, colors_.none, suite.name (),
395
+ suite.successful_checks (),
396
+ suite.successful_checks () == 1 ? "check" : "checks",
397
+ suite.test_cases (),
398
+ suite.test_cases () == 1 ? "case" : "cases");
399
+ }
400
+ else
401
+ {
402
+ printf ("%s✗%s %s - test suite %sFAILED%s (%d %s passed, %d failed, "
403
+ "in %d test %s)\n",
404
+ colors_.fail, colors_.none, suite.name (), colors_.fail,
405
+ colors_.none, suite.successful_checks (),
406
+ suite.successful_checks () == 1 ? "check" : "checks",
407
+ suite.failed_checks (), suite.test_cases (),
408
+ suite.test_cases () == 1 ? "case" : "cases");
409
+ }
410
+ flush ();
411
+ }
412
+
413
+ void
414
+ test_reporter::output (void)
415
+ {
416
+ printf ("%s", out_.c_str ()); // No `\n` here.
417
+ out_.clear ();
418
+ }
419
+
420
+ // --------------------------------------------------------------------------
421
+ } // namespace micro_os_plus::micro_test_plus
422
+
423
+ // ----------------------------------------------------------------------------
@@ -0,0 +1,186 @@
1
+ /*
2
+ * This file is part of the µOS++ distribution.
3
+ * (https://github.com/micro-os-plus/)
4
+ * Copyright (c) 2021 Liviu Ionescu.
5
+ *
6
+ * Permission to use, copy, modify, and/or distribute this software
7
+ * for any purpose is hereby granted, under the terms of the MIT license.
8
+ *
9
+ * If a copy of the license was not distributed with this file, it can
10
+ * be obtained from <https://opensource.org/licenses/MIT/>.
11
+ *
12
+ * Major parts of the code are inspired from v1.1.8 of the Boost UT project,
13
+ * released under the terms of the Boost Version 1.0 Software License,
14
+ * which can be obtained from <https://www.boost.org/LICENSE_1_0.txt>.
15
+ */
16
+
17
+ // ----------------------------------------------------------------------------
18
+
19
+ #if defined(MICRO_OS_PLUS_INCLUDE_CONFIG_H)
20
+ #include <micro-os-plus/config.h>
21
+ #endif // MICRO_OS_PLUS_INCLUDE_CONFIG_H
22
+
23
+ #include <micro-os-plus/micro-test-plus.h>
24
+
25
+ #include <stdio.h>
26
+ #include <vector>
27
+
28
+ // ----------------------------------------------------------------------------
29
+
30
+ #pragma GCC diagnostic ignored "-Waggregate-return"
31
+ #if defined(__clang__)
32
+ #pragma clang diagnostic ignored "-Wc++98-compat"
33
+ #pragma clang diagnostic ignored "-Wc++98-c++11-c++14-compat"
34
+ #endif
35
+
36
+ namespace micro_os_plus::micro_test_plus
37
+ {
38
+ // --------------------------------------------------------------------------
39
+
40
+ test_runner::test_runner ()
41
+ {
42
+ #if defined(MICRO_TEST_PLUS_TRACE)
43
+ printf ("%s\n", __PRETTY_FUNCTION__);
44
+ #endif // MICRO_TEST_PLUS_TRACE
45
+ }
46
+
47
+ void
48
+ test_runner::initialize (int argc, char* argv[], const char* name)
49
+ {
50
+ #if defined(MICRO_TEST_PLUS_TRACE)
51
+ printf ("%s\n", __PRETTY_FUNCTION__);
52
+ #endif // MICRO_TEST_PLUS_TRACE
53
+
54
+ argc_ = argc;
55
+ argv_ = argv;
56
+
57
+ default_suite_name_ = name;
58
+
59
+ #if defined(MICRO_OS_PLUS_DEBUG)
60
+ printf ("argv[");
61
+ for (int i = 0; i < argc; ++i)
62
+ {
63
+ if (i > 0)
64
+ {
65
+ printf (", ");
66
+ }
67
+ printf ("'%s'", argv[i]);
68
+ }
69
+ puts ("]");
70
+ #endif
71
+
72
+ verbosity_t verbosity = verbosity::normal;
73
+ for (int i = 0; i < argc; ++i)
74
+ {
75
+ if (strcmp (argv[i], "--verbose") == 0)
76
+ {
77
+ verbosity = verbosity::verbose;
78
+ }
79
+ else if (strcmp (argv[i], "--quiet") == 0)
80
+ {
81
+ verbosity = verbosity::quiet;
82
+ }
83
+ else if (strcmp (argv[i], "--silent") == 0)
84
+ {
85
+ verbosity = verbosity::silent;
86
+ }
87
+ }
88
+
89
+ // Pass the verbosity to the reporter.
90
+ reporter.verbosity = verbosity;
91
+
92
+ // ------------------------------------------------------------------------
93
+
94
+ if (verbosity == verbosity::normal || verbosity == verbosity::verbose)
95
+ {
96
+ #if defined(__clang__)
97
+ printf ("Built with clang " __VERSION__);
98
+ #elif defined(__GNUC__)
99
+ printf ("Built with GCC " __VERSION__);
100
+ #elif defined(_MSC_VER)
101
+ // https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=msvc-170
102
+ printf ("Built with MSVC %d", _MSC_VER);
103
+ #else
104
+ printf ("Built with an unknown compiler");
105
+ #endif
106
+ #if defined(__ARM_PCS_VFP)
107
+ printf (", with FP");
108
+ #else
109
+ printf (", no FP");
110
+ #endif
111
+ #if defined(__EXCEPTIONS)
112
+ printf (", with exceptions");
113
+ #else
114
+ printf (", no exceptions");
115
+ #endif
116
+ #if defined(MICRO_OS_PLUS_DEBUG)
117
+ printf (", with MICRO_OS_PLUS_DEBUG");
118
+ #endif
119
+ puts (".");
120
+ }
121
+
122
+ // ------------------------------------------------------------------------
123
+
124
+ default_test_suite_ = new test_suite_base (default_suite_name_);
125
+ current_test_suite = default_test_suite_;
126
+
127
+ // Deferred to first test case or test suite end, to allow various
128
+ // initialisations to display their messages.
129
+ // default_test_suite_->begin_test_suite ();
130
+ }
131
+
132
+ int
133
+ test_runner::exit_code (void)
134
+ {
135
+ bool was_successful = true;
136
+
137
+ if (!default_test_suite_->unused ())
138
+ {
139
+ default_test_suite_->end_test_suite ();
140
+ was_successful = default_test_suite_->was_successful ();
141
+ }
142
+
143
+ if (suites_ != nullptr)
144
+ {
145
+ for (auto suite : *suites_)
146
+ {
147
+ current_test_suite = suite;
148
+
149
+ suite->begin_test_suite ();
150
+ suite->run ();
151
+ suite->end_test_suite();
152
+
153
+ was_successful &= suite->was_successful ();
154
+ }
155
+ if (reporter.verbosity != verbosity::silent)
156
+ {
157
+ printf ("\n");
158
+ }
159
+ }
160
+ return was_successful ? 0 : 1;
161
+ }
162
+
163
+ void
164
+ test_runner::register_test_suite (test_suite_base* suite)
165
+ {
166
+ #if 0 // defined(MICRO_TEST_PLUS_TRACE)
167
+ printf ("%s\n", __PRETTY_FUNCTION__);
168
+ #endif // MICRO_TEST_PLUS_TRACE
169
+
170
+ if (suites_ == nullptr)
171
+ {
172
+ suites_ = new std::vector<test_suite_base*> ();
173
+ }
174
+ suites_->push_back (suite);
175
+ }
176
+
177
+ void
178
+ test_runner::abort (void)
179
+ {
180
+ ::abort ();
181
+ }
182
+
183
+ // --------------------------------------------------------------------------
184
+ } // namespace micro_os_plus::micro_test_plus
185
+
186
+ // ----------------------------------------------------------------------------