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