micro-test-plus
6.0.0
µTest++ Testing Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
runner-options.cpp
Go to the documentation of this file.
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
12
// ----------------------------------------------------------------------------
13
29
30
// ----------------------------------------------------------------------------
31
32
#include "
micro-os-plus/micro-test-plus/runner-options.h
"
33
34
#if __has_include("micro-os-plus/diag/trace.h")
35
#include "micro-os-plus/diag/trace.h"
36
#endif
// __has_include("micro-os-plus/diag/trace.h")
37
38
#include <string>
39
40
// ----------------------------------------------------------------------------
41
42
#if defined(__GNUC__)
43
#pragma GCC diagnostic ignored "-Waggregate-return"
44
#if defined(__clang__)
45
#pragma clang diagnostic ignored "-Wunknown-warning-option"
46
#pragma clang diagnostic ignored "-Wc++98-compat"
47
#pragma clang diagnostic ignored "-Wc++98-c++11-c++14-compat"
48
#pragma clang diagnostic ignored "-Wpre-c++17-compat"
49
#pragma clang diagnostic ignored "-Wc++20-compat"
50
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-libc-call"
51
#endif
// defined(__clang__)
52
#endif
// defined(__GNUC__)
53
54
// ============================================================================
55
56
#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_ENABLED)
57
58
// ----------------------------------------------------------------------------
59
60
namespace
micro_os_plus::micro_test_plus
61
{
62
// --------------------------------------------------------------------------
63
64
#if defined(__GNUC__)
65
#pragma GCC diagnostic push
66
67
#if defined(__clang__)
68
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
69
#endif
// defined(__clang__)
70
#endif
// defined(__GNUC__)
71
119
runner_options::runner_options
(
int
argc,
char
* argv[])
120
{
121
#if defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED)
122
trace::printf (
"%s\n"
, __PRETTY_FUNCTION__);
123
#endif
// MICRO_OS_PLUS_MICRO_TEST_PLUS_TRACE_ENABLED
124
125
if
(argc <= 0 || argv ==
nullptr
)
126
{
127
return
;
128
}
129
130
// Copy the strings one by one, since the vector assignment uses
131
// std::copy, which triggers -Waggregate-return in the standard library
132
// headers on some targets.
133
arguments_
.reserve (
static_cast<
size_t
>
(argc));
134
for
(
int
i = 0; i < argc; ++i)
135
{
136
arguments_
.emplace_back (argv[i] !=
nullptr
? argv[i] :
""
);
137
}
138
139
// Unless the parsing stops earlier, there are no application arguments.
140
application_begin_
=
arguments_
.size ();
141
142
// What an option with a value sets.
143
enum class
setting
144
{
145
set_reporter,
146
set_output_file,
147
set_colour,
148
add_filter
149
};
150
151
// The options with a value, which is given as `--option=<value>`,
152
// or, if `value_may_follow`, also as `--option <value>`. As in the GNU
153
// tools, `--colour` and `--color` alone mean `always`, and the next
154
// argument is never taken as their value.
155
#if defined(__GNUC__)
156
#pragma GCC diagnostic push
157
158
#pragma GCC diagnostic ignored "-Wpadded"
159
#endif
// defined(__GNUC__)
160
161
struct
value_option
162
{
163
std::string_view name;
164
setting what;
165
bool
value_may_follow;
166
};
167
168
#if defined(__GNUC__)
169
#pragma GCC diagnostic pop
170
#endif
// defined(__GNUC__)
171
172
static
constexpr
value_option value_options[]
173
= { {
"--reporter"
, setting::set_reporter,
true
},
174
{
"--output-file"
, setting::set_output_file,
true
},
175
{
"--use-colour"
, setting::set_colour,
true
},
176
{
"--use-color"
, setting::set_colour,
true
},
177
{
"--colour"
, setting::set_colour,
false
},
178
{
"--color"
, setting::set_colour,
false
},
179
{
"--filter"
, setting::add_filter,
true
} };
180
181
// Set the colour mode from the value of `--colour`, `--color`,
182
// `--use-colour`, or `--use-color`; all accept the values and the
183
// synonyms of the GNU tools, which include those of Catch2 and Boost
184
// UT (`yes`, `no`, and `auto`). An unknown mode is reported as an
185
// error.
186
auto
set_colour_mode = [&] (std::string_view value)
187
{
188
if
(value ==
"always"
|| value ==
"yes"
|| value ==
"force"
)
189
{
190
colour
=
colour_mode::always
;
191
}
192
else
if
(value ==
"never"
|| value ==
"no"
|| value ==
"none"
)
193
{
194
colour
=
colour_mode::never
;
195
}
196
else
if
(value ==
"auto"
|| value ==
"tty"
|| value ==
"if-tty"
)
197
{
198
colour
=
colour_mode::automatic
;
199
}
200
else
201
{
202
add_error
(
"unknown colour mode '"
, value,
"'"
);
203
}
204
};
205
206
// Whether an argument is a value of `--colour`, to detect a value
207
// given separately, which the option does not take.
208
auto
is_colour_mode = [] (std::string_view value) ->
bool
209
{
210
for
(
const
std::string_view mode :
211
{
"always"
,
"yes"
,
"force"
,
"never"
,
"no"
,
"none"
,
"auto"
,
"tty"
,
212
"if-tty"
})
213
{
214
if
(value == mode)
215
{
216
return
true
;
217
}
218
}
219
return
false
;
220
};
221
222
// Apply the value of an option with a value; an invalid value is
223
// reported as an error.
224
auto
apply_value = [&] (setting what, std::string_view value)
225
{
226
if
(what == setting::set_reporter)
227
{
228
if
(value ==
"human"
)
229
{
230
selected_reporter
=
reporter_kind::human
;
231
}
232
else
if
(value ==
"tap"
)
233
{
234
selected_reporter
=
reporter_kind::tap
;
235
}
236
else
237
{
238
add_error
(
"unknown reporter '"
, value,
"'"
);
239
}
240
}
241
else
if
(what == setting::set_output_file)
242
{
243
// An empty path disables the output file.
244
output_file_path
= value;
245
}
246
else
if
(what == setting::set_colour)
247
{
248
set_colour_mode (value);
249
}
250
else
251
{
252
filter_patterns
.emplace_back (value);
253
}
254
};
255
256
for
(
size_t
i = 1; i <
arguments_
.size (); ++i)
257
{
258
const
std::string_view argument{
arguments_
[i] };
259
260
// The application arguments start at the first argument that does
261
// not start with a dash, or after the first `--` alone.
262
if
(argument ==
"--"
)
263
{
264
application_begin_
= i + 1;
265
break
;
266
}
267
if
(!argument.starts_with (
'-'
))
268
{
269
application_begin_
= i;
270
break
;
271
}
272
273
if
(argument ==
"--verbose"
)
274
{
275
verbosity_level
=
verbosity::verbose
;
276
continue
;
277
}
278
if
(argument ==
"--quiet"
)
279
{
280
verbosity_level
=
verbosity::quiet
;
281
continue
;
282
}
283
if
(argument ==
"--silent"
)
284
{
285
verbosity_level
=
verbosity::silent
;
286
continue
;
287
}
288
if
(argument ==
"--list-tests"
|| argument ==
"--list"
)
289
{
290
list_tests
=
true
;
291
continue
;
292
}
293
if
(argument ==
"--help"
|| argument ==
"-h"
)
294
{
295
help
=
true
;
296
continue
;
297
}
298
299
// Match the options with a value, alone or followed by `=`.
300
const
value_option* matched =
nullptr
;
301
bool
has_inline_value =
false
;
302
std::string_view value{};
303
for
(
const
value_option& option : value_options)
304
{
305
if
(argument == option.name)
306
{
307
matched = &option;
308
break
;
309
}
310
if
(argument.starts_with (option.name)
311
&& argument.substr (option.name.size ()).starts_with (
'='
))
312
{
313
matched = &option;
314
has_inline_value =
true
;
315
value = argument.substr (option.name.size () + 1);
316
break
;
317
}
318
}
319
320
if
(matched ==
nullptr
)
321
{
322
// A mistyped option must not silently disable the tests.
323
add_error
(
"unknown option '"
, argument,
"'"
);
324
unknown_option_
=
true
;
325
continue
;
326
}
327
328
if
(!has_inline_value)
329
{
330
if
(!matched->value_may_follow)
331
{
332
// The option alone means `always`. If the next argument
333
// looks like a mode, it was probably meant to be the
334
// value, so report it instead of silently passing it to
335
// the application.
336
colour
=
colour_mode::always
;
337
if
(i + 1 <
arguments_
.size ()
338
&& is_colour_mode (
arguments_
[i + 1]))
339
{
340
std::string text{
"'"
};
341
text.append (argument);
342
text.append (
"' takes its value only after '='; write '"
);
343
text.append (argument);
344
text.append (
"="
);
345
text.append (
arguments_
[i + 1]);
346
text.append (
347
"', or put '--' before the application argument"
);
348
add_error
(text);
349
}
350
continue
;
351
}
352
353
if
(i + 1 >=
arguments_
.size ())
354
{
355
add_error
(
""
, matched->name,
" option requires an argument"
);
356
continue
;
357
}
358
value =
arguments_
[++i];
359
}
360
361
apply_value (matched->what, value);
362
}
363
}
364
365
#if defined(__GNUC__)
366
#pragma GCC diagnostic pop
367
#endif
// defined(__GNUC__)
368
375
void
376
runner_options::add_error
(std::string_view before, std::string_view value,
377
std::string_view after)
378
{
379
std::string text{ before };
380
text.append (value);
381
text.append (after);
382
383
errors_
.push_back (std::move (text));
384
}
385
386
// --------------------------------------------------------------------------
387
}
// namespace micro_os_plus::micro_test_plus
388
389
// ----------------------------------------------------------------------------
390
391
#endif
// defined(MICRO_OS_PLUS_MICRO_TEST_PLUS_ENABLED)
392
393
// ----------------------------------------------------------------------------
micro_os_plus::micro_test_plus::runner_options::application_begin_
std::size_t application_begin_
The index in arguments_ of the first argument left to the application.
Definition
runner-options.h:629
micro_os_plus::micro_test_plus::runner_options::runner_options
runner_options(void)=default
Constructs the default options.
micro_os_plus::micro_test_plus::runner_options::help
bool help
Whether to display the usage and the list of the options, instead of running the tests.
Definition
runner-options.h:471
micro_os_plus::micro_test_plus::runner_options::errors_
std::vector< std::string > errors_
The errors found while parsing the command line.
Definition
runner-options.h:600
micro_os_plus::micro_test_plus::runner_options::colour
colour_mode colour
Whether the console output uses colours.
Definition
runner-options.h:389
micro_os_plus::micro_test_plus::runner_options::filter_patterns
std::vector< std::string > filter_patterns
The patterns that select the suites and the test cases to run, one per nesting level.
Definition
runner-options.h:418
micro_os_plus::micro_test_plus::runner_options::unknown_option_
bool unknown_option_
Whether an unknown option was found.
Definition
runner-options.h:609
micro_os_plus::micro_test_plus::runner_options::output_file_path
std::string output_file_path
Path of the optional output file.
Definition
runner-options.h:368
micro_os_plus::micro_test_plus::runner_options::add_error
void add_error(std::string_view before, std::string_view value={}, std::string_view after={})
Records a command-line error.
Definition
runner-options.cpp:376
micro_os_plus::micro_test_plus::runner_options::list_tests
bool list_tests
Whether the test cases are listed instead of run.
Definition
runner-options.h:455
micro_os_plus::micro_test_plus::runner_options::selected_reporter
reporter_kind selected_reporter
The reporter that displays the results.
Definition
runner-options.h:345
micro_os_plus::micro_test_plus::runner_options::arguments_
std::vector< std::string > arguments_
The complete command line, including argv[0], if any.
Definition
runner-options.h:619
micro_os_plus::micro_test_plus::runner_options::verbosity_level
micro_test_plus::verbosity verbosity_level
The level of detail of the console output.
Definition
runner-options.h:354
micro_os_plus::micro_test_plus::colour_mode::automatic
@ automatic
Definition
runner-options.h:154
micro_os_plus::micro_test_plus::colour_mode::never
@ never
Definition
runner-options.h:161
micro_os_plus::micro_test_plus::colour_mode::always
@ always
Definition
runner-options.h:157
micro_os_plus::micro_test_plus::verbosity::verbose
@ verbose
Definition
runner-options.h:111
micro_os_plus::micro_test_plus::verbosity::quiet
@ quiet
Definition
runner-options.h:103
micro_os_plus::micro_test_plus::verbosity::silent
@ silent
Definition
runner-options.h:102
micro_os_plus::micro_test_plus::reporter_kind::tap
@ tap
Definition
runner-options.h:129
micro_os_plus::micro_test_plus::reporter_kind::human
@ human
Definition
runner-options.h:130
micro_os_plus::micro_test_plus
Primary namespace for the µTest++ testing framework.
Definition
check-result.h:76
runner-options.h
C++ header file with declarations for the µTest++ runner options.
src
runner-options.cpp
Generated by
1.18.0