LCOV - code coverage report
Current view: top level - /opt/artdaq/srcs/artdaq-database/test/StorageProviders/FileSystemJson - FileSystemJson_t.cc (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 74.1 % 197 146
Test Date: 2026-10-29 00:35:58 Functions: 100.0 % 6 6

            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 : }
        

Generated by: LCOV version 2.0-1