diff --git a/unittests/cfdp/handler/testSourceHandler.cpp b/unittests/cfdp/handler/testSourceHandler.cpp index e7f62def..c268130b 100644 --- a/unittests/cfdp/handler/testSourceHandler.cpp +++ b/unittests/cfdp/handler/testSourceHandler.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "fsfw/cfdp.h" #include "fsfw/cfdp/handler/PutRequest.h" @@ -26,6 +27,8 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") { using namespace cfdp; using namespace returnvalue; using namespace std::filesystem; + const size_t MAX_FILE_SEGMENT_SIZE = 255; + MessageQueueId_t destQueueId = 2; AcceptsTmMock tmReceiver(destQueueId); MessageQueueMock mqMock(destQueueId); @@ -48,6 +51,7 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") { auto sourceHandler = SourceHandler(dp, fp); RemoteEntityCfg cfg; + cfg.maxFileSegmentLen = MAX_FILE_SEGMENT_SIZE; EntityId id(cfdp::WidthInBytes::TWO_BYTES, 5); cfg.remoteId = id; std::string srcFileName = "/tmp/cfdp-test.txt"; @@ -138,6 +142,8 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") { // Verify metadata PDU was sent. genericMetadataCheck(fsmResult, expectedFileSize); + + // Verify that a small file data PDU was sent. fsmResult = sourceHandler.stateMachine(); TmTcMessage tmtcMessage; const uint8_t* pduPtr; @@ -167,5 +173,61 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") { CHECK(sourceHandler.getState() == CfdpState::IDLE); } - SECTION("Transfer two segment file") {} + SECTION("Transfer two segment file") { + // Create 400 bytes of random data. This should result in two file segments, with one + // having the maximum size. + std::random_device dev; + std::mt19937 rng(dev()); + std::uniform_int_distribution distU8(0, 255); + std::array largerFileData{}; + for (auto& val : largerFileData) { + val = distU8(rng); + } + size_t expectedFileSize = largerFileData.size(); + fsMock.createFile(srcFileNameFs); + FileOpParams params(srcFileName.c_str(), expectedFileSize); + fsMock.writeToFile(params, reinterpret_cast(largerFileData.data())); + CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK); + SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine(); + // Verify metadata PDU was sent. + genericMetadataCheck(fsmResult, expectedFileSize); + + // Check first file data PDU. It should have the maximum file segment size. + fsmResult = sourceHandler.stateMachine(); + TmTcMessage tmtcMessage; + const uint8_t* pduPtr; + FileDataInfo fdInfo; + auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr); + { + FileDataReader fdReader(pduPtr, accessor.second.size(), fdInfo); + // 10 byte PDU header, 4 byte offset, 255 byte file data + CHECK(accessor.second.size() == 269); + CHECK(fdReader.parseData() == OK); + CHECK(fdInfo.getOffset().value() == 0); + size_t fileSize = 0; + const uint8_t* fileData = fdInfo.getFileData(&fileSize); + // Maximum file segment size. + REQUIRE(fileSize == MAX_FILE_SEGMENT_SIZE); + for (unsigned i = 0; i < fileSize; i++) { + CHECK(fileData[i] == largerFileData[i]); + } + } + mqMock.clearMessages(); + + // Check second file data PDU. + fsmResult = sourceHandler.stateMachine(); + accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr); + FileDataReader fdReader(pduPtr, accessor.second.size(), fdInfo); + // 10 byte PDU header, 4 byte offset, remaining file data (400 - 255 == 145). + CHECK(accessor.second.size() == 10 + 4 + largerFileData.size() - MAX_FILE_SEGMENT_SIZE); + CHECK(fdReader.parseData() == OK); + CHECK(fdInfo.getOffset().value() == MAX_FILE_SEGMENT_SIZE); + size_t fileDataSize = 0; + const uint8_t* fileData = fdInfo.getFileData(&fileDataSize); + // Maximum file segment size. + REQUIRE(fileDataSize == largerFileData.size() - MAX_FILE_SEGMENT_SIZE); + for (unsigned i = 0; i < fileDataSize; i++) { + CHECK(fileData[i] == largerFileData[MAX_FILE_SEGMENT_SIZE + i]); + } + } } \ No newline at end of file