GCC Code Coverage Report


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