GCC Code Coverage Report


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