GCC Code Coverage Report


Directory: ./
File: Svc/CmdSequencer/FPrimeSequence.cpp
Date: 2026-09-03 21:13:48
Exec Total Coverage
Lines: 197 207 95.2%
Functions: 23 23 100.0%
Branches: 122 134 91.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title FPrimeSequence.cpp
3 // \author Bocchino/Canham
4 // \brief CmdSequencerComponentImpl::FPrimeSequence implementation
5 //
6 // Copyright (C) 2009-2018 California Institute of Technology.
7 // ALL RIGHTS RESERVED. United States Government Sponsorship
8 // acknowledged.
9 // ======================================================================
10
11 #include "Fw/Types/Assert.hpp"
12 #include "Svc/CmdSequencer/CmdSequencerImpl.hpp"
13
14 namespace Svc {
15
16 222 CmdSequencerComponentImpl::FPrimeSequence::CRC ::CRC() : m_computed(), m_stored(0) {}
17
18 186 void CmdSequencerComponentImpl::FPrimeSequence::CRC ::init() {
19 186 this->m_computed.init();
20 186 }
21
22 280 void CmdSequencerComponentImpl::FPrimeSequence::CRC ::update(const BYTE* buffer, FwSizeType bufferSize) {
23 280 FW_ASSERT(buffer != nullptr);
24 280 this->m_computed.update(buffer, bufferSize);
25 280 }
26
27 102 U32 CmdSequencerComponentImpl::FPrimeSequence::CRC ::finalize() {
28 102 U32 computed = 0;
29
1/1
✓ Branch 3 taken 102 times.
102 this->m_computed.finalize(computed);
30 102 return computed;
31 }
32
33 74 CmdSequencerComponentImpl::FPrimeSequence ::FPrimeSequence(CmdSequencerComponentImpl& component)
34
2/2
✓ Branch 9 taken 74 times.
✓ Branch 15 taken 74 times.
74 : Sequence(component) {}
35
36 68 bool CmdSequencerComponentImpl::FPrimeSequence ::validateCRC() {
37 68 bool result = true;
38 68 U32 computed = this->m_crc.finalize();
39
2/2
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 67 times.
68 if (this->m_crc.m_stored != computed) {
40 1 this->m_events.fileCRCFailure(this->m_crc.m_stored, computed);
41 1 result = false;
42 }
43 68 return result;
44 }
45
46 84 bool CmdSequencerComponentImpl::FPrimeSequence ::loadFile(const Fw::ConstStringBase& fileName) {
47 // make sure there is a buffer allocated
48 84 FW_ASSERT(this->m_buffer.getBuffAddr() != nullptr);
49
50 84 this->setFileName(fileName);
51
52
6/6
✓ Branch 4 taken 68 times.
✓ Branch 5 taken 16 times.
✓ Branch 10 taken 67 times.
✓ Branch 11 taken 1 times.
✓ Branch 21 taken 65 times.
✓ Branch 22 taken 2 times.
149 const bool status = this->readFile() and this->validateCRC() and this->m_header.validateTime(this->m_component) and
53
2/2
✓ Branch 4 taken 54 times.
✓ Branch 5 taken 11 times.
65 this->validateRecords();
54
55 84 return status;
56 }
57
58 95 bool CmdSequencerComponentImpl::FPrimeSequence ::hasMoreRecords() const {
59 95 return this->m_buffer.getDeserializeSizeLeft() > 0;
60 }
61
62 90 void CmdSequencerComponentImpl::FPrimeSequence ::nextRecord(Record& record) {
63 90 Fw::SerializeStatus status = this->deserializeRecord(record);
64 90 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
65 90 }
66
67 5 void CmdSequencerComponentImpl::FPrimeSequence ::reset() {
68 5 this->m_buffer.resetDeser();
69 5 }
70
71 76 void CmdSequencerComponentImpl::FPrimeSequence ::clear() {
72 76 this->m_buffer.resetSer();
73 76 }
74
75 84 bool CmdSequencerComponentImpl::FPrimeSequence ::readFile() {
76 bool result;
77
78 84 Os::File::Status status = this->m_sequenceFile.open(this->m_fileName.toChar(), Os::File::OPEN_READ);
79
80
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 5 times.
84 if (status == Os::File::OP_OK) {
81 79 result = this->readOpenFile();
82
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 } else if (status == Os::File::DOESNT_EXIST) {
83 3 this->m_events.fileNotFound();
84 3 result = false;
85 } else {
86 2 this->m_events.fileReadError();
87 2 result = false;
88 }
89
90 84 this->m_sequenceFile.close();
91 84 return result;
92 }
93
94 79 bool CmdSequencerComponentImpl::FPrimeSequence ::readOpenFile() {
95 79 U8* const buffAddr = this->m_buffer.getBuffAddr();
96 79 this->m_crc.init();
97 79 bool status = this->readHeader();
98
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 3 times.
79 if (status) {
99 76 this->m_crc.update(buffAddr, Sequence::Header::SERIALIZED_SIZE);
100
6/6
✓ Branch 4 taken 75 times.
✓ Branch 5 taken 1 times.
✓ Branch 10 taken 71 times.
✓ Branch 11 taken 4 times.
✓ Branch 16 taken 68 times.
✓ Branch 17 taken 3 times.
76 status = this->deserializeHeader() and this->readRecordsAndCRC() and this->extractCRC();
101 }
102
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 11 times.
79 if (status) {
103 68 const FwSizeType buffLen = this->m_buffer.getSize();
104 68 this->m_crc.update(buffAddr, buffLen);
105 }
106 79 return status;
107 }
108
109 79 bool CmdSequencerComponentImpl::FPrimeSequence ::readHeader() {
110 79 Os::File& file = this->m_sequenceFile;
111 79 Fw::LinearBufferBase& buffer = this->m_buffer;
112 79 bool status = true;
113
114 79 FwSizeType readLen = Sequence::Header::SERIALIZED_SIZE;
115
116
1/1
✓ Branch 7 taken 79 times.
79 const FwSizeType capacity = buffer.getCapacity();
117 79 FW_ASSERT(capacity >= readLen, static_cast<FwAssertArgType>(capacity), static_cast<FwAssertArgType>(readLen));
118
1/1
✓ Branch 8 taken 79 times.
79 Os::File::Status fileStatus = file.read(buffer.getBuffAddr(), readLen);
119
120
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 77 times.
79 if (fileStatus != Os::File::OP_OK) {
121
1/1
✓ Branch 4 taken 2 times.
2 this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_HEADER, fileStatus);
122 2 status = false;
123 }
124
125
4/4
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 76 times.
79 if (status and readLen != Sequence::Header::SERIALIZED_SIZE) {
126
1/1
✓ Branch 4 taken 1 times.
1 this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_HEADER_SIZE, static_cast<I32>(readLen));
127 1 status = false;
128 }
129
130
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 3 times.
79 if (status) {
131
1/1
✓ Branch 7 taken 76 times.
76 const Fw::SerializeStatus serializeStatus = buffer.setBuffLen(static_cast<Fw::Serializable::SizeType>(readLen));
132 76 FW_ASSERT(serializeStatus == Fw::FW_SERIALIZE_OK, serializeStatus);
133 }
134
135 79 return status;
136 }
137
138 76 bool CmdSequencerComponentImpl::FPrimeSequence ::deserializeHeader() {
139 76 Fw::LinearBufferBase& buffer = this->m_buffer;
140 76 Header& header = this->m_header;
141
142 // File size
143
1/1
✓ Branch 9 taken 76 times.
76 Fw::SerializeStatus serializeStatus = buffer.deserializeTo(header.m_fileSize);
144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
76 if (serializeStatus != Fw::FW_SERIALIZE_OK) {
145 this->m_events.fileInvalid(CmdSequencer_FileReadStage::DESER_SIZE, serializeStatus);
146 return false;
147 }
148
3/3
✓ Branch 8 taken 76 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 75 times.
76 if (header.m_fileSize > buffer.getCapacity()) {
149
1/1
✓ Branch 5 taken 1 times.
1 this->m_events.fileSizeError(header.m_fileSize);
150 1 return false;
151 }
152 // Number of records
153
1/1
✓ Branch 10 taken 75 times.
75 serializeStatus = buffer.deserializeTo(header.m_numRecords);
154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (serializeStatus != Fw::FW_SERIALIZE_OK) {
155 this->m_events.fileInvalid(CmdSequencer_FileReadStage::DESER_NUM_RECORDS, serializeStatus);
156 return false;
157 }
158 // Time base
159
1/1
✓ Branch 2 taken 75 times.
75 TimeBase tbase;
160
1/1
✓ Branch 7 taken 75 times.
75 serializeStatus = buffer.deserializeTo(tbase);
161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (serializeStatus != Fw::FW_SERIALIZE_OK) {
162 this->m_events.fileInvalid(CmdSequencer_FileReadStage::DESER_TIME_BASE, serializeStatus);
163 return false;
164 }
165
1/1
✓ Branch 6 taken 75 times.
75 header.m_timeBase = (tbase);
166 // Time context
167
1/1
✓ Branch 10 taken 75 times.
75 serializeStatus = buffer.deserializeTo(header.m_timeContext);
168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (serializeStatus != Fw::FW_SERIALIZE_OK) {
169 this->m_events.fileInvalid(CmdSequencer_FileReadStage::DESER_TIME_CONTEXT, serializeStatus);
170 return false;
171 }
172 75 return true;
173 75 }
174
175 75 bool CmdSequencerComponentImpl::FPrimeSequence ::readRecordsAndCRC() {
176 75 Os::File& file = this->m_sequenceFile;
177 75 const FwSizeType size = this->m_header.m_fileSize;
178 75 Fw::LinearBufferBase& buffer = this->m_buffer;
179
180 75 FwSizeType readLen = size;
181
1/1
✓ Branch 8 taken 75 times.
75 Os::File::Status fileStatus = file.read(buffer.getBuffAddr(), readLen);
182 // check read status
183
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 73 times.
75 if (fileStatus != Os::File::OP_OK) {
184
1/1
✓ Branch 4 taken 2 times.
2 this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_SEQ_DATA, fileStatus);
185 2 return false;
186 }
187 // check read size
188
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 71 times.
73 if (size != static_cast<FwSizeType>(readLen)) {
189
1/1
✓ Branch 4 taken 2 times.
2 this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_SEQ_DATA_SIZE, static_cast<I32>(readLen));
190 2 return false;
191 }
192 // set buffer size
193
1/1
✓ Branch 7 taken 71 times.
71 Fw::SerializeStatus serializeStatus = buffer.setBuffLen(size);
194 71 FW_ASSERT(serializeStatus == Fw::FW_SERIALIZE_OK, serializeStatus);
195 71 return true;
196 }
197
198 71 bool CmdSequencerComponentImpl::FPrimeSequence ::extractCRC() {
199 71 Fw::LinearBufferBase& buffer = this->m_buffer;
200 71 U32& crc = this->m_crc.m_stored;
201
202 // Compute the data size
203
1/1
✓ Branch 7 taken 71 times.
71 const FwSizeType buffSize = buffer.getSize();
204 71 const FwSizeType crcSize = sizeof(crc);
205 71 U8* const buffAddr = buffer.getBuffAddr();
206
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 68 times.
71 if (buffSize < crcSize) {
207
1/1
✓ Branch 4 taken 3 times.
3 this->m_events.fileInvalid(CmdSequencer_FileReadStage::READ_SEQ_CRC, static_cast<I32>(buffSize));
208 3 return false;
209 }
210 68 FW_ASSERT(buffSize >= crcSize, static_cast<FwAssertArgType>(buffSize), crcSize);
211 68 const FwSizeType dataSize = buffSize - crcSize;
212 // Create a CRC buffer pointing at the CRC in the main buffer, after the data
213
1/1
✓ Branch 3 taken 68 times.
68 Fw::ExternalSerializeBuffer crcBuff(&buffAddr[dataSize], crcSize);
214
1/1
✓ Branch 2 taken 68 times.
68 Fw::SerializeStatus status = crcBuff.setBuffLen(crcSize);
215 68 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
216 // Deserialize the CRC from the CRC buffer
217
1/1
✓ Branch 2 taken 68 times.
68 status = crcBuff.deserializeTo(crc);
218 68 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
219 // Set the main buffer size to the data size
220
1/1
✓ Branch 7 taken 68 times.
68 status = buffer.setBuffLen(dataSize);
221 68 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
222 68 return true;
223 68 }
224
225 338 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::deserializeRecord(Record& record) {
226 338 U32 recordSize;
227
228
1/1
✓ Branch 6 taken 338 times.
338 Fw::SerializeStatus status = this->deserializeDescriptor(record.m_descriptor);
229
230
5/6
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 336 times.
✓ Branch 5 taken 23 times.
✓ Branch 6 taken 313 times.
338 if (status == Fw::FW_SERIALIZE_OK and record.m_descriptor == Record::END_OF_SEQUENCE) {
231 23 return Fw::FW_SERIALIZE_OK;
232 }
233
234
2/2
✓ Branch 0 taken 313 times.
✓ Branch 1 taken 2 times.
315 if (status == Fw::FW_SERIALIZE_OK) {
235
1/1
✓ Branch 7 taken 313 times.
313 status = this->deserializeTimeTag(record.m_timeTag);
236 }
237
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 6 times.
315 if (status == Fw::FW_SERIALIZE_OK) {
238
1/1
✓ Branch 4 taken 309 times.
309 status = this->deserializeRecordSize(recordSize);
239 }
240
2/2
✓ Branch 0 taken 307 times.
✓ Branch 1 taken 8 times.
315 if (status == Fw::FW_SERIALIZE_OK) {
241
1/1
✓ Branch 7 taken 307 times.
307 status = this->copyCommand(record.m_command, recordSize);
242 }
243
244 315 return status;
245 }
246
247 338 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::deserializeDescriptor(Record::Descriptor& descriptor) {
248 338 Fw::LinearBufferBase& buffer = this->m_buffer;
249 338 U8 descEntry;
250
251
1/1
✓ Branch 7 taken 338 times.
338 Fw::SerializeStatus status = buffer.deserializeTo(descEntry);
252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 if (status != Fw::FW_SERIALIZE_OK) {
253 return status;
254 }
255
256
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 336 times.
338 if (descEntry > Sequence::Record::END_OF_SEQUENCE) {
257 2 return Fw::FW_DESERIALIZE_FORMAT_ERROR;
258 }
259
260 336 descriptor = static_cast<Record::Descriptor>(descEntry);
261 336 return Fw::FW_SERIALIZE_OK;
262 }
263
264 313 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::deserializeTimeTag(Fw::Time& timeTag) {
265 313 Fw::LinearBufferBase& buffer = this->m_buffer;
266 313 U32 seconds;
267 313 U32 useconds;
268
1/1
✓ Branch 7 taken 313 times.
313 Fw::SerializeStatus status = buffer.deserializeTo(seconds);
269
2/2
✓ Branch 0 taken 311 times.
✓ Branch 1 taken 2 times.
313 if (status == Fw::FW_SERIALIZE_OK) {
270
1/1
✓ Branch 7 taken 311 times.
311 status = buffer.deserializeTo(useconds);
271 }
272
2/2
✓ Branch 0 taken 309 times.
✓ Branch 1 taken 4 times.
313 if (status == Fw::FW_SERIALIZE_OK) {
273
1/1
✓ Branch 4 taken 309 times.
309 timeTag.set(seconds, useconds);
274 }
275 626 return status;
276 }
277
278 309 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::deserializeRecordSize(U32& recordSize) {
279 309 Fw::LinearBufferBase& buffer = this->m_buffer;
280 309 Fw::SerializeStatus status = buffer.deserializeTo(recordSize);
281
5/6
✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 307 times.
✓ Branch 12 taken 2 times.
✓ Branch 13 taken 307 times.
309 if (status == Fw::FW_SERIALIZE_OK and recordSize > buffer.getDeserializeSizeLeft()) {
282 // Not enough data left
283 2 status = Fw::FW_DESERIALIZE_SIZE_MISMATCH;
284 }
285
3/4
✓ Branch 0 taken 307 times.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 307 times.
309 if (status == Fw::FW_SERIALIZE_OK and recordSize + sizeof(FwPacketDescriptorType) > FW_COM_BUFFER_MAX_SIZE) {
286 // Record size is too big for com buffer
287 status = Fw::FW_DESERIALIZE_SIZE_MISMATCH;
288 }
289 309 return status;
290 }
291
292 307 Fw::SerializeStatus CmdSequencerComponentImpl::FPrimeSequence ::copyCommand(Fw::ComBuffer& comBuffer,
293 const U32 recordSize) {
294 307 Fw::LinearBufferBase& buffer = this->m_buffer;
295
1/1
✓ Branch 5 taken 307 times.
307 comBuffer.resetSer();
296 307 FwSizeType size = recordSize;
297
1/1
✓ Branch 5 taken 307 times.
307 Fw::SerializeStatus status = comBuffer.setBuffLen(recordSize);
298 307 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
299
1/1
✓ Branch 12 taken 307 times.
307 status = buffer.deserializeTo(comBuffer.getBuffAddr(), size, Fw::Serialization::OMIT_LENGTH);
300 307 return status;
301 }
302
303 65 bool CmdSequencerComponentImpl::FPrimeSequence ::validateRecords() {
304 65 Fw::LinearBufferBase& buffer = this->m_buffer;
305 65 const U32 numRecords = this->m_header.m_numRecords;
306
1/1
✓ Branch 2 taken 65 times.
65 Sequence::Record record;
307
308
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 63 times.
65 if (numRecords == 0) {
309
1/1
✓ Branch 4 taken 2 times.
2 this->m_events.noRecords();
310 2 return false;
311 }
312
313 // Deserialize all records
314
2/2
✓ Branch 0 taken 248 times.
✓ Branch 1 taken 55 times.
303 for (U32 recordNumber = 0; recordNumber < numRecords; recordNumber++) {
315
1/1
✓ Branch 4 taken 248 times.
248 Fw::SerializeStatus status = this->deserializeRecord(record);
316
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 240 times.
248 if (status != Fw::FW_SERIALIZE_OK) {
317
1/1
✓ Branch 4 taken 8 times.
8 this->m_events.recordInvalid(recordNumber, status);
318 8 return false;
319 }
320 }
321 // Check there is no data left
322
1/1
✓ Branch 7 taken 55 times.
55 const FwSizeType buffLeftSize = buffer.getDeserializeSizeLeft();
323
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 54 times.
55 if (buffLeftSize > 0) {
324
1/1
✓ Branch 4 taken 1 times.
1 this->m_events.recordMismatch(numRecords, static_cast<U32>(buffLeftSize));
325 1 return false;
326 }
327 // Rewind deserialization
328
1/1
✓ Branch 7 taken 54 times.
54 buffer.resetDeser();
329
330 54 return true;
331 65 }
332
333 } // namespace Svc
334