Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions Svc/FileWorker/FileWorker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,16 @@ void FileWorker ::writeIn_handler(FwIndexType portNum,
fileName[sizeof(fileName) - 1] = 0; // guarantee termination

// Write
bool isWrite = this->writeBufferToFile(buffer, fileName, offsetBytes, append);
const bool isWrite = this->writeBufferToFile(buffer, fileName, offsetBytes, append);
if (isWrite) {
this->writeBufferHashToFile(buffer, fileName, offsetBytes, append);
}

this->writeDoneOut_out(0, FW_STATUS_DONE_WRITE, buffer.getSize());
// Report the actual outcome of the write. A failed writeBufferToFile (open
// failure, permission denied, disk full, partial write) must not be reported
// to ground as a successful FW_STATUS_DONE_WRITE.
const FileWorkerStatus writeStatus = isWrite ? FW_STATUS_DONE_WRITE : FW_STATUS_FAILED_TO_WRITE;
this->writeDoneOut_out(0, writeStatus, isWrite ? buffer.getSize() : 0);
this->m_state = FW_STATE_IDLE;
return;
}
Expand Down Expand Up @@ -288,6 +292,11 @@ Svc ::FileWorkerReadStatus FileWorker ::readFileBytes(Fw::Buffer& buffer,
Os::File::Status ret = file.read(buffer.getData() + bytesRead, readAmtActual);

if (Os::File::OP_OK != ret || readAmt != readAmtActual) {
// Count the bytes actually transferred so ReadError telemetry reports
// the true amount. A short read stays an error on purpose: FileWorker
// reads a fixed, caller-specified size and must not silently accept a
// file shorter than expected (e.g. truncated mid-read).
bytesRead += readAmtActual;
return FileWorkerReadStatus::FW_READ_ERROR;
}

Expand Down
5 changes: 5 additions & 0 deletions Svc/FileWorker/test/ut/FileWorkerErrTestMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ TEST(Nominal, testWriteErr) {
tester.testWriteErr();
}

TEST(Nominal, testWriteErrStatusReported) {
Svc::FileWorkerTester tester;
tester.testWriteErrStatusReported();
}

TEST(Nominal, testWriteHashErr) {
Svc::FileWorkerTester tester;
tester.testWriteHashErr();
Expand Down
29 changes: 29 additions & 0 deletions Svc/FileWorker/test/ut/FileWorkerErrTester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,35 @@ void FileWorkerTester ::testWriteErr() {
fTest.setOpen(Os::FileInterface::OP_OK);
}

// Regression test: when the underlying write fails, writeIn must report a
// failure status on writeDoneOut rather than FW_STATUS_DONE_WRITE. Drives the
// full writeIn port handler (not just the writeBufferToFile helper) so the
// status-propagation path is exercised.
void FileWorkerTester ::testWriteErrStatusReported() {
FwSizeType dataSize = 1024;
U8 data[dataSize];
for (FwSizeType i = 0; i < dataSize; i++) {
data[i] = static_cast<U8>(i % 256);
}
Fw::Buffer buffer(data, dataSize);
Fw::String fname = "testwrite.txt";
FwSizeType offsetBytes = 0;

// Force the write's open() to fail so writeBufferToFile returns false.
this->clearHistory();
fTest.setOpen(Os::FileInterface::INVALID_MODE);

this->invoke_to_writeIn(0, fname, buffer, offsetBytes, false);
this->component.doDispatch();

// The write failed, so ground must be told it failed.
ASSERT_from_writeDoneOut_SIZE(1);
ASSERT_from_writeDoneOut(0, FileWorkerStatus::FW_STATUS_FAILED_TO_WRITE, 0);
ASSERT_EQ(this->component.m_state, FileWorkerState::FW_STATE_IDLE);

fTest.setOpen(Os::FileInterface::OP_OK);
}

void FileWorkerTester ::testWriteHashErr() {
FwSizeType offsetBytes = 0;
const char* fnameChar = "testfile.txt";
Expand Down
1 change: 1 addition & 0 deletions Svc/FileWorker/test/ut/FileWorkerErrTester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class FileWorkerTester final : public FileWorkerGTestBase {
void testReadErr();
void testVerifyErr();
void testWriteErr();
void testWriteErrStatusReported();
void testWriteHashErr();

// Input-validation paths (assert -> event/return-status conversions)
Expand Down
Loading