LCOV - code coverage report
Current view: top level - /opt/artdaq/srcs/artdaq-database/test/CaseStudy/OtsDaqCPPInterface/test016 - SearchPatterns_t.cc (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 94.8 % 115 109
Test Date: 2026-10-29 00:35:58 Functions: 100.0 % 15 15

            Line data    Source code
       1              : #define BOOST_TEST_DYN_LINK
       2              : #define BOOST_TEST_MODULE (SearchPatterns test)
       3              : 
       4              : #include <boost/test/unit_test.hpp>
       5              : 
       6              : #include <cstdlib>
       7              : #include <ctime>
       8              : #include <iostream>
       9              : #include <memory>
      10              : #include <string>
      11              : #include <vector>
      12              : 
      13              : #include "../DatabaseConfigurationInterface.h"
      14              : 
      15              : using namespace ots;
      16              : 
      17              : struct SearchPatternsTestData {
      18            2 :   SearchPatternsTestData() {
      19            2 :     srand(time(nullptr));
      20            2 :     baseVersion = rand() % 99999 + 100000;
      21            2 :     std::cout << "=== SEARCH PATTERNS TEST SUITE ===\n";
      22            2 :     std::cout << "Base version: " << baseVersion << "\n\n";
      23            2 :   }
      24              : 
      25            2 :   ~SearchPatternsTestData() { std::cout << "\n=== TEST SUITE COMPLETE ===\n"; }
      26              : 
      27              :   int baseVersion;
      28              : };
      29              : 
      30              : SearchPatternsTestData fixture;
      31              : 
      32              : BOOST_AUTO_TEST_SUITE(search_patterns_test)
      33              : 
      34            6 : void createSearchTestData(DatabaseConfigurationInterface& ifc, int version, const std::string& prefix) {
      35            6 :   std::shared_ptr<ConfigurationBase> cfg = std::make_shared<TestConfiguration001>();
      36            6 :   cfg->getView().version = version;
      37            6 :   ifc.saveActiveVersion(cfg.get());
      38              : 
      39            6 :   auto map = DatabaseConfigurationInterface::config_version_map_t{};
      40            6 :   map[cfg->getConfigurationName()] = version;
      41              : 
      42           36 :   for (int i = 0; i < 5; i++) {
      43           30 :     std::string compName = prefix + "_" + std::to_string(i);
      44           30 :     ifc.storeGlobalConfiguration(map, compName);
      45           30 :   }
      46            6 : }
      47              : 
      48            4 : BOOST_AUTO_TEST_CASE(wildcard_only_search) {
      49            2 :   std::cout << "\n=== TEST 1: Wildcard only search ===\n";
      50              : 
      51            2 :   auto ifc = DatabaseConfigurationInterface();
      52              : 
      53            2 :   auto results = ifc.findAllGlobalConfigurations("*");
      54            2 :   std::cout << "Step 1: findAllGlobalConfigurations(\"*\") returned " << results.size() << " results\n";
      55              : 
      56            2 :   BOOST_CHECK_GE(results.size(), 0);
      57              : 
      58            2 :   std::cout << "  Verified: Wildcard search returns valid results\n";
      59            2 : }
      60              : 
      61            4 : BOOST_AUTO_TEST_CASE(multiple_wildcards) {
      62            2 :   std::cout << "\n=== TEST 2: Multiple wildcards ===\n";
      63              : 
      64            2 :   auto ifc = DatabaseConfigurationInterface();
      65            2 :   int testVersion = fixture.baseVersion;
      66              : 
      67            2 :   std::string prefix = "MultiWild_" + std::to_string(fixture.baseVersion);
      68            2 :   createSearchTestData(ifc, testVersion, prefix);
      69            2 :   std::cout << "Step 1: Created compositions with prefix: " << prefix << "\n";
      70              : 
      71            2 :   std::string pattern = "*Wild*" + std::to_string(fixture.baseVersion) + "*";
      72              : 
      73              :   try {
      74            2 :     auto results = ifc.findAllGlobalConfigurations(pattern);
      75            1 :     std::cout << "Step 2: Search pattern \"" << pattern << "\" returned " << results.size() << " results\n";
      76            1 :     BOOST_CHECK_GE(results.size(), 0);
      77            2 :   } catch (std::exception& e) {
      78            1 :     std::cout << "Step 2: Multiple wildcards threw exception (may be provider limitation)\n";
      79            1 :     std::cout << "  Exception: " << e.what() << "\n";
      80            1 :     BOOST_WARN_MESSAGE(false, "Multiple wildcards not supported by provider");
      81            1 :   }
      82              : 
      83            2 :   BOOST_CHECK(true);
      84            2 :   std::cout << "  Documented: Multiple wildcards behavior\n";
      85            2 : }
      86              : 
      87            4 : BOOST_AUTO_TEST_CASE(prefix_search) {
      88            2 :   std::cout << "\n=== TEST 3: Prefix search ===\n";
      89              : 
      90            2 :   auto ifc = DatabaseConfigurationInterface();
      91            2 :   int testVersion = fixture.baseVersion + 100;
      92              : 
      93            2 :   std::string prefix = "PrefixSearch_" + std::to_string(fixture.baseVersion);
      94            2 :   createSearchTestData(ifc, testVersion, prefix);
      95            2 :   std::cout << "Step 1: Created 5 compositions with prefix: " << prefix << "\n";
      96              : 
      97            2 :   std::string pattern = prefix + "*";
      98            2 :   auto results = ifc.findAllGlobalConfigurations(pattern);
      99            2 :   std::cout << "Step 2: Search pattern \"" << pattern << "\" returned " << results.size() << " results\n";
     100              : 
     101            2 :   BOOST_CHECK_GE(results.size(), 5);
     102              : 
     103            2 :   std::cout << "  Verified: Prefix search works correctly\n";
     104            2 : }
     105              : 
     106            4 : BOOST_AUTO_TEST_CASE(regex_special_chars_escaped) {
     107            2 :   std::cout << "\n=== TEST 4: Regex special chars escaped ===\n";
     108              : 
     109            2 :   auto ifc = DatabaseConfigurationInterface();
     110              : 
     111            4 :   std::vector<std::string> regexPatterns = {"config.name", "config[1]", "config(test)", "config^start", "config$end"};
     112              : 
     113            2 :   int safeCount = 0;
     114           12 :   for (const auto& pattern : regexPatterns) {
     115           10 :     bool handled = false;
     116              :     try {
     117           10 :       auto results = ifc.findAllGlobalConfigurations(pattern);
     118           10 :       handled = true;
     119           10 :       std::cout << "  \"" << pattern << "\": returned " << results.size() << " results\n";
     120           10 :     } catch (std::exception& e) {
     121            0 :       handled = true;
     122            0 :       std::cout << "  \"" << pattern << "\": threw (acceptable)\n";
     123            0 :     }
     124           10 :     if (handled) safeCount++;
     125              :   }
     126              : 
     127            2 :   std::cout << "Step 1: Handled " << safeCount << "/" << regexPatterns.size() << " patterns safely\n";
     128              : 
     129            2 :   BOOST_CHECK_EQUAL(safeCount, regexPatterns.size());
     130            2 :   std::cout << "  Verified: Regex special characters handled safely\n";
     131            2 : }
     132              : 
     133            4 : BOOST_AUTO_TEST_CASE(sql_injection_like_patterns) {
     134            2 :   std::cout << "\n=== TEST 5: SQL injection like patterns ===\n";
     135              : 
     136            2 :   auto ifc = DatabaseConfigurationInterface();
     137            2 :   int testVersion = fixture.baseVersion + 200;
     138              : 
     139            2 :   std::string prefix = "SafeTest_" + std::to_string(fixture.baseVersion);
     140            2 :   createSearchTestData(ifc, testVersion, prefix);
     141              : 
     142              :   std::vector<std::string> injectionPatterns = {"'; DROP TABLE configs; --", "config' OR '1'='1", "config\"; DELETE FROM *; --", "$(rm -rf /)",
     143            4 :                                                 "`ls -la`"};
     144              : 
     145            2 :   int safeCount = 0;
     146           12 :   for (const auto& pattern : injectionPatterns) {
     147              :     try {
     148           10 :       auto results = ifc.findAllGlobalConfigurations(pattern);
     149            8 :       safeCount++;
     150            8 :       std::cout << "  \"" << pattern.substr(0, 20) << "...\": returned " << results.size() << " results (safe)\n";
     151           10 :     } catch (std::exception& e) {
     152            2 :       safeCount++;
     153            2 :       std::cout << "  \"" << pattern.substr(0, 20) << "...\": threw (safe)\n";
     154            2 :     }
     155              :   }
     156              : 
     157            2 :   auto safeResults = ifc.findAllGlobalConfigurations(prefix + "*");
     158            2 :   bool dbStillWorks = (safeResults.size() >= 5);
     159            2 :   std::cout << "Step 1: Database still working: " << (dbStillWorks ? "yes" : "NO!") << "\n";
     160              : 
     161            2 :   BOOST_CHECK_EQUAL(safeCount, injectionPatterns.size());
     162            2 :   BOOST_CHECK(dbStillWorks);
     163              : 
     164            2 :   std::cout << "  Verified: Injection patterns handled safely\n";
     165            2 : }
     166              : 
     167            4 : BOOST_AUTO_TEST_CASE(empty_search_behavior) {
     168            2 :   std::cout << "\n=== TEST 6: Empty search behavior ===\n";
     169              : 
     170            2 :   auto ifc = DatabaseConfigurationInterface();
     171              : 
     172            4 :   auto emptyResults = ifc.findAllGlobalConfigurations("");
     173            2 :   auto wildcardResults = ifc.findAllGlobalConfigurations("*");
     174              : 
     175            2 :   std::cout << "Step 1: Empty search returned " << emptyResults.size() << " results\n";
     176            2 :   std::cout << "Step 2: Wildcard search returned " << wildcardResults.size() << " results\n";
     177              : 
     178            2 :   if (emptyResults.size() == wildcardResults.size()) {
     179            2 :     std::cout << "  Behavior: Empty search = wildcard search\n";
     180            0 :   } else if (emptyResults.size() == 0) {
     181            0 :     std::cout << "  Behavior: Empty search returns no results\n";
     182              :   } else {
     183            0 :     std::cout << "  Behavior: Empty search is different from wildcard\n";
     184              :   }
     185              : 
     186            2 :   BOOST_CHECK(true);
     187            2 :   std::cout << "  Documented: Empty search behavior\n";
     188            2 : }
     189              : 
     190              : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1