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