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 | 29 | int main(int argc, char** argv) | |
10 | { | ||
11 | // user parameters | ||
12 | 29 | std::string command = ""; | |
13 |
1/2✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
|
29 | std::string data_file = ""; |
14 | 29 | int num_events = 10; | |
15 |
1/2✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
|
29 | std::string algo_name = ""; |
16 | int test_num = 0; | ||
17 | 29 | int num_threads = 0; | |
18 |
1/2✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
|
29 | std::string concurrency_model = ""; |
19 | bool vary_run = false; | ||
20 |
2/4✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
|
29 | 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 taken 29 times.
✗ Branch 1 not taken.
|
29 | 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 | 29 | }; | |
43 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 28 times.
|
29 | if(argc <= 1) |
44 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | return UsageCommands(2); |
45 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | command = std::string(argv[1]); |
46 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 28 times.
|
28 | if(command == "--help" || command == "-h") |
47 | ✗ | return UsageCommands(0); | |
48 | // omit the command, for getopt | ||
49 | 28 | argv++; | |
50 | 28 | argc--; | |
51 | |||
52 | // usage options | ||
53 | // clang-format off | ||
54 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 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 taken 5 times.
✗ Branch 1 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 taken 5 times.
✗ Branch 1 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 taken 5 times.
✗ Branch 1 not taken.
|
5 | {"o", [&]() |
111 | { | ||
112 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 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 taken 60 times.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 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 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 5 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 5 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 5 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 5 times.
✓ Branch 24 taken 30 times.
✓ Branch 25 taken 5 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
|
65 | }; |
127 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 5 times.
|
35 | for(auto& it : available_options) |
128 |
1/2✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
|
60 | it.second.push_back("v"); |
129 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | if(auto it{available_options.find(command)}; it != available_options.end()) { |
130 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | fmt::print("\nUSAGE: {} {} [OPTIONS]...\n", exe, command); |
131 | 4 | fmt::print("\n OPTIONS:\n\n"); | |
132 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 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 taken 1 times.
✗ Branch 1 not taken.
|
1 | fmt::print(stderr, "ERROR: unknown command '{}'\n", command); |
140 | 1 | return 1; | |
141 | } | ||
142 |
6/16✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
30 | }; |
143 | // clang-format on | ||
144 | |||
145 |
4/6✓ Branch 0 taken 22 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
28 | auto first_option = argc >= 2 ? std::string(argv[1]) : ""; |
146 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
28 | if(first_option == "--help" || first_option == "-h") |
147 | ✗ | return UsageOptions(0); | |
148 |
4/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 5 times.
|
28 | if(argc <= 2 && command != "logger") |
149 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | return UsageOptions(2); |
150 | |||
151 | // parse option arguments | ||
152 | int opt; | ||
153 |
2/2✓ Branch 0 taken 100 times.
✓ Branch 1 taken 23 times.
|
123 | while((opt = getopt(argc, argv, "hf:n:a:b:p:t:j:m:Vo:v|")) != -1) { |
154 |
8/13✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 26 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 8 times.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
100 | switch(opt) { |
155 | ✗ | case 'h': | |
156 | ✗ | return UsageOptions(0); | |
157 | case 'f': | ||
158 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | data_file = std::string(optarg); |
159 | 19 | break; | |
160 | case 'n': | ||
161 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
38 | num_events = std::stoi(optarg); |
162 | 19 | break; | |
163 | case 'a': | ||
164 |
1/2✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
|
19 | algo_name = std::string(optarg); |
165 | 19 | break; | |
166 | case 'b': | ||
167 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
26 | bank_names.push_back(std::string(optarg)); |
168 | 26 | break; | |
169 | case 'p': | ||
170 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | prerequisite_algos.push_back(std::string(optarg)); |
171 | 3 | break; | |
172 | case 't': | ||
173 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 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 taken 8 times.
✗ Branch 1 not taken.
|
8 | output_dir = std::string(optarg); |
188 | 8 | 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 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 11 times.
|
46 | "REC::Traj"}; |
206 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 11 times.
|
23 | if(bank_names.empty()) |
207 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | bank_names = all_bank_names; |
208 | |||
209 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | fmt::print("TEST IGUANA:\n"); |
210 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | fmt::print(" {:>20} = {}\n", "command", command); |
211 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | fmt::print(" {:>20} = {}\n", "data_file", data_file); |
212 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | fmt::print(" {:>20} = {}\n", "num_events", num_events); |
213 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | fmt::print(" {:>20} = {}\n", "algo_name", algo_name); |
214 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | fmt::print(" {:>20} = {}\n", "banks", fmt::join(bank_names, ", ")); |
215 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | fmt::print(" {:>20} = {}\n", "prerequisite_algos", fmt::join(prerequisite_algos, ", ")); |
216 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | fmt::print(" {:>20} = {}\n", "test_num", test_num); |
217 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | fmt::print(" {:>20} = {}\n", "num_threads", num_threads); |
218 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | fmt::print(" {:>20} = {}\n", "concurrency_model", concurrency_model); |
219 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | fmt::print(" {:>20} = {}\n", "vary_run", vary_run); |
220 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | fmt::print(" {:>20} = {}\n", "output_dir", output_dir); |
221 | 23 | fmt::print("\n"); | |
222 | |||
223 | // run test | ||
224 |
3/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
23 | if(command == "algorithm" || command == "unit") |
225 |
4/8✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
|
44 | return TestAlgorithm(command, algo_name, prerequisite_algos, bank_names, data_file, num_events, verbose); |
226 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | 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 taken 8 times.
✓ Branch 1 taken 4 times.
|
12 | else if(command == "validator") |
229 |
4/8✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
|
40 | return TestValidator(algo_name, bank_names, data_file, num_events, output_dir, verbose); |
230 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | else if(command == "config") |
231 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | return TestConfig(test_num, verbose); |
232 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | else if(command == "logger") |
233 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | return TestLogger(); |
234 | else { | ||
235 | ✗ | fmt::print(stderr, "ERROR: unknown command '{}'\n", command); | |
236 | ✗ | return 1; | |
237 | } | ||
238 | return 0; | ||
239 | 29 | } | |
240 |