GCC Code Coverage Report


Directory: ./
File: Svc/ComLogger/ComLogger.cpp
Date: 2026-09-03 21:13:48
Exec Total Coverage
Lines: 114 117 97.4%
Functions: 11 12 91.7%
Branches: 72 86 83.7%

Line Branch Exec Source
1 // ----------------------------------------------------------------------
2 //
3 // ComLogger.cpp
4 //
5 // ----------------------------------------------------------------------
6
7 #include <Fw/FPrimeBasicTypes.hpp>
8 #include <Fw/Types/SerialBuffer.hpp>
9 #include <Fw/Types/StringUtils.hpp>
10 #include <Os/ValidateFile.hpp>
11 #include <Svc/ComLogger/ComLogger.hpp>
12 #include <cstdio>
13
14 namespace Svc {
15 static_assert(std::numeric_limits<U16>::max() <= std::numeric_limits<FwSizeType>::max(),
16 "U16 must fit in the positive range of FwSizeType");
17 // ----------------------------------------------------------------------
18 // Construction, initialization, and destruction
19 // ----------------------------------------------------------------------
20
21 5 ComLogger ::ComLogger(const char* compName, const char* incomingFilePrefix, U32 maxFileSize, bool storeBufferLength)
22 : ComLoggerComponentBase(compName),
23 5 m_maxFileSize(maxFileSize),
24 5 m_fileMode(CLOSED),
25 5 m_byteCount(0),
26 5 m_writeErrorOccurred(false),
27 5 m_openErrorOccurred(false),
28 5 m_storeBufferLength(storeBufferLength),
29
4/4
✓ Branch 9 taken 5 times.
✓ Branch 15 taken 5 times.
✓ Branch 21 taken 5 times.
✓ Branch 27 taken 5 times.
15 m_initialized(true) {
30
1/1
✓ Branch 4 taken 5 times.
5 this->init_log_file(incomingFilePrefix, maxFileSize, storeBufferLength);
31 5 }
32
33 2 ComLogger ::ComLogger(const char* compName)
34 : ComLoggerComponentBase(compName),
35
1/1
✓ Branch 4 taken 2 times.
2 m_filePrefix(),
36 2 m_maxFileSize(0),
37 2 m_fileMode(CLOSED),
38
1/1
✓ Branch 5 taken 2 times.
2 m_fileName(),
39
1/1
✓ Branch 5 taken 2 times.
2 m_hashFileName(),
40 2 m_byteCount(0),
41 2 m_writeErrorOccurred(false),
42 2 m_openErrorOccurred(false),
43 2 m_storeBufferLength(),
44
1/1
✓ Branch 10 taken 2 times.
6 m_initialized(false) {}
45
46 7 void ComLogger ::init_log_file(const char* incomingFilePrefix, U32 maxFileSize, bool storeBufferLength) {
47 7 FW_ASSERT(incomingFilePrefix != nullptr);
48 7 this->m_maxFileSize = maxFileSize;
49 7 this->m_storeBufferLength = storeBufferLength;
50
2/4
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
7 if (this->m_storeBufferLength) {
51 7 FW_ASSERT(maxFileSize > sizeof(U16), static_cast<FwAssertArgType>(maxFileSize));
52 }
53 // Assign the prefix checking if it is too big
54 7 Fw::FormatStatus formatStatus = this->m_filePrefix.format("%s", incomingFilePrefix);
55 7 FW_ASSERT(formatStatus == Fw::FormatStatus::SUCCESS);
56 7 this->m_initialized = true;
57 7 }
58
59 70 ComLogger ::~ComLogger() {
60 // Close file:
61 // this->closeFile();
62 // NOTE: the above did not work because we don't want to issue an event
63 // in the destructor. This can cause "virtual method called" segmentation
64 // faults.
65 // So I am copying part of that function here.
66
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 2 times.
14 if (OPEN == this->m_fileMode) {
67 // Close file:
68 10 this->m_file.close();
69
70 // Write out the hash file to disk:
71 10 this->writeHashFile();
72
73 // Update mode:
74 10 this->m_fileMode = CLOSED;
75 }
76 56 }
77
78 // ----------------------------------------------------------------------
79 // Handler implementations
80 // ----------------------------------------------------------------------
81
82 71 void ComLogger ::comIn_handler(FwIndexType portNum, Fw::ComBuffer& data, U32 context) {
83 71 FW_ASSERT(portNum == 0);
84
85 // Get length of buffer:
86 71 FwSizeType sizeNative = data.getSize();
87 // ComLogger only writes 16-bit sizes to save space
88 // on disk:
89 71 FW_ASSERT(sizeNative < 65536, static_cast<FwAssertArgType>(sizeNative));
90 71 U16 size = sizeNative & 0xFFFF;
91
92 // Close the file if it will be too big:
93
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 71 times.
✓ Branch 5 taken 57 times.
✓ Branch 6 taken 14 times.
71 if (OPEN == this->m_fileMode) {
94 57 U32 projectedByteCount = this->m_byteCount + size;
95
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 57 times.
✓ Branch 5 taken 43 times.
✓ Branch 6 taken 14 times.
57 if (this->m_storeBufferLength) {
96 43 projectedByteCount += static_cast<U32>(sizeof(size));
97 }
98
2/2
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 51 times.
57 if (projectedByteCount > this->m_maxFileSize) {
99 6 this->closeFile();
100 }
101 }
102
103 // Open the file if it there is not one open:
104
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 71 times.
✓ Branch 5 taken 20 times.
✓ Branch 6 taken 51 times.
71 if (CLOSED == this->m_fileMode) {
105 20 this->openFile();
106 }
107
108 // Write to the file if it is open:
109
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 71 times.
✓ Branch 5 taken 64 times.
✓ Branch 6 taken 7 times.
71 if (OPEN == this->m_fileMode) {
110 64 this->writeComBufferToFile(data, size);
111 }
112 71 }
113
114 6 void ComLogger ::CloseFile_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
115 6 this->closeFile();
116
2/2
✓ Branch 6 taken 6 times.
✓ Branch 9 taken 6 times.
6 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
117 6 }
118
119 void ComLogger ::pingIn_handler(const FwIndexType portNum, U32 key) {
120 // return key
121 this->pingOut_out(0, key);
122 }
123
124 21 void ComLogger ::openFile() {
125 21 FW_ASSERT(CLOSED == this->m_fileMode);
126
127
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 21 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 20 times.
21 if (!this->m_initialized) {
128
1/1
✓ Branch 5 taken 1 times.
1 this->log_WARNING_LO_FileNotInitialized();
129 1 return;
130 }
131
132 // Create filename:
133
1/1
✓ Branch 3 taken 20 times.
20 Fw::Time timestamp = getTime();
134
3/3
✓ Branch 6 taken 20 times.
✓ Branch 9 taken 20 times.
✓ Branch 13 taken 20 times.
80 Fw::FormatStatus formatStatus = this->m_fileName.format(
135 20 "%s_%" PRI_FwTimeBaseStoreType "_%" PRIu32 "_%06" PRIu32 ".com", this->m_filePrefix.toChar(),
136
1/1
✓ Branch 4 taken 20 times.
80 static_cast<FwTimeBaseStoreType>(timestamp.getTimeBase()), timestamp.getSeconds(), timestamp.getUSeconds());
137 20 FW_ASSERT(formatStatus == Fw::FormatStatus::SUCCESS);
138 formatStatus =
139
2/2
✓ Branch 6 taken 20 times.
✓ Branch 15 taken 20 times.
20 this->m_hashFileName.format("%s%s", this->m_fileName.toChar(), Utils::Hash::getFileExtensionString());
140 20 FW_ASSERT(formatStatus == Fw::FormatStatus::SUCCESS);
141
142
1/1
✓ Branch 12 taken 20 times.
20 Os::File::Status ret = m_file.open(this->m_fileName.toChar(), Os::File::OPEN_WRITE);
143
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 14 times.
20 if (Os::File::OP_OK != ret) {
144
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 4 times.
6 if (!this->m_openErrorOccurred) { // throttle this event, otherwise a positive
145 // feedback event loop can occur!
146
1/1
✓ Branch 8 taken 2 times.
2 this->log_WARNING_HI_FileOpenError(ret, this->m_fileName);
147 }
148 6 this->m_openErrorOccurred = true;
149 } else {
150 // Reset event throttle:
151 14 this->m_openErrorOccurred = false;
152
153 // Reset byte count:
154 14 this->m_byteCount = 0;
155
156 // Set mode:
157 14 this->m_fileMode = OPEN;
158 }
159 20 }
160
161 13 void ComLogger ::closeFile() {
162
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 5 times.
13 if (OPEN == this->m_fileMode) {
163 // Close file:
164 8 this->m_file.close();
165
166 // Write out the hash file to disk:
167 8 this->writeHashFile();
168
169 // Update mode:
170 8 this->m_fileMode = CLOSED;
171
172 // Send event:
173 8 this->log_DIAGNOSTIC_FileClosed(this->m_fileName);
174 }
175 13 }
176
177 64 void ComLogger ::writeComBufferToFile(Fw::ComBuffer& data, U16 size) {
178
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 64 times.
✓ Branch 5 taken 49 times.
✓ Branch 6 taken 15 times.
64 if (this->m_storeBufferLength) {
179 49 U8 buffer[sizeof(size)];
180
1/1
✓ Branch 2 taken 49 times.
49 Fw::SerialBuffer serialLength(&buffer[0], sizeof(size));
181
1/1
✓ Branch 2 taken 49 times.
49 Fw::SerializeStatus serStatus = serialLength.serializeFrom(size);
182 49 FW_ASSERT(serStatus == Fw::FW_SERIALIZE_OK, serStatus);
183 const bool lengthWritten =
184
2/2
✓ Branch 5 taken 49 times.
✓ Branch 10 taken 49 times.
49 this->writeToFile(serialLength.getBuffAddr(), static_cast<U16>(serialLength.getSize()));
185
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 6 times.
49 if (lengthWritten) {
186
1/1
✓ Branch 2 taken 43 times.
43 this->m_byteCount += static_cast<U32>(serialLength.getSize());
187 } else {
188 6 return;
189 }
190 49 }
191
192 // Write buffer to file:
193 58 const bool dataWritten = this->writeToFile(data.getBuffAddr(), size);
194
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 if (dataWritten) {
195 58 this->m_byteCount += size;
196 }
197 }
198
199 107 bool ComLogger ::writeToFile(void* data, U16 length) {
200 107 FwSizeType size = length;
201
1/1
✓ Branch 6 taken 107 times.
107 Os::File::Status ret = m_file.write(reinterpret_cast<const U8*>(data), size);
202
3/4
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 101 times.
107 if ((Os::File::OP_OK != ret) || (size != length)) {
203
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 4 times.
6 if (!this->m_writeErrorOccurred) { // throttle this event, otherwise a positive
204 // feedback event loop can occur!
205
1/1
✓ Branch 8 taken 2 times.
2 this->log_WARNING_HI_FileWriteError(ret, static_cast<U32>(size), length, this->m_fileName);
206 }
207 6 this->m_writeErrorOccurred = true;
208 6 return false;
209 }
210
211 101 this->m_writeErrorOccurred = false;
212 101 return true;
213 }
214
215 13 void ComLogger ::writeHashFile() {
216 Os::ValidateFile::Status validateStatus;
217 13 validateStatus = Os::ValidateFile::createValidation(this->m_fileName.toChar(), this->m_hashFileName.toChar());
218
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8 times.
13 if (Os::ValidateFile::VALIDATION_OK != validateStatus) {
219 5 this->log_WARNING_LO_FileValidationError(this->m_hashFileName, this->m_fileName, validateStatus);
220 }
221 13 }
222 } // namespace Svc
223