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

thetic / mu.tiny / 24642562173

20 Apr 2026 12:12AM UTC coverage: 98.89% (+0.01%) from 98.879%
24642562173

Pull #84

github

web-flow
Merge 37778513a into a2dfbd6ba
Pull Request #84: apply clang-tidy fixes

625 of 626 new or added lines in 45 files covered. (99.84%)

2 existing lines in 2 files now uncovered.

5254 of 5313 relevant lines covered (98.89%)

3352.89 hits per line

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

98.77
/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(Plugin* plugin)
124✔
57
{
58
  bool correct_parameters = true;
124✔
59
  for (int i = 1; i < ac_; i++) {
299✔
60
    String argument = av_[i];
184✔
61

62
    if (argument == "-h") {
184✔
63
      need_help_ = true;
3✔
64
    } else if (argument == "-v") {
181✔
65
      verbose_ = true;
46✔
66
    } else if (argument == "-vv") {
135✔
67
      very_verbose_ = true;
12✔
68
    } else if (argument == "-c") {
123✔
69
      color_ = true;
11✔
70
    } else if (argument == "-b") {
112✔
71
      reversing_ = true;
2✔
72
    } else if (argument == "-lg") {
110✔
73
      list_test_group_names_ = true;
2✔
74
    } else if (argument == "-ln") {
108✔
75
      list_test_group_and_case_names_ = true;
2✔
76
    } else if (argument == "-lo") {
106✔
77
      list_ordered_test_locations_ = true;
1✔
78
    } else if (argument == "-lgl") {
105✔
79
      list_test_group_locations_ = true;
2✔
80
    } else if (argument == "-ll") {
103✔
81
      list_test_locations_ = true;
2✔
82
    } else if (argument == "-ri") {
101✔
83
      run_ignored_ = true;
2✔
84
    } else if (argument == "-f") {
99✔
85
      crash_on_fail_ = true;
1✔
86
    } else if (argument == "-e") {
98✔
87
      rethrow_exceptions_ = false;
1✔
88
    } else if (string_starts_with(argument, "-r")) {
97✔
89
      set_repeat_count(ac_, av_, i);
3✔
90
    } else if (string_starts_with(argument, "-g")) {
94✔
91
      add_group_filter(ac_, av_, i);
3✔
92
    } else if (string_starts_with(argument, "-t")) {
91✔
93
      correct_parameters =
94
          add_group_dot_name_filter(ac_, av_, i, "-t", false, false);
2✔
95
    } else if (string_starts_with(argument, "-st")) {
89✔
96
      correct_parameters =
97
          add_group_dot_name_filter(ac_, av_, i, "-st", true, false);
2✔
98
    } else if (string_starts_with(argument, "-xt")) {
87✔
99
      correct_parameters =
100
          add_group_dot_name_filter(ac_, av_, i, "-xt", false, true);
2✔
101
    } else if (string_starts_with(argument, "-xst")) {
85✔
102
      correct_parameters =
103
          add_group_dot_name_filter(ac_, av_, i, "-xst", true, true);
2✔
104
    } else if (string_starts_with(argument, "-sg")) {
83✔
105
      add_strict_group_filter(ac_, av_, i);
48✔
106
    } else if (string_starts_with(argument, "-xg")) {
35✔
107
      add_exclude_group_filter(ac_, av_, i);
2✔
108
    } else if (string_starts_with(argument, "-xsg")) {
33✔
109
      add_exclude_strict_group_filter(ac_, av_, i);
2✔
110
    } else if (string_starts_with(argument, "-n")) {
31✔
111
      add_name_filter(ac_, av_, i);
2✔
112
    } else if (string_starts_with(argument, "-sn")) {
29✔
113
      add_strict_name_filter(ac_, av_, i);
6✔
114
    } else if (string_starts_with(argument, "-xn")) {
23✔
115
      add_exclude_name_filter(ac_, av_, i);
3✔
116
    } else if (string_starts_with(argument, "-xsn")) {
20✔
117
      add_exclude_strict_name_filter(ac_, av_, i);
2✔
118
    } else if (string_starts_with(argument, "-s")) {
18✔
119
      correct_parameters = set_shuffle(ac_, av_, i);
9✔
120
    } else if (string_starts_with(argument, "TEST(")) {
9✔
121
      add_test_to_run_based_on_verbose_output(ac_, av_, i, "TEST(");
2✔
122
    } else if (string_starts_with(argument, "SKIPPED_TEST(")) {
7✔
123
      add_test_to_run_based_on_verbose_output(ac_, av_, i, "SKIPPED_TEST(");
1✔
124
    } else if (string_starts_with(argument, "-p")) {
6✔
125
      correct_parameters = plugin->parse_all_arguments(ac_, av_, i);
3✔
126
    } else {
127
      correct_parameters = false;
3✔
128
    }
129

130
    if (!correct_parameters) {
184✔
131
      return false;
9✔
132
    }
133
  }
184✔
134
  return true;
115✔
135
}
136

137
String CommandLineArguments::help()
5✔
138
{
139
  String help_str =
140
      "mutiny v" MUTINY_VERSION_STRING "\n\n"
141
      "Options that do not run tests but query:\n"
142
      "  -h                - this wonderful help screen. Joy!\n"
143
      "  -lg               - print a list of group names, separated by "
144
      "spaces\n"
145
      "  -ln               - print a list of test names in the form of "
146
      "group.name, separated by spaces\n"
147
      "  -ll               - print a list of test names in the form of "
148
      "group.name.test_file_path.line\n"
149
      "  -lo               - print a list of ordered test names in the form "
150
      "of group.name.test_file_path.line\n"
151
      "  -lgl              - print a list of group locations in the form of "
152
      "group.file_path.line\n"
153
      "\n"
154
      "Options that change the output format:\n"
155
      "  -c                - colorize output, print green if OK, or red if "
156
      "failed\n"
157
      "  -v                - verbose, print each test name as it runs\n"
158
      "  -vv               - very verbose, print internal information "
159
      "during test run\n";
5✔
160

161
  Plugin* plugin = Registry::get_current_registry()->get_first_plugin();
5✔
162
  String plugin_help = plugin->get_all_help();
5✔
163

164
  if (!plugin_help.empty()) {
5✔
165
    help_str += "\nOptions that are provided by plugins:\n";
5✔
166
    help_str += plugin_help;
5✔
167
  }
168

169
  help_str +=
170
      "\n"
171
      "Options that control which tests are run:\n"
172
      "  -g <group>        - only run tests whose group contains <group>\n"
173
      "  -n <name>         - only run tests whose name contains <name>\n"
174
      "  -t <group>.<name> - only run tests whose group and name contain "
175
      "<group> and <name>\n"
176
      "  -sg <group>       - only run tests whose group exactly matches "
177
      "<group>\n"
178
      "  -sn <name>        - only run tests whose name exactly matches "
179
      "<name>\n"
180
      "  -st <grp>.<name>  - only run tests whose group and name exactly "
181
      "match <grp> and <name>\n"
182
      "  -xg <group>       - exclude tests whose group contains <group>\n"
183
      "  -xn <name>        - exclude tests whose name contains <name>\n"
184
      "  -xt <grp>.<name>  - exclude tests whose group and name contain "
185
      "<grp> and <name>\n"
186
      "  -xsg <group>      - exclude tests whose group exactly matches "
187
      "<group>\n"
188
      "  -xsn <name>       - exclude tests whose name exactly matches "
189
      "<name>\n"
190
      "  -xst <grp>.<name> - exclude tests whose group and name exactly "
191
      "match <grp> and <name>\n"
192
      "  \"[IGNORE_]TEST(<group>, <name>)\"\n"
193
      "                    - only run tests whose group and name exactly "
194
      "match <group> and <name>\n"
195
      "                      (this can be used to copy-paste output from "
196
      "the -v option on the command line)\n"
197
      "\n"
198
      "Options that control how the tests are run:\n"
199
      "  -b                - run the tests backwards, reversing the normal "
200
      "way\n"
201
      "  -s [<seed>]       - shuffle tests randomly (randomization seed is "
202
      "optional, must be greater than 0)\n"
203
      "  -r[<#>]           - repeat the tests <#> times (or twice if <#> is "
204
      "not specified)\n"
205
      "  -ri               - run ignored tests as if they are not ignored\n"
206
      "  -f                - Cause the tests to crash on failure (to allow "
207
      "the test to be debugged if necessary)\n"
208
      "  -e                - do not rethrow unexpected exceptions on "
209
      "failure\n";
5✔
210

211
  return help_str;
10✔
212
}
5✔
213

214
bool CommandLineArguments::need_help() const
70✔
215
{
216
  return need_help_;
70✔
217
}
218

219
bool CommandLineArguments::is_verbose() const
81✔
220
{
221
  return verbose_;
81✔
222
}
223

224
bool CommandLineArguments::is_very_verbose() const
79✔
225
{
226
  return very_verbose_;
79✔
227
}
228

229
bool CommandLineArguments::is_color() const
69✔
230
{
231
  return color_;
69✔
232
}
233

234
bool CommandLineArguments::is_listing_test_group_names() const
69✔
235
{
236
  return list_test_group_names_;
69✔
237
}
238

239
bool CommandLineArguments::is_listing_test_group_and_case_names() const
68✔
240
{
241
  return list_test_group_and_case_names_;
68✔
242
}
243

244
bool CommandLineArguments::is_listing_test_locations() const
66✔
245
{
246
  return list_test_locations_;
66✔
247
}
248

249
bool CommandLineArguments::is_listing_ordered_test_locations() const
64✔
250
{
251
  return list_ordered_test_locations_;
64✔
252
}
253

254
bool CommandLineArguments::is_listing_test_group_locations() const
64✔
255
{
256
  return list_test_group_locations_;
64✔
257
}
258

259
bool CommandLineArguments::is_run_ignored() const
69✔
260
{
261
  return run_ignored_;
69✔
262
}
263

264
size_t CommandLineArguments::get_repeat_count() const
72✔
265
{
266
  return repeat_;
72✔
267
}
268

269
bool CommandLineArguments::is_reversing() const
63✔
270
{
271
  return reversing_;
63✔
272
}
273

274
bool CommandLineArguments::is_crashing_on_fail() const
70✔
275
{
276
  return crash_on_fail_;
70✔
277
}
278

279
bool CommandLineArguments::is_rethrowing_exceptions() const
70✔
280
{
281
  return rethrow_exceptions_;
70✔
282
}
283

284
bool CommandLineArguments::is_shuffling() const
127✔
285
{
286
  return shuffling_;
127✔
287
}
288

289
size_t CommandLineArguments::get_shuffle_seed() const
8✔
290
{
291
  return shuffle_seed_;
8✔
292
}
293

294
const Filter* CommandLineArguments::get_group_filters() const
85✔
295
{
296
  return group_filters_;
85✔
297
}
298

299
const Filter* CommandLineArguments::get_name_filters() const
84✔
300
{
301
  return name_filters_;
84✔
302
}
303

304
void CommandLineArguments::set_repeat_count(
3✔
305
    int argc,
306
    const char* const* argv,
307
    int& i
308
)
309
{
310
  repeat_ = 0;
3✔
311

312
  String repeat_parameter(argv[i]);
3✔
313
  if (repeat_parameter.size() > 2) {
3✔
314
    repeat_ = static_cast<size_t>(strtol(argv[i] + 2));
1✔
315
  } else if (i + 1 < argc) {
2✔
316
    repeat_ = static_cast<size_t>(strtol(argv[i + 1]));
1✔
317
    if (repeat_ != 0) {
1✔
318
      i++;
1✔
319
    }
320
  }
321

322
  if (0 == repeat_) {
3✔
323
    repeat_ = 2;
1✔
324
  }
325
}
3✔
326

327
bool CommandLineArguments::set_shuffle(
9✔
328
    int argc,
329
    const char* const* argv,
330
    int& i
331
)
332
{
333
  shuffling_ = true;
9✔
334
  shuffle_seed_ = static_cast<unsigned int>(get_time_in_millis());
9✔
335
  if (shuffle_seed_ == 0) {
9✔
336
    shuffle_seed_++;
×
337
  }
338

339
  String shuffle_parameter = argv[i];
9✔
340
  if (shuffle_parameter.size() > 2) {
9✔
341
    shuffling_pre_seeded_ = true;
5✔
342
    shuffle_seed_ = static_cast<unsigned>(strtoul(argv[i] + 2));
5✔
343
  } else if (i + 1 < argc) {
4✔
344
    auto parsed_parameter = static_cast<unsigned>(strtoul(argv[i + 1]));
2✔
345
    if (parsed_parameter != 0) {
2✔
346
      shuffling_pre_seeded_ = true;
1✔
347
      shuffle_seed_ = parsed_parameter;
1✔
348
      i++;
1✔
349
    }
350
  }
351
  return (shuffle_seed_ != 0);
9✔
352
}
9✔
353

354
String CommandLineArguments::get_parameter_field(
79✔
355
    int argc,
356
    const char* const* argv,
357
    int& i,
358
    const String& parameter_name
359
)
360
{
361
  size_t parameter_length = parameter_name.size();
79✔
362
  String parameter(argv[i]);
79✔
363
  if (parameter.size() > parameter_length) {
79✔
364
    return argv[i] + parameter_length;
20✔
365
  }
366
  if (i + 1 < argc) {
59✔
367
    return argv[++i];
59✔
368
  }
UNCOV
369
  return "";
×
370
}
79✔
371

372
void CommandLineArguments::add_group_filter(
3✔
373
    int argc,
374
    const char* const* argv,
375
    int& i
376
)
377
{
378
  auto* group_filter = new Filter(get_parameter_field(argc, argv, i, "-g"));
3✔
379
  group_filters_ = group_filter->add(group_filters_);
3✔
380
}
3✔
381

382
bool CommandLineArguments::add_group_dot_name_filter(
8✔
383
    int argc,
384
    const char* const* argv,
385
    int& i,
386
    const String& parameter_name,
387
    bool strict,
388
    bool exclude
389
)
390
{
391
  String group_dot_name = get_parameter_field(argc, argv, i, parameter_name);
8✔
392
  StringCollection collection(group_dot_name, '.');
8✔
393

394
  if (collection.size() != 2) {
8✔
395
    return false;
4✔
396
  }
397

398
  auto* group_filter =
399
      new Filter(collection[0].substr(0, collection[0].size() - 1));
4✔
400
  auto* name_filter = new Filter(collection[1]);
4✔
401
  if (strict) {
4✔
402
    group_filter->strict_matching();
2✔
403
    name_filter->strict_matching();
2✔
404
  }
405
  if (exclude) {
4✔
406
    group_filter->invert_matching();
2✔
407
    name_filter->invert_matching();
2✔
408
  }
409
  group_filters_ = group_filter->add(group_filters_);
4✔
410
  name_filters_ = name_filter->add(name_filters_);
4✔
411
  return true;
4✔
412
}
8✔
413

414
void CommandLineArguments::add_strict_group_filter(
48✔
415
    int argc,
416
    const char* const* argv,
417
    int& i
418
)
419
{
420
  auto* group_filter = new Filter(get_parameter_field(argc, argv, i, "-sg"));
48✔
421
  group_filter->strict_matching();
48✔
422
  group_filters_ = group_filter->add(group_filters_);
48✔
423
}
48✔
424

425
void CommandLineArguments::add_exclude_group_filter(
2✔
426
    int argc,
427
    const char* const* argv,
428
    int& i
429
)
430
{
431
  auto* group_filter = new Filter(get_parameter_field(argc, argv, i, "-xg"));
2✔
432
  group_filter->invert_matching();
2✔
433
  group_filters_ = group_filter->add(group_filters_);
2✔
434
}
2✔
435

436
void CommandLineArguments::add_exclude_strict_group_filter(
2✔
437
    int argc,
438
    const char* const* argv,
439
    int& i
440
)
441
{
442
  auto* group_filter = new Filter(get_parameter_field(argc, argv, i, "-xsg"));
2✔
443
  group_filter->strict_matching();
2✔
444
  group_filter->invert_matching();
2✔
445
  group_filters_ = group_filter->add(group_filters_);
2✔
446
}
2✔
447

448
void CommandLineArguments::add_name_filter(
2✔
449
    int argc,
450
    const char* const* argv,
451
    int& i
452
)
453
{
454
  auto* name_filter = new Filter(get_parameter_field(argc, argv, i, "-n"));
2✔
455
  name_filters_ = name_filter->add(name_filters_);
2✔
456
}
2✔
457

458
void CommandLineArguments::add_strict_name_filter(
6✔
459
    int argc,
460
    const char* const* argv,
461
    int& index
462
)
463
{
464
  auto* name_filter = new Filter(get_parameter_field(argc, argv, index, "-sn"));
6✔
465
  name_filter->strict_matching();
6✔
466
  name_filters_ = name_filter->add(name_filters_);
6✔
467
}
6✔
468

469
void CommandLineArguments::add_exclude_name_filter(
3✔
470
    int argc,
471
    const char* const* argv,
472
    int& index
473
)
474
{
475
  auto* name_filter = new Filter(get_parameter_field(argc, argv, index, "-xn"));
3✔
476
  name_filter->invert_matching();
3✔
477
  name_filters_ = name_filter->add(name_filters_);
3✔
478
}
3✔
479

480
void CommandLineArguments::add_exclude_strict_name_filter(
2✔
481
    int argc,
482
    const char* const* argv,
483
    int& index
484
)
485
{
486
  auto* name_filter =
487
      new Filter(get_parameter_field(argc, argv, index, "-xsn"));
2✔
488
  name_filter->invert_matching();
2✔
489
  name_filter->strict_matching();
2✔
490
  name_filters_ = name_filter->add(name_filters_);
2✔
491
}
2✔
492

493
void CommandLineArguments::add_test_to_run_based_on_verbose_output(
3✔
494
    int argc,
495
    const char* const* argv,
496
    int& index,
497
    const char* parameter_name
498
)
499
{
500
  String wholename = get_parameter_field(argc, argv, index, parameter_name);
3✔
501
  String testname = sub_string_from_till(wholename, ',', ')');
3✔
502
  testname = testname.substr(2);
3✔
503
  auto* namefilter = new Filter(testname);
3✔
504
  auto* groupfilter =
505
      new Filter(sub_string_from_till(wholename, wholename[0], ','));
3✔
506
  namefilter->strict_matching();
3✔
507
  groupfilter->strict_matching();
3✔
508
  group_filters_ = groupfilter->add(group_filters_);
3✔
509
  name_filters_ = namefilter->add(name_filters_);
3✔
510
}
3✔
511

512
} // namespace test
513
} // namespace tiny
514
} // 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