#include "IR_config.h" #include "RingBuffer.h" #include #include #include #include // Test-only visibility: exercise the private reason enum and logging bound without // widening the production API. Dependencies are included first so this macro // cannot rewrite access specifiers in the standard library. #define private public #include "IR_DecoderRaw.h" #undef private namespace { constexpr const char kZeroStats[] = "RXSTAT,MUTEB=0,MUTEE=0,QRAW=0,QFLT=0,HOLD=0,GLITCH=0,TIME=0," "PREAMB=0,SYNC=0,BUF=0,TIMEOUT=0,CRC=0,OK=0\n"; constexpr const char kOneEachStats[] = "RXSTAT,MUTEB=1,MUTEE=1,QRAW=1,QFLT=1,HOLD=1,GLITCH=1,TIME=1," "PREAMB=1,SYNC=1,BUF=1,TIMEOUT=1,CRC=1,OK=1\n"; static_assert(IR_DecoderRaw::rxReasonCounterCount() > 0U, "RX reason counter storage must not be empty"); static_assert(IR_DecoderRaw::rxReasonCounterCount() == static_cast(IR_DecoderRaw::RxBriefReason::Count), "public RX reason count must follow the enum sentinel"); static_assert(static_cast(IR_DecoderRaw::RxBriefReason::Count) == static_cast(IR_DecoderRaw::RxBriefReason::Ok) + 1U, "RX reason Count must remain one past the final reason"); static_assert(std::extent::value == IR_DecoderRaw::rxReasonCounterCount(), "RX reason counter array must follow the enum-derived count"); void testStatsWireFormatAndClearCoverage() { IR_DecoderRaw decoder(0U, 0U); Print out; decoder.printRxReasonStats(out); assert(out.str() == kZeroStats); const uint8_t first = static_cast(IR_DecoderRaw::RxBriefReason::MuteBegin); const uint8_t count = IR_DecoderRaw::rxReasonCounterCount(); for (uint8_t i = first; i < count; ++i) decoder.rxBriefLog(static_cast(i)); // The sentinel is a bound, not a loggable reason. decoder.rxBriefLog(IR_DecoderRaw::RxBriefReason::Count); const uint16_t *const counters = decoder.rxReasonCounters(); assert(counters[0] == 0U); for (uint8_t i = first; i < count; ++i) assert(counters[i] == 1U); out.clear(); decoder.printRxReasonStats(out); assert(out.str() == kOneEachStats); decoder.rxReasonCountersClear(); for (uint8_t i = 0U; i < count; ++i) assert(counters[i] == 0U); out.clear(); decoder.printRxReasonStats(out); assert(out.str() == kZeroStats); } } // namespace int main() { testStatsWireFormatAndClearCoverage(); std::cout << "RX reason counter/tag contract tests: OK\n"; return 0; }