GCC Code Coverage Report


Directory: ./
File: src/iguana/tests/iguana_test.cc
Date: 2025-06-02 23:22:06
Exec Total Coverage
Lines: 124 151 82.1%
Functions: 7 10 70.0%
Branches: 129 305 42.3%

Line Branch Exec Source
1 #include <getopt.h>
2
3 #include "TestAlgorithm.h"
4 #include "TestMultithreading.h"
5 #include "TestConfig.h"
6 #include "TestLogger.h"
7 #include "TestValidator.h"
8
9 31 int main(int argc, char** argv)
10 {
11 // user parameters
12 31 std::string command = "";
13
1/4
✓ Branch 0 (3→4) taken 31 times.
✗ Branch 1 (3→440) not taken.
✗ Branch 2 (440→441) not taken.
✗ Branch 3 (440→443) not taken.
31 std::string data_file = "";
14 31 int num_events = 10;
15
1/4
✓ Branch 0 (4→5) taken 31 times.
✗ Branch 1 (4→434) not taken.
✗ Branch 2 (434→435) not taken.
✗ Branch 3 (434→437) not taken.
31 std::string algo_name = "";
16 int test_num = 0;
17 31 int num_threads = 0;
18
1/4
✓ Branch 0 (5→6) taken 31 times.
✗ Branch 1 (5→428) not taken.
✗ Branch 2 (428→429) not taken.
✗ Branch 3 (428→431) not taken.
31 std::string concurrency_model = "";
19 bool vary_run = false;
20
2/6
✓ Branch 0 (6→7) taken 31 times.
✗ Branch 1 (6→422) not taken.
✓ Branch 2 (7→8) taken 31 times.
✗ Branch 3 (7→412) not taken.
✗ Branch 4 (422→423) not taken.
✗ Branch 5 (422→425) not taken.
31 std::string output_dir = "";
21 bool verbose = false;
22 std::vector<std::string> bank_names;
23 std::vector<std::string> prerequisite_algos;
24
25 // get the command
26
1/2
✓ Branch 0 (7→8) taken 31 times.
✗ Branch 1 (7→412) not taken.
31 auto exe = std::string(argv[0]);
27 1 auto UsageCommands = [&](int exit_code)
28 {
29
1/2
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 1 times.
2 fmt::print("\nUSAGE: {} [COMMAND] [OPTIONS]...\n", exe);
30 1 fmt::print("\n COMMANDS:\n\n");
31 1 fmt::print(" {:<20} {}\n", "algorithm", "call `Run` on an algorithm");
32 1 fmt::print(" {:<20} {}\n", "multithreading", "call `Run` on an algorithm, multithreaded");
33 1 fmt::print(" {:<20} {}\n", "validator", "run an algorithm's validator");
34 1 fmt::print(" {:<20} {}\n", "unit", "call `Test` on an algorithm, for unit tests");
35 1 fmt::print(" {:<20} {}\n", "config", "test config file parsing");
36 1 fmt::print(" {:<20} {}\n", "logger", "test Logger");
37 1 fmt::print("\n OPTIONS:\n\n");
38 1 fmt::print(" Each command has its own set of OPTIONS; either provide no OPTIONS\n");
39 1 fmt::print(" or use the --help option for more usage information about a specific command\n");
40 1 fmt::print("\n");
41 1 return exit_code;
42 31 };
43
2/2
✓ Branch 0 (8→9) taken 1 times.
✓ Branch 1 (8→10) taken 30 times.
31 if(argc <= 1)
44
1/2
✓ Branch 0 (9→265) taken 1 times.
✗ Branch 1 (9→406) not taken.
1 return UsageCommands(2);
45
1/2
✓ Branch 0 (10→11) taken 30 times.
✗ Branch 1 (10→406) not taken.
30 command = std::string(argv[1]);
46
2/4
✓ Branch 0 (17→18) taken 30 times.
✗ Branch 1 (17→19) not taken.
✗ Branch 2 (18→19) not taken.
✓ Branch 3 (18→20) taken 30 times.
30 if(command == "--help" || command == "-h")
47 return UsageCommands(0);
48 // omit the command, for getopt
49 30 argv++;
50 30 argc--;
51
52 // usage options
53 // clang-format off
54
1/2
✓ Branch 0 (2→3) taken 5 times.
✗ Branch 1 (2→123) not taken.
5 auto UsageOptions = [&](int exit_code)
55 {
56 std::unordered_map<std::string, std::function<void()>> print_option = {
57 {"f", [&]()
58 {
59 3 fmt::print(" {:<20} {}\n", "-f FILE", "input data file");
60 }},
61
1/2
✓ Branch 0 (3→4) taken 5 times.
✗ Branch 1 (3→123) not taken.
8 {"n", [&]()
62 {
63 3 fmt::print(" {:<20} {}\n", "-n NUM_EVENTS", "number of events from the data file");
64 3 fmt::print(" {:<20} set to 0 to process ALL events\n", "");
65 3 fmt::print(" {:<20} default: {}\n", "", num_events);
66 3 }},
67
68 {"a-algo", [&]()
69 {
70 2 fmt::print(" {:<20} {}\n", "-a ALGORITHM", "the name of the algorithm");
71 }},
72 {"a-vdor", [&]()
73 {
74 1 fmt::print(" {:<20} {}\n", "-a VALIDATOR", "the name of the validator");
75 }},
76 3 {"b", [&]()
77 {
78 3 fmt::print(" {:<20} {}\n", "-b BANKS", "add a single bank to process");
79 3 fmt::print(" {:<20} you may add as many banks as you need (-b BANK1 -b BANK2 ...)\n", "");
80 3 fmt::print(" {:<20} default: if you do not add any banks, ALL of them will be used\n", "");
81 3 }},
82 2 {"p", [&]()
83 {
84 2 fmt::print(" {:<20} {}\n", "-p PREREQUISITE_ALGOS", "add a prerequisite algorithm");
85 2 fmt::print(" {:<20} these are the algorithms needed upstream of ALGORITHM\n", "");
86 2 fmt::print(" {:<20} this option is repeatable\n", "");
87 2 fmt::print(" {:<20} default: no prerequisites\n", "");
88 2 }},
89 {"t", [&]()
90 {
91 1 fmt::print(" {:<20} {}\n", "-t TESTNUM", "test number");
92 }},
93
1/2
✓ Branch 0 (9→10) taken 5 times.
✗ Branch 1 (9→123) not taken.
5 {"j", [&]()
94 {
95 fmt::print(" {:<20} {}\n", "-j NUM_THREADS", "number of threads to run");
96 fmt::print(" {:<20} - if = 0: run with `std::thread::hardware_concurrency()` threads\n", "");
97 fmt::print(" {:<20} - if > 0: run with NUM_THREADS threads\n", "");
98 fmt::print(" {:<20} default: {}\n", "", num_threads);
99 }},
100 {"m", [&]()
101 {
102 fmt::print(" {:<20} {}\n", "-m CONCURRENCY_MODEL", "concurrency model");
103 fmt::print(" {:<20} 'memoize' is currently the only option\n", "");
104 }},
105 {"V", [&]()
106 {
107 fmt::print(" {:<20} {}\n", "-V", "randomly vary the run number");
108 fmt::print(" {:<20} this is for testing run-dependent configuration thread safety\n", "");
109 }},
110
1/2
✓ Branch 0 (12→13) taken 5 times.
✗ Branch 1 (12→123) not taken.
5 {"o", [&]()
111 {
112
3/6
✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 1 times.
✗ Branch 2 (5→6) not taken.
✓ Branch 3 (5→7) taken 1 times.
✗ Branch 4 (8→9) not taken.
✓ Branch 5 (8→11) taken 1 times.
4 fmt::print(" {:<20} {}\n", "-o OUTPUT_DIR", fmt::format("if specified, {} output will write to this directory;", command));
113 1 fmt::print(" {:<20} if not specified, output will not be written\n", "");
114 1 }},
115 {"v", [&]()
116 {
117 4 fmt::print(" {:<20} {}\n", "-v", "increase verbosity");
118
2/4
✓ Branch 0 (18→19) taken 60 times.
✓ Branch 1 (18→20) taken 5 times.
✗ Branch 2 (120→121) not taken.
✗ Branch 3 (120→122) not taken.
65 }}};
119 std::map<std::string, std::vector<std::string>> available_options = {
120
1/2
✓ Branch 0 (20→21) taken 5 times.
✗ Branch 1 (20→178) not taken.
5 {"algorithm", {"f", "n", "a-algo", "b", "p"}},
121
1/2
✓ Branch 0 (23→24) taken 5 times.
✗ Branch 1 (23→170) not taken.
5 {"unit", {"f", "n", "a-algo", "b", "p"}},
122
1/2
✓ Branch 0 (26→27) taken 5 times.
✗ Branch 1 (26→162) not taken.
5 {"multithreading", {"f", "n", "a-algo", "b", "p", "j", "m", "V"}},
123
1/2
✓ Branch 0 (29→30) taken 5 times.
✗ Branch 1 (29→154) not taken.
5 {"validator", {"f", "n", "a-vdor", "b", "o"}},
124
1/2
✓ Branch 0 (32→33) taken 5 times.
✗ Branch 1 (32→146) not taken.
5 {"config", {"t"}},
125
1/2
✓ Branch 0 (35→36) taken 5 times.
✗ Branch 1 (35→138) not taken.
5 {"logger", {}}
126
14/40
✓ Branch 0 (21→22) taken 5 times.
✗ Branch 1 (21→172) not taken.
✓ Branch 2 (24→25) taken 5 times.
✗ Branch 3 (24→164) not taken.
✓ Branch 4 (27→28) taken 5 times.
✗ Branch 5 (27→156) not taken.
✓ Branch 6 (30→31) taken 5 times.
✗ Branch 7 (30→148) not taken.
✓ Branch 8 (33→34) taken 5 times.
✗ Branch 9 (33→140) not taken.
✗ Branch 10 (37→38) not taken.
✓ Branch 11 (37→39) taken 5 times.
✓ Branch 12 (40→41) taken 30 times.
✓ Branch 13 (40→42) taken 5 times.
✓ Branch 14 (43→44) taken 5 times.
✗ Branch 15 (43→46) not taken.
✓ Branch 16 (49→50) taken 5 times.
✗ Branch 17 (49→52) not taken.
✓ Branch 18 (55→56) taken 5 times.
✗ Branch 19 (55→58) not taken.
✓ Branch 20 (61→62) taken 5 times.
✗ Branch 21 (61→64) not taken.
✓ Branch 22 (67→68) taken 5 times.
✗ Branch 23 (67→70) not taken.
✓ Branch 24 (73→74) taken 5 times.
✗ Branch 25 (73→76) not taken.
✗ Branch 26 (127→128) not taken.
✗ Branch 27 (127→129) not taken.
✗ Branch 28 (132→133) not taken.
✗ Branch 29 (132→135) not taken.
✗ Branch 30 (140→141) not taken.
✗ Branch 31 (140→143) not taken.
✗ Branch 32 (148→149) not taken.
✗ Branch 33 (148→151) not taken.
✗ Branch 34 (156→157) not taken.
✗ Branch 35 (156→159) not taken.
✗ Branch 36 (164→165) not taken.
✗ Branch 37 (164→167) not taken.
✗ Branch 38 (172→173) not taken.
✗ Branch 39 (172→175) not taken.
90 };
127
2/2
✓ Branch 0 (87→79) taken 30 times.
✓ Branch 1 (87→88) taken 5 times.
35 for(auto& it : available_options)
128
1/2
✓ Branch 0 (79→80) taken 30 times.
✗ Branch 1 (79→194) not taken.
60 it.second.push_back("v");
129
2/2
✓ Branch 0 (88→89) taken 4 times.
✓ Branch 1 (88→113) taken 1 times.
5 if(auto it{available_options.find(command)}; it != available_options.end()) {
130
2/4
✗ Branch 0 (89→90) not taken.
✓ Branch 1 (89→91) taken 4 times.
✓ Branch 2 (94→95) taken 4 times.
✗ Branch 3 (94→194) not taken.
8 fmt::print("\nUSAGE: {} {} [OPTIONS]...\n", exe, command);
131 4 fmt::print("\n OPTIONS:\n\n");
132
2/2
✓ Branch 0 (111→96) taken 20 times.
✓ Branch 1 (111→112) taken 4 times.
24 for(auto available_opt : it->second) {
133 print_option.at(available_opt)();
134
1/2
✓ Branch 0 (105→106) taken 20 times.
✗ Branch 1 (105→108) not taken.
20 fmt::print("\n");
135 }
136 4 return exit_code;
137 }
138 else {
139
1/2
✗ Branch 0 (113→114) not taken.
✓ Branch 1 (113→115) taken 1 times.
1 fmt::print(stderr, "ERROR: unknown command '{}'\n", command);
140 1 return 1;
141 }
142
6/16
✓ Branch 0 (22→23) taken 5 times.
✗ Branch 1 (22→170) not taken.
✓ Branch 2 (25→26) taken 5 times.
✗ Branch 3 (25→162) not taken.
✓ Branch 4 (28→29) taken 5 times.
✗ Branch 5 (28→154) not taken.
✓ Branch 6 (31→32) taken 5 times.
✗ Branch 7 (31→146) not taken.
✓ Branch 8 (34→35) taken 5 times.
✗ Branch 9 (34→138) not taken.
✓ Branch 10 (36→37) taken 5 times.
✗ Branch 11 (36→130) not taken.
✗ Branch 12 (124→125) not taken.
✗ Branch 13 (124→126) not taken.
✗ Branch 14 (179→180) not taken.
✗ Branch 15 (179→181) not taken.
30 };
143 // clang-format on
144
145
4/8
✓ Branch 0 (20→21) taken 24 times.
✓ Branch 1 (20→22) taken 6 times.
✓ Branch 2 (21→23) taken 24 times.
✗ Branch 3 (21→406) not taken.
✓ Branch 4 (22→23) taken 6 times.
✗ Branch 5 (22→406) not taken.
✗ Branch 6 (406→407) not taken.
✗ Branch 7 (406→409) not taken.
30 auto first_option = argc >= 2 ? std::string(argv[1]) : "";
146
2/4
✓ Branch 0 (23→24) taken 30 times.
✗ Branch 1 (23→26) not taken.
✓ Branch 2 (24→25) taken 30 times.
✗ Branch 3 (24→26) not taken.
30 if(first_option == "--help" || first_option == "-h")
147 return UsageOptions(0);
148
4/4
✓ Branch 0 (25→27) taken 6 times.
✓ Branch 1 (25→28) taken 24 times.
✓ Branch 2 (27→28) taken 1 times.
✓ Branch 3 (27→29) taken 5 times.
30 if(argc <= 2 && command != "logger")
149
1/2
✓ Branch 0 (29→259) taken 5 times.
✗ Branch 1 (29→400) not taken.
5 return UsageOptions(2);
150
151 // parse option arguments
152 int opt;
153
2/2
✓ Branch 0 (113→30) taken 108 times.
✓ Branch 1 (113→114) taken 25 times.
133 while((opt = getopt(argc, argv, "hf:n:a:b:p:t:j:m:Vo:v|")) != -1) {
154
8/13
✗ Branch 0 (30→31) not taken.
✓ Branch 1 (30→32) taken 21 times.
✓ Branch 2 (30→40) taken 21 times.
✓ Branch 3 (30→48) taken 21 times.
✓ Branch 4 (30→56) taken 26 times.
✓ Branch 5 (30→64) taken 4 times.
✓ Branch 6 (30→73) taken 3 times.
✗ Branch 7 (30→81) not taken.
✗ Branch 8 (30→91) not taken.
✓ Branch 9 (30→100) taken 9 times.
✓ Branch 10 (30→108) taken 3 times.
✗ Branch 11 (30→109) not taken.
✗ Branch 12 (30→111) not taken.
108 switch(opt) {
155 case 'h':
156 return UsageOptions(0);
157 case 'f':
158
1/2
✓ Branch 0 (32→33) taken 21 times.
✗ Branch 1 (32→400) not taken.
21 data_file = std::string(optarg);
159 21 break;
160 case 'n':
161
2/4
✓ Branch 0 (40→41) taken 21 times.
✗ Branch 1 (40→400) not taken.
✓ Branch 2 (42→43) taken 21 times.
✗ Branch 3 (42→45) not taken.
42 num_events = std::stoi(optarg);
162 21 break;
163 case 'a':
164
1/2
✓ Branch 0 (48→49) taken 21 times.
✗ Branch 1 (48→400) not taken.
21 algo_name = std::string(optarg);
165 21 break;
166 case 'b':
167
1/2
✓ Branch 0 (56→57) taken 26 times.
✗ Branch 1 (56→400) not taken.
26 bank_names.push_back(std::string(optarg));
168 26 break;
169 case 'p':
170
1/2
✓ Branch 0 (64→65) taken 4 times.
✗ Branch 1 (64→400) not taken.
4 prerequisite_algos.push_back(std::string(optarg));
171 4 break;
172 case 't':
173
1/2
✓ Branch 0 (73→74) taken 3 times.
✗ Branch 1 (73→400) not taken.
3 test_num = std::stoi(optarg);
174 3 break;
175 case 'j':
176 num_threads = std::stoi(optarg);
177 if(num_threads == 0)
178 num_threads = std::thread::hardware_concurrency();
179 break;
180 case 'm':
181 concurrency_model = std::string(optarg);
182 break;
183 case 'V':
184 vary_run = true;
185 break;
186 case 'o':
187
1/2
✓ Branch 0 (100→101) taken 9 times.
✗ Branch 1 (100→400) not taken.
9 output_dir = std::string(optarg);
188 9 break;
189 3 case 'v':
190 verbose = true;
191 3 break;
192 default:
193 return UsageOptions(2);
194 }
195 }
196
197 // list of ALL banks needed by the algorithms and validators; we need all of them here,
198 // so that the caller does not have to specifiy the banks
199 std::vector<std::string> const all_bank_names = {
200 "RUN::config",
201 "REC::Particle",
202 "REC::Calorimeter",
203 "REC::Track",
204 "REC::Scintillator",
205
3/6
✓ Branch 0 (114→115) taken 25 times.
✗ Branch 1 (114→400) not taken.
✓ Branch 2 (115→116) taken 14 times.
✓ Branch 3 (115→117) taken 11 times.
✗ Branch 4 (400→401) not taken.
✗ Branch 5 (400→403) not taken.
50 "REC::Traj"};
206
2/2
✓ Branch 0 (115→116) taken 14 times.
✓ Branch 1 (115→117) taken 11 times.
25 if(bank_names.empty())
207
1/2
✓ Branch 0 (116→117) taken 14 times.
✗ Branch 1 (116→398) not taken.
14 bank_names = all_bank_names;
208
209
1/2
✗ Branch 0 (118→119) not taken.
✓ Branch 1 (118→120) taken 25 times.
25 fmt::print("TEST IGUANA:\n");
210
1/2
✗ Branch 0 (121→122) not taken.
✓ Branch 1 (121→123) taken 25 times.
25 fmt::print(" {:>20} = {}\n", "command", command);
211
1/2
✓ Branch 0 (124→125) taken 25 times.
✗ Branch 1 (124→398) not taken.
25 fmt::print(" {:>20} = {}\n", "data_file", data_file);
212
1/2
✗ Branch 0 (125→126) not taken.
✓ Branch 1 (125→127) taken 25 times.
25 fmt::print(" {:>20} = {}\n", "num_events", num_events);
213
1/2
✓ Branch 0 (128→129) taken 25 times.
✗ Branch 1 (128→398) not taken.
25 fmt::print(" {:>20} = {}\n", "algo_name", algo_name);
214
1/2
✓ Branch 0 (129→130) taken 25 times.
✗ Branch 1 (129→398) not taken.
25 fmt::print(" {:>20} = {}\n", "banks", fmt::join(bank_names, ", "));
215
1/2
✓ Branch 0 (130→131) taken 25 times.
✗ Branch 1 (130→398) not taken.
25 fmt::print(" {:>20} = {}\n", "prerequisite_algos", fmt::join(prerequisite_algos, ", "));
216
1/2
✓ Branch 0 (131→132) taken 25 times.
✗ Branch 1 (131→398) not taken.
25 fmt::print(" {:>20} = {}\n", "test_num", test_num);
217
1/2
✗ Branch 0 (132→133) not taken.
✓ Branch 1 (132→134) taken 25 times.
25 fmt::print(" {:>20} = {}\n", "num_threads", num_threads);
218
1/2
✓ Branch 0 (135→136) taken 25 times.
✗ Branch 1 (135→398) not taken.
25 fmt::print(" {:>20} = {}\n", "concurrency_model", concurrency_model);
219
1/2
✗ Branch 0 (136→137) not taken.
✓ Branch 1 (136→138) taken 25 times.
25 fmt::print(" {:>20} = {}\n", "vary_run", vary_run);
220
1/2
✓ Branch 0 (139→140) taken 25 times.
✗ Branch 1 (139→398) not taken.
25 fmt::print(" {:>20} = {}\n", "output_dir", output_dir);
221 25 fmt::print("\n");
222
223 // run test
224
3/4
✓ Branch 0 (140→141) taken 13 times.
✓ Branch 1 (140→143) taken 12 times.
✓ Branch 2 (141→142) taken 13 times.
✗ Branch 3 (141→143) not taken.
25 if(command == "algorithm" || command == "unit")
225
6/16
✗ Branch 0 (143→144) not taken.
✓ Branch 1 (143→145) taken 12 times.
✓ Branch 2 (147→148) taken 12 times.
✗ Branch 3 (147→344) not taken.
✓ Branch 4 (148→149) taken 12 times.
✗ Branch 5 (148→342) not taken.
✓ Branch 6 (157→158) taken 12 times.
✗ Branch 7 (157→328) not taken.
✗ Branch 8 (163→164) not taken.
✓ Branch 9 (163→166) taken 12 times.
✗ Branch 10 (170→171) not taken.
✓ Branch 11 (170→173) taken 12 times.
✗ Branch 12 (334→335) not taken.
✗ Branch 13 (334→337) not taken.
✗ Branch 14 (344→345) not taken.
✗ Branch 15 (344→347) not taken.
72 return TestAlgorithm(command, algo_name, prerequisite_algos, bank_names, data_file, num_events, verbose);
226
1/2
✗ Branch 0 (142→176) not taken.
✓ Branch 1 (142→218) taken 13 times.
13 if(command == "multithreading")
227 return TestMultithreading(command, algo_name, prerequisite_algos, bank_names, data_file, num_events, num_threads, concurrency_model, vary_run, verbose);
228
2/2
✓ Branch 0 (218→219) taken 9 times.
✓ Branch 1 (218→250) taken 4 times.
13 else if(command == "validator")
229
6/16
✗ Branch 0 (219→220) not taken.
✓ Branch 1 (219→221) taken 9 times.
✗ Branch 2 (223→224) not taken.
✓ Branch 3 (223→225) taken 9 times.
✓ Branch 4 (227→228) taken 9 times.
✗ Branch 5 (227→386) not taken.
✓ Branch 6 (232→233) taken 9 times.
✗ Branch 7 (232→378) not taken.
✗ Branch 8 (239→240) not taken.
✓ Branch 9 (239→242) taken 9 times.
✗ Branch 10 (244→245) not taken.
✓ Branch 11 (244→247) taken 9 times.
✗ Branch 12 (386→387) not taken.
✗ Branch 13 (386→389) not taken.
✗ Branch 14 (392→393) not taken.
✗ Branch 15 (392→395) not taken.
63 return TestValidator(algo_name, bank_names, data_file, num_events, output_dir, verbose);
230
2/2
✓ Branch 0 (250→251) taken 3 times.
✓ Branch 1 (250→252) taken 1 times.
4 else if(command == "config")
231
1/2
✓ Branch 0 (251→258) taken 3 times.
✗ Branch 1 (251→398) not taken.
3 return TestConfig(test_num, verbose);
232
1/2
✓ Branch 0 (252→253) taken 1 times.
✗ Branch 1 (252→254) not taken.
1 else if(command == "logger")
233
1/2
✓ Branch 0 (253→258) taken 1 times.
✗ Branch 1 (253→398) not taken.
1 return TestLogger();
234 else {
235 fmt::print(stderr, "ERROR: unknown command '{}'\n", command);
236 return 1;
237 }
238 return 0;
239 31 }
240