LCOV - code coverage report
Current view: top level - /opt/artdaq/srcs/artdaq-database/test/CaseStudy/OtsDaqCPPInterface/test019 - OverwriteVersion_t.cc (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 97.4 % 195 190
Test Date: 2026-10-29 00:35:58 Functions: 100.0 % 16 16

            Line data    Source code
       1              : #define BOOST_TEST_DYN_LINK
       2              : #define BOOST_TEST_MODULE (OverwriteVersion 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              : 
      12              : #include "../DatabaseConfigurationInterface.h"
      13              : 
      14              : using namespace ots;
      15              : 
      16              : struct OverwriteVersionTestData {
      17            2 :   OverwriteVersionTestData() {
      18            2 :     srand(time(nullptr));
      19            2 :     baseVersion = rand() % 99999 + 100000;
      20            2 :     std::cout << "=== OVERWRITE VERSION TEST SUITE ===\n";
      21            2 :     std::cout << "Base version: " << baseVersion << "\n\n";
      22            2 :   }
      23              : 
      24            2 :   ~OverwriteVersionTestData() { std::cout << "\n=== TEST SUITE COMPLETE ===\n"; }
      25              : 
      26              :   int baseVersion;
      27              : };
      28              : 
      29              : OverwriteVersionTestData fixture;
      30              : 
      31              : BOOST_AUTO_TEST_SUITE(overwrite_version_test)
      32              : 
      33            4 : BOOST_AUTO_TEST_CASE(basic_overwrite_succeeds) {
      34            2 :   std::cout << "\n=== TEST 1: Basic overwrite succeeds ===\n";
      35              : 
      36            2 :   auto ifc = DatabaseConfigurationInterface();
      37              : 
      38            2 :   auto cfg = std::make_shared<TestConfiguration001>();
      39            2 :   int testVersion = fixture.baseVersion + 1;
      40            2 :   cfg->getView().version = testVersion;
      41            4 :   cfg->getView().fillFromJSON("{\"field\": \"initial_value\"}");
      42              : 
      43            2 :   std::cout << "Step 1: Creating initial version " << testVersion << " with 'initial_value'\n";
      44            2 :   auto createResult = ifc.saveActiveVersion(cfg.get(), false);
      45            2 :   BOOST_REQUIRE_EQUAL(createResult, 0);
      46            2 :   std::cout << "  Initial version created successfully\n";
      47              : 
      48            2 :   std::cout << "Step 2: Overwriting with 'updated_value'\n";
      49            4 :   cfg->getView().fillFromJSON("{\"field\": \"updated_value\"}");
      50            2 :   auto overwriteResult = ifc.saveActiveVersion(cfg.get(), true);
      51            2 :   BOOST_REQUIRE_EQUAL(overwriteResult, 0);
      52            2 :   std::cout << "  Overwrite completed successfully\n";
      53              : 
      54            2 :   std::cout << "Step 3: Loading version and verifying content\n";
      55            2 :   auto loaded = std::make_shared<TestConfiguration001>();
      56            2 :   auto loadResult = ifc.fill(loaded.get(), testVersion);
      57            2 :   BOOST_REQUIRE_EQUAL(loadResult, 0);
      58              : 
      59            2 :   std::stringstream ss;
      60            2 :   loaded->getView().printJSON(ss);
      61            2 :   std::string loadedJson = ss.str();
      62            2 :   std::cout << "  Loaded content: " << loadedJson << "\n";
      63              : 
      64            2 :   BOOST_CHECK(loadedJson.find("updated_value") != std::string::npos);
      65            2 :   std::cout << "  Verified: Content was updated to 'updated_value'\n";
      66            2 : }
      67              : 
      68            4 : BOOST_AUTO_TEST_CASE(overwrite_nonexistent_behavior) {
      69            2 :   std::cout << "\n=== TEST 2: Overwrite non-existent version behavior ===\n";
      70              : 
      71            2 :   auto ifc = DatabaseConfigurationInterface();
      72              : 
      73            2 :   auto cfg = std::make_shared<TestConfiguration001>();
      74            2 :   cfg->getView().version = 999999997;
      75            4 :   cfg->getView().fillFromJSON("{\"field\": \"value\"}");
      76              : 
      77            2 :   std::cout << "Step 1: Attempting to overwrite non-existent version 999999997\n";
      78            2 :   auto overwriteResult = ifc.saveActiveVersion(cfg.get(), true);
      79            2 :   std::cout << "  Overwrite returned: " << overwriteResult << "\n";
      80              : 
      81            2 :   if (overwriteResult == 0) {
      82            1 :     std::cout << "  Observation: Overwrite on non-existent version SUCCEEDED (upsert behavior)\n";
      83            1 :     auto versions = ifc.getVersions(cfg.get());
      84            1 :     bool found = versions.find(999999997) != versions.end();
      85            1 :     std::cout << "  Version 999999997 exists after overwrite: " << (found ? "yes" : "no") << "\n";
      86            1 :     BOOST_CHECK(found);
      87            1 :   } else {
      88            1 :     std::cout << "  Observation: Overwrite on non-existent version FAILED as expected\n";
      89            1 :     BOOST_CHECK(true);
      90              :   }
      91            2 : }
      92              : 
      93            4 : BOOST_AUTO_TEST_CASE(overwrite_preserves_version_number) {
      94            2 :   std::cout << "\n=== TEST 3: Overwrite preserves version number ===\n";
      95              : 
      96            2 :   auto ifc = DatabaseConfigurationInterface();
      97              : 
      98            2 :   auto cfg = std::make_shared<TestConfiguration001>();
      99            2 :   int testVersion = fixture.baseVersion + 2;
     100            2 :   cfg->getView().version = testVersion;
     101            4 :   cfg->getView().fillFromJSON("{\"field\": \"original\"}");
     102              : 
     103            2 :   std::cout << "Step 1: Creating version " << testVersion << "\n";
     104            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg.get(), false), 0);
     105              : 
     106            2 :   std::cout << "Step 2: Getting versions before overwrite\n";
     107            2 :   auto versionsBefore = ifc.getVersions(cfg.get());
     108            2 :   std::cout << "  Versions count before: " << versionsBefore.size() << "\n";
     109            2 :   BOOST_REQUIRE(versionsBefore.find(testVersion) != versionsBefore.end());
     110              : 
     111            2 :   std::cout << "Step 3: Overwriting version " << testVersion << "\n";
     112            6 :   cfg->getView().fillFromJSON("{\"field\": \"overwritten\"}");
     113            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg.get(), true), 0);
     114              : 
     115            2 :   std::cout << "Step 4: Getting versions after overwrite\n";
     116            2 :   auto versionsAfter = ifc.getVersions(cfg.get());
     117            2 :   std::cout << "  Versions count after: " << versionsAfter.size() << "\n";
     118              : 
     119            2 :   BOOST_CHECK_EQUAL(versionsBefore.size(), versionsAfter.size());
     120            2 :   BOOST_CHECK(versionsAfter.find(testVersion) != versionsAfter.end());
     121            2 :   std::cout << "  Verified: No new version was created, version " << testVersion << " still exists\n";
     122            2 : }
     123              : 
     124            4 : BOOST_AUTO_TEST_CASE(overwrite_readonly_behavior) {
     125            2 :   std::cout << "\n=== TEST 4: Overwrite read-only version behavior ===\n";
     126              : 
     127            2 :   auto ifc = DatabaseConfigurationInterface();
     128              : 
     129            2 :   auto cfg = std::make_shared<TestConfiguration001>();
     130            2 :   int testVersion = fixture.baseVersion + 3;
     131            2 :   cfg->getView().version = testVersion;
     132            4 :   cfg->getView().fillFromJSON("{\"field\": \"readonly_test\"}");
     133              : 
     134            2 :   std::cout << "Step 1: Creating version " << testVersion << "\n";
     135            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg.get(), false), 0);
     136              : 
     137            2 :   std::cout << "Step 2: Attempting to mark version as read-only\n";
     138            2 :   auto markResult = ifc.markActiveVersionReadonly(cfg.get());
     139            2 :   std::cout << "  markActiveVersionReadonly returned: " << markResult << "\n";
     140              : 
     141            2 :   if (markResult != 0) {
     142            0 :     std::cout << "  Observation: markVersionReadonly returned error for existing version\n";
     143            0 :     std::cout << "  SKIPPING overwrite test - cannot verify readonly protection\n";
     144            0 :     BOOST_CHECK(true);
     145            0 :     return;
     146              :   }
     147              : 
     148            2 :   std::cout << "  Version marked read-only successfully\n";
     149              : 
     150            2 :   std::cout << "Step 3: Attempting to overwrite read-only version\n";
     151            4 :   cfg->getView().fillFromJSON("{\"field\": \"should_fail\"}");
     152            2 :   auto overwriteResult = ifc.saveActiveVersion(cfg.get(), true);
     153            2 :   std::cout << "  Overwrite returned: " << overwriteResult << "\n";
     154              : 
     155            2 :   if (overwriteResult != 0) {
     156            0 :     std::cout << "  Verified: Overwrite of read-only version correctly rejected\n";
     157              :   } else {
     158            2 :     std::cout << "  Observation: Overwrite of read-only version was ALLOWED\n";
     159              :   }
     160            2 :   BOOST_CHECK(true);
     161            2 : }
     162              : 
     163            4 : BOOST_AUTO_TEST_CASE(multiple_overwrites_work) {
     164            2 :   std::cout << "\n=== TEST 5: Multiple overwrites work correctly ===\n";
     165              : 
     166            2 :   auto ifc = DatabaseConfigurationInterface();
     167              : 
     168            2 :   auto cfg = std::make_shared<TestConfiguration001>();
     169            2 :   int testVersion = fixture.baseVersion + 4;
     170            2 :   cfg->getView().version = testVersion;
     171            4 :   cfg->getView().fillFromJSON("{\"counter\": 0}");
     172              : 
     173            2 :   std::cout << "Step 1: Creating initial version " << testVersion << " with counter=0\n";
     174            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg.get(), false), 0);
     175              : 
     176            8 :   for (int i = 1; i <= 3; ++i) {
     177            6 :     std::cout << "Step " << (i + 1) << ": Overwriting with counter=" << i << "\n";
     178            6 :     std::string newJson = "{\"counter\": " + std::to_string(i) + "}";
     179            6 :     cfg->getView().fillFromJSON(newJson);
     180            6 :     auto result = ifc.saveActiveVersion(cfg.get(), true);
     181            6 :     BOOST_REQUIRE_EQUAL(result, 0);
     182            6 :     std::cout << "  Overwrite " << i << " succeeded\n";
     183            6 :   }
     184              : 
     185            2 :   std::cout << "Step 5: Verifying final content\n";
     186            2 :   auto loaded = std::make_shared<TestConfiguration001>();
     187            2 :   BOOST_REQUIRE_EQUAL(ifc.fill(loaded.get(), testVersion), 0);
     188              : 
     189            2 :   std::stringstream ss;
     190            2 :   loaded->getView().printJSON(ss);
     191            2 :   std::string finalJson = ss.str();
     192            2 :   std::cout << "  Final content: " << finalJson << "\n";
     193              : 
     194            2 :   BOOST_CHECK(finalJson.find("3") != std::string::npos);
     195            2 :   std::cout << "  Verified: Final content has counter=3\n";
     196              : 
     197            2 :   std::cout << "Step 6: Verifying only one version exists\n";
     198            2 :   auto versions = ifc.getVersions(cfg.get());
     199            2 :   auto count = std::count(versions.begin(), versions.end(), testVersion);
     200            2 :   BOOST_CHECK_EQUAL(count, 1);
     201            2 :   std::cout << "  Verified: Version " << testVersion << " appears exactly once\n";
     202            2 : }
     203              : 
     204            4 : BOOST_AUTO_TEST_CASE(overwrite_does_not_create_new_version) {
     205            2 :   std::cout << "\n=== TEST 6: Overwrite does not create a new version ===\n";
     206              : 
     207            2 :   auto ifc = DatabaseConfigurationInterface();
     208              : 
     209            2 :   auto cfg = std::make_shared<TestConfiguration001>();
     210            2 :   int testVersion = fixture.baseVersion + 5;
     211            2 :   cfg->getView().version = testVersion;
     212            4 :   cfg->getView().fillFromJSON("{\"data\": \"test\"}");
     213              : 
     214            2 :   std::cout << "Step 1: Creating version " << testVersion << "\n";
     215            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg.get(), false), 0);
     216              : 
     217            2 :   std::cout << "Step 2: Recording version count before overwrite\n";
     218            2 :   auto versionsBefore = ifc.getVersions(cfg.get());
     219            2 :   size_t countBefore = versionsBefore.size();
     220            2 :   std::cout << "  Version count before: " << countBefore << "\n";
     221              : 
     222            2 :   std::cout << "Step 3: Performing 5 overwrites\n";
     223           12 :   for (int i = 0; i < 5; ++i) {
     224           10 :     cfg->getView().fillFromJSON("{\"data\": \"overwrite_" + std::to_string(i) + "\"}");
     225           10 :     BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg.get(), true), 0);
     226              :   }
     227            2 :   std::cout << "  5 overwrites completed\n";
     228              : 
     229            2 :   std::cout << "Step 4: Checking version count after overwrites\n";
     230            2 :   auto versionsAfter = ifc.getVersions(cfg.get());
     231            2 :   size_t countAfter = versionsAfter.size();
     232            2 :   std::cout << "  Version count after: " << countAfter << "\n";
     233              : 
     234            2 :   BOOST_CHECK_EQUAL(countBefore, countAfter);
     235            2 :   std::cout << "  Verified: No new versions were created during overwrites\n";
     236            2 : }
     237              : 
     238            4 : BOOST_AUTO_TEST_CASE(overwrite_different_config_types_independent) {
     239            2 :   std::cout << "\n=== TEST 7: Overwrite of different config types are independent ===\n";
     240              : 
     241            2 :   auto ifc = DatabaseConfigurationInterface();
     242              : 
     243            2 :   int testVersion = fixture.baseVersion + 6;
     244              : 
     245            2 :   auto cfg1 = std::make_shared<TestConfiguration001>();
     246            2 :   cfg1->getView().version = testVersion;
     247            4 :   cfg1->getView().fillFromJSON("{\"type\": \"config1_original\"}");
     248              : 
     249            2 :   auto cfg2 = std::make_shared<TestConfiguration002>();
     250            2 :   cfg2->getView().version = testVersion;
     251            4 :   cfg2->getView().fillFromJSON("{\"type\": \"config2_original\"}");
     252              : 
     253            2 :   std::cout << "Step 1: Creating both config types with version " << testVersion << "\n";
     254            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg1.get(), false), 0);
     255            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg2.get(), false), 0);
     256              : 
     257            2 :   std::cout << "Step 2: Overwriting only TestConfiguration001\n";
     258            6 :   cfg1->getView().fillFromJSON("{\"type\": \"config1_updated\"}");
     259            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg1.get(), true), 0);
     260              : 
     261            2 :   std::cout << "Step 3: Verifying TestConfiguration002 is unchanged\n";
     262            2 :   auto loaded2 = std::make_shared<TestConfiguration002>();
     263            2 :   BOOST_REQUIRE_EQUAL(ifc.fill(loaded2.get(), testVersion), 0);
     264              : 
     265            2 :   std::stringstream ss2;
     266            2 :   loaded2->getView().printJSON(ss2);
     267            2 :   std::string loaded2Json = ss2.str();
     268            2 :   std::cout << "  TestConfiguration002 content: " << loaded2Json << "\n";
     269              : 
     270            2 :   BOOST_CHECK(loaded2Json.find("config2_original") != std::string::npos);
     271            2 :   std::cout << "  Verified: TestConfiguration002 was not affected by TestConfiguration001 overwrite\n";
     272              : 
     273            2 :   std::cout << "Step 4: Verifying TestConfiguration001 was updated\n";
     274            2 :   auto loaded1 = std::make_shared<TestConfiguration001>();
     275            2 :   BOOST_REQUIRE_EQUAL(ifc.fill(loaded1.get(), testVersion), 0);
     276              : 
     277            2 :   std::stringstream ss1;
     278            2 :   loaded1->getView().printJSON(ss1);
     279            2 :   std::string loaded1Json = ss1.str();
     280            2 :   std::cout << "  TestConfiguration001 content: " << loaded1Json << "\n";
     281              : 
     282            2 :   BOOST_CHECK(loaded1Json.find("config1_updated") != std::string::npos);
     283            2 :   std::cout << "  Verified: TestConfiguration001 was correctly updated\n";
     284            2 : }
     285              : 
     286              : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1