Line data Source code
1 : #include "artdaq-database/BasicTypes/basictypes.h"
2 : #include "test/common.h"
3 :
4 : #include "artdaq-database/JsonDocument/JSONDocument.h"
5 : #include "artdaq-database/JsonDocument/JSONDocumentBuilder.h"
6 : #include "artdaq-database/StorageProviders/MongoDB/provider_mongodb.h"
7 : #include "artdaq-database/StorageProviders/storage_providers.h"
8 :
9 : namespace bpo = boost::program_options;
10 : using namespace artdaq::database;
11 :
12 : using artdaq::database::basictypes::JsonData;
13 : using artdaq::database::basictypes::XmlData;
14 : using artdaq::database::docrecord::JSONDocument;
15 : using artdaq::database::docrecord::JSONDocumentBuilder;
16 : namespace ovl = artdaq::database::overlay;
17 :
18 : using test_case = bool (*)(const std::string&, const std::string&, const std::string&);
19 :
20 : bool test_insert(std::string const& /*source_xml*/, std::string const& /*compare_xml*/, std::string const& /*filter*/);
21 : bool test_search1(std::string const& /*source_xml*/, std::string const& /*compare_xml*/, std::string const& /*filter*/);
22 : bool test_search2(std::string const& /*source_xml*/, std::string const& /*compare_xml*/, std::string const& /*options*/);
23 : bool test_update(std::string const& /*source_xml*/, std::string const& /*compare_xml*/, std::string const& /*update_xml*/);
24 :
25 4 : int main(int argc, char* argv[]) try {
26 4 : artdaq::database::mongo::debug::enable();
27 : // artdaq::database::docrecord::debug::JSONDocument();
28 :
29 4 : debug::registerUngracefullExitHandlers();
30 4 : artdaq::database::useFakeTime(true);
31 :
32 4 : std::ostringstream descstr;
33 : descstr << argv[0]
34 : << " <-s <source-file>> <-c <compare-with-file>> <-t <test-name>> [<-o <options file>>] (available test "
35 4 : "names: insert,search1,search1,update)";
36 :
37 4 : bpo::options_description desc = descstr.str();
38 :
39 4 : desc.add_options()("source,s", bpo::value<std::string>(), "Input source file.")("compare,c", bpo::value<std::string>(), "Expected result.")(
40 4 : "testname,t", bpo::value<std::string>(), "Test name.")("options,o", bpo::value<std::string>(), "Test options file.")
41 :
42 4 : ("help,h", "produce help message");
43 :
44 4 : bpo::variables_map vm;
45 :
46 : try {
47 4 : bpo::store(bpo::command_line_parser(argc, argv).options(desc).run(), vm);
48 4 : bpo::notify(vm);
49 0 : } catch (bpo::error const& e) {
50 0 : std::cerr << "Exception from command line processing in " << argv[0] << ": " << e.what() << "\n";
51 0 : return process_exit_code::INVALID_ARGUMENT;
52 0 : }
53 :
54 8 : if (vm.count("help") != 0u) {
55 0 : std::cout << desc << std::endl;
56 0 : return process_exit_code::HELP;
57 : }
58 :
59 8 : if (vm.count("source") == 0u) {
60 : std::cerr << "Exception from command line processing in " << argv[0] << ": no source file given.\n"
61 : << "For usage and an options list, please do '" << argv[0] << " --help"
62 0 : << "'.\n";
63 0 : return process_exit_code::INVALID_ARGUMENT | 1;
64 : }
65 :
66 8 : if (vm.count("compare") == 0u) {
67 : std::cerr << "Exception from command line processing in " << argv[0] << ": no compare file given.\n"
68 : << "For usage and an options list, please do '" << argv[0] << " --help"
69 0 : << "'.\n";
70 0 : return process_exit_code::INVALID_ARGUMENT | 2;
71 : }
72 :
73 8 : if (vm.count("testname") == 0u) {
74 : std::cerr << "Exception from command line processing in " << argv[0] << ": no test name given.\n"
75 : << "For usage and an options list, please do '" << argv[0] << " --help"
76 0 : << "'.\n";
77 0 : return process_exit_code::INVALID_ARGUMENT | 3;
78 : }
79 :
80 8 : auto input_name = vm["source"].as<std::string>();
81 8 : auto compare_name = vm["compare"].as<std::string>();
82 4 : auto test_name = vm["testname"].as<std::string>();
83 :
84 4 : auto input = std::string{};
85 4 : db::read_buffer_from_file(input, input_name);
86 :
87 4 : auto compare = std::string{};
88 4 : db::read_buffer_from_file(compare, compare_name);
89 :
90 4 : auto options = std::string();
91 :
92 8 : if (vm.count("options") != 0u) {
93 2 : auto opts_name = vm["options"].as<std::string>();
94 :
95 2 : db::read_buffer_from_file(options, opts_name);
96 2 : }
97 :
98 4 : auto runTest = [](std::string const& name) {
99 : auto tests =
100 24 : std::map<std::string, test_case>{{"insert", test_insert}, {"update", test_update}, {"search1", test_search1}, {"search2", test_search2}};
101 :
102 4 : std::cout << "Running test:<" << name << ">\n";
103 :
104 8 : return tests.at(name);
105 8 : };
106 :
107 4 : auto testResult = runTest(test_name)(input, compare, options);
108 :
109 4 : if (testResult) {
110 4 : return process_exit_code::SUCCESS;
111 : }
112 :
113 0 : return process_exit_code::FAILURE;
114 4 : } catch (...) {
115 0 : std::cerr << "Process exited with error: " << ::debug::current_exception_diagnostic_information();
116 0 : return process_exit_code::UNCAUGHT_EXCEPTION;
117 0 : }
118 :
119 1 : bool test_insert(std::string const& source_xml, std::string const& compare_xml, std::string const& filter) {
120 1 : confirm(!source_xml.empty());
121 1 : confirm(!compare_xml.empty());
122 :
123 1 : JsonData source = XmlData(source_xml);
124 1 : JsonData compare = XmlData(compare_xml);
125 :
126 : // validate source
127 1 : auto insert = JSONDocument(source);
128 :
129 : // validate compare
130 1 : auto cmpdoc = JSONDocument(compare);
131 :
132 : namespace DBI = artdaq::database::mongo;
133 :
134 1 : auto config = DBI::DBConfig{};
135 1 : auto database = DBI::DB::create(config);
136 1 : auto provider = DBI::DBProvider<JSONDocument>::create(database);
137 :
138 1 : auto collection = std::string("testXML_V001");
139 :
140 1 : auto json = JSONDocument{"{\"document\":" + insert.to_string() + ", \"collection\":\"" + collection + "\"}"};
141 :
142 1 : auto object_id = provider->writeDocument(json);
143 :
144 1 : auto search = JSONDocument{"{\"filter\":" + (filter.empty() ? object_id : filter) + ", \"collection\":\"" + collection + "\"}"};
145 :
146 1 : std::cout << "Search criteria " << search << "\n";
147 :
148 1 : auto results = provider->readDocument(search);
149 :
150 1 : if (results.size() != 1) {
151 0 : std::cout << "Search returned " << results.size() << " results.\n";
152 :
153 0 : for (auto&& element : results) {
154 0 : std::cout << element << "\n";
155 : }
156 0 : return false;
157 : }
158 :
159 1 : auto retdoc = JSONDocument{*results.begin()};
160 :
161 1 : JSONDocumentBuilder returned{retdoc};
162 1 : JSONDocumentBuilder expected{cmpdoc};
163 :
164 : using namespace artdaq::database::overlay;
165 1 : ovl::useCompareMask(DOCUMENT_COMPARE_MUTE_TIMESTAMPS | DOCUMENT_COMPARE_MUTE_OUIDS | DOCUMENT_COMPARE_MUTE_UPDATES |
166 : DOCUMENT_COMPARE_MUTE_COLLECTION);
167 :
168 1 : auto result = returned == expected;
169 :
170 1 : if (result.first) {
171 1 : return true;
172 : }
173 :
174 0 : std::cout << "Error returned!=expected.\n";
175 0 : std::cerr << "returned:\n" << returned << "\n";
176 0 : std::cerr << "expected:\n" << expected << "\n";
177 0 : std::cerr << "error:\n" << result.second << "\n";
178 0 : return false;
179 1 : }
180 :
181 1 : bool test_search1(std::string const& source_xml, std::string const& compare_xml, std::string const& filter) {
182 1 : confirm(!source_xml.empty());
183 1 : confirm(!compare_xml.empty());
184 :
185 1 : JsonData source = XmlData(source_xml);
186 1 : JsonData compare = XmlData(compare_xml);
187 :
188 : // validate source
189 1 : auto insert = JSONDocument(source);
190 :
191 : // validate compare
192 1 : auto cmpdoc = JSONDocument(compare);
193 :
194 : using artdaq::database::basictypes::JsonData;
195 : using artdaq::database::basictypes::XmlData;
196 :
197 : namespace DBI = artdaq::database::mongo;
198 :
199 1 : auto config = DBI::DBConfig{};
200 1 : auto database = DBI::DB::create(config);
201 1 : auto provider = DBI::DBProvider<JSONDocument>::create(database);
202 :
203 1 : auto collection = std::string("testXML_V001");
204 :
205 1 : auto json = JSONDocument{"{\"document\":" + insert.to_string() + ", \"collection\":\"" + collection + "\"}"};
206 :
207 1 : auto object_id = provider->writeDocument(json);
208 :
209 1 : auto search = JSONDocument{"{\"filter\":" + (filter.empty() ? object_id : filter) + ", \"collection\":\"" + collection + "\"}"};
210 :
211 1 : std::cout << "Search criteria " << search << "\n";
212 :
213 1 : auto results = provider->readDocument(search);
214 :
215 1 : if (results.size() != 1) {
216 0 : std::cout << "Search returned " << results.size() << " results.\n";
217 :
218 0 : for (auto&& element : results) {
219 0 : std::cout << element << "\n";
220 : }
221 0 : return false;
222 : }
223 :
224 1 : auto retdoc = JSONDocument{*results.begin()};
225 1 : JSONDocumentBuilder returned{retdoc};
226 1 : JSONDocumentBuilder expected{cmpdoc};
227 :
228 : using namespace artdaq::database::overlay;
229 1 : ovl::useCompareMask(DOCUMENT_COMPARE_MUTE_TIMESTAMPS | DOCUMENT_COMPARE_MUTE_OUIDS | DOCUMENT_COMPARE_MUTE_UPDATES |
230 : DOCUMENT_COMPARE_MUTE_COLLECTION | DOCUMENT_COMPARE_MUTE_COMMENTS);
231 :
232 1 : auto result = returned == expected;
233 :
234 1 : if (result.first) {
235 1 : return true;
236 : }
237 :
238 0 : std::cout << "Error returned!=expected.\n";
239 0 : std::cerr << "returned:\n" << returned << "\n";
240 0 : std::cerr << "expected:\n" << expected << "\n";
241 0 : std::cerr << "error:\n" << result.second << "\n";
242 0 : return false;
243 1 : }
244 1 : bool test_search2(std::string const& source_xml, std::string const& compare_xml, std::string const& options [[gnu::unused]]) {
245 1 : confirm(!source_xml.empty());
246 1 : confirm(!compare_xml.empty());
247 :
248 1 : JsonData source = XmlData(source_xml);
249 1 : JsonData compare = XmlData(compare_xml);
250 :
251 : namespace DBI = artdaq::database::mongo;
252 :
253 1 : auto config = DBI::DBConfig{};
254 1 : auto database = DBI::DB::create(config);
255 1 : auto provider = DBI::DBProvider<JSONDocument>::create(database);
256 :
257 1 : auto collection = std::string("testXML_V001");
258 :
259 1 : auto json = JSONDocument{"{\"document\":" + source.json_buffer + ", \"collection\":\"" + collection + "\"}"};
260 :
261 1 : auto repeatCount = std::size_t{10};
262 :
263 1 : auto object_ids = std::vector<std::string>();
264 :
265 1 : std::ostringstream oss;
266 1 : oss << R"({"_id" : { "$in" : [)";
267 :
268 1 : auto nodata_pos = oss.tellp();
269 :
270 11 : for (int i = repeatCount; i != 0; i--) {
271 10 : auto object_id = provider->writeDocument(json);
272 10 : object_ids.push_back(object_id);
273 30 : oss << JSONDocument(object_id).findChildDocument("_id").to_string() << ",";
274 10 : }
275 :
276 1 : if (oss.tellp() != nodata_pos) {
277 1 : oss.seekp(-1, oss.cur);
278 : }
279 :
280 1 : oss << "]} }";
281 :
282 1 : auto filter = oss.str();
283 :
284 1 : auto search = JSONDocument{"{\"filter\":" + (filter.empty() ? options : filter) + ", \"collection\":\"" + collection + "\"}"};
285 :
286 1 : std::cout << "Search criteria " << search << "\n";
287 :
288 1 : auto results = provider->readDocument(search);
289 :
290 1 : if (results.size() != repeatCount) {
291 0 : std::cout << "Search returned " << results.size() << " results.\n";
292 :
293 0 : for (auto&& element : results) {
294 0 : std::cout << element << "\n";
295 : }
296 0 : return false;
297 : }
298 :
299 1 : return true;
300 1 : }
301 :
302 1 : bool test_update(std::string const& source_xml, std::string const& compare_xml, std::string const& update_xml) {
303 1 : confirm(!source_xml.empty());
304 1 : confirm(!compare_xml.empty());
305 :
306 1 : JsonData source = XmlData(source_xml);
307 1 : JsonData compare = XmlData(compare_xml);
308 1 : JsonData update = XmlData(update_xml);
309 :
310 : // validate source
311 1 : auto insert = JSONDocument(source);
312 : // insert.deleteChild(literal::comments_node);
313 :
314 : // validate compare
315 1 : auto cmpdoc = JSONDocument(compare);
316 : // expected.deleteChild(literal::comments_node);
317 :
318 1 : auto changes = JSONDocument(update);
319 : // changes.deleteChild(literal::comments_node);
320 :
321 : namespace DBI = artdaq::database::mongo;
322 :
323 1 : auto config = DBI::DBConfig{};
324 1 : auto database = DBI::DB::create(config);
325 1 : auto provider = DBI::DBProvider<JSONDocument>::create(database);
326 :
327 1 : auto collection = std::string("testXML_V001");
328 :
329 1 : auto json = JSONDocument{"{\"document\":" + insert.to_string() + ", \"collection\":\"" + collection + "\"}"};
330 :
331 1 : auto object_id = provider->writeDocument(json);
332 :
333 1 : auto search = JSONDocument{"{\"filter\":" + object_id + ", \"collection\":\"" + collection + "\"}"};
334 :
335 1 : std::cout << "Search criteria " << search << "\n";
336 :
337 1 : auto results = provider->readDocument(search);
338 :
339 1 : if (results.size() != 1) {
340 0 : std::cout << "Search returned " << results.size() << " results.\n";
341 :
342 0 : for (auto&& element : results) {
343 0 : std::cout << element << "\n";
344 : }
345 0 : return false;
346 : }
347 :
348 1 : auto found = JSONDocument{*results.begin()};
349 2 : auto payload = changes.findChild("document");
350 1 : found.replaceChild(payload, "document");
351 :
352 1 : json = JSONDocument{"{\"document\":" + found.to_string() + ", \"filter\":" + object_id + ",\"collection\":\"" + collection + "\"}"};
353 :
354 1 : object_id = provider->writeDocument(json);
355 :
356 1 : search = JSONDocument{"{\"filter\":" + object_id + ", \"collection\":\"" + collection + "\"}"};
357 1 : results = provider->readDocument(search);
358 :
359 1 : if (results.size() != 1) {
360 0 : std::cout << "Search returned " << results.size() << " results.\n";
361 :
362 0 : for (auto&& element : results) {
363 0 : std::cout << element << "\n";
364 : }
365 0 : return false;
366 : }
367 :
368 1 : auto retdoc = JSONDocument{*results.begin()};
369 1 : JSONDocumentBuilder returned{retdoc};
370 1 : JSONDocumentBuilder expected{cmpdoc};
371 :
372 : using namespace artdaq::database::overlay;
373 1 : ovl::useCompareMask(DOCUMENT_COMPARE_MUTE_TIMESTAMPS | DOCUMENT_COMPARE_MUTE_OUIDS | DOCUMENT_COMPARE_MUTE_UPDATES |
374 : DOCUMENT_COMPARE_MUTE_COLLECTION | DOCUMENT_COMPARE_MUTE_COMMENTS);
375 :
376 1 : auto result = returned == expected;
377 :
378 1 : if (result.first) {
379 1 : return true;
380 : }
381 :
382 0 : std::cout << "Error returned!=expected.\n";
383 0 : std::cerr << "returned:\n" << returned << "\n";
384 0 : std::cerr << "expected:\n" << expected << "\n";
385 0 : std::cerr << "error:\n" << result.second << "\n";
386 0 : return false;
387 1 : }
|