LCOV - code coverage report
Current view: top level - /opt/artdaq/srcs/artdaq-database/test/CaseStudy/OtsDaqCPPInterface/test026 - StringLineRoundTrip_t.cc (source / functions) Coverage Total Hit
Test: artdaq.info.cleaned Lines: 88.6 % 88 78
Test Date: 2026-10-29 00:35:58 Functions: 100.0 % 10 10

            Line data    Source code
       1              : #define BOOST_TEST_DYN_LINK
       2              : #define BOOST_TEST_MODULE (StringLineRoundTrip test)
       3              : 
       4              : #include <algorithm>
       5              : #include <boost/test/unit_test.hpp>
       6              : #include <fstream>
       7              : #include <numeric>
       8              : #include <random>
       9              : 
      10              : #include "../DatabaseConfigurationInterface.h"
      11              : #include "artdaq-database/DataFormats/Fhicl/helper_functions.h"
      12              : #include "artdaq-database/JsonDocument/JSONDocument.h"
      13              : 
      14              : using namespace ots;
      15              : using artdaq::database::docrecord::JSONDocument;
      16              : using artdaq::database::fhicl::from_json_string;
      17              : using artdaq::database::fhicl::to_json_string;
      18              : 
      19              : namespace {
      20              : 
      21            4 : bool isQuickMode() {
      22            4 :   auto* q = getenv("QUICK_TEST");
      23           12 :   return q && (std::string(q) == "1" || std::string(q) == "true");
      24              : }
      25              : 
      26            2 : std::vector<std::string> loadLines(const std::string& filename) {
      27            2 :   std::vector<std::string> lines;
      28            2 :   std::ifstream file(filename);
      29            2 :   std::string line;
      30         3092 :   while (std::getline(file, line))
      31         3088 :     if (!line.empty()) lines.push_back(line);
      32            4 :   return lines;
      33            2 : }
      34              : 
      35          894 : std::string wrapInJson(const std::string& value) { return "{\"value\": \"" + to_json_string(value) + "\"}"; }
      36              : 
      37         1788 : std::string extractValue(const std::string& json) { return from_json_string(JSONDocument(json).findChild("value").value()); }
      38              : 
      39              : struct TestFixture {
      40            2 :   TestFixture() : baseVersion((srand(time(nullptr)), rand() % 99999 + 100000)) {
      41            2 :     lines = loadLines("test_cases.txt");
      42              : 
      43            2 :     if (isQuickMode() && lines.size() > 10) {
      44            2 :       std::vector<size_t> idx(lines.size());
      45            2 :       std::iota(idx.begin(), idx.end(), 0);
      46            2 :       std::shuffle(idx.begin(), idx.end(), std::mt19937{std::random_device{}()});
      47            2 :       idx.resize(lines.size() / 10);
      48            2 :       std::sort(idx.begin(), idx.end());
      49            2 :       std::vector<std::string> sampled;
      50          300 :       for (auto i : idx) sampled.push_back(lines[i]);
      51            2 :       lines = std::move(sampled);
      52            2 :     }
      53              : 
      54            2 :     std::cout << "Loaded " << lines.size() << " test lines" << (isQuickMode() ? " (QUICK MODE)" : "") << "\n";
      55            2 :   }
      56              : 
      57         1192 :   int nextVersion() { return baseVersion + (++versionOffset); }
      58              : 
      59              :   const int baseVersion;
      60              :   std::vector<std::string> lines;
      61              : 
      62              :  private:
      63              :   int versionOffset = 0;
      64              : };
      65              : 
      66              : }  // namespace
      67              : 
      68              : TestFixture fixture;
      69              : 
      70              : BOOST_AUTO_TEST_SUITE(string_line_roundtrip_test)
      71              : 
      72            4 : BOOST_AUTO_TEST_CASE(json_roundtrip_ast_comparison) {
      73            2 :   DatabaseConfigurationInterface ifc;
      74            2 :   int passed = 0, failed = 0;
      75              : 
      76          300 :   for (const auto& line : fixture.lines) {
      77          298 :     int version = fixture.nextVersion();
      78          298 :     std::string inputJson = wrapInJson(line);
      79              : 
      80          298 :     auto writer = std::make_shared<TestConfiguration001>();
      81          298 :     writer->getView().fillFromJSON(inputJson);
      82          298 :     writer->getView().version = version;
      83          298 :     if (ifc.saveActiveVersion(writer.get()) != 0) {
      84            0 :       failed++;
      85            0 :       continue;
      86              :     }
      87              : 
      88          298 :     auto reader = std::make_shared<TestConfiguration001>();
      89          298 :     if (ifc.fill(reader.get(), version) != 0) {
      90            0 :       failed++;
      91            0 :       continue;
      92              :     }
      93              : 
      94          298 :     std::string outputJson = reader->getView()._json;
      95          298 :     std::string extractedValue = extractValue(outputJson);
      96              : 
      97          298 :     bool astMatch = (JSONDocument(inputJson) == JSONDocument(outputJson));
      98          298 :     bool verbatimMatch = (extractedValue == line);
      99              : 
     100          298 :     if (astMatch && verbatimMatch) {
     101          298 :       passed++;
     102              :     } else {
     103            0 :       failed++;
     104            0 :       std::cout << "FAIL: " << line.substr(0, 50) << (line.size() > 50 ? "..." : "") << " [AST:" << (astMatch ? "OK" : "FAIL")
     105            0 :                 << " Verbatim:" << (verbatimMatch ? "OK" : "FAIL") << "]\n";
     106              :     }
     107          298 :   }
     108              : 
     109            2 :   std::cout << "Passed: " << passed << "/" << fixture.lines.size() << "\n";
     110            2 :   BOOST_CHECK_EQUAL(failed, 0);
     111            2 : }
     112              : 
     113            4 : BOOST_AUTO_TEST_CASE(multiple_roundtrips_stability) {
     114            2 :   DatabaseConfigurationInterface ifc;
     115            2 :   int stable = 0, unstable = 0;
     116              : 
     117          300 :   for (const auto& line : fixture.lines) {
     118          298 :     std::string current = wrapInJson(line);
     119          298 :     std::vector<std::string> reads;
     120              : 
     121         1192 :     for (int round = 0; round < 3; ++round) {
     122          894 :       int version = fixture.nextVersion();
     123          894 :       auto writer = std::make_shared<TestConfiguration001>();
     124          894 :       writer->getView().fillFromJSON(current);
     125          894 :       writer->getView().version = version;
     126          894 :       if (ifc.saveActiveVersion(writer.get()) != 0) break;
     127              : 
     128          894 :       auto reader = std::make_shared<TestConfiguration001>();
     129          894 :       if (ifc.fill(reader.get(), version) != 0) break;
     130          894 :       current = reader->getView()._json;
     131          894 :       reads.push_back(current);
     132          894 :     }
     133              : 
     134          298 :     if (reads.size() == 3) {
     135          298 :       JSONDocument d0(wrapInJson(line)), d1(reads[0]), d2(reads[1]), d3(reads[2]);
     136          298 :       bool astStable = (d0 == d1 && d1 == d2 && d2 == d3);
     137          298 :       bool verbatimMatch = (extractValue(reads[0]) == line);
     138              : 
     139          298 :       if (astStable && verbatimMatch) {
     140          298 :         stable++;
     141              :       } else {
     142            0 :         unstable++;
     143            0 :         std::cout << "UNSTABLE: " << line.substr(0, 40) << "..."
     144            0 :                   << " [AST:" << (astStable ? "OK" : "FAIL") << " Verbatim:" << (verbatimMatch ? "OK" : "FAIL") << "]\n";
     145              :       }
     146          298 :     }
     147          298 :   }
     148              : 
     149            2 :   std::cout << "Stable: " << stable << "/" << fixture.lines.size() << "\n";
     150            2 :   BOOST_CHECK_EQUAL(unstable, 0);
     151            2 : }
     152              : 
     153              : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1