GCC Code Coverage Report


Directory: ./
File: Svc/Health/HealthComponentImpl.cpp
Date: 2026-11-03 22:10:14
Exec Total Coverage
Lines: 51 120 42.5%
Functions: 6 10 60.0%
Branches: 21 97 21.6%

Line Branch Exec Source
1 // ======================================================================
2 // \title Health.hpp
3 // \author Tim
4 // \brief hpp file for Health component implementation class
5 //
6 // \copyright
7 // Copyright 2009-2015, by the California Institute of Technology.
8 // ALL RIGHTS RESERVED. United States Government Sponsorship
9 // acknowledged.
10 //
11 // ======================================================================
12
13 #include <Fw/FPrimeBasicTypes.hpp>
14 #include <Fw/Types/Assert.hpp>
15 #include <Svc/Health/HealthComponentImpl.hpp>
16
17 namespace Svc {
18
19 // ----------------------------------------------------------------------
20 // Construction, initialization, and destruction
21 // ----------------------------------------------------------------------
22
23 1 HealthImpl::HealthImpl(const char* const compName)
24 : HealthComponentBase(compName),
25 1 m_numPingEntries(0),
26 1 m_key(0),
27 1 m_watchDogCode(0),
28 1 m_warnings(0),
29 1 m_enabled(Fw::Enabled::ENABLED),
30
4/10
✓ Branch 2 taken 25 times.
✓ Branch 4 taken 25 times.
✓ Branch 5 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
26 queue_depth(0) {
31 static_assert((HealthComponentBase::NUM_PINGSEND_OUTPUT_PORTS >= 0) &&
32 (HealthComponentBase::NUM_PINGSEND_OUTPUT_PORTS <= std::numeric_limits<FwIndexType>::max()),
33 "NUM_PINGSEND_OUTPUT_PORTS must fit in the positive range of FwIndexType");
34 // clear tracker by disabling pings
35
2/2
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 1 times.
26 for (FwIndexType entry = 0; entry < static_cast<FwIndexType>(FW_NUM_ARRAY_ELEMENTS(this->m_pingTrackerEntries));
36 entry++) {
37 25 this->m_pingTrackerEntries[entry].enabled = Fw::Enabled::DISABLED;
38 }
39 1 }
40
41 1 void HealthImpl::init(const FwSizeType queueDepth, const FwEnumStoreType instance) {
42 1 HealthComponentBase::init(queueDepth, instance);
43 1 this->queue_depth = queueDepth;
44 1 }
45
46 1 void HealthImpl::setPingEntries(PingEntry* pingEntries, FwIndexType numPingEntries, U32 watchDogCode) {
47 1 FW_ASSERT(pingEntries != nullptr);
48 // make sure not asking for more pings than ports
49 1 FW_ASSERT(numPingEntries <= NUM_PINGSEND_OUTPUT_PORTS);
50
51 1 this->m_numPingEntries = numPingEntries;
52 1 this->m_watchDogCode = watchDogCode;
53
54 // copy entries to private data
55
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1 times.
16 for (FwIndexType entry = 0; entry < numPingEntries; entry++) {
56 15 FW_ASSERT(pingEntries[entry].warnCycles <= pingEntries[entry].fatalCycles,
57 static_cast<FwAssertArgType>(pingEntries[entry].warnCycles),
58 static_cast<FwAssertArgType>(pingEntries[entry].fatalCycles));
59 15 this->m_pingTrackerEntries[entry].entry = pingEntries[entry];
60 15 this->m_pingTrackerEntries[entry].cycleCount = 0;
61 15 this->m_pingTrackerEntries[entry].fatalReported = false;
62 15 this->m_pingTrackerEntries[entry].enabled = Fw::Enabled::ENABLED;
63 15 this->m_pingTrackerEntries[entry].key = 0;
64 }
65 1 }
66
67
3/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 25 times.
✓ Branch 4 taken 1 times.
52 HealthImpl::~HealthImpl() {}
68
69 // ----------------------------------------------------------------------
70 // Handler implementations for user-defined typed input ports
71 // ----------------------------------------------------------------------
72
73 975 void HealthImpl::PingReturn_handler(const FwIndexType portNum, U32 key) {
74 // verify the key value
75
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 975 times.
975 if (key != this->m_pingTrackerEntries[portNum].key) {
76 ✗ Fw::LogStringArg _arg = this->m_pingTrackerEntries[portNum].entry.entryName;
77 ✗ this->log_FATAL_HLTH_PING_WRONG_KEY(_arg, key);
78 ✗ } else {
79 // reset the counter and FATAL reporting state, and clear the key
80 975 this->m_pingTrackerEntries[portNum].cycleCount = 0;
81 975 this->m_pingTrackerEntries[portNum].fatalReported = false;
82 975 this->m_pingTrackerEntries[portNum].key = 0;
83 }
84 975 }
85
86 66 void HealthImpl::Run_handler(const FwIndexType portNum, U32 context) {
87 // dispatch messages
88
1/2
✓ Branch 0 taken 1041 times.
✗ Branch 1 not taken.
1041 for (FwSizeType i = 0; i < this->queue_depth; i++) {
89 1041 MsgDispatchStatus stat = this->doDispatch();
90
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 975 times.
1041 if (MSG_DISPATCH_EMPTY == stat) {
91 66 break;
92 }
93 975 FW_ASSERT(MSG_DISPATCH_OK == stat);
94 }
95
96
1/2
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
66 if (this->m_enabled == Fw::Enabled::ENABLED) {
97 // cycle through ping table, pinging ports that are not awaiting a reply
98 // for ports that are awaiting a reply, increment their counters
99 // and check for violations
100
101
2/2
✓ Branch 0 taken 990 times.
✓ Branch 1 taken 66 times.
1056 for (FwIndexType entry = 0; entry < this->m_numPingEntries; entry++) {
102
1/2
✓ Branch 0 taken 990 times.
✗ Branch 1 not taken.
990 if (Fw::Enabled::ENABLED == this->m_pingTrackerEntries[entry].enabled) {
103 // If clear entry
104
1/2
✓ Branch 0 taken 990 times.
✗ Branch 1 not taken.
990 if (0 == this->m_pingTrackerEntries[entry].cycleCount) {
105 // start a ping with a fresh timeout reporting state
106 990 this->m_pingTrackerEntries[entry].fatalReported = false;
107 990 this->m_pingTrackerEntries[entry].key = this->m_key;
108 // send ping
109 990 this->PingSend_out(static_cast<FwIndexType>(entry), this->m_pingTrackerEntries[entry].key);
110 // increment key
111 990 this->m_key++;
112 // increment cycles for the entry
113 990 this->m_pingTrackerEntries[entry].cycleCount++;
114 } else {
115 // Check FATAL first: equal warning and FATAL thresholds are valid.
116 // A zero FATAL threshold disables timeout detection (legacy behavior).
117 // Once FATAL is reported, this ping must not emit another FATAL or
118 // be downgraded to WARNING if the thresholds are raised.
119 ✗ if (this->m_pingTrackerEntries[entry].entry.fatalCycles > 0 &&
120 ✗ this->m_pingTrackerEntries[entry].cycleCount >=
121 ✗ this->m_pingTrackerEntries[entry].entry.fatalCycles) {
122 ✗ if (!this->m_pingTrackerEntries[entry].fatalReported) {
123 ✗ Fw::LogStringArg _arg = this->m_pingTrackerEntries[entry].entry.entryName;
124 ✗ this->m_pingTrackerEntries[entry].fatalReported = true;
125 ✗ this->log_FATAL_HLTH_PING_LATE(_arg);
126 ✗ }
127 ✗ } else if (!this->m_pingTrackerEntries[entry].fatalReported &&
128 ✗ this->m_pingTrackerEntries[entry].cycleCount ==
129 ✗ this->m_pingTrackerEntries[entry].entry.warnCycles) {
130 ✗ Fw::LogStringArg _arg = this->m_pingTrackerEntries[entry].entry.entryName;
131 ✗ this->log_WARNING_HI_HLTH_PING_WARN(_arg);
132 ✗ this->tlmWrite_PingLateWarnings(++this->m_warnings);
133 ✗ } // if at warning or fatal threshold
134
135 ✗ this->m_pingTrackerEntries[entry].cycleCount++;
136 } // if clear entry
137 } // if entry has ping enabled
138 } // for each entry
139 } // If health checking is enabled
140
141 // stroke watchdog.
142
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 66 times.
66 if (this->isConnected_WdogStroke_OutputPort(0)) {
143 ✗ this->WdogStroke_out(0, this->m_watchDogCode);
144 }
145 66 }
146
147 // ----------------------------------------------------------------------
148 // Command handler implementations
149 // ----------------------------------------------------------------------
150
151 ✗ void HealthImpl::HLTH_ENABLE_cmdHandler(const FwOpcodeType opCode, U32 cmdSeq, const Fw::Enabled& enable) {
152 ✗ this->m_enabled = enable;
153 ✗ Fw::Enabled isEnabled = Fw::Enabled::DISABLED;
154 ✗ if (enable == Fw::Enabled::ENABLED) {
155 ✗ isEnabled = Fw::Enabled::ENABLED;
156 }
157 ✗ this->log_ACTIVITY_HI_HLTH_CHECK_ENABLE(isEnabled);
158 ✗ this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
159 ✗ }
160
161 ✗ void HealthImpl::HLTH_PING_ENABLE_cmdHandler(const FwOpcodeType opCode,
162 U32 cmdSeq,
163 const Fw::CmdStringArg& entry,
164 const Fw::Enabled& enable) {
165 // check to see if entry is in range
166 ✗ FwIndexType entryIndex = this->findEntry(entry);
167
168 ✗ if (-1 == entryIndex) {
169 ✗ this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
170 ✗ return;
171 }
172 ✗ FW_ASSERT(
173 entryIndex >= 0 && entryIndex < static_cast<FwIndexType>(FW_NUM_ARRAY_ELEMENTS(this->m_pingTrackerEntries)),
174 static_cast<FwAssertArgType>(entryIndex));
175
176 ✗ this->m_pingTrackerEntries[entryIndex].enabled = enable.e;
177 ✗ Fw::Enabled isEnabled(Fw::Enabled::DISABLED);
178 ✗ if (enable == Fw::Enabled::ENABLED) {
179 ✗ isEnabled = Fw::Enabled::ENABLED;
180 }
181 ✗ Fw::LogStringArg arg;
182 ✗ arg = entry;
183 ✗ this->log_ACTIVITY_HI_HLTH_CHECK_PING(isEnabled, arg);
184 ✗ this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
185 ✗ }
186
187 ✗ void HealthImpl::HLTH_CHNG_PING_cmdHandler(const FwOpcodeType opCode,
188 U32 cmdSeq,
189 const Fw::CmdStringArg& entry,
190 U32 warningValue,
191 U32 fatalValue) {
192 // check to see if entry is in range
193 ✗ FwIndexType entryIndex = this->findEntry(entry);
194 ✗ if (-1 == entryIndex) {
195 ✗ this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
196 ✗ return;
197 }
198
199 // check to see if warningValue less than or equal to fatalValue
200 ✗ if (warningValue > fatalValue) {
201 ✗ Fw::LogStringArg arg;
202 ✗ arg = entry;
203 ✗ this->log_WARNING_HI_HLTH_PING_INVALID_VALUES(arg, warningValue, fatalValue);
204 ✗ this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
205 ✗ return;
206 ✗ }
207
208 ✗ this->m_pingTrackerEntries[entryIndex].entry.warnCycles = warningValue;
209 ✗ this->m_pingTrackerEntries[entryIndex].entry.fatalCycles = fatalValue;
210 ✗ Fw::LogStringArg arg = entry;
211 ✗ this->log_ACTIVITY_HI_HLTH_PING_UPDATED(arg, warningValue, fatalValue);
212 ✗ this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
213 ✗ }
214
215 ✗ FwIndexType HealthImpl::findEntry(const Fw::CmdStringArg& entry) {
216 static_assert(std::numeric_limits<FwIndexType>::is_signed, "FwIndexType must be signed to return -1 for error");
217 // walk through entries
218 ✗ for (FwIndexType tableEntry = 0; tableEntry < this->m_numPingEntries; tableEntry++) {
219 ✗ if (entry == this->m_pingTrackerEntries[tableEntry].entry.entryName) {
220 ✗ return static_cast<FwIndexType>(tableEntry);
221 }
222 }
223 ✗ Fw::LogStringArg arg = entry;
224 ✗ this->log_WARNING_LO_HLTH_CHECK_LOOKUP_ERROR(arg);
225
226 ✗ return -1;
227 ✗ }
228
229 } // end namespace Svc
230