GCC Code Coverage Report


Directory: /home/runner/work/fprime/fprime/Svc/FprimeRouter/
File: FprimeRouter.cpp
Date: 2026-09-03 22:13:45
Exec Total Coverage
Lines: 44 57 77.2%
Functions: 7 7 100.0%
Branches: 31 56 55.4%

Line Branch Exec Source
1 // ======================================================================
2 // \title FprimeRouter.cpp
3 // \author thomas-bc
4 // \brief cpp file for FprimeRouter component implementation class
5 // ======================================================================
6
7 #include "Svc/FprimeRouter/FprimeRouter.hpp"
8 #include "Fw/Com/ComPacket.hpp"
9 #include "Fw/FPrimeBasicTypes.hpp"
10 #include "Fw/Logger/Logger.hpp"
11 #include "config/ApidEnumAc.hpp"
12
13 namespace Svc {
14
15 // ----------------------------------------------------------------------
16 // Component construction and destruction
17 // ----------------------------------------------------------------------
18
19
3/9
✓ Branch 2 taken 50 times.
✓ Branch 4 taken 50 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
51 FprimeRouter ::FprimeRouter(const char* const compName) : FprimeRouterComponentBase(compName) {
20 // Mark every table entry unused
21
2/2
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 1 times.
51 for (FwSizeType i = 0; i < FW_NUM_ARRAY_ELEMENTS(this->m_bufferContextTable); i++) {
22
1/1
✓ Branch 1 taken 50 times.
50 this->m_bufferContextTable[i].state = Fw::Active::INACTIVE;
23 }
24 1 }
25
26
3/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 1 times.
102 FprimeRouter ::~FprimeRouter() {}
27
28 // ----------------------------------------------------------------------
29 // Handler implementations for user-defined typed input ports
30 // ----------------------------------------------------------------------
31
32 146 void FprimeRouter ::dataIn_handler(FwIndexType portNum, Fw::Buffer& packetBuffer, const ComCfg::FrameContext& context) {
33 Fw::SerializeStatus status;
34 146 Fw::ComPacketType packetType = context.get_apid();
35 // Route based on received APID (packet type)
36
2/3
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
146 switch (packetType) {
37 // Handle a command packet
38 140 case Fw::ComPacketType::FW_PACKET_COMMAND: {
39 // Allocate a com buffer on the stack
40
1/1
✓ Branch 1 taken 140 times.
140 Fw::ComBuffer com;
41 // Copy the contents of the packet buffer into the com buffer
42
3/3
✓ Branch 1 taken 140 times.
✓ Branch 4 taken 140 times.
✓ Branch 7 taken 140 times.
140 status = com.setBuff(packetBuffer.getData(), packetBuffer.getSize());
43
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 if (status == Fw::FW_SERIALIZE_OK) {
44 // Send the com buffer - critical functionality so it is considered an error not to
45 // have the port connected. This is why we don't check isConnected() before sending.
46
1/1
✓ Branch 1 taken 140 times.
140 this->commandOut_out(0, com, 0);
47 } else {
48 this->log_WARNING_HI_SerializationError(status);
49 }
50 // The command buffer was copied into the com buffer above, so ownership of the
51 // incoming packetBuffer is returned immediately with the context it was received with.
52
1/1
✓ Branch 1 taken 140 times.
140 this->dataReturnOut_out(0, packetBuffer, context);
53 140 break;
54 140 }
55 // Handle a file packet
56 6 case Fw::ComPacketType::FW_PACKET_FILE: {
57 // If the file uplink output port is connected, send the file packet directly.
58 // Ownership is passed to the receiver and will come back on fileBufferReturnIn,
59 // at which point we return it to the deframer via dataReturnOut. fileOut carries
60 // only Fw::Buffer, so remember the context here to restore it on return.
61
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 if (this->isConnected_fileOut_OutputPort(0)) {
62
2/3
✓ Branch 1 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
6 if (this->insertContext(packetBuffer, context) == Fw::Success::FAILURE) {
63 this->log_WARNING_HI_FileOutContextTableFull();
64 }
65 6 this->fileOut_out(0, packetBuffer);
66 } else {
67 // Port not connected, return the buffer immediately with its context
68 this->dataReturnOut_out(0, packetBuffer, context);
69 }
70 6 break;
71 }
72 default: {
73 // Packet type is not known to the F Prime protocol. If the unknownDataOut port is
74 // connected, forward packet and context for further processing.
75 // Ownership is passed to the receiver and will come back on fileBufferReturnIn,
76 // at which point we return it to the deframer via dataReturnOut. The return path
77 // (fileBufferReturnIn) carries no context, so remember it here to restore on return.
78 if (this->isConnected_unknownDataOut_OutputPort(0)) {
79 if (this->insertContext(packetBuffer, context) == Fw::Success::FAILURE) {
80 this->log_WARNING_HI_UnknownDataOutContextTableFull();
81 }
82 this->unknownDataOut_out(0, packetBuffer, context);
83 } else {
84 // Port not connected, return the buffer immediately with its context
85 this->dataReturnOut_out(0, packetBuffer, context);
86 }
87 break;
88 }
89 }
90 146 }
91
92 140 void FprimeRouter ::cmdResponseIn_handler(FwIndexType portNum,
93 FwOpcodeType opcode,
94 U32 cmdSeq,
95 const Fw::CmdResponse& response) {
96 // Nothing to do
97 140 }
98
99 6 void FprimeRouter ::fileBufferReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) {
100 // Restore the context that was saved when this buffer was handed off on
101 // fileOut/unknownDataOut
102
1/1
✓ Branch 1 taken 6 times.
6 ComCfg::FrameContext context;
103
2/3
✓ Branch 1 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
6 if (this->takeContext(fwBuffer, context) == Fw::Success::FAILURE) {
104 // Buffer not found in the table: return with an empty context (already default)
105 this->log_WARNING_HI_BufferContextNotFound();
106 }
107
1/1
✓ Branch 1 taken 6 times.
6 this->dataReturnOut_out(0, fwBuffer, context);
108 6 }
109
110 // ----------------------------------------------------------------------
111 // Buffer-to-context association table helpers
112 // ----------------------------------------------------------------------
113
114 6 Fw::Success FprimeRouter ::insertContext(const Fw::Buffer& buffer, const ComCfg::FrameContext& context) {
115 6 const U8* key = buffer.getData();
116
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 for (FwSizeType i = 0; i < FW_NUM_ARRAY_ELEMENTS(this->m_bufferContextTable); i++) {
117
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 if (this->m_bufferContextTable[i].state == Fw::Active::INACTIVE) {
118 6 this->m_bufferContextTable[i].state = Fw::Active::ACTIVE;
119 6 this->m_bufferContextTable[i].key = key;
120 6 this->m_bufferContextTable[i].context = context;
121 6 return Fw::Success::SUCCESS;
122 }
123 }
124 // Table full
125 return Fw::Success::FAILURE;
126 }
127
128 6 Fw::Success FprimeRouter ::takeContext(const Fw::Buffer& buffer, ComCfg::FrameContext& context) {
129 6 const U8* key = buffer.getData();
130
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 for (FwSizeType i = 0; i < FW_NUM_ARRAY_ELEMENTS(this->m_bufferContextTable); i++) {
131
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
6 if (this->m_bufferContextTable[i].state == Fw::Active::ACTIVE && this->m_bufferContextTable[i].key == key) {
132 6 context = this->m_bufferContextTable[i].context;
133 6 this->m_bufferContextTable[i].state = Fw::Active::INACTIVE;
134 6 return Fw::Success::SUCCESS;
135 }
136 }
137 // Not found
138 return Fw::Success::FAILURE;
139 }
140
141 } // namespace Svc
142