diff --git a/src/fsfw/cfdp/handler/SourceHandler.cpp b/src/fsfw/cfdp/handler/SourceHandler.cpp index e31903ae..3ce1b898 100644 --- a/src/fsfw/cfdp/handler/SourceHandler.cpp +++ b/src/fsfw/cfdp/handler/SourceHandler.cpp @@ -44,7 +44,6 @@ cfdp::SourceHandler::SourceHandler(SourceHandlerParams params, FsfwParams fsfwPa cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() { ReturnValue_t result; if (step == TransactionStep::IDLE) { - fsmResult.packetsSent = 0; step = TransactionStep::TRANSACTION_START; } if (step == TransactionStep::TRANSACTION_START) { @@ -66,11 +65,14 @@ cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() { return fsmResult; } if (step == TransactionStep::SENDING_FILE_DATA) { - result = prepareAndSendNextFileDataPdu(); + bool noFdPdu = false; + result = prepareAndSendNextFileDataPdu(noFdPdu); if (result != OK) { // TODO: Error handling } - return fsmResult; + if (!noFdPdu) { + return fsmResult; + } } if (step == TransactionStep::SENDING_EOF) { result = prepareAndSendEofPdu(); @@ -99,6 +101,7 @@ cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::fsmNacked() { } cfdp::SourceHandler::FsmResult& cfdp::SourceHandler::stateMachine() { + fsmResult.packetsSent = 0; if (state == cfdp::CfdpState::IDLE) { return fsmResult; } @@ -216,19 +219,20 @@ ReturnValue_t cfdp::SourceHandler::prepareAndSendMetadataPdu() { if (result != OK) { return result; } - fsmResult.packetsSent += 1; // Advance FSM if everything works step = TransactionStep::SENDING_FILE_DATA; return OK; } -ReturnValue_t cfdp::SourceHandler::prepareAndSendNextFileDataPdu() { +ReturnValue_t cfdp::SourceHandler::prepareAndSendNextFileDataPdu(bool& noFileDataPdu) { cfdp::Fss offset(transactionParams.progress); uint64_t readLen; uint64_t fileSize = transactionParams.fileSize.value(); + noFileDataPdu = false; if (fileSize == 0) { // We are done, no need to send file data PDUs for an empty file. step = TransactionStep::SENDING_EOF; + noFileDataPdu = true; return OK; } if (fileSize < transactionParams.remoteCfg.maxFileSegmentLen) { @@ -292,7 +296,7 @@ ReturnValue_t cfdp::SourceHandler::initialize() { return OK; } -ReturnValue_t cfdp::SourceHandler::sendGenericPdu(const SerializeIF& pdu) const { +ReturnValue_t cfdp::SourceHandler::sendGenericPdu(const SerializeIF& pdu) { uint8_t* dataPtr; store_address_t storeId; ReturnValue_t result = @@ -307,7 +311,12 @@ ReturnValue_t cfdp::SourceHandler::sendGenericPdu(const SerializeIF& pdu) const return result; } TmTcMessage tmMsg(storeId); - return fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &tmMsg); + result = + fsfwParams.msgQueue->sendMessage(fsfwParams.packetDest.getReportReceptionQueue(), &tmMsg); + if (result == OK) { + fsmResult.packetsSent += 1; + } + return result; } ReturnValue_t cfdp::SourceHandler::noticeOfCompletion() { diff --git a/src/fsfw/cfdp/handler/SourceHandler.h b/src/fsfw/cfdp/handler/SourceHandler.h index c31ebc26..afbbdf1f 100644 --- a/src/fsfw/cfdp/handler/SourceHandler.h +++ b/src/fsfw/cfdp/handler/SourceHandler.h @@ -96,12 +96,12 @@ class SourceHandler { FsmResult& fsmNacked(); ReturnValue_t checksumGeneration(); ReturnValue_t prepareAndSendMetadataPdu(); - ReturnValue_t prepareAndSendNextFileDataPdu(); + ReturnValue_t prepareAndSendNextFileDataPdu(bool& noFileDataPdu); ReturnValue_t prepareAndSendEofPdu(); ReturnValue_t noticeOfCompletion(); ReturnValue_t reset(); - [[nodiscard]] ReturnValue_t sendGenericPdu(const SerializeIF& pdu) const; + [[nodiscard]] ReturnValue_t sendGenericPdu(const SerializeIF& pdu); }; } // namespace cfdp diff --git a/unittests/cfdp/handler/testSourceHandler.cpp b/unittests/cfdp/handler/testSourceHandler.cpp index ec93f2bf..a46eae44 100644 --- a/unittests/cfdp/handler/testSourceHandler.cpp +++ b/unittests/cfdp/handler/testSourceHandler.cpp @@ -2,15 +2,12 @@ #include #include "fsfw/cfdp.h" -#include "fsfw/cfdp/CfdpMessage.h" #include "fsfw/cfdp/handler/PutRequest.h" #include "fsfw/cfdp/handler/SourceHandler.h" #include "fsfw/cfdp/pdu/EofPduCreator.h" -#include "fsfw/cfdp/pdu/FileDataCreator.h" +#include "fsfw/cfdp/pdu/EofPduReader.h" #include "fsfw/cfdp/pdu/MetadataPduCreator.h" #include "fsfw/cfdp/pdu/MetadataPduReader.h" -#include "fsfw/globalfunctions/arrayprinter.h" -#include "fsfw/storagemanager/StorageManagerIF.h" #include "fsfw/tmtcservices/TmTcMessage.h" #include "fsfw/util/SeqCountProvider.h" #include "mocks/AcceptsTmMock.h" @@ -68,26 +65,50 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") { CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK); SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine(); - // Verify metadata PDU was sent. - CHECK(fsmResult.packetsSent == 1); - CHECK(mqMock.numberOfSentMessages() == 1); TmTcMessage tmtcMessage; - REQUIRE(mqMock.getNextSentMessage(destQueueId, tmtcMessage) == OK); - auto accessor = tmStore.getData(tmtcMessage.getStorageId()); - REQUIRE(accessor.first == OK); - const uint8_t* pduPtr = accessor.second.data(); - CHECK(accessor.second.size() == 55); - MetadataGenericInfo metadataInfo; - MetadataPduReader metadataReader(pduPtr, accessor.second.size(), metadataInfo, nullptr, 0); - REQUIRE(metadataReader.parseData() == OK); - std::string srcNameRead = metadataReader.getSourceFileName().getString(); - CHECK(srcNameRead == srcFileName); - std::string destNameRead = metadataReader.getDestFileName().getString(); - CHECK(destNameRead == destFileName); - CHECK(metadataInfo.getChecksumType() == ChecksumType::NULL_CHECKSUM); - CHECK(metadataInfo.getFileSize().value() == 0); - CHECK(!metadataInfo.isClosureRequested()); + const uint8_t* pduPtr; + // Verify metadata PDU was sent. + { + CHECK(fsmResult.packetsSent == 1); + CHECK(mqMock.numberOfSentMessages() == 1); + REQUIRE(mqMock.getNextSentMessage(destQueueId, tmtcMessage) == OK); + auto accessor = tmStore.getData(tmtcMessage.getStorageId()); + REQUIRE(accessor.first == OK); + pduPtr = accessor.second.data(); + CHECK(accessor.second.size() == 55); + MetadataGenericInfo metadataInfo; + MetadataPduReader metadataReader(pduPtr, accessor.second.size(), metadataInfo, nullptr, 0); + REQUIRE(metadataReader.parseData() == OK); + std::string srcNameRead = metadataReader.getSourceFileName().getString(); + CHECK(srcNameRead == srcFileName); + std::string destNameRead = metadataReader.getDestFileName().getString(); + CHECK(destNameRead == destFileName); + CHECK(metadataInfo.getChecksumType() == ChecksumType::NULL_CHECKSUM); + CHECK(metadataInfo.getFileSize().value() == 0); + CHECK(!metadataInfo.isClosureRequested()); + } // Verify EOF PDU was sent. No file data PDU is sent for an empty file. + { + mqMock.clearMessages(); + fsmResult = sourceHandler.stateMachine(); + CHECK(fsmResult.packetsSent == 1); + CHECK(mqMock.numberOfSentMessages() == 1); + REQUIRE(mqMock.getNextSentMessage(destQueueId, tmtcMessage) == OK); + auto accessor = tmStore.getData(tmtcMessage.getStorageId()); + REQUIRE(accessor.first == OK); + pduPtr = accessor.second.data(); + // 10 byte PDU header, 1 byte directive field, 1 byte condition code, 4 byte checksum, + // 4 byte FSS + CHECK(accessor.second.size() == 20); + EofInfo eofInfo; + EofPduReader eofReader(pduPtr, accessor.second.size(), eofInfo); + REQUIRE(eofReader.parseData() == OK); + CHECK(eofInfo.getChecksum() == 0); + CHECK(eofInfo.getConditionCode() == ConditionCode::NO_ERROR); + CHECK(eofInfo.getFileSize().value() == 0); + } + CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE); + CHECK(sourceHandler.getState() == CfdpState::IDLE); } } \ No newline at end of file