• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

thetic / mu.tiny / 24643414799

20 Apr 2026 12:51AM UTC coverage: 98.907% (+0.03%) from 98.879%
24643414799

Pull #84

github

web-flow
Merge 4942ce390 into a2dfbd6ba
Pull Request #84: apply clang-tidy fixes

821 of 822 new or added lines in 45 files covered. (99.88%)

2 existing lines in 2 files now uncovered.

5341 of 5400 relevant lines covered (98.91%)

3300.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.89
/src/test/CommandLineArguments.cpp
1
#include "mu/tiny/test/CommandLineArguments.hpp"
2

3
#include "mu/tiny/test/Plugin.hpp"
4
#include "mu/tiny/test/Registry.hpp"
5

6
#include "mu/tiny/StringCollection.hpp"
7
#include "mu/tiny/time.hpp"
8
#include "mu/tiny/version.h"
9

10
namespace mu {
11
namespace tiny {
12
namespace test {
13

14
namespace {
15
String sub_string_from_till(
6✔
16
    const String& str,
17
    char start_char,
18
    char last_excluded_char
19
)
20
{
21
  size_t begin_pos = str.find(start_char);
6✔
22
  if (begin_pos == String::npos) {
6✔
23
    return "";
×
24
  }
25

26
  size_t end_pos = str.find(last_excluded_char, begin_pos);
6✔
27
  if (end_pos == String::npos) {
6✔
28
    return str.substr(begin_pos);
1✔
29
  }
30

31
  return str.substr(begin_pos, end_pos - begin_pos);
5✔
32
}
33
} // namespace
34

35
CommandLineArguments::CommandLineArguments(int argc, const char* const* argv)
124✔
36
  : ac_(argc)
124✔
37
  , av_(argv)
124✔
38

39
{
40
}
124✔
41

42
CommandLineArguments::~CommandLineArguments()
248✔
43
{
44
  while (group_filters_ != nullptr) {
310✔
45
    Filter* current = group_filters_;
62✔
46
    group_filters_ = group_filters_->get_next();
62✔
47
    delete current;
62✔
48
  }
49
  while (name_filters_ != nullptr) {
268✔
50
    Filter* current = name_filters_;
20✔
51
    name_filters_ = name_filters_->get_next();
20✔
52
    delete current;
20✔
53
  }
54
}
248✔
55

56
bool CommandLineArguments::parse_simple_flag(const String& argument)
184✔
57
{
58
  if (argument == "-h") {
184✔
59
    need_help_ = true;
3✔
60
    return true;
3✔
61
  }
62
  if (argument == "-v") {
181✔
63
    verbose_ = true;
46✔
64
    return true;
46✔
65
  }
66
  if (argument == "-vv") {
135✔
67
    very_verbose_ = true;
12✔
68
    return true;
12✔
69
  }
70
  if (argument == "-c") {
123✔
71
    color_ = true;
11✔
72
    return true;
11✔
73
  }
74
  if (argument == "-b") {
112✔
75
    reversing_ = true;
2✔
76
    return true;
2✔
77
  }
78
  if (argument == "-lg") {
110✔
79
    list_test_group_names_ = true;
2✔
80
    return true;
2✔
81
  }
82
  if (argument == "-ln") {
108✔
83
    list_test_group_and_case_names_ = true;
2✔
84
    return true;
2✔
85
  }
86
  if (argument == "-lo") {
106✔
87
    list_ordered_test_locations_ = true;
1✔
88
    return true;
1✔
89
  }
90
  if (argument == "-lgl") {
105✔
91
    list_test_group_locations_ = true;
2✔
92
    return true;
2✔
93
  }
94
  if (argument == "-ll") {
103✔
95
    list_test_locations_ = true;
2✔
96
    return true;
2✔
97
  }
98
  if (argument == "-ri") {
101✔
99
    run_ignored_ = true;
2✔
100
    return true;
2✔
101
  }
102
  if (argument == "-f") {
99✔
103
    crash_on_fail_ = true;
1✔
104
    return true;
1✔
105
  }
106
  if (argument == "-e") {
98✔
107
    rethrow_exceptions_ = false;
1✔
108
    return true;
1✔
109
  }
110
  return false;
97✔
111
}
112

113
bool CommandLineArguments::parse_prefix_arg(
97✔
114
    const String& argument,
115
    Plugin* plugin,
116
    int& index
117
)
118
{
119
  if (string_starts_with(argument, "-r")) {
97✔
120
    set_repeat_count(ac_, av_, index);
3✔
121
    return true;
3✔
122
  }
123
  if (string_starts_with(argument, "-g")) {
94✔
124
    add_group_filter(ac_, av_, index);
3✔
125
    return true;
3✔
126
  }
127
  if (string_starts_with(argument, "-t")) {
91✔
128
    return add_group_dot_name_filter(ac_, av_, index, "-t", false, false);
2✔
129
  }
130
  if (string_starts_with(argument, "-st")) {
89✔
131
    return add_group_dot_name_filter(ac_, av_, index, "-st", true, false);
2✔
132
  }
133
  if (string_starts_with(argument, "-xt")) {
87✔
134
    return add_group_dot_name_filter(ac_, av_, index, "-xt", false, true);
2✔
135
  }
136
  if (string_starts_with(argument, "-xst")) {
85✔
137
    return add_group_dot_name_filter(ac_, av_, index, "-xst", true, true);
2✔
138
  }
139
  if (string_starts_with(argument, "-sg")) {
83✔
140
    add_strict_group_filter(ac_, av_, index);
48✔
141
    return true;
48✔
142
  }
143
  if (string_starts_with(argument, "-xg")) {
35✔
144
    add_exclude_group_filter(ac_, av_, index);
2✔
145
    return true;
2✔
146
  }
147
  if (string_starts_with(argument, "-xsg")) {
33✔
148
    add_exclude_strict_group_filter(ac_, av_, index);
2✔
149
    return true;
2✔
150
  }
151
  if (string_starts_with(argument, "-n")) {
31✔
152
    add_name_filter(ac_, av_, index);
2✔
153
    return true;
2✔
154
  }
155
  if (string_starts_with(argument, "-sn")) {
29✔
156
    add_strict_name_filter(ac_, av_, index);
6✔
157
    return true;
6✔
158
  }
159
  if (string_starts_with(argument, "-xn")) {
23✔
160
    add_exclude_name_filter(ac_, av_, index);
3✔
161
    return true;
3✔
162
  }
163
  if (string_starts_with(argument, "-xsn")) {
20✔
164
    add_exclude_strict_name_filter(ac_, av_, index);
2✔
165
    return true;
2✔
166
  }
167
  if (string_starts_with(argument, "-s")) {
18✔
168
    return set_shuffle(ac_, av_, index);
9✔
169
  }
170
  if (string_starts_with(argument, "TEST(")) {
9✔
171
    add_test_to_run_based_on_verbose_output(ac_, av_, index, "TEST(");
2✔
172
    return true;
2✔
173
  }
174
  if (string_starts_with(argument, "SKIPPED_TEST(")) {
7✔
175
    add_test_to_run_based_on_verbose_output(ac_, av_, index, "SKIPPED_TEST(");
1✔
176
    return true;
1✔
177
  }
178
  if (string_starts_with(argument, "-p")) {
6✔
179
    return plugin->parse_all_arguments(ac_, av_, index);
3✔
180
  }
181
  return false;
3✔
182
}
183

184
bool CommandLineArguments::parse_argument(
184✔
185
    const String& argument,
186
    Plugin* plugin,
187
    int& index
188
)
189
{
190
  if (parse_simple_flag(argument)) {
184✔
191
    return true;
87✔
192
  }
193
  return parse_prefix_arg(argument, plugin, index);
97✔
194
}
195

196
bool CommandLineArguments::parse(Plugin* plugin)
124✔
197
{
198
  for (int i = 1; i < ac_; i++) {
299✔
199
    if (!parse_argument(av_[i], plugin, i)) {
184✔
200
      return false;
9✔
201
    }
202
  }
203
  return true;
115✔
204
}
205

206
String CommandLineArguments::help()
5✔
207
{
208
  String help_str =
209
      "mutiny v" MUTINY_VERSION_STRING "\n\n"
210
      "Options that do not run tests but query:\n"
211
      "  -h                - this wonderful help screen. Joy!\n"
212
      "  -lg               - print a list of group names, separated by "
213
      "spaces\n"
214
      "  -ln               - print a list of test names in the form of "
215
      "group.name, separated by spaces\n"
216
      "  -ll               - print a list of test names in the form of "
217
      "group.name.test_file_path.line\n"
218
      "  -lo               - print a list of ordered test names in the form "
219
      "of group.name.test_file_path.line\n"
220
      "  -lgl              - print a list of group locations in the form of "
221
      "group.file_path.line\n"
222
      "\n"
223
      "Options that change the output format:\n"
224
      "  -c                - colorize output, print green if OK, or red if "
225
      "failed\n"
226
      "  -v                - verbose, print each test name as it runs\n"
227
      "  -vv               - very verbose, print internal information "
228
      "during test run\n";
5✔
229

230
  Plugin* plugin = Registry::get_current_registry()->get_first_plugin();
5✔
231
  String plugin_help = plugin->get_all_help();
5✔
232

233
  if (!plugin_help.empty()) {
5✔
234
    help_str += "\nOptions that are provided by plugins:\n";
5✔
235
    help_str += plugin_help;
5✔
236
  }
237

238
  help_str +=
239
      "\n"
240
      "Options that control which tests are run:\n"
241
      "  -g <group>        - only run tests whose group contains <group>\n"
242
      "  -n <name>         - only run tests whose name contains <name>\n"
243
      "  -t <group>.<name> - only run tests whose group and name contain "
244
      "<group> and <name>\n"
245
      "  -sg <group>       - only run tests whose group exactly matches "
246
      "<group>\n"
247
      "  -sn <name>        - only run tests whose name exactly matches "
248
      "<name>\n"
249
      "  -st <grp>.<name>  - only run tests whose group and name exactly "
250
      "match <grp> and <name>\n"
251
      "  -xg <group>       - exclude tests whose group contains <group>\n"
252
      "  -xn <name>        - exclude tests whose name contains <name>\n"
253
      "  -xt <grp>.<name>  - exclude tests whose group and name contain "
254
      "<grp> and <name>\n"
255
      "  -xsg <group>      - exclude tests whose group exactly matches "
256
      "<group>\n"
257
      "  -xsn <name>       - exclude tests whose name exactly matches "
258
      "<name>\n"
259
      "  -xst <grp>.<name> - exclude tests whose group and name exactly "
260
      "match <grp> and <name>\n"
261
      "  \"[IGNORE_]TEST(<group>, <name>)\"\n"
262
      "                    - only run tests whose group and name exactly "
263
      "match <group> and <name>\n"
264
      "                      (this can be used to copy-paste output from "
265
      "the -v option on the command line)\n"
266
      "\n"
267
      "Options that control how the tests are run:\n"
268
      "  -b                - run the tests backwards, reversing the normal "
269
      "way\n"
270
      "  -s [<seed>]       - shuffle tests randomly (randomization seed is "
271
      "optional, must be greater than 0)\n"
272
      "  -r[<#>]           - repeat the tests <#> times (or twice if <#> is "
273
      "not specified)\n"
274
      "  -ri               - run ignored tests as if they are not ignored\n"
275
      "  -f                - Cause the tests to crash on failure (to allow "
276
      "the test to be debugged if necessary)\n"
277
      "  -e                - do not rethrow unexpected exceptions on "
278
      "failure\n";
5✔
279

280
  return help_str;
10✔
281
}
5✔
282

283
bool CommandLineArguments::need_help() const
70✔
284
{
285
  return need_help_;
70✔
286
}
287

288
bool CommandLineArguments::is_verbose() const
81✔
289
{
290
  return verbose_;
81✔
291
}
292

293
bool CommandLineArguments::is_very_verbose() const
79✔
294
{
295
  return very_verbose_;
79✔
296
}
297

298
bool CommandLineArguments::is_color() const
69✔
299
{
300
  return color_;
69✔
301
}
302

303
bool CommandLineArguments::is_listing_test_group_names() const
69✔
304
{
305
  return list_test_group_names_;
69✔
306
}
307

308
bool CommandLineArguments::is_listing_test_group_and_case_names() const
68✔
309
{
310
  return list_test_group_and_case_names_;
68✔
311
}
312

313
bool CommandLineArguments::is_listing_test_locations() const
66✔
314
{
315
  return list_test_locations_;
66✔
316
}
317

318
bool CommandLineArguments::is_listing_ordered_test_locations() const
64✔
319
{
320
  return list_ordered_test_locations_;
64✔
321
}
322

323
bool CommandLineArguments::is_listing_test_group_locations() const
64✔
324
{
325
  return list_test_group_locations_;
64✔
326
}
327

328
bool CommandLineArguments::is_run_ignored() const
69✔
329
{
330
  return run_ignored_;
69✔
331
}
332

333
size_t CommandLineArguments::get_repeat_count() const
72✔
334
{
335
  return repeat_;
72✔
336
}
337

338
bool CommandLineArguments::is_reversing() const
63✔
339
{
340
  return reversing_;
63✔
341
}
342

343
bool CommandLineArguments::is_crashing_on_fail() const
70✔
344
{
345
  return crash_on_fail_;
70✔
346
}
347

348
bool CommandLineArguments::is_rethrowing_exceptions() const
70✔
349
{
350
  return rethrow_exceptions_;
70✔
351
}
352

353
bool CommandLineArguments::is_shuffling() const
127✔
354
{
355
  return shuffling_;
127✔
356
}
357

358
size_t CommandLineArguments::get_shuffle_seed() const
8✔
359
{
360
  return shuffle_seed_;
8✔
361
}
362

363
const Filter* CommandLineArguments::get_group_filters() const
85✔
364
{
365
  return group_filters_;
85✔
366
}
367

368
const Filter* CommandLineArguments::get_name_filters() const
84✔
369
{
370
  return name_filters_;
84✔
371
}
372

373
void CommandLineArguments::set_repeat_count(
3✔
374
    int argc,
375
    const char* const* argv,
376
    int& i
377
)
378
{
379
  repeat_ = 0;
3✔
380

381
  String repeat_parameter(argv[i]);
3✔
382
  if (repeat_parameter.size() > 2) {
3✔
383
    repeat_ = static_cast<size_t>(strtol(argv[i] + 2));
1✔
384
  } else if (i + 1 < argc) {
2✔
385
    repeat_ = static_cast<size_t>(strtol(argv[i + 1]));
1✔
386
    if (repeat_ != 0) {
1✔
387
      i++;
1✔
388
    }
389
  }
390

391
  if (0 == repeat_) {
3✔
392
    repeat_ = 2;
1✔
393
  }
394
}
3✔
395

396
bool CommandLineArguments::set_shuffle(
9✔
397
    int argc,
398
    const char* const* argv,
399
    int& i
400
)
401
{
402
  shuffling_ = true;
9✔
403
  shuffle_seed_ = static_cast<unsigned int>(get_time_in_millis());
9✔
404
  if (shuffle_seed_ == 0) {
9✔
405
    shuffle_seed_++;
×
406
  }
407

408
  String shuffle_parameter = argv[i];
9✔
409
  if (shuffle_parameter.size() > 2) {
9✔
410
    shuffling_pre_seeded_ = true;
5✔
411
    shuffle_seed_ = static_cast<unsigned>(strtoul(argv[i] + 2));
5✔
412
  } else if (i + 1 < argc) {
4✔
413
    auto parsed_parameter = static_cast<unsigned>(strtoul(argv[i + 1]));
2✔
414
    if (parsed_parameter != 0) {
2✔
415
      shuffling_pre_seeded_ = true;
1✔
416
      shuffle_seed_ = parsed_parameter;
1✔
417
      i++;
1✔
418
    }
419
  }
420
  return (shuffle_seed_ != 0);
9✔
421
}
9✔
422

423
String CommandLineArguments::get_parameter_field(
79✔
424
    int argc,
425
    const char* const* argv,
426
    int& i,
427
    const String& parameter_name
428
)
429
{
430
  size_t parameter_length = parameter_name.size();
79✔
431
  String parameter(argv[i]);
79✔
432
  if (parameter.size() > parameter_length) {
79✔
433
    return argv[i] + parameter_length;
20✔
434
  }
435
  if (i + 1 < argc) {
59✔
436
    return argv[++i];
59✔
437
  }
UNCOV
438
  return "";
×
439
}
79✔
440

441
void CommandLineArguments::add_group_filter(
3✔
442
    int argc,
443
    const char* const* argv,
444
    int& i
445
)
446
{
447
  auto* group_filter = new Filter(get_parameter_field(argc, argv, i, "-g"));
3✔
448
  group_filters_ = group_filter->add(group_filters_);
3✔
449
}
3✔
450

451
bool CommandLineArguments::add_group_dot_name_filter(
8✔
452
    int argc,
453
    const char* const* argv,
454
    int& i,
455
    const String& parameter_name,
456
    bool strict,
457
    bool exclude
458
)
459
{
460
  String group_dot_name = get_parameter_field(argc, argv, i, parameter_name);
8✔
461
  StringCollection collection(group_dot_name, '.');
8✔
462

463
  if (collection.size() != 2) {
8✔
464
    return false;
4✔
465
  }
466

467
  auto* group_filter =
468
      new Filter(collection[0].substr(0, collection[0].size() - 1));
4✔
469
  auto* name_filter = new Filter(collection[1]);
4✔
470
  if (strict) {
4✔
471
    group_filter->strict_matching();
2✔
472
    name_filter->strict_matching();
2✔
473
  }
474
  if (exclude) {
4✔
475
    group_filter->invert_matching();
2✔
476
    name_filter->invert_matching();
2✔
477
  }
478
  group_filters_ = group_filter->add(group_filters_);
4✔
479
  name_filters_ = name_filter->add(name_filters_);
4✔
480
  return true;
4✔
481
}
8✔
482

483
void CommandLineArguments::add_strict_group_filter(
48✔
484
    int argc,
485
    const char* const* argv,
486
    int& i
487
)
488
{
489
  auto* group_filter = new Filter(get_parameter_field(argc, argv, i, "-sg"));
48✔
490
  group_filter->strict_matching();
48✔
491
  group_filters_ = group_filter->add(group_filters_);
48✔
492
}
48✔
493

494
void CommandLineArguments::add_exclude_group_filter(
2✔
495
    int argc,
496
    const char* const* argv,
497
    int& i
498
)
499
{
500
  auto* group_filter = new Filter(get_parameter_field(argc, argv, i, "-xg"));
2✔
501
  group_filter->invert_matching();
2✔
502
  group_filters_ = group_filter->add(group_filters_);
2✔
503
}
2✔
504

505
void CommandLineArguments::add_exclude_strict_group_filter(
2✔
506
    int argc,
507
    const char* const* argv,
508
    int& i
509
)
510
{
511
  auto* group_filter = new Filter(get_parameter_field(argc, argv, i, "-xsg"));
2✔
512
  group_filter->strict_matching();
2✔
513
  group_filter->invert_matching();
2✔
514
  group_filters_ = group_filter->add(group_filters_);
2✔
515
}
2✔
516

517
void CommandLineArguments::add_name_filter(
2✔
518
    int argc,
519
    const char* const* argv,
520
    int& i
521
)
522
{
523
  auto* name_filter = new Filter(get_parameter_field(argc, argv, i, "-n"));
2✔
524
  name_filters_ = name_filter->add(name_filters_);
2✔
525
}
2✔
526

527
void CommandLineArguments::add_strict_name_filter(
6✔
528
    int argc,
529
    const char* const* argv,
530
    int& index
531
)
532
{
533
  auto* name_filter = new Filter(get_parameter_field(argc, argv, index, "-sn"));
6✔
534
  name_filter->strict_matching();
6✔
535
  name_filters_ = name_filter->add(name_filters_);
6✔
536
}
6✔
537

538
void CommandLineArguments::add_exclude_name_filter(
3✔
539
    int argc,
540
    const char* const* argv,
541
    int& index
542
)
543
{
544
  auto* name_filter = new Filter(get_parameter_field(argc, argv, index, "-xn"));
3✔
545
  name_filter->invert_matching();
3✔
546
  name_filters_ = name_filter->add(name_filters_);
3✔
547
}
3✔
548

549
void CommandLineArguments::add_exclude_strict_name_filter(
2✔
550
    int argc,
551
    const char* const* argv,
552
    int& index
553
)
554
{
555
  auto* name_filter =
556
      new Filter(get_parameter_field(argc, argv, index, "-xsn"));
2✔
557
  name_filter->invert_matching();
2✔
558
  name_filter->strict_matching();
2✔
559
  name_filters_ = name_filter->add(name_filters_);
2✔
560
}
2✔
561

562
void CommandLineArguments::add_test_to_run_based_on_verbose_output(
3✔
563
    int argc,
564
    const char* const* argv,
565
    int& index,
566
    const char* parameter_name
567
)
568
{
569
  String wholename = get_parameter_field(argc, argv, index, parameter_name);
3✔
570
  String testname = sub_string_from_till(wholename, ',', ')');
3✔
571
  testname = testname.substr(2);
3✔
572
  auto* namefilter = new Filter(testname);
3✔
573
  auto* groupfilter =
574
      new Filter(sub_string_from_till(wholename, wholename[0], ','));
3✔
575
  namefilter->strict_matching();
3✔
576
  groupfilter->strict_matching();
3✔
577
  group_filters_ = groupfilter->add(group_filters_);
3✔
578
  name_filters_ = namefilter->add(name_filters_);
3✔
579
}
3✔
580

581
} // namespace test
582
} // namespace tiny
583
} // namespace mu
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc