LCOV - code coverage report
Current view: top level - mu2e-pcie-utils/dtcInterfaceLib/test - evbErrorStatusTest.cc (source / functions) Coverage Total Hit
Test: mu2edaq.info.cleaned Lines: 38.0 % 79 30
Test Date: 2026-10-29 01:38:59 Functions: 100.0 % 3 3

            Line data    Source code
       1              : #include "dtcInterfaceLib/EVBErrorStatus.h"
       2              : 
       3              : #include <array>
       4              : #include <iostream>
       5              : #include <stdexcept>
       6              : 
       7              : namespace {
       8          893 : void require(bool condition, const std::string& message)
       9              : {
      10          893 :         if (!condition)
      11            1 :                 throw std::runtime_error(message);
      12          892 : }
      13              : 
      14          864 : std::string bitLine(const std::vector<std::string>& lines, unsigned bit)
      15              : {
      16          864 :         const std::string prefix = "  Bit " + std::to_string(bit) + " set: ";
      17         3413 :         for (const auto& line : lines)
      18         2576 :                 if (line.compare(0, prefix.size(), prefix) == 0)
      19           27 :                         return line;
      20          837 :         return {};
      21          864 : }
      22              : }  // namespace
      23              : 
      24            1 : int main()
      25              : try
      26              : {
      27            1 :         const std::array<const char*, 32> names = {{
      28              :                 "write-while-full",
      29              :                 "sequence gap",
      30              :                 "valid EVB frame rejected",
      31              :                 "DDR write CDC FIFO empty",
      32              :                 "undefined TX state",
      33              :                 "sent/drained counters disagree",
      34              :                 "local stream misaligned",
      35              :                 "stats pipeline collision",
      36              :                 "DDR read desync",
      37              :                 "staging FIFO write-while-full",
      38              :                 "staging FIFO empty inside TX payload",
      39              :                 "TX frame malformed",
      40              :                 "Rx frame had fewer/more data words than its header declared",
      41              :                 "Rx FCS bad",
      42              :                 "ROC tag slip",
      43              :                 "ROC record shape",
      44              :                 "ROC input held",
      45              :                 "self-subevent throttle",
      46              :                 "destination has no credit",
      47              :                 "DDR channel almost-full",
      48              :                 "DDR write CDC FIFO full",
      49              :                 "both staging FIFOs owned",
      50              :                 "Rx source buffer",
      51              :                 "DMA back-pressure",
      52              :                 "peer frontier known",
      53              :                 "DDR calibration complete",
      54              :                 "frame not for this DTC",
      55              :                 nullptr,
      56              :                 nullptr,
      57              :                 nullptr,
      58              :                 nullptr,
      59              :                 nullptr,
      60              :         }};
      61            1 :         require(DTCLib::DecodeEVBErrorStatus(0).size() == 2, "Zero value must hide all bit details");
      62           56 :         for (unsigned bit = 0; bit < names.size(); ++bit)
      63              :         {
      64           28 :                 const auto lines = DTCLib::DecodeEVBErrorStatus(uint32_t{1} << bit);
      65           28 :                 require(lines.size() == (names[bit] ? 3u : 2u),
      66           58 :                                 "Unexpected detail count for bit " + std::to_string(bit));
      67         1782 :                 for (unsigned other = 0; other < names.size(); ++other)
      68              :                 {
      69          864 :                         const auto line = bitLine(lines, other);
      70          864 :                         if (other == bit && names[bit])
      71           27 :                                 require(line.find(names[bit]) != std::string::npos,
      72           54 :                                                 "Wrong decode for bit " + std::to_string(bit));
      73              :                         else
      74         1674 :                                 require(line.empty(), "Displayed an unset or reserved bit");
      75          864 :                 }
      76           28 :         }
      77              : 
      78            0 :         const auto mixed = DTCLib::DecodeEVBErrorStatus(0x040007C4u);
      79            0 :         require(mixed.front().find("0x07c4") != std::string::npos, "Wrong sticky error mask");
      80            0 :         require(bitLine(mixed, 2).find("valid EVB frame rejected") != std::string::npos,
      81              :                         "Bit 2 must describe rejected EVB frames");
      82            0 :         require(bitLine(mixed, 6).find("not dropped") != std::string::npos,
      83              :                         "Bit 6 must describe forwarding, not loss at the buffer manager");
      84            0 :         require(bitLine(mixed, 7).find("data intact") != std::string::npos,
      85              :                         "Bit 7 must distinguish stats corruption from data loss");
      86            0 :         require(bitLine(mixed, 26).find("sticky since SoftReset, informational") != std::string::npos,
      87              :                         "Bit 26 must be sticky informational");
      88            0 :         const auto foreignOnly = DTCLib::DecodeEVBErrorStatus(1u << 26);
      89            0 :         require(foreignOnly.front().find("0x0000") != std::string::npos,
      90              :                         "Foreign frames must not set the error field");
      91            0 :         require(foreignOnly[1].find("bit 26 sticky-informational, others live") != std::string::npos,
      92              :                         "Status heading must describe the sticky exception");
      93            0 :         require(foreignOnly[1].find("0x0400") != std::string::npos, "Wrong status mask");
      94            0 :         const auto all = DTCLib::DecodeEVBErrorStatus(0xFFFFFFFFu);
      95            0 :         require(all.size() == 29, "All bits must display only the 27 defined details and two headings");
      96            0 :         require(all.front().find("0xffff") != std::string::npos, "Raw error field must show all 16 bits");
      97            0 :         require(bitLine(all, 4).find("TX window overrun") != std::string::npos,
      98              :                         "Bit 4 must include the 2026-09-19 window-overrun meaning");
      99            0 :         require(bitLine(all, 14).find("upstream") != std::string::npos,
     100              :                         "Bit 14 must say the slip originated upstream of EVB3");
     101            0 :         require(bitLine(all, 2).find("addressed to this DTC but source offset > 31") != std::string::npos,
     102              :                         "Bit 2 must exclude foreign frames");
     103            0 :         require(bitLine(all, 7).find("bit 1 and Rx BRAM rows/rates untrustworthy") != std::string::npos,
     104              :                         "Bit 7 must qualify sequence-gap and Rx statistics");
     105            0 :         require(bitLine(all, 12).find("receiver-side print of a peer's bit 9") != std::string::npos,
     106              :                         "Bit 12 must identify itself as the receiver-side view of a peer's staging-FIFO fault (hw agent 2026-10-16)");
     107            0 :         require(bitLine(all, 13).find("shifted 0x33 frames not checked") != std::string::npos,
     108              :                         "FCS checking must not be claimed for shifted frames");
     109              : 
     110            0 :         constexpr uint32_t calibrated = 1u << 25;
     111            0 :         require(!DTCLib::CheckEVBStatus(0).readyToStart(), "Missing DDR calibration must block start");
     112            0 :         require(DTCLib::CheckEVBStatus(calibrated).readyToStart(), "Calibrated idle DTC must be ready");
     113            0 :         for (unsigned bit = 0; bit < 32; ++bit)
     114              :         {
     115            0 :                 const auto check = DTCLib::CheckEVBStatus(calibrated | (1u << bit));
     116            0 :                 require(check.stickyErrors == (bit < 16 ? (1u << bit) : 0u),
     117            0 :                                 "Wrong defined error mask for bit " + std::to_string(bit));
     118            0 :                 require(check.readyToStart() == (bit >= 16),
     119              :                                 "Only defined sticky errors should block a calibrated DTC");
     120              :         }
     121            0 :         require(!DTCLib::CheckEVBStatus(calibrated, false).missingFrontier,
     122              :                         "No frontier warning before traffic");
     123            0 :         require(DTCLib::CheckEVBStatus(calibrated, true).missingFrontier,
     124              :                         "Missing frontier after traffic must warn");
     125            0 :         require(!DTCLib::CheckEVBStatus(calibrated | (1u << 24), true).missingFrontier,
     126              :                         "Valid frontier must not warn");
     127            0 :         require(!DTCLib::CheckEVBStatus(calibrated, true, false).missingFrontier,
     128              :                         "Single-node partition has no peer frontier requirement");
     129            0 :         const auto report = DTCLib::FormatEVBStatusCheck(calibrated | 0xFFFFu, "DTC_1", true);
     130            0 :         require(report.find("DTC DTC_1 EVB error/status (0x9370): 0x0200ffff") != std::string::npos,
     131              :                         "Report must identify the DTC and exact raw snapshot");
     132            0 :         require(report.find("ROC input (upstream of EVB3)") == std::string::npos,
     133              :                         "Bits 14-15 belong in the data-corrupt group, not a separate one");
     134            0 :         require(report.find("ERROR: run INVALID") != std::string::npos, "Errors must invalidate run");
     135            0 :         require(report.find("Data lost: Bit 0 RX_BUF_WRITE_FULL; Bit 1 RX_SEQ_GAP; Bit 9 STAGING_WRITE_FULL; Bit 12 RX_FRAME_SIZE;") != std::string::npos,
     136              :                         "Wrong data-loss group");
     137            0 :         require(report.find("Data corrupt: Bit 3 DDR_WR_UNDERFLOW; Bit 6 LOCAL_BAD_HEADER; Bit 8 DDR_RD_BAD_COUNT; Bit 10 TX_PAYLOAD_UNDERFLOW; Bit 11 TX_FRAME_MALFORMED; Bit 13 RX_FCS_BAD; Bit 14 ROC_TAG_SLIP; Bit 15 ROC_RECORD_SHAPE;") != std::string::npos,
     138              :                         "Wrong data-corruption group");
     139            0 :         require(report.find("Protocol / config: Bit 2 RX_PKT_REJECTED; Bit 4 TX_FSM_FAULT; Bit 5 CREDIT_VIOLATION; Bit 7 RX_STATS_COLLISION;") != std::string::npos,
     140              :                         "Wrong protocol/config group");
     141            0 :         require(report.find("SoftReset all DTCs together") != std::string::npos,
     142              :                         "Report must require coordinated reset");
     143            0 :         const auto informational = DTCLib::FormatEVBStatusCheck(0x07FF0000u, "DTC_0", true);
     144            0 :         require(informational.find("ERROR:") == std::string::npos,
     145              :                         "Back-pressure and foreign frames must never invalidate a run");
     146            0 :         const auto plain = DTCLib::FormatEVBStatusCheck(calibrated | (1u << 11), "DTC_0", false, true, false);
     147            0 :         require(plain.find("TX_FRAME_MALFORMED") == std::string::npos &&
     148            0 :                                 plain.find("Bit 11 set: TX frame malformed") != std::string::npos,
     149              :                         "GUI mode must retain plain-language descriptions without symbolic names");
     150            0 :         const auto noDDR = DTCLib::FormatEVBStatusCheck(0, "DTC_0");
     151            0 :         require(noDDR.find("DDR not calibrated; do not start") != std::string::npos,
     152              :                         "Missing calibration must be explicit");
     153              : 
     154            0 :         std::cout << "EVB error/status decoding and B3 checks passed\n";
     155            0 :         return 0;
     156            0 : }
     157            1 : catch (const std::exception& error)
     158              : {
     159            1 :         std::cerr << error.what() << '\n';
     160            1 :         return 1;
     161            1 : }
        

Generated by: LCOV version 2.0-1