Line data Source code
1 : #include "test/common.h"
2 :
3 : #include "artdaq-database/DataFormats/Fhicl/convertfhicl2jsondb.h"
4 : #include "artdaq-database/DataFormats/Fhicl/fhicl_common.h"
5 : #include "artdaq-database/DataFormats/Fhicl/fhicljsondb.h"
6 :
7 : #include "artdaq-database/DataFormats/Json/convertjson2guijson.h"
8 : #include "artdaq-database/DataFormats/Json/json_common.h"
9 :
10 : #include <fstream>
11 : #include <regex>
12 :
13 : namespace bpo = boost::program_options;
14 : using namespace artdaq::database;
15 :
16 : using test_case = bool (*)(const std::string&, const std::string&, const std::string&);
17 :
18 : bool test_convert2fcl(std::string const& /*input*/, std::string const& /*compare*/, std::string const& /*source_filename*/);
19 : bool test_convert2json(std::string const& /*input*/, std::string const& /*compare*/, std::string const& /*source_filename*/);
20 : bool test_roundconvertfcl(std::string const& /*input*/, std::string const& /*compare*/, std::string const& /*source_filename*/);
21 : bool test_roundconvertjson(std::string const& /*input*/, std::string const& /*compare*/, std::string const& /*source_filename*/);
22 :
23 : // Helper function to extract test number from filename
24 : // e.g., "test001.src.fcl" -> "001"
25 0 : std::string extract_test_number(const std::string& filename) {
26 0 : std::regex pattern(R"(test(\d{3}))");
27 0 : std::smatch matches;
28 :
29 0 : if (std::regex_search(filename, matches, pattern)) {
30 0 : return matches[1].str();
31 : }
32 :
33 0 : return "unknown";
34 0 : }
35 :
36 : // Helper function to write content to a file
37 0 : bool write_to_file(const std::string& filename, const std::string& content) {
38 0 : std::ofstream outfile(filename);
39 :
40 0 : if (!outfile.is_open()) {
41 0 : std::cerr << "ERROR: Failed to open file for writing: " << filename << "\n";
42 0 : return false;
43 : }
44 :
45 0 : outfile << content;
46 0 : outfile.close();
47 :
48 0 : std::cout << "Debug file written: " << filename << "\n";
49 0 : return true;
50 0 : }
51 :
52 29 : int main(int argc, char* argv[]) try {
53 29 : artdaq::database::fhicl::debug::FhiclReader();
54 29 : artdaq::database::fhicl::debug::FhiclWriter();
55 29 : artdaq::database::fhicljson::debug::FhiclJson();
56 29 : artdaq::database::fhicljson::debug::FCL2JSON();
57 :
58 29 : debug::registerUngracefullExitHandlers();
59 29 : artdaq::database::useFakeTime(true);
60 :
61 29 : std::ostringstream descstr;
62 : descstr << argv[0]
63 : << " <-s <source-file>> <-c <compare-with-file>> <-t <test-name>> (available test names: "
64 : "Convert_Fhicl2DBJson,Convert_DBJson2Fhicl, "
65 29 : "RoundConvert_Fhicl2DBJson,RoundConvert_DBJson2Fhicl)";
66 :
67 29 : bpo::options_description desc = descstr.str();
68 :
69 29 : desc.add_options()("source,s", bpo::value<std::string>(), "Input source file.")(
70 29 : "compare,c", bpo::value<std::string>(), "Expected result of convertion.")("testname,t", bpo::value<std::string>(), "Test name.")
71 :
72 29 : ("help,h", "produce help message");
73 :
74 29 : bpo::variables_map vm;
75 :
76 : try {
77 29 : bpo::store(bpo::command_line_parser(argc, argv).options(desc).run(), vm);
78 29 : bpo::notify(vm);
79 0 : } catch (bpo::error const& e) {
80 0 : std::cerr << "Exception from command line processing in " << argv[0] << ": " << e.what() << "\n";
81 0 : return process_exit_code::INVALID_ARGUMENT;
82 0 : }
83 :
84 58 : if (vm.count("help") != 0u) {
85 0 : std::cout << desc << std::endl;
86 0 : return process_exit_code::HELP;
87 : }
88 :
89 58 : if (vm.count("source") == 0u) {
90 : std::cerr << "Exception from command line processing in " << argv[0] << ": no source file given.\n"
91 : << "For usage and an options list, please do '" << argv[0] << " --help"
92 0 : << "'.\n";
93 0 : return process_exit_code::INVALID_ARGUMENT | 1;
94 : }
95 :
96 58 : if (vm.count("compare") == 0u) {
97 : std::cerr << "Exception from command line processing in " << argv[0] << ": no compare file given.\n"
98 : << "For usage and an options list, please do '" << argv[0] << " --help"
99 0 : << "'.\n";
100 0 : return process_exit_code::INVALID_ARGUMENT | 2;
101 : }
102 :
103 58 : if (vm.count("testname") == 0u) {
104 : std::cerr << "Exception from command line processing in " << argv[0] << ": no test name given.\n"
105 : << "For usage and an options list, please do '" << argv[0] << " --help"
106 0 : << "'.\n";
107 0 : return process_exit_code::INVALID_ARGUMENT | 3;
108 : }
109 :
110 58 : auto input_name = vm["source"].as<std::string>();
111 58 : auto compare_name = vm["compare"].as<std::string>();
112 29 : auto test_name = vm["testname"].as<std::string>();
113 :
114 29 : std::ifstream is1(input_name);
115 :
116 29 : std::string input((std::istreambuf_iterator<char>(is1)), std::istreambuf_iterator<char>());
117 :
118 29 : std::ifstream is2(compare_name);
119 :
120 29 : std::string compare((std::istreambuf_iterator<char>(is2)), std::istreambuf_iterator<char>());
121 :
122 29 : auto runTest = [](std::string const& name) {
123 : auto tests = std::map<std::string, test_case>{{"Convert_Fhicl2DBJson", test_convert2json},
124 : {"Convert_DBJson2Fhicl", test_convert2fcl},
125 : {"RoundConvert_Fhicl2DBJson", test_roundconvertfcl},
126 174 : {"RoundConvert_DBJson2Fhicl", test_roundconvertjson}};
127 :
128 29 : std::cout << "Running test:<" << name << ">\n";
129 :
130 58 : return tests.at(name);
131 58 : };
132 :
133 29 : auto testResult = runTest(test_name)(input, compare, input_name);
134 :
135 29 : if (testResult) {
136 29 : return process_exit_code::SUCCESS;
137 : }
138 :
139 0 : return process_exit_code::FAILURE;
140 29 : } catch (...) {
141 0 : std::cerr << "Process exited with error: " << ::debug::current_exception_diagnostic_information();
142 0 : return process_exit_code::UNCAUGHT_EXCEPTION;
143 0 : }
144 :
145 3 : bool test_convert2fcl(std::string const& input, std::string const& compare, std::string const& source_filename) {
146 3 : confirm(!input.empty());
147 3 : confirm(!compare.empty());
148 :
149 3 : auto output = std::string();
150 3 : auto filename = std::string();
151 :
152 3 : if (!fhicljson::json_to_fhicl(input, output, filename)) {
153 0 : std::cout << "Convertion failed. \n";
154 0 : std::cerr << "input:\n" << input << "\n";
155 0 : std::cerr << "output:\n" << output << "\n";
156 0 : return false;
157 : };
158 :
159 3 : if (output == compare) {
160 3 : return true;
161 : } else {
162 0 : std::cout << "Convertion failed. \n";
163 0 : std::cerr << "output:\n" << output << "\n";
164 0 : std::cerr << "expected:\n" << compare << "\n";
165 :
166 0 : auto mismatch = std::mismatch(compare.begin(), compare.end(), output.begin());
167 0 : std::cerr << "File sizes (exp,ret)=(" << std::distance(compare.begin(), compare.end()) << "," << std::distance(output.begin(), output.end())
168 0 : << ")\n";
169 :
170 0 : std::cerr << "First mismatch at position " << std::distance(compare.begin(), mismatch.first) << ", (exp,ret)=(0x" << std::hex
171 0 : << static_cast<unsigned int>(*mismatch.first) << ",0x" << static_cast<unsigned int>(*mismatch.second) << ")\n";
172 :
173 : // Write debug files
174 0 : std::string test_number = extract_test_number(source_filename);
175 0 : write_to_file("test" + test_number + ".output.json", output);
176 0 : write_to_file("test" + test_number + ".expected.json", compare);
177 0 : }
178 :
179 0 : return false;
180 3 : }
181 :
182 8 : bool test_convert2json(std::string const& input, std::string const& compare, std::string const& source_filename) {
183 8 : confirm(!input.empty());
184 8 : confirm(!compare.empty());
185 :
186 8 : auto output = std::string();
187 8 : auto filename = std::string("notprovided");
188 :
189 8 : std::cout << "Convertion started. \n";
190 :
191 8 : if (!fhicljson::fhicl_to_json(input, filename, output)) {
192 0 : std::cout << "Convertion failed. \n";
193 0 : std::cerr << "input:\n" << input << "\n";
194 0 : std::cerr << "output:\n" << output << "\n";
195 0 : return false;
196 : }
197 :
198 8 : auto compare_result = artdaq::database::json::compare_json_objects(output, compare);
199 8 : if (compare_result.first) {
200 8 : return true;
201 : } else {
202 0 : std::cout << "Convertion failed; error: " << compare_result.second << "\n";
203 0 : std::cerr << "output:\n" << output << "\n";
204 0 : std::cerr << "expected:\n" << compare << "\n";
205 :
206 : // Write debug files
207 0 : std::string test_number = extract_test_number(source_filename);
208 0 : write_to_file("test" + test_number + ".output.json", output);
209 0 : write_to_file("test" + test_number + ".expected.json", compare);
210 0 : }
211 :
212 0 : return false;
213 8 : }
214 :
215 16 : bool test_roundconvertfcl(std::string const& input, std::string const& compare, std::string const& source_filename) {
216 16 : confirm(!input.empty());
217 16 : confirm(!compare.empty());
218 :
219 16 : auto tmp = std::string();
220 16 : auto output = std::string();
221 16 : auto filename = std::string("notprovided");
222 :
223 : try {
224 16 : if (!fhicljson::fhicl_to_json(input, filename, tmp)) {
225 0 : std::cout << "Convertion failed. \n";
226 0 : std::cerr << "input:\n" << input << "\n";
227 0 : std::cerr << "tmp:\n" << tmp << "\n";
228 0 : return false;
229 : }
230 :
231 16 : std::cout << "fhicl_to_json succeeded.\n";
232 :
233 16 : if (!fhicljson::json_to_fhicl(tmp, output, filename)) {
234 0 : std::cout << "Convertion failed. \n";
235 0 : std::cerr << "tmp:\n" << tmp << "\n";
236 0 : std::cerr << "output:\n" << output << "\n";
237 0 : return false;
238 : };
239 :
240 16 : std::cout << "json_to_fhicl succeeded.\n";
241 :
242 0 : } catch (...) {
243 0 : std::cout << "Convertion failed. \n";
244 0 : std::cerr << "output:\n" << output << "\n";
245 0 : std::cerr << "expected:\n" << compare << "\n";
246 0 : std::cerr << "tmp:\n" << tmp << "\n";
247 :
248 : // Write debug files
249 0 : std::string test_number = extract_test_number(source_filename);
250 0 : write_to_file("test" + test_number + ".output.json", output);
251 0 : write_to_file("test" + test_number + ".expected.json", compare);
252 0 : write_to_file("test" + test_number + ".tmp.json", tmp);
253 :
254 0 : throw;
255 0 : }
256 :
257 16 : if (output == compare) {
258 16 : return true;
259 : } else {
260 0 : std::cout << "Convertion failed. \n";
261 0 : std::cerr << "output:\n" << output << "\n";
262 0 : std::cerr << "expected:\n" << compare << "\n";
263 0 : std::cerr << "tmp:\n" << tmp << "\n";
264 :
265 0 : auto mismatch = std::mismatch(compare.begin(), compare.end(), output.begin());
266 0 : std::cerr << "File sizes (exp,ret)=(" << std::distance(compare.begin(), compare.end()) << "," << std::distance(output.begin(), output.end())
267 0 : << ")\n";
268 :
269 0 : std::cerr << "First mismatch at position " << std::distance(compare.begin(), mismatch.first) << ", (exp,ret)=(0x" << std::hex
270 0 : << static_cast<unsigned int>(*mismatch.first) << ",0x" << static_cast<unsigned int>(*mismatch.second) << ")\n";
271 :
272 : // Write debug files
273 0 : std::string test_number = extract_test_number(source_filename);
274 0 : write_to_file("test" + test_number + ".output.json", output);
275 0 : write_to_file("test" + test_number + ".expected.json", compare);
276 0 : write_to_file("test" + test_number + ".tmp.json", tmp);
277 0 : }
278 :
279 0 : return false;
280 16 : }
281 :
282 2 : bool test_roundconvertjson(std::string const& input, std::string const& compare, std::string const& source_filename) {
283 2 : confirm(!input.empty());
284 2 : confirm(!compare.empty());
285 :
286 2 : auto tmp = std::string();
287 2 : auto output = std::string();
288 2 : auto filename = std::string();
289 :
290 : try {
291 2 : if (!fhicljson::json_to_fhicl(input, tmp, filename)) {
292 0 : std::cout << "Convertion failed. \n";
293 0 : std::cerr << "input:\n" << input << "\n";
294 0 : std::cerr << "tmp:\n" << tmp << "\n";
295 0 : return false;
296 : }
297 :
298 2 : std::cout << "json_to_fhicl succeeded.\n";
299 :
300 2 : if (!fhicljson::fhicl_to_json(tmp, filename, output)) {
301 0 : std::cout << "Convertion failed. \n";
302 0 : std::cerr << "tmp:\n" << tmp << "\n";
303 0 : std::cerr << "output:\n" << output << "\n";
304 0 : return false;
305 : };
306 :
307 2 : std::cout << "fhicl_to_json succeeded.\n";
308 :
309 0 : } catch (...) {
310 0 : std::cout << "Convertion failed. \n";
311 0 : std::cerr << "output:\n" << output << "\n";
312 0 : std::cerr << "expected:\n" << compare << "\n";
313 0 : std::cerr << "tmp:\n" << tmp << "\n";
314 :
315 : // Write debug files
316 0 : std::string test_number = extract_test_number(source_filename);
317 0 : write_to_file("test" + test_number + ".output.json", output);
318 0 : write_to_file("test" + test_number + ".expected.json", compare);
319 0 : write_to_file("test" + test_number + ".tmp.json", tmp);
320 :
321 0 : throw;
322 0 : }
323 :
324 2 : auto compare_result = artdaq::database::json::compare_json_objects(output, compare);
325 2 : if (compare_result.first) {
326 2 : return true;
327 : } else {
328 0 : std::cout << "Convertion failed. \n";
329 0 : std::cerr << "output:\n" << output << "\n";
330 0 : std::cerr << "expected:\n" << compare << "\n";
331 0 : std::cerr << "tmp:\n" << tmp << "\n";
332 :
333 : // Write debug files
334 0 : std::string test_number = extract_test_number(source_filename);
335 0 : write_to_file("test" + test_number + ".output.json", output);
336 0 : write_to_file("test" + test_number + ".expected.json", compare);
337 0 : write_to_file("test" + test_number + ".tmp.json", tmp);
338 0 : }
339 :
340 0 : return false;
341 2 : }
|