GCC Code Coverage Report


Directory: Svc/CmdSequencer/
File: FPrimeSequence.cpp
Date: 2026-11-03 21:18:07
Exec Total Coverage
Lines: 199 209 95.2%
Functions: 23 23 100.0%
Branches: 126 138 91.3%

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