LCOV - code coverage report
Current view: top level - /opt/artdaq/srcs/artdaq-database/test/StorageProviders/FileSystemXml - FileSystemXml_t.cc (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 62.6 % 203 127
Test Date: 2026-10-29 00:35:58 Functions: 83.3 % 6 5

            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::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            3 : int main(int argc, char* argv[]) try {
      26            3 :   artdaq::database::filesystem::debug::enable();
      27              :   //    artdaq::database::docrecord::debug::JSONDocument();
      28              : 
      29            3 :   debug::registerUngracefullExitHandlers();
      30            3 :   artdaq::database::useFakeTime(true);
      31              : 
      32            3 :   std::ostringstream descstr;
      33              :   descstr << argv[0]
      34              :           << " <-s <source-file>> <-c <compare-with-file>> <-t <test-name>> [<-o <options file>>] (available test "
      35            3 :              "names: insert,search1,search1,update)";
      36              : 
      37            3 :   bpo::options_description desc = descstr.str();
      38              : 
      39            3 :   desc.add_options()("source,s", bpo::value<std::string>(), "Input source file.")("compare,c", bpo::value<std::string>(), "Expected result.")(
      40            3 :       "testname,t", bpo::value<std::string>(), "Test name.")("options,o", bpo::value<std::string>(), "Test options file.")
      41              : 
      42            3 :       ("help,h", "produce help message");
      43              : 
      44            3 :   bpo::variables_map vm;
      45              : 
      46              :   try {
      47            3 :     bpo::store(bpo::command_line_parser(argc, argv).options(desc).run(), vm);
      48            3 :     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            6 :   if (vm.count("help") != 0u) {
      55            0 :     std::cout << desc << std::endl;
      56            0 :     return process_exit_code::HELP;
      57              :   }
      58              : 
      59            6 :   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            6 :   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            6 :   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            6 :   auto input_name = vm["source"].as<std::string>();
      81            6 :   auto compare_name = vm["compare"].as<std::string>();
      82            3 :   auto test_name = vm["testname"].as<std::string>();
      83              : 
      84            3 :   auto input = std::string{};
      85            3 :   db::read_buffer_from_file(input, input_name);
      86              : 
      87            3 :   auto compare = std::string{};
      88            3 :   db::read_buffer_from_file(compare, compare_name);
      89              : 
      90            3 :   auto options = std::string();
      91              : 
      92            6 :   if (vm.count("options") != 0u) {
      93            1 :     auto opts_name = vm["options"].as<std::string>();
      94              : 
      95            1 :     db::read_buffer_from_file(options, opts_name);
      96            1 :   }
      97              : 
      98            3 :   auto runTest = [](std::string const& name) {
      99              :     auto tests =
     100           18 :         std::map<std::string, test_case>{{"insert", test_insert}, {"update", test_update}, {"search1", test_search1}, {"search2", test_search2}};
     101              : 
     102            3 :     std::cout << "Running test:<" << name << ">\n";
     103              : 
     104            6 :     return tests.at(name);
     105            6 :   };
     106              : 
     107            3 :   auto testResult = runTest(test_name)(input, compare, options);
     108              : 
     109            3 :   if (testResult) {
     110            3 :     return process_exit_code::SUCCESS;
     111              :   }
     112              : 
     113            0 :   return process_exit_code::FAILURE;
     114            3 : } 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::filesystem;
     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            0 : bool test_search1(std::string const& source_xml, std::string const& compare_xml, std::string const& filter) {
     182            0 :   confirm(!source_xml.empty());
     183            0 :   confirm(!compare_xml.empty());
     184              : 
     185            0 :   JsonData source = XmlData(source_xml);
     186            0 :   JsonData compare = XmlData(compare_xml);
     187              : 
     188              :   // validate source
     189            0 :   auto insert = JSONDocument(source);
     190              : 
     191              :   // validate compare
     192            0 :   auto cmpdoc = JSONDocument(compare);
     193              : 
     194              :   using artdaq::database::basictypes::JsonData;
     195              :   using artdaq::database::basictypes::XmlData;
     196              : 
     197              :   namespace DBI = artdaq::database::filesystem;
     198              : 
     199            0 :   auto config = DBI::DBConfig{};
     200            0 :   auto database = DBI::DB::create(config);
     201            0 :   auto provider = DBI::DBProvider<JSONDocument>::create(database);
     202              : 
     203            0 :   auto collection = std::string("testXML_V001");
     204              : 
     205            0 :   auto json = JSONDocument{"{\"document\":" + insert.to_string() + ", \"collection\":\"" + collection + "\"}"};
     206              : 
     207            0 :   auto object_id = provider->writeDocument(json);
     208              : 
     209            0 :   auto search = JSONDocument{"{\"filter\":" + (filter.empty() ? object_id : filter) + ", \"collection\":\"" + collection + "\"}"};
     210              : 
     211            0 :   std::cout << "Search criteria " << search << "\n";
     212              : 
     213            0 :   auto results = provider->readDocument(search);
     214              : 
     215            0 :   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            0 :   auto retdoc = JSONDocument{*results.begin()};
     225            0 :   JSONDocumentBuilder returned{retdoc};
     226            0 :   JSONDocumentBuilder expected{cmpdoc};
     227              : 
     228              :   using namespace artdaq::database::overlay;
     229            0 :   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            0 :   auto result = returned == expected;
     233              : 
     234            0 :   if (result.first) {
     235            0 :     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            0 : }
     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::filesystem;
     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::filesystem;
     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 = JsonData{"{\"document\":" + found.to_string() + ", \"filter\":" + object_id + ",\"collection\":\"" + collection + "\"}"};
     353              : 
     354            1 :   object_id = provider->writeDocument(json);
     355              : 
     356            1 :   results = provider->readDocument(search);
     357              : 
     358            1 :   if (results.size() != 1) {
     359            0 :     std::cout << "Search returned " << results.size() << " results.\n";
     360              : 
     361            0 :     for (auto&& element : results) {
     362            0 :       std::cout << element << "\n";
     363              :     }
     364            0 :     return false;
     365              :   }
     366              : 
     367            1 :   auto retdoc = JSONDocument{*results.begin()};
     368            1 :   JSONDocumentBuilder returned{retdoc};
     369            1 :   JSONDocumentBuilder expected{cmpdoc};
     370              : 
     371              :   using namespace artdaq::database::overlay;
     372            1 :   ovl::useCompareMask(DOCUMENT_COMPARE_MUTE_TIMESTAMPS | DOCUMENT_COMPARE_MUTE_OUIDS | DOCUMENT_COMPARE_MUTE_UPDATES |
     373              :                       DOCUMENT_COMPARE_MUTE_COLLECTION | DOCUMENT_COMPARE_MUTE_COMMENTS);
     374              : 
     375            1 :   auto result = returned == expected;
     376              : 
     377            1 :   if (result.first) {
     378            1 :     return true;
     379              :   }
     380              : 
     381            0 :   std::cout << "Error returned!=expected.\n";
     382            0 :   std::cerr << "returned:\n" << returned << "\n";
     383            0 :   std::cerr << "expected:\n" << expected << "\n";
     384            0 :   std::cerr << "error:\n" << result.second << "\n";
     385            0 :   return false;
     386            1 : }
        

Generated by: LCOV version 2.0-1