GCC Code Coverage Report


Directory: /home/runner/work/fprime/fprime/Svc/ComStub/
File: ComStub.cpp
Date: 2026-09-23 22:12:53
Exec Total Coverage
Lines: 34 69 49.3%
Functions: 7 10 70.0%
Branches: 24 48 50.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title ComStub.cpp
3 // \author mstarch
4 // \brief cpp file for ComStub component implementation class
5 // ======================================================================
6
7 #include <Fw/Logger/Logger.hpp>
8 #include <Svc/ComStub/ComStub.hpp>
9 #include "Fw/Types/Assert.hpp"
10 #include "Fw/Types/BasicTypes.hpp"
11
12 namespace Svc {
13
14 // ----------------------------------------------------------------------
15 // Construction, initialization, and destruction
16 // ----------------------------------------------------------------------
17
18
1/1
✓ Branch 2 taken 1 times.
1 ComStub::ComStub(const char* const compName) : ComStubComponentBase(compName), m_reinitialize(true), m_retry_count(0) {}
19
20 2 ComStub::~ComStub() {}
21
22 // ----------------------------------------------------------------------
23 // Handler implementations for user-defined typed input ports
24 // ----------------------------------------------------------------------
25
26 239 void ComStub::dataIn_handler(const FwIndexType portNum, Fw::Buffer& sendBuffer, const ComCfg::FrameContext& context) {
27 // A message should never get here if we need to reinitialize
28 239 FW_ASSERT(!this->m_reinitialize || !this->isConnected_comStatusOut_OutputPort(0));
29
1/2
✓ Branch 1 taken 239 times.
✗ Branch 2 not taken.
239 if (this->isConnected_drvSendOut_OutputPort(0)) {
30 239 this->handleSynchronousSend(sendBuffer, context);
31 ✗ } else if (this->isConnected_drvAsyncSendOut_OutputPort(0)) {
32 ✗ this->handleAsynchronousSend(sendBuffer, context);
33 } else {
34 ✗ FW_ASSERT(false); // Neither send port is connected, this should never happen
35 }
36 239 }
37
38 1 void ComStub::drvConnected_handler(const FwIndexType portNum) {
39
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 if (this->isConnected_comStatusOut_OutputPort(0) && m_reinitialize) {
40
1/1
✓ Branch 1 taken 1 times.
1 Fw::Success radioSuccess = Fw::Success::SUCCESS;
41 1 this->m_reinitialize = false;
42
1/1
✓ Branch 1 taken 1 times.
1 this->comStatusOut_out(0, radioSuccess);
43 1 }
44 1 }
45
46 630 void ComStub::drvReceiveIn_handler(const FwIndexType portNum,
47 Fw::Buffer& recvBuffer,
48 const Drv::ByteStreamStatus& recvStatus) {
49
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 629 times.
630 if (recvStatus != Drv::ByteStreamStatus::OP_OK) {
50 // Receive failed - return buffer without processing
51 1 this->drvReceiveReturnOut_out(0, recvBuffer);
52 } else {
53 // Receive successful - forward data with empty context
54
1/1
✓ Branch 1 taken 629 times.
629 ComCfg::FrameContext emptyContext; // ComStub knows nothing about the received bytes, empty context
55
1/1
✓ Branch 1 taken 629 times.
629 this->dataOut_out(0, recvBuffer, emptyContext);
56 629 }
57 630 }
58
59 ✗ void ComStub::drvAsyncSendReturnIn_handler(FwIndexType portNum, //!< The port number
60 Fw::Buffer& fwBuffer, //!< The buffer
61 const Drv::ByteStreamStatus& sendStatus) {
62 // This should never be called if the drvAsyncSendOut port is not connected
63 ✗ FW_ASSERT(this->isConnected_drvAsyncSendOut_OutputPort(0));
64 ✗ if (sendStatus == Drv::ByteStreamStatus::SEND_RETRY) {
65 // Driver indicates we should retry
66 ✗ this->handleAsyncRetry(fwBuffer);
67 } else {
68 // Return buffer ownership and send status
69 ✗ this->dataReturnOut_out(0, fwBuffer, this->m_storedContext);
70 ✗ this->m_reinitialize = (sendStatus.e != Drv::ByteStreamStatus::OP_OK);
71 ✗ this->m_retry_count = 0; // Reset retry count
72 // Send Com status
73 Fw::Success comSuccess =
74 ✗ (sendStatus.e == Drv::ByteStreamStatus::OP_OK) ? Fw::Success::SUCCESS : Fw::Success::FAILURE;
75 ✗ this->comStatusOut_out(0, comSuccess);
76 ✗ }
77 ✗ }
78
79 629 void ComStub ::dataReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer, const ComCfg::FrameContext& context) {
80 629 this->drvReceiveReturnOut_out(0, fwBuffer);
81 629 }
82
83 // ----------------------------------------------------------------------
84 // Helper method implementations
85 // ----------------------------------------------------------------------
86
87 239 void ComStub::handleSynchronousSend(Fw::Buffer& sendBuffer, const ComCfg::FrameContext& context) {
88
1/1
✓ Branch 1 taken 239 times.
239 Drv::ByteStreamStatus sendStatus = Drv::ByteStreamStatus::SEND_RETRY;
89
1/1
✓ Branch 1 taken 239 times.
239 Fw::Success comSuccess = Fw::Success::FAILURE;
90
91 // Send to driver (and retry up to the retry limit)
92
5/6
✓ Branch 1 taken 239 times.
✓ Branch 2 taken 239 times.
✓ Branch 3 taken 239 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 239 times.
✓ Branch 6 taken 239 times.
478 for (FwIndexType i = 0; sendStatus == Drv::ByteStreamStatus::SEND_RETRY && i < RETRY_LIMIT; i++) {
93
2/2
✓ Branch 1 taken 239 times.
✓ Branch 4 taken 239 times.
239 sendStatus = this->drvSendOut_out(0, sendBuffer);
94 }
95
96 // Handle the send status
97
1/2
✓ Branch 1 taken 239 times.
✗ Branch 2 not taken.
239 if (sendStatus == Drv::ByteStreamStatus::OP_OK) {
98
1/1
✓ Branch 1 taken 239 times.
239 comSuccess = Fw::Success::SUCCESS;
99 ✗ } else if (sendStatus == Drv::ByteStreamStatus::SEND_RETRY) {
100 // Retry exhaustion requires a driver reconnect to emit the recovery SUCCESS
101 ✗ this->m_reinitialize = true;
102 ✗ Fw::Logger::log("ComStub RETRY_LIMIT exceeded, skipped sending data");
103 } else {
104 // Other error - need to reinitialize
105 ✗ this->m_reinitialize = true;
106 }
107
108 // Return buffer and send status
109
1/1
✓ Branch 1 taken 239 times.
239 this->dataReturnOut_out(0, sendBuffer, context);
110
1/1
✓ Branch 1 taken 239 times.
239 this->comStatusOut_out(0, comSuccess);
111 239 }
112
113 ✗ void ComStub::handleAsynchronousSend(Fw::Buffer& sendBuffer, const ComCfg::FrameContext& context) {
114 ✗ this->m_storedContext = context; // Store the context for async callback
115 ✗ this->drvAsyncSendOut_out(0, sendBuffer);
116 ✗ }
117
118 ✗ void ComStub::handleAsyncRetry(Fw::Buffer& fwBuffer) {
119 ✗ FW_ASSERT(this->m_retry_count <= this->RETRY_LIMIT, static_cast<FwAssertArgType>(this->m_retry_count));
120 ✗ if (this->m_retry_count < this->RETRY_LIMIT) {
121 // Attempt retry if under the limit
122 ✗ this->m_retry_count++;
123 ✗ this->drvAsyncSendOut_out(0, fwBuffer);
124 } else {
125 // Exceeded retry limit - return buffer and notify failure
126 // Retry exhaustion requires a driver reconnect to emit the recovery SUCCESS
127 ✗ this->m_reinitialize = true;
128 ✗ this->dataReturnOut_out(0, fwBuffer, this->m_storedContext);
129 ✗ Fw::Success comStatus = Fw::Success::FAILURE;
130 ✗ this->comStatusOut_out(0, comStatus);
131 ✗ Fw::Logger::log("ComStub RETRY_LIMIT exceeded, skipped sending data");
132 ✗ this->m_retry_count = 0; // Reset retry count
133 ✗ }
134 ✗ }
135
136 } // end namespace Svc
137