LCOV - code coverage report
Current view: top level - /opt/artdaq/srcs/artdaq-database/test/StorageProviders/MongoFhicl - MongoFhicl_t.cc (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 74.4 % 215 160
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/MongoDB/provider_mongodb.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            4 : int main(int argc, char* argv[]) try {
      30            4 :   artdaq::database::mongo::debug::enable();
      31              :   //  artdaq::database::docrecord::debug::JSONDocument();
      32              : 
      33            4 :   debug::registerUngracefullExitHandlers();
      34            4 :   artdaq::database::useFakeTime(true);
      35              : 
      36            4 :   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            4 :              "(available test names: insert,search1,search1,update)";
      40              : 
      41            4 :   bpo::options_description desc = descstr.str();
      42              : 
      43            4 :   desc.add_options()("source,s", bpo::value<std::string>(), "Input source file.")("compare,c", bpo::value<std::string>(), "Expected result.")(
      44            4 :       "testname,t", bpo::value<std::string>(), "Test name.")("options,o", bpo::value<std::string>(), "Test options file.")(
      45           12 :       "collection,n", bpo::value<std::string>()->default_value("testFHICL_V001"), "Collection name.")
      46              : 
      47            4 :       ("help,h", "produce help message");
      48              : 
      49            4 :   bpo::variables_map vm;
      50              : 
      51              :   try {
      52            4 :     bpo::store(bpo::command_line_parser(argc, argv).options(desc).run(), vm);
      53            4 :     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            8 :   if (vm.count("help") != 0u) {
      60            0 :     std::cout << desc << std::endl;
      61            0 :     return process_exit_code::HELP;
      62              :   }
      63              : 
      64            8 :   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            8 :   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            8 :   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            8 :   auto input_name = vm["source"].as<std::string>();
      86            8 :   auto compare_name = vm["compare"].as<std::string>();
      87            4 :   auto test_name = vm["testname"].as<std::string>();
      88              : 
      89            4 :   auto input = std::string{};
      90            4 :   db::read_buffer_from_file(input, input_name);
      91              : 
      92            4 :   auto compare = std::string{};
      93            4 :   db::read_buffer_from_file(compare, compare_name);
      94              : 
      95            4 :   auto options = std::string();
      96              : 
      97            8 :   if (vm.count("options") != 0u) {
      98            2 :     auto opts_name = vm["options"].as<std::string>();
      99              : 
     100            2 :     db::read_buffer_from_file(options, opts_name);
     101            2 :   }
     102              : 
     103            4 :   auto collection_name = vm["collection"].as<std::string>();
     104              : 
     105            4 :   auto runTest = [](std::string const& name) {
     106              :     auto tests =
     107           24 :         std::map<std::string, test_case>{{"insert", test_insert}, {"update", test_update}, {"search1", test_search1}, {"search2", test_search2}};
     108              : 
     109            4 :     std::cout << "Running test:<" << name << ">\n";
     110              : 
     111            8 :     return tests.at(name);
     112            8 :   };
     113              : 
     114            4 :   auto testResult = runTest(test_name)(input, compare, options, collection_name);
     115              : 
     116            4 :   if (testResult) {
     117            4 :     return process_exit_code::SUCCESS;
     118              :   }
     119              : 
     120            0 :   return process_exit_code::FAILURE;
     121            4 : } 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::mongo;
     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 :   std::cout << "filter returned " << filter << "\n";
     150            1 :   auto search = JSONDocument{"{\"filter\":" + (filter.empty() ? object_id : filter) + ", \"collection\":\"" + collection + "\"}"};
     151              : 
     152            1 :   std::cout << "Search criteria " << search << "\n";
     153              : 
     154            1 :   auto results = provider->readDocument(search);
     155              : 
     156            1 :   if (results.size() != 1) {
     157            0 :     std::cout << "Search returned " << results.size() << " results.\n";
     158              : 
     159            0 :     for (auto&& element : results) {
     160            0 :       std::cout << element << "\n";
     161              :     }
     162            0 :     return false;
     163              :   }
     164              : 
     165            1 :   auto retdoc = JSONDocument{*results.begin()};
     166              : 
     167            1 :   JSONDocumentBuilder returned{retdoc};
     168            1 :   JSONDocumentBuilder expected{cmpdoc};
     169              : 
     170              :   using namespace artdaq::database::overlay;
     171            1 :   ovl::useCompareMask(DOCUMENT_COMPARE_MUTE_TIMESTAMPS | DOCUMENT_COMPARE_MUTE_OUIDS | DOCUMENT_COMPARE_MUTE_UPDATES |
     172              :                       DOCUMENT_COMPARE_MUTE_COLLECTION);
     173              : 
     174            1 :   auto result = returned == expected;
     175              : 
     176            1 :   if (result.first) {
     177            1 :     return true;
     178              :   }
     179              : 
     180            0 :   std::cout << "Error returned!=expected.\n";
     181            0 :   std::cerr << "returned:\n" << returned << "\n";
     182            0 :   std::cerr << "expected:\n" << expected << "\n";
     183            0 :   std::cerr << "error:\n" << result.second << "\n";
     184            0 :   return false;
     185            1 : }
     186              : 
     187            1 : bool test_search1(std::string const& source_fcl, std::string const& compare_fcl, std::string const& filter, std::string const& collection) {
     188            1 :   confirm(!source_fcl.empty());
     189            1 :   confirm(!compare_fcl.empty());
     190              : 
     191            1 :   JsonData source = FhiclData(source_fcl);
     192            1 :   JsonData compare = FhiclData(compare_fcl);
     193              : 
     194              :   // validate source
     195            1 :   auto insert = JSONDocument(source);
     196              : 
     197              :   // validate compare
     198            1 :   auto cmpdoc = JSONDocument(compare);
     199              : 
     200              :   using artdaq::database::basictypes::FhiclData;
     201              :   using artdaq::database::basictypes::JsonData;
     202              : 
     203              :   namespace DBI = artdaq::database::mongo;
     204              : 
     205            1 :   auto config = DBI::DBConfig{};
     206            1 :   auto database = DBI::DB::create(config);
     207            1 :   auto provider = DBI::DBProvider<JSONDocument>::create(database);
     208              : 
     209            1 :   auto json = JSONDocument{"{\"document\":" + insert.to_string() + ", \"collection\":\"" + collection + "\"}"};
     210              : 
     211            1 :   auto object_id = provider->writeDocument(json);
     212              : 
     213            1 :   auto search = JSONDocument{"{\"filter\":" + (filter.empty() ? object_id : filter) + ", \"collection\":\"" + collection + "\"}"};
     214              : 
     215            1 :   std::cout << "Search criteria " << search << "\n";
     216              : 
     217            1 :   auto results = provider->readDocument(search);
     218              : 
     219            1 :   if (results.size() != 1) {
     220            0 :     std::cout << "Search returned " << results.size() << " results.\n";
     221              : 
     222            0 :     for (auto&& element : results) {
     223            0 :       std::cout << element << "\n";
     224              :     }
     225            0 :     return false;
     226              :   }
     227              : 
     228            1 :   auto retdoc = JSONDocument{*results.begin()};
     229            1 :   JSONDocumentBuilder returned{retdoc};
     230            1 :   JSONDocumentBuilder expected{cmpdoc};
     231              : 
     232              :   using namespace artdaq::database::overlay;
     233            1 :   ovl::useCompareMask(DOCUMENT_COMPARE_MUTE_TIMESTAMPS | DOCUMENT_COMPARE_MUTE_OUIDS | DOCUMENT_COMPARE_MUTE_UPDATES |
     234              :                       DOCUMENT_COMPARE_MUTE_COLLECTION | DOCUMENT_COMPARE_MUTE_COMMENTS);
     235              : 
     236            1 :   auto result = returned == expected;
     237              : 
     238            1 :   if (result.first) {
     239            1 :     return true;
     240              :   }
     241              : 
     242            0 :   std::cout << "Error returned!=expected.\n";
     243            0 :   std::cerr << "returned:\n" << returned << "\n";
     244            0 :   std::cerr << "expected:\n" << expected << "\n";
     245            0 :   std::cerr << "error:\n" << result.second << "\n";
     246            0 :   return false;
     247            1 : }
     248              : 
     249            1 : bool test_search2(std::string const& source_fcl, std::string const& compare_fcl, std::string const& options [[gnu::unused]],
     250              :                   std::string const& collection) {
     251            1 :   confirm(!source_fcl.empty());
     252            1 :   confirm(!compare_fcl.empty());
     253              : 
     254            1 :   JsonData source = FhiclData(source_fcl);
     255            1 :   JsonData compare = FhiclData(compare_fcl);
     256              : 
     257              :   namespace DBI = artdaq::database::mongo;
     258              : 
     259            1 :   auto config = DBI::DBConfig{};
     260            1 :   auto database = DBI::DB::create(config);
     261            1 :   auto provider = DBI::DBProvider<JSONDocument>::create(database);
     262              : 
     263            1 :   auto repeatCount = std::size_t{10};
     264              : 
     265            1 :   auto object_ids = std::vector<std::string>();
     266              : 
     267            1 :   std::ostringstream oss;
     268            1 :   oss << "{\"_id\" : { \"$in\" : [";
     269              : 
     270            1 :   auto nodata_pos = oss.tellp();
     271              : 
     272           11 :   for (int i = repeatCount; i != 0; i--) {
     273           10 :     auto version_str = "version_search2_" + std::to_string(i);
     274              : 
     275           10 :     auto source_with_version = source.json_buffer;
     276           10 :     auto version_pattern = std::string{"\"version\" : \"notprovided\""};
     277           10 :     auto pos = source_with_version.find(version_pattern);
     278           10 :     if (pos == std::string::npos) {
     279            0 :       version_pattern = "\"version\":\"notprovided\"";
     280            0 :       pos = source_with_version.find(version_pattern);
     281              :     }
     282           10 :     if (pos == std::string::npos) {
     283            0 :       version_pattern = "\"version\": \"notprovided\"";
     284            0 :       pos = source_with_version.find(version_pattern);
     285              :     }
     286           10 :     if (pos != std::string::npos) {
     287           10 :       source_with_version.replace(pos, version_pattern.length(), "\"version\" : \"" + version_str + "\"");
     288              :     }
     289              : 
     290              :     auto json =
     291           10 :         JSONDocument{"{\"document\":" + source_with_version + ", \"version\":\"" + version_str + "\", \"collection\":\"" + collection + "\"}"};
     292           10 :     auto object_id = provider->writeDocument(json);
     293           10 :     object_ids.push_back(object_id);
     294           30 :     oss << JSONDocument(object_id).findChildDocument("_id").to_string() << ",";
     295           10 :   }
     296              : 
     297            1 :   if (oss.tellp() != nodata_pos) {
     298            1 :     oss.seekp(-1, oss.cur);
     299              :   }
     300              : 
     301            1 :   oss << "]} }";
     302              : 
     303            1 :   auto filter = oss.str();
     304              : 
     305            1 :   auto search = JSONDocument{"{\"filter\":" + (filter.empty() ? options : filter) + ", \"collection\":\"" + collection + "\"}"};
     306              : 
     307            1 :   std::cout << "Search criteria " << search << "\n";
     308              : 
     309            1 :   auto results = provider->readDocument(search);
     310              : 
     311            1 :   if (results.size() != repeatCount) {
     312            0 :     std::cout << "Search returned " << results.size() << " results.\n";
     313              : 
     314            0 :     for (auto&& element : results) {
     315            0 :       std::cout << element << "\n";
     316              :     }
     317            0 :     return false;
     318              :   }
     319              : 
     320            1 :   return true;
     321            1 : }
     322              : 
     323            1 : bool test_update(std::string const& source_fcl, std::string const& compare_fcl, std::string const& update_fcl, std::string const& collection) {
     324            1 :   confirm(!source_fcl.empty());
     325            1 :   confirm(!compare_fcl.empty());
     326              : 
     327            1 :   JsonData source = FhiclData(source_fcl);
     328            1 :   JsonData compare = FhiclData(compare_fcl);
     329            1 :   JsonData update = FhiclData(update_fcl);
     330              : 
     331              :   // validate source
     332            1 :   auto insert = JSONDocument(source);
     333              :   // insert.deleteChild(literal::comments);
     334              : 
     335              :   // validate compare
     336            1 :   auto cmpdoc = JSONDocument(compare);
     337              :   // cmpdoc.deleteChild(literal::comments);
     338              : 
     339            1 :   auto changes = JSONDocument(update);
     340              :   // changes.deleteChild(literal::comments);
     341              : 
     342              :   namespace DBI = artdaq::database::mongo;
     343              : 
     344            1 :   auto config = DBI::DBConfig{};
     345            1 :   auto database = DBI::DB::create(config);
     346            1 :   auto provider = DBI::DBProvider<JSONDocument>::create(database);
     347              : 
     348            1 :   auto json = JSONDocument{"{\"document\":" + insert.to_string() + ", \"collection\":\"" + collection + "\"}"};
     349              : 
     350            1 :   auto object_id = provider->writeDocument(json);
     351              : 
     352            1 :   auto search = JSONDocument{"{\"filter\":" + object_id + ", \"collection\":\"" + collection + "\"}"};
     353              : 
     354            1 :   std::cout << "Search criteria " << search << "\n";
     355              : 
     356            1 :   auto 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 found = JSONDocument{*results.begin()};
     368            2 :   auto payload = changes.findChild("document");
     369            1 :   found.replaceChild(payload, "document");
     370              : 
     371            1 :   json = JSONDocument{"{\"document\":" + found.to_string() + ", \"filter\":" + object_id + ",\"collection\":\"" + collection + "\"}"};
     372              : 
     373            1 :   object_id = provider->writeDocument(json);
     374              : 
     375            1 :   search = JSONDocument{"{\"filter\":" + object_id + ", \"collection\":\"" + collection + "\"}"};
     376            1 :   results = provider->readDocument(search);
     377              : 
     378            1 :   if (results.size() != 1) {
     379            0 :     std::cout << "Search returned " << results.size() << " results.\n";
     380              : 
     381            0 :     for (auto&& element : results) {
     382            0 :       std::cout << element << "\n";
     383              :     }
     384            0 :     return false;
     385              :   }
     386              : 
     387            1 :   auto retdoc = JSONDocument{*results.begin()};
     388            1 :   JSONDocumentBuilder returned{retdoc};
     389            1 :   JSONDocumentBuilder expected{cmpdoc};
     390              : 
     391              :   using namespace artdaq::database::overlay;
     392            1 :   ovl::useCompareMask(DOCUMENT_COMPARE_MUTE_TIMESTAMPS | DOCUMENT_COMPARE_MUTE_OUIDS | DOCUMENT_COMPARE_MUTE_UPDATES |
     393              :                       DOCUMENT_COMPARE_MUTE_COLLECTION | DOCUMENT_COMPARE_MUTE_COMMENTS);
     394              : 
     395            1 :   auto result = returned == expected;
     396              : 
     397            1 :   if (result.first) {
     398            1 :     return true;
     399              :   }
     400              : 
     401            0 :   std::cout << "Error returned!=expected.\n";
     402            0 :   std::cerr << "returned:\n" << returned << "\n";
     403            0 :   std::cerr << "expected:\n" << expected << "\n";
     404            0 :   std::cerr << "error:\n" << result.second << "\n";
     405            0 :   return false;
     406            1 : }
        

Generated by: LCOV version 2.0-1