GCC Code Coverage Report


Directory: Svc/Health/
File: HealthComponentImpl.cpp
Date: 2026-11-03 21:19:03
Exec Total Coverage
Lines: 120 120 100.0%
Functions: 10 10 100.0%
Branches: 92 105 87.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 12 HealthImpl::HealthImpl(const char* const compName)
24 : HealthComponentBase(compName),
25 12 m_numPingEntries(0),
26 12 m_key(0),
27 12 m_watchDogCode(0),
28 12 m_warnings(0),
29
1/1
✓ Branch 4 taken 12 times.
12 m_enabled(Fw::Enabled::ENABLED),
30
3/9
✓ Branch 9 taken 300 times.
✓ Branch 12 taken 300 times.
✓ Branch 13 taken 12 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
324 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 300 times.
✓ Branch 2 taken 12 times.
312 for (FwIndexType entry = 0; entry < static_cast<FwIndexType>(FW_NUM_ARRAY_ELEMENTS(this->m_pingTrackerEntries));
36 entry++) {
37 300 this->m_pingTrackerEntries[entry].enabled = Fw::Enabled::DISABLED;
38 }
39 12 }
40
41 12 void HealthImpl::init(const FwSizeType queueDepth, const FwEnumStoreType instance) {
42 12 HealthComponentBase::init(queueDepth, instance);
43 12 this->queue_depth = queueDepth;
44 12 }
45
46 13 void HealthImpl::setPingEntries(PingEntry* pingEntries, FwIndexType numPingEntries, U32 watchDogCode) {
47 13 FW_ASSERT(pingEntries != nullptr);
48 // make sure not asking for more pings than ports
49 13 FW_ASSERT(numPingEntries <= NUM_PINGSEND_OUTPUT_PORTS);
50
51 13 this->m_numPingEntries = numPingEntries;
52 13 this->m_watchDogCode = watchDogCode;
53
54 // copy entries to private data
55
2/2
✓ Branch 0 taken 325 times.
✓ Branch 1 taken 13 times.
338 for (FwIndexType entry = 0; entry < numPingEntries; entry++) {
56 325 FW_ASSERT(pingEntries[entry].warnCycles <= pingEntries[entry].fatalCycles,
57 static_cast<FwAssertArgType>(pingEntries[entry].warnCycles),
58 static_cast<FwAssertArgType>(pingEntries[entry].fatalCycles));
59 325 this->m_pingTrackerEntries[entry].entry = pingEntries[entry];
60 325 this->m_pingTrackerEntries[entry].cycleCount = 0;
61 325 this->m_pingTrackerEntries[entry].fatalReported = false;
62 325 this->m_pingTrackerEntries[entry].enabled = Fw::Enabled::ENABLED;
63 325 this->m_pingTrackerEntries[entry].key = 0;
64 }
65 13 }
66
67
3/4
✓ Branch 10 taken 12 times.
✗ Branch 11 not taken.
✓ Branch 17 taken 300 times.
✓ Branch 18 taken 12 times.
624 HealthImpl::~HealthImpl() {}
68
69 // ----------------------------------------------------------------------
70 // Handler implementations for user-defined typed input ports
71 // ----------------------------------------------------------------------
72
73 1828 void HealthImpl::PingReturn_handler(const FwIndexType portNum, U32 key) {
74 // verify the key value
75
2/2
✓ Branch 5 taken 25 times.
✓ Branch 6 taken 1803 times.
1828 if (key != this->m_pingTrackerEntries[portNum].key) {
76
1/1
✓ Branch 6 taken 25 times.
25 Fw::LogStringArg _arg = this->m_pingTrackerEntries[portNum].entry.entryName;
77
1/1
✓ Branch 5 taken 25 times.
25 this->log_FATAL_HLTH_PING_WRONG_KEY(_arg, key);
78 25 } else {
79 // reset the counter and FATAL reporting state, and clear the key
80 1803 this->m_pingTrackerEntries[portNum].cycleCount = 0;
81 1803 this->m_pingTrackerEntries[portNum].fatalReported = false;
82 1803 this->m_pingTrackerEntries[portNum].key = 0;
83 }
84 1828 }
85
86 1085 void HealthImpl::Run_handler(const FwIndexType portNum, U32 context) {
87 // dispatch messages
88
1/2
✓ Branch 4 taken 2861 times.
✗ Branch 5 not taken.
2861 for (FwSizeType i = 0; i < this->queue_depth; i++) {
89 2861 MsgDispatchStatus stat = this->doDispatch();
90
2/2
✓ Branch 0 taken 1085 times.
✓ Branch 1 taken 1776 times.
2861 if (MSG_DISPATCH_EMPTY == stat) {
91 1085 break;
92 }
93 1776 FW_ASSERT(MSG_DISPATCH_OK == stat);
94 }
95
96
2/2
✓ Branch 6 taken 935 times.
✓ Branch 7 taken 150 times.
1085 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 4 taken 23375 times.
✓ Branch 5 taken 935 times.
24310 for (FwIndexType entry = 0; entry < this->m_numPingEntries; entry++) {
102
3/4
✗ Branch 4 not taken.
✓ Branch 5 taken 23375 times.
✓ Branch 6 taken 22750 times.
✓ Branch 7 taken 625 times.
23375 if (Fw::Enabled::ENABLED == this->m_pingTrackerEntries[entry].enabled) {
103 // If clear entry
104
2/2
✓ Branch 5 taken 2653 times.
✓ Branch 6 taken 20097 times.
22750 if (0 == this->m_pingTrackerEntries[entry].cycleCount) {
105 // start a ping with a fresh timeout reporting state
106 2653 this->m_pingTrackerEntries[entry].fatalReported = false;
107 2653 this->m_pingTrackerEntries[entry].key = this->m_key;
108 // send ping
109 2653 this->PingSend_out(static_cast<FwIndexType>(entry), this->m_pingTrackerEntries[entry].key);
110 // increment key
111 2653 this->m_key++;
112 // increment cycles for the entry
113 2653 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
2/2
✓ Branch 5 taken 20095 times.
✓ Branch 6 taken 2 times.
20097 if (this->m_pingTrackerEntries[entry].entry.fatalCycles > 0 &&
120 20095 this->m_pingTrackerEntries[entry].cycleCount >=
121
2/2
✓ Branch 5 taken 679 times.
✓ Branch 6 taken 19416 times.
20095 this->m_pingTrackerEntries[entry].entry.fatalCycles) {
122
3/4
✗ Branch 4 not taken.
✓ Branch 5 taken 679 times.
✓ Branch 6 taken 77 times.
✓ Branch 7 taken 602 times.
679 if (!this->m_pingTrackerEntries[entry].fatalReported) {
123
1/1
✓ Branch 6 taken 77 times.
77 Fw::LogStringArg _arg = this->m_pingTrackerEntries[entry].entry.entryName;
124 77 this->m_pingTrackerEntries[entry].fatalReported = true;
125
1/1
✓ Branch 5 taken 77 times.
77 this->log_FATAL_HLTH_PING_LATE(_arg);
126 77 }
127
3/4
✗ Branch 4 not taken.
✓ Branch 5 taken 19418 times.
✓ Branch 6 taken 19417 times.
✓ Branch 7 taken 1 times.
20097 } else if (!this->m_pingTrackerEntries[entry].fatalReported &&
128 19417 this->m_pingTrackerEntries[entry].cycleCount ==
129
2/2
✓ Branch 5 taken 77 times.
✓ Branch 6 taken 19340 times.
19417 this->m_pingTrackerEntries[entry].entry.warnCycles) {
130
1/1
✓ Branch 6 taken 77 times.
77 Fw::LogStringArg _arg = this->m_pingTrackerEntries[entry].entry.entryName;
131
1/1
✓ Branch 5 taken 77 times.
77 this->log_WARNING_HI_HLTH_PING_WARN(_arg);
132
2/2
✓ Branch 6 taken 77 times.
✓ Branch 17 taken 77 times.
77 this->tlmWrite_PingLateWarnings(++this->m_warnings);
133 77 } // if at warning or fatal threshold
134
135 20097 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 5 taken 1085 times.
✗ Branch 6 not taken.
1085 if (this->isConnected_WdogStroke_OutputPort(0)) {
143 1085 this->WdogStroke_out(0, this->m_watchDogCode);
144 }
145 1085 }
146
147 // ----------------------------------------------------------------------
148 // Command handler implementations
149 // ----------------------------------------------------------------------
150
151 6 void HealthImpl::HLTH_ENABLE_cmdHandler(const FwOpcodeType opCode, U32 cmdSeq, const Fw::Enabled& enable) {
152
1/1
✓ Branch 6 taken 6 times.
6 this->m_enabled = enable;
153
1/1
✓ Branch 2 taken 6 times.
6 Fw::Enabled isEnabled = Fw::Enabled::DISABLED;
154
2/2
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 3 times.
6 if (enable == Fw::Enabled::ENABLED) {
155
1/1
✓ Branch 2 taken 3 times.
3 isEnabled = Fw::Enabled::ENABLED;
156 }
157
1/1
✓ Branch 5 taken 6 times.
6 this->log_ACTIVITY_HI_HLTH_CHECK_ENABLE(isEnabled);
158
2/2
✓ Branch 6 taken 6 times.
✓ Branch 9 taken 6 times.
6 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
159 12 }
160
161 52 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
1/1
✓ Branch 4 taken 52 times.
52 FwIndexType entryIndex = this->findEntry(entry);
167
168
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 51 times.
52 if (-1 == entryIndex) {
169
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
170 1 return;
171 }
172 51 FW_ASSERT(
173 entryIndex >= 0 && entryIndex < static_cast<FwIndexType>(FW_NUM_ARRAY_ELEMENTS(this->m_pingTrackerEntries)),
174 static_cast<FwAssertArgType>(entryIndex));
175
176
1/2
✗ Branch 6 not taken.
✓ Branch 7 taken 51 times.
51 this->m_pingTrackerEntries[entryIndex].enabled = enable.e;
177
1/1
✓ Branch 2 taken 51 times.
51 Fw::Enabled isEnabled(Fw::Enabled::DISABLED);
178
2/2
✓ Branch 4 taken 25 times.
✓ Branch 5 taken 26 times.
51 if (enable == Fw::Enabled::ENABLED) {
179
1/1
✓ Branch 2 taken 25 times.
25 isEnabled = Fw::Enabled::ENABLED;
180 }
181
1/1
✓ Branch 2 taken 51 times.
51 Fw::LogStringArg arg;
182
1/1
✓ Branch 5 taken 51 times.
51 arg = entry;
183
1/1
✓ Branch 5 taken 51 times.
51 this->log_ACTIVITY_HI_HLTH_CHECK_PING(isEnabled, arg);
184
2/2
✓ Branch 6 taken 51 times.
✓ Branch 9 taken 51 times.
51 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
185 51 }
186
187 32 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
1/1
✓ Branch 4 taken 32 times.
32 FwIndexType entryIndex = this->findEntry(entry);
194
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 31 times.
32 if (-1 == entryIndex) {
195
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
196 1 return;
197 }
198
199 // check to see if warningValue less than or equal to fatalValue
200
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 30 times.
31 if (warningValue > fatalValue) {
201
1/1
✓ Branch 2 taken 1 times.
1 Fw::LogStringArg arg;
202
1/1
✓ Branch 5 taken 1 times.
1 arg = entry;
203
1/1
✓ Branch 5 taken 1 times.
1 this->log_WARNING_HI_HLTH_PING_INVALID_VALUES(arg, warningValue, fatalValue);
204
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::VALIDATION_ERROR);
205 1 return;
206 1 }
207
208 30 this->m_pingTrackerEntries[entryIndex].entry.warnCycles = warningValue;
209 30 this->m_pingTrackerEntries[entryIndex].entry.fatalCycles = fatalValue;
210
1/1
✓ Branch 5 taken 30 times.
30 Fw::LogStringArg arg = entry;
211
1/1
✓ Branch 5 taken 30 times.
30 this->log_ACTIVITY_HI_HLTH_PING_UPDATED(arg, warningValue, fatalValue);
212
2/2
✓ Branch 6 taken 30 times.
✓ Branch 9 taken 30 times.
30 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
213 30 }
214
215 84 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
2/2
✓ Branch 4 taken 1032 times.
✓ Branch 5 taken 2 times.
1034 for (FwIndexType tableEntry = 0; tableEntry < this->m_numPingEntries; tableEntry++) {
219
3/3
✓ Branch 11 taken 1032 times.
✓ Branch 13 taken 82 times.
✓ Branch 14 taken 950 times.
1032 if (entry == this->m_pingTrackerEntries[tableEntry].entry.entryName) {
220 82 return static_cast<FwIndexType>(tableEntry);
221 }
222 }
223
1/1
✓ Branch 5 taken 2 times.
2 Fw::LogStringArg arg = entry;
224
1/1
✓ Branch 5 taken 2 times.
2 this->log_WARNING_LO_HLTH_CHECK_LOOKUP_ERROR(arg);
225
226 2 return -1;
227 2 }
228
229 } // end namespace Svc
230