LCOV - code coverage report
Current view: top level - /opt/artdaq/srcs/artdaq-database/test/CaseStudy/OtsDaqCPPInterface/test021 - MarkReadonlyExpanded_t.cc (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 99.3 % 152 151
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 (MarkReadonlyExpanded 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 MarkReadonlyExpandedTestData {
      17            2 :   MarkReadonlyExpandedTestData() {
      18            2 :     srand(time(nullptr));
      19            2 :     baseVersion = rand() % 99999 + 300000;
      20            2 :     std::cout << "=== MARK READONLY EXPANDED TEST SUITE ===\n";
      21            2 :     std::cout << "Base version: " << baseVersion << "\n\n";
      22            2 :   }
      23              : 
      24            2 :   ~MarkReadonlyExpandedTestData() { std::cout << "\n=== TEST SUITE COMPLETE ===\n"; }
      25              : 
      26              :   int baseVersion;
      27              : };
      28              : 
      29              : MarkReadonlyExpandedTestData fixture;
      30              : 
      31              : BOOST_AUTO_TEST_SUITE(mark_readonly_expanded_test)
      32              : 
      33            4 : BOOST_AUTO_TEST_CASE(mark_readonly_on_existing_version_succeeds) {
      34            2 :   std::cout << "\n=== TEST 1: Mark readonly on existing version 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\": \"test_data\"}");
      42              : 
      43            2 :   std::cout << "Step 1: Creating version " << testVersion << "\n";
      44            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg.get(), false), 0);
      45              : 
      46            2 :   std::cout << "Step 2: Marking version as read-only\n";
      47            2 :   auto markResult = ifc.markActiveVersionReadonly(cfg.get());
      48            2 :   std::cout << "  markActiveVersionReadonly returned: " << markResult << "\n";
      49              : 
      50            2 :   BOOST_CHECK_EQUAL(markResult, 0);
      51            2 :   std::cout << "  Verified: markVersionReadonly succeeds on existing version\n";
      52            2 : }
      53              : 
      54            4 : BOOST_AUTO_TEST_CASE(mark_readonly_is_idempotent) {
      55            2 :   std::cout << "\n=== TEST 2: Mark readonly is idempotent ===\n";
      56              : 
      57            2 :   auto ifc = DatabaseConfigurationInterface();
      58              : 
      59            2 :   auto cfg = std::make_shared<TestConfiguration001>();
      60            2 :   int testVersion = fixture.baseVersion + 2;
      61            2 :   cfg->getView().version = testVersion;
      62            4 :   cfg->getView().fillFromJSON("{\"field\": \"idempotent_test\"}");
      63              : 
      64            2 :   std::cout << "Step 1: Creating version " << testVersion << "\n";
      65            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg.get(), false), 0);
      66              : 
      67            2 :   std::cout << "Step 2: Marking version as read-only (first time)\n";
      68            2 :   auto firstMark = ifc.markActiveVersionReadonly(cfg.get());
      69            2 :   std::cout << "  First mark returned: " << firstMark << "\n";
      70            2 :   BOOST_REQUIRE_EQUAL(firstMark, 0);
      71              : 
      72            2 :   std::cout << "Step 3: Marking version as read-only (second time)\n";
      73            2 :   auto secondMark = ifc.markActiveVersionReadonly(cfg.get());
      74            2 :   std::cout << "  Second mark returned: " << secondMark << "\n";
      75              : 
      76            2 :   BOOST_CHECK_EQUAL(secondMark, 0);
      77            2 :   std::cout << "  Verified: Marking read-only twice succeeds (idempotent)\n";
      78            2 : }
      79              : 
      80            4 : BOOST_AUTO_TEST_CASE(readonly_version_can_be_loaded) {
      81            2 :   std::cout << "\n=== TEST 3: Read-only version can still be loaded ===\n";
      82              : 
      83            2 :   auto ifc = DatabaseConfigurationInterface();
      84              : 
      85            2 :   auto cfg = std::make_shared<TestConfiguration001>();
      86            2 :   int testVersion = fixture.baseVersion + 3;
      87            2 :   cfg->getView().version = testVersion;
      88            4 :   cfg->getView().fillFromJSON("{\"field\": \"loadable_readonly\"}");
      89              : 
      90            2 :   std::cout << "Step 1: Creating version " << testVersion << "\n";
      91            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg.get(), false), 0);
      92              : 
      93            2 :   std::cout << "Step 2: Marking version as read-only\n";
      94            2 :   BOOST_REQUIRE_EQUAL(ifc.markActiveVersionReadonly(cfg.get()), 0);
      95              : 
      96            2 :   std::cout << "Step 3: Loading the read-only version\n";
      97            2 :   auto loaded = std::make_shared<TestConfiguration001>();
      98            2 :   auto loadResult = ifc.fill(loaded.get(), testVersion);
      99            2 :   std::cout << "  fill() returned: " << loadResult << "\n";
     100              : 
     101            2 :   BOOST_REQUIRE_EQUAL(loadResult, 0);
     102              : 
     103            2 :   std::stringstream ss;
     104            2 :   loaded->getView().printJSON(ss);
     105            2 :   std::string loadedJson = ss.str();
     106            2 :   std::cout << "  Loaded content: " << loadedJson << "\n";
     107              : 
     108            2 :   BOOST_CHECK(loadedJson.find("loadable_readonly") != std::string::npos);
     109            2 :   std::cout << "  Verified: Read-only version can still be loaded and content is correct\n";
     110            2 : }
     111              : 
     112            4 : BOOST_AUTO_TEST_CASE(readonly_version_appears_in_version_list) {
     113            2 :   std::cout << "\n=== TEST 4: Read-only version appears in getVersions ===\n";
     114              : 
     115            2 :   auto ifc = DatabaseConfigurationInterface();
     116              : 
     117            2 :   auto cfg = std::make_shared<TestConfiguration001>();
     118            2 :   int testVersion = fixture.baseVersion + 4;
     119            2 :   cfg->getView().version = testVersion;
     120            4 :   cfg->getView().fillFromJSON("{\"field\": \"version_list_test\"}");
     121              : 
     122            2 :   std::cout << "Step 1: Creating version " << testVersion << "\n";
     123            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg.get(), false), 0);
     124              : 
     125            2 :   std::cout << "Step 2: Verifying version appears in list before marking readonly\n";
     126            2 :   auto versionsBefore = ifc.getVersions(cfg.get());
     127            2 :   bool foundBefore = versionsBefore.find(testVersion) != versionsBefore.end();
     128            2 :   std::cout << "  Version " << testVersion << " in list before: " << (foundBefore ? "YES" : "NO") << "\n";
     129            2 :   BOOST_REQUIRE(foundBefore);
     130              : 
     131            2 :   std::cout << "Step 3: Marking version as read-only\n";
     132            2 :   BOOST_REQUIRE_EQUAL(ifc.markActiveVersionReadonly(cfg.get()), 0);
     133              : 
     134            2 :   std::cout << "Step 4: Verifying version still appears in list after marking readonly\n";
     135            2 :   auto versionsAfter = ifc.getVersions(cfg.get());
     136            2 :   bool foundAfter = versionsAfter.find(testVersion) != versionsAfter.end();
     137            2 :   std::cout << "  Version " << testVersion << " in list after: " << (foundAfter ? "YES" : "NO") << "\n";
     138              : 
     139            2 :   BOOST_CHECK(foundAfter);
     140            2 :   std::cout << "  Verified: Read-only version still appears in version listing\n";
     141            2 : }
     142              : 
     143            4 : BOOST_AUTO_TEST_CASE(readonly_blocks_overwrite) {
     144            2 :   std::cout << "\n=== TEST 5: Read-only blocks overwrite ===\n";
     145              : 
     146            2 :   auto ifc = DatabaseConfigurationInterface();
     147              : 
     148            2 :   auto cfg = std::make_shared<TestConfiguration001>();
     149            2 :   int testVersion = fixture.baseVersion + 5;
     150            2 :   cfg->getView().version = testVersion;
     151            4 :   cfg->getView().fillFromJSON("{\"field\": \"original_content\"}");
     152              : 
     153            2 :   std::cout << "Step 1: Creating version " << testVersion << "\n";
     154            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg.get(), false), 0);
     155              : 
     156            2 :   std::cout << "Step 2: Marking version as read-only\n";
     157            2 :   BOOST_REQUIRE_EQUAL(ifc.markActiveVersionReadonly(cfg.get()), 0);
     158              : 
     159            2 :   std::cout << "Step 3: Attempting to overwrite read-only version\n";
     160            4 :   cfg->getView().fillFromJSON("{\"field\": \"modified_content\"}");
     161            2 :   auto overwriteResult = ifc.saveActiveVersion(cfg.get(), true);
     162            2 :   std::cout << "  Overwrite returned: " << overwriteResult << "\n";
     163              : 
     164            2 :   if (overwriteResult != 0) {
     165            0 :     std::cout << "  Verified: Read-only version correctly blocks overwrite\n";
     166              :   } else {
     167            2 :     std::cout << "  Observation: Read-only version allowed overwrite (may be implementation choice)\n";
     168              :   }
     169              : 
     170            2 :   auto loaded = std::make_shared<TestConfiguration001>();
     171            2 :   ifc.fill(loaded.get(), testVersion);
     172            2 :   std::stringstream ss;
     173            2 :   loaded->getView().printJSON(ss);
     174            2 :   std::cout << "  Final content: " << ss.str() << "\n";
     175              : 
     176            2 :   BOOST_CHECK(true);
     177            2 : }
     178              : 
     179            4 : BOOST_AUTO_TEST_CASE(readonly_blocks_store_same_version) {
     180            2 :   std::cout << "\n=== TEST 6: Read-only blocks storing same version ===\n";
     181              : 
     182            2 :   auto ifc = DatabaseConfigurationInterface();
     183              : 
     184            2 :   auto cfg = std::make_shared<TestConfiguration001>();
     185            2 :   int testVersion = fixture.baseVersion + 6;
     186            2 :   cfg->getView().version = testVersion;
     187            4 :   cfg->getView().fillFromJSON("{\"field\": \"readonly_store_test\"}");
     188              : 
     189            2 :   std::cout << "Step 1: Creating version " << testVersion << "\n";
     190            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg.get(), false), 0);
     191              : 
     192            2 :   std::cout << "Step 2: Marking version as read-only\n";
     193            2 :   BOOST_REQUIRE_EQUAL(ifc.markActiveVersionReadonly(cfg.get()), 0);
     194              : 
     195            2 :   std::cout << "Step 3: Attempting to store same version again (not overwrite)\n";
     196            4 :   cfg->getView().fillFromJSON("{\"field\": \"new_content\"}");
     197            2 :   auto storeResult = ifc.saveActiveVersion(cfg.get(), false);
     198            2 :   std::cout << "  Store same version returned: " << storeResult << "\n";
     199              : 
     200            2 :   BOOST_CHECK_NE(storeResult, 0);
     201            2 :   std::cout << "  Verified: Cannot store duplicate version (readonly or not)\n";
     202            2 : }
     203              : 
     204            4 : BOOST_AUTO_TEST_CASE(mark_readonly_different_config_types) {
     205            2 :   std::cout << "\n=== TEST 7: Mark readonly on different config types ===\n";
     206              : 
     207            2 :   auto ifc = DatabaseConfigurationInterface();
     208              : 
     209            2 :   int testVersion = fixture.baseVersion + 7;
     210              : 
     211            2 :   auto cfg1 = std::make_shared<TestConfiguration001>();
     212            2 :   cfg1->getView().version = testVersion;
     213            4 :   cfg1->getView().fillFromJSON("{\"type\": \"config1\"}");
     214              : 
     215            2 :   auto cfg2 = std::make_shared<TestConfiguration002>();
     216            2 :   cfg2->getView().version = testVersion;
     217            4 :   cfg2->getView().fillFromJSON("{\"type\": \"config2\"}");
     218              : 
     219            2 :   std::cout << "Step 1: Creating both config types with version " << testVersion << "\n";
     220            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg1.get(), false), 0);
     221            2 :   BOOST_REQUIRE_EQUAL(ifc.saveActiveVersion(cfg2.get(), false), 0);
     222              : 
     223            2 :   std::cout << "Step 2: Marking TestConfiguration001 as read-only\n";
     224            2 :   BOOST_REQUIRE_EQUAL(ifc.markActiveVersionReadonly(cfg1.get()), 0);
     225              : 
     226            2 :   std::cout << "Step 3: Verifying TestConfiguration002 can still be overwritten\n";
     227            4 :   cfg2->getView().fillFromJSON("{\"type\": \"config2_updated\"}");
     228            2 :   auto overwriteResult = ifc.saveActiveVersion(cfg2.get(), true);
     229            2 :   std::cout << "  Overwrite cfg2 returned: " << overwriteResult << "\n";
     230              : 
     231            2 :   BOOST_CHECK_EQUAL(overwriteResult, 0);
     232            2 :   std::cout << "  Verified: Marking one config type readonly doesn't affect other types\n";
     233            2 : }
     234              : 
     235              : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1