GCC Code Coverage Report


Directory: ./
File: src/iguana/tests/iguana_test.cc
Date: 2025-03-24 18:50:00
Exec Total Coverage
Lines: 118 145 81.4%
Functions: 7 10 70.0%
Branches: 114 229 49.8%

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/2
✓ Branch 0 (3→4) taken 31 times.
✗ Branch 1 (3→216) not taken.
31 std::string data_file = "";
14 31 int num_events = 10;
15
1/2
✓ Branch 0 (4→5) taken 31 times.
✗ Branch 1 (4→214) not taken.
31 std::string algo_name = "";
16 int test_num = 0;
17 31 int num_threads = 0;
18
1/2
✓ Branch 0 (5→6) taken 31 times.
✗ Branch 1 (5→212) not taken.
31 std::string concurrency_model = "";
19 bool vary_run = false;
20
2/4
✓ Branch 0 (6→7) taken 31 times.
✗ Branch 1 (6→210) not taken.
✓ Branch 2 (7→8) taken 31 times.
✗ Branch 3 (7→204) 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→204) not taken.
31 auto exe = std::string(argv[0]);
27 1 auto UsageCommands = [&](int exit_code)
28 {
29 1 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→149) taken 1 times.
✗ Branch 1 (9→202) not taken.
1 return UsageCommands(2);
45
1/2
✓ Branch 0 (10→11) taken 30 times.
✗ Branch 1 (10→202) not taken.
30 command = std::string(argv[1]);
46
2/4
✓ Branch 0 (13→14) taken 30 times.
✗ Branch 1 (13→15) not taken.
✗ Branch 2 (14→15) not taken.
✓ Branch 3 (14→16) 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→85) 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→85) 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→85) 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→85) not taken.
5 {"o", [&]()
111 {
112
1/2
✓ Branch 0 (3→4) taken 1 times.
✗ Branch 1 (3→7) not taken.
1 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 (82→83) not taken.
✗ Branch 3 (82→84) not taken.
65 }}};
119 std::map<std::string, std::vector<std::string>> available_options = {
120 {"algorithm", {"f", "n", "a-algo", "b", "p"}},
121 {"unit", {"f", "n", "a-algo", "b", "p"}},
122 {"multithreading", {"f", "n", "a-algo", "b", "p", "j", "m", "V"}},
123 {"validator", {"f", "n", "a-vdor", "b", "o"}},
124 {"config", {"t"}},
125 {"logger", {}}
126
14/28
✓ Branch 0 (20→21) taken 5 times.
✗ Branch 1 (20→118) not taken.
✓ Branch 2 (21→22) taken 5 times.
✗ Branch 3 (21→116) not taken.
✓ Branch 4 (23→24) taken 5 times.
✗ Branch 5 (23→114) not taken.
✓ Branch 6 (24→25) taken 5 times.
✗ Branch 7 (24→112) not taken.
✓ Branch 8 (26→27) taken 5 times.
✗ Branch 9 (26→110) not taken.
✓ Branch 10 (27→28) taken 5 times.
✗ Branch 11 (27→108) not taken.
✓ Branch 12 (29→30) taken 5 times.
✗ Branch 13 (29→106) not taken.
✓ Branch 14 (30→31) taken 5 times.
✗ Branch 15 (30→104) not taken.
✓ Branch 16 (32→33) taken 5 times.
✗ Branch 17 (32→102) not taken.
✓ Branch 18 (33→34) taken 5 times.
✗ Branch 19 (33→100) not taken.
✓ Branch 20 (35→36) taken 5 times.
✗ Branch 21 (35→98) not taken.
✗ Branch 22 (37→38) not taken.
✓ Branch 23 (37→39) taken 5 times.
✓ Branch 24 (40→41) taken 30 times.
✓ Branch 25 (40→44) taken 5 times.
✗ Branch 26 (89→90) not taken.
✗ Branch 27 (89→93) not taken.
65 };
127
2/2
✓ Branch 0 (61→57) taken 30 times.
✓ Branch 1 (61→62) taken 5 times.
35 for(auto& it : available_options)
128
1/2
✓ Branch 0 (57→58) taken 30 times.
✗ Branch 1 (57→128) not taken.
60 it.second.push_back("v");
129
2/2
✓ Branch 0 (62→63) taken 4 times.
✓ Branch 1 (62→77) taken 1 times.
5 if(auto it{available_options.find(command)}; it != available_options.end()) {
130
2/4
✓ Branch 0 (63→64) taken 4 times.
✗ Branch 1 (63→128) not taken.
✓ Branch 2 (64→65) taken 4 times.
✗ Branch 3 (64→128) not taken.
4 fmt::print("\nUSAGE: {} {} [OPTIONS]...\n", exe, command);
131 4 fmt::print("\n OPTIONS:\n\n");
132
2/2
✓ Branch 0 (75→66) taken 20 times.
✓ Branch 1 (75→76) taken 4 times.
24 for(auto available_opt : it->second) {
133 print_option.at(available_opt)();
134 20 fmt::print("\n");
135 }
136 4 return exit_code;
137 }
138 else {
139
1/2
✓ Branch 0 (77→78) taken 1 times.
✗ Branch 1 (77→128) not taken.
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→114) not taken.
✓ Branch 2 (25→26) taken 5 times.
✗ Branch 3 (25→110) not taken.
✓ Branch 4 (28→29) taken 5 times.
✗ Branch 5 (28→106) not taken.
✓ Branch 6 (31→32) taken 5 times.
✗ Branch 7 (31→102) not taken.
✓ Branch 8 (34→35) taken 5 times.
✗ Branch 9 (34→98) not taken.
✓ Branch 10 (36→37) taken 5 times.
✗ Branch 11 (36→94) not taken.
✗ Branch 12 (86→87) not taken.
✗ Branch 13 (86→88) not taken.
✗ Branch 14 (119→120) not taken.
✗ Branch 15 (119→123) not taken.
30 };
143 // clang-format on
144
145
4/6
✓ Branch 0 (16→17) taken 24 times.
✓ Branch 1 (16→18) taken 6 times.
✓ Branch 2 (17→19) taken 24 times.
✗ Branch 3 (17→202) not taken.
✓ Branch 4 (18→19) taken 6 times.
✗ Branch 5 (18→202) not taken.
30 auto first_option = argc >= 2 ? std::string(argv[1]) : "";
146
2/4
✓ Branch 0 (19→20) taken 30 times.
✗ Branch 1 (19→22) not taken.
✓ Branch 2 (20→21) taken 30 times.
✗ Branch 3 (20→22) not taken.
30 if(first_option == "--help" || first_option == "-h")
147 return UsageOptions(0);
148
4/4
✓ Branch 0 (21→23) taken 6 times.
✓ Branch 1 (21→24) taken 24 times.
✓ Branch 2 (23→24) taken 1 times.
✓ Branch 3 (23→25) taken 5 times.
30 if(argc <= 2 && command != "logger")
149
1/2
✓ Branch 0 (25→147) taken 5 times.
✗ Branch 1 (25→200) not taken.
5 return UsageOptions(2);
150
151 // parse option arguments
152 int opt;
153
2/2
✓ Branch 0 (73→26) taken 108 times.
✓ Branch 1 (73→74) 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 (26→27) not taken.
✓ Branch 1 (26→28) taken 21 times.
✓ Branch 2 (26→32) taken 21 times.
✓ Branch 3 (26→36) taken 21 times.
✓ Branch 4 (26→40) taken 26 times.
✓ Branch 5 (26→44) taken 4 times.
✓ Branch 6 (26→49) taken 3 times.
✗ Branch 7 (26→53) not taken.
✗ Branch 8 (26→59) not taken.
✓ Branch 9 (26→64) taken 9 times.
✓ Branch 10 (26→68) taken 3 times.
✗ Branch 11 (26→69) not taken.
✗ Branch 12 (26→71) not taken.
108 switch(opt) {
155 case 'h':
156 return UsageOptions(0);
157 case 'f':
158
1/2
✓ Branch 0 (28→29) taken 21 times.
✗ Branch 1 (28→200) not taken.
21 data_file = std::string(optarg);
159 21 break;
160 case 'n':
161
1/2
✓ Branch 0 (32→33) taken 21 times.
✗ Branch 1 (32→200) not taken.
42 num_events = std::stoi(optarg);
162 21 break;
163 case 'a':
164
1/2
✓ Branch 0 (36→37) taken 21 times.
✗ Branch 1 (36→200) not taken.
21 algo_name = std::string(optarg);
165 21 break;
166 case 'b':
167
1/2
✓ Branch 0 (40→41) taken 26 times.
✗ Branch 1 (40→200) not taken.
26 bank_names.push_back(std::string(optarg));
168 26 break;
169 case 'p':
170
1/2
✓ Branch 0 (44→45) taken 4 times.
✗ Branch 1 (44→200) not taken.
4 prerequisite_algos.push_back(std::string(optarg));
171 4 break;
172 case 't':
173
1/2
✓ Branch 0 (49→50) taken 3 times.
✗ Branch 1 (49→200) 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 (64→65) taken 9 times.
✗ Branch 1 (64→200) 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/4
✓ Branch 0 (74→75) taken 25 times.
✗ Branch 1 (74→200) not taken.
✓ Branch 2 (75→76) taken 14 times.
✓ Branch 3 (75→77) taken 11 times.
50 "REC::Traj"};
206
2/2
✓ Branch 0 (75→76) taken 14 times.
✓ Branch 1 (75→77) taken 11 times.
25 if(bank_names.empty())
207
1/2
✓ Branch 0 (76→77) taken 14 times.
✗ Branch 1 (76→198) not taken.
14 bank_names = all_bank_names;
208
209
1/2
✓ Branch 0 (78→79) taken 25 times.
✗ Branch 1 (78→198) not taken.
25 fmt::print("TEST IGUANA:\n");
210
1/2
✓ Branch 0 (79→80) taken 25 times.
✗ Branch 1 (79→198) not taken.
25 fmt::print(" {:>20} = {}\n", "command", command);
211
1/2
✓ Branch 0 (80→81) taken 25 times.
✗ Branch 1 (80→198) not taken.
25 fmt::print(" {:>20} = {}\n", "data_file", data_file);
212
1/2
✓ Branch 0 (81→82) taken 25 times.
✗ Branch 1 (81→198) not taken.
25 fmt::print(" {:>20} = {}\n", "num_events", num_events);
213
1/2
✓ Branch 0 (82→83) taken 25 times.
✗ Branch 1 (82→198) not taken.
25 fmt::print(" {:>20} = {}\n", "algo_name", algo_name);
214
1/2
✓ Branch 0 (83→84) taken 25 times.
✗ Branch 1 (83→198) not taken.
25 fmt::print(" {:>20} = {}\n", "banks", fmt::join(bank_names, ", "));
215
1/2
✓ Branch 0 (84→85) taken 25 times.
✗ Branch 1 (84→198) not taken.
25 fmt::print(" {:>20} = {}\n", "prerequisite_algos", fmt::join(prerequisite_algos, ", "));
216
1/2
✓ Branch 0 (85→86) taken 25 times.
✗ Branch 1 (85→198) not taken.
25 fmt::print(" {:>20} = {}\n", "test_num", test_num);
217
1/2
✓ Branch 0 (86→87) taken 25 times.
✗ Branch 1 (86→198) not taken.
25 fmt::print(" {:>20} = {}\n", "num_threads", num_threads);
218
1/2
✓ Branch 0 (87→88) taken 25 times.
✗ Branch 1 (87→198) not taken.
25 fmt::print(" {:>20} = {}\n", "concurrency_model", concurrency_model);
219
1/2
✓ Branch 0 (88→89) taken 25 times.
✗ Branch 1 (88→198) not taken.
25 fmt::print(" {:>20} = {}\n", "vary_run", vary_run);
220
1/2
✓ Branch 0 (89→90) taken 25 times.
✗ Branch 1 (89→198) 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 (90→91) taken 13 times.
✓ Branch 1 (90→93) taken 12 times.
✓ Branch 2 (91→92) taken 13 times.
✗ Branch 3 (91→93) not taken.
25 if(command == "algorithm" || command == "unit")
225
4/8
✓ Branch 0 (93→94) taken 12 times.
✗ Branch 1 (93→198) not taken.
✓ Branch 2 (95→96) taken 12 times.
✗ Branch 3 (95→176) not taken.
✓ Branch 4 (96→97) taken 12 times.
✗ Branch 5 (96→174) not taken.
✓ Branch 6 (101→102) taken 12 times.
✗ Branch 7 (101→168) not taken.
48 return TestAlgorithm(command, algo_name, prerequisite_algos, bank_names, data_file, num_events, verbose);
226
1/2
✗ Branch 0 (92→108) not taken.
✓ Branch 1 (92→126) 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 (126→127) taken 9 times.
✓ Branch 1 (126→140) taken 4 times.
13 else if(command == "validator")
229
4/8
✓ Branch 0 (127→128) taken 9 times.
✗ Branch 1 (127→198) not taken.
✓ Branch 2 (129→130) taken 9 times.
✗ Branch 3 (129→196) not taken.
✓ Branch 4 (131→132) taken 9 times.
✗ Branch 5 (131→194) not taken.
✓ Branch 6 (134→135) taken 9 times.
✗ Branch 7 (134→190) not taken.
45 return TestValidator(algo_name, bank_names, data_file, num_events, output_dir, verbose);
230
2/2
✓ Branch 0 (140→141) taken 3 times.
✓ Branch 1 (140→142) taken 1 times.
4 else if(command == "config")
231
1/2
✓ Branch 0 (141→146) taken 3 times.
✗ Branch 1 (141→198) not taken.
3 return TestConfig(test_num, verbose);
232
1/2
✓ Branch 0 (142→143) taken 1 times.
✗ Branch 1 (142→144) not taken.
1 else if(command == "logger")
233
1/2
✓ Branch 0 (143→146) taken 1 times.
✗ Branch 1 (143→198) 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