LCOV - code coverage report
Current view: top level - /opt/artdaq/srcs/artdaq-database/test/StorageProviders/FileSystemFhicl - FileSystemFhicl_t.cc (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 62.9 % 213 134
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::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 : }
        

Generated by: LCOV version 2.0-1