From 6c6b5520599f4855570c22db91b3bb5226173abe Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 3 Aug 2023 17:43:03 +0200 Subject: [PATCH] start small file transfer test --- src/fsfw/cfdp/handler/SourceHandler.cpp | 9 +- src/fsfw/cfdp/handler/SourceHandler.h | 1 + src/fsfw/filesystem/HasFileSystemIF.h | 2 +- unittests/cfdp/handler/testSourceHandler.cpp | 133 +++++++++++-------- unittests/mocks/FilesystemMock.cpp | 8 +- 5 files changed, 94 insertions(+), 59 deletions(-) diff --git a/src/fsfw/cfdp/handler/SourceHandler.cpp b/src/fsfw/cfdp/handler/SourceHandler.cpp index 3ce1b898..5d6f0929 100644 --- a/src/fsfw/cfdp/handler/SourceHandler.cpp +++ b/src/fsfw/cfdp/handler/SourceHandler.cpp @@ -204,6 +204,11 @@ ReturnValue_t cfdp::SourceHandler::transactionStart(PutRequest& putRequest, Remo if (fileSize > UINT32_MAX) { transactionParams.pduConf.largeFile = true; } + if (fileSize == 0) { + transactionParams.checksumType = ChecksumType::NULL_CHECKSUM; + } else { + transactionParams.checksumType = ChecksumType::CRC_32; + } transactionParams.fileSize.setFileSize(fileSize, transactionParams.pduConf.largeFile); transactionParams.remoteCfg = cfg; return OK; @@ -212,7 +217,9 @@ ReturnValue_t cfdp::SourceHandler::transactionStart(PutRequest& putRequest, Remo ReturnValue_t cfdp::SourceHandler::prepareAndSendMetadataPdu() { cfdp::StringLv sourceName(transactionParams.sourceName.data(), transactionParams.sourceNameSize); cfdp::StringLv destName(transactionParams.destName.data(), transactionParams.destNameSize); - auto metadataInfo = MetadataGenericInfo(transactionParams.fileSize); + auto metadataInfo = + MetadataGenericInfo(transactionParams.closureRequested, transactionParams.checksumType, + transactionParams.fileSize); auto metadataPdu = MetadataPduCreator(transactionParams.pduConf, metadataInfo, sourceName, destName, nullptr, 0); ReturnValue_t result = sendGenericPdu(metadataPdu); diff --git a/src/fsfw/cfdp/handler/SourceHandler.h b/src/fsfw/cfdp/handler/SourceHandler.h index afbbdf1f..dfdf94ad 100644 --- a/src/fsfw/cfdp/handler/SourceHandler.h +++ b/src/fsfw/cfdp/handler/SourceHandler.h @@ -73,6 +73,7 @@ class SourceHandler { cfdp::Fss fileSize; size_t progress = 0; bool closureRequested = false; + ChecksumType checksumType = ChecksumType::NULL_CHECKSUM; RemoteEntityCfg remoteCfg; PduConfig pduConf; cfdp::TransactionId id{}; diff --git a/src/fsfw/filesystem/HasFileSystemIF.h b/src/fsfw/filesystem/HasFileSystemIF.h index db3e8ddf..3f7088d6 100644 --- a/src/fsfw/filesystem/HasFileSystemIF.h +++ b/src/fsfw/filesystem/HasFileSystemIF.h @@ -17,7 +17,7 @@ struct FilesystemParams { }; struct FileOpParams { - FileOpParams(const char* path, size_t size) : fsParams(path), size(size) {} + FileOpParams(const char* path, size_t opSize) : fsParams(path), size(opSize) {} [[nodiscard]] const char* path() const { return fsParams.path; } diff --git a/unittests/cfdp/handler/testSourceHandler.cpp b/unittests/cfdp/handler/testSourceHandler.cpp index 8acdcd4c..b76bc24a 100644 --- a/unittests/cfdp/handler/testSourceHandler.cpp +++ b/unittests/cfdp/handler/testSourceHandler.cpp @@ -43,75 +43,102 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") { fp.tcStore = &tcStore; fp.tmStore = &tmStore; auto sourceHandler = SourceHandler(dp, fp); + + RemoteEntityCfg cfg; + EntityId id(cfdp::WidthInBytes::TWO_BYTES, 5); + cfg.remoteId = id; + std::string srcFileName = "/tmp/cfdp-test.txt"; + std::string destFileName = "/tmp/cfdp-test2.txt"; + FilesystemParams srcFileNameFs(srcFileName.c_str()); + fsMock.createFile(srcFileNameFs); + cfdp::StringLv srcNameLv(srcFileNameFs.path, std::strlen(srcFileNameFs.path)); + FilesystemParams destFileNameFs(destFileName.c_str()); + cfdp::StringLv destNameLv(destFileNameFs.path, std::strlen(destFileNameFs.path)); + PutRequest putRequest(id, srcNameLv, destNameLv); CHECK(sourceHandler.initialize() == OK); + auto genericMetadataCheck = [&](SourceHandler::FsmResult& fsmResult, size_t expectedFileSize) { + TmTcMessage tmtcMessage; + const uint8_t* pduPtr; + 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); + if (expectedFileSize == 0) { + CHECK(metadataInfo.getChecksumType() == ChecksumType::NULL_CHECKSUM); + } else { + CHECK(metadataInfo.getChecksumType() == ChecksumType::CRC_32); + } + CHECK(metadataInfo.getFileSize().value() == expectedFileSize); + CHECK(!metadataInfo.isClosureRequested()); + mqMock.clearMessages(); + }; + auto genericEofCheck = [&](SourceHandler::FsmResult& fsmResult, size_t expectedFileSize, + uint32_t expectedChecksum) { + TmTcMessage tmtcMessage; + const uint8_t* pduPtr; + 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() == expectedChecksum); + CHECK(eofInfo.getConditionCode() == ConditionCode::NO_ERROR); + CHECK(eofInfo.getFileSize().value() == expectedFileSize); + }; SECTION("Test Basic") { CHECK(sourceHandler.getState() == CfdpState::IDLE); CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE); } SECTION("Transfer empty file") { - RemoteEntityCfg cfg; - EntityId id(cfdp::WidthInBytes::TWO_BYTES, 5); - cfg.remoteId = id; - std::string srcFileName = "/tmp/cfdp-test.txt"; - std::string destFileName = "/tmp/cfdp-test2.txt"; - FilesystemParams srcFileNameFs(srcFileName.c_str()); - fsMock.createFile(srcFileNameFs); - cfdp::StringLv srcNameLv(srcFileNameFs.path, std::strlen(srcFileNameFs.path)); - FilesystemParams destFileNameFs(destFileName.c_str()); - cfdp::StringLv destNameLv(destFileNameFs.path, std::strlen(destFileNameFs.path)); - PutRequest putRequest(id, srcNameLv, destNameLv); CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK); + SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine(); - - TmTcMessage tmtcMessage; - 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()); - } + genericMetadataCheck(fsmResult, 0); + fsmResult = sourceHandler.stateMachine(); // 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); - } + genericEofCheck(fsmResult, 0, 0); + CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE); CHECK(sourceHandler.getState() == CfdpState::IDLE); } - SECTION("Transfer small file") {} + SECTION("Transfer small file") { + fsMock.createFile(srcFileNameFs); + std::string fileContent = "hello world\n"; + size_t expectedFileSize = fileContent.size(); + FileOpParams params(srcFileName.c_str(), expectedFileSize); + fsMock.writeToFile(params, reinterpret_cast(fileContent.data())); + CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK); + SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine(); + + // Verify metadata PDU was sent. + genericMetadataCheck(fsmResult, expectedFileSize); + fsmResult = sourceHandler.stateMachine(); + // TODO: Verify one file data PDU was sent. + + // TODO: Verify one EOF PDU was sent. + } + SECTION("Transfer two segment file") {} } \ No newline at end of file diff --git a/unittests/mocks/FilesystemMock.cpp b/unittests/mocks/FilesystemMock.cpp index 6efa12f2..faee7e71 100644 --- a/unittests/mocks/FilesystemMock.cpp +++ b/unittests/mocks/FilesystemMock.cpp @@ -80,7 +80,7 @@ ReturnValue_t FilesystemMock::removeDirectory(FilesystemParams params, bool dele ReturnValue_t FilesystemMock::rename(const char *oldPath, const char *newPath, FileSystemArgsIF *args) { - renameQueue.push(RenameInfo(oldPath, newPath)); + renameQueue.emplace(oldPath, newPath); return returnvalue::OK; } @@ -90,7 +90,7 @@ void FilesystemMock::createOrAddToFile(FileOpParams params, const uint8_t *data) if (iter == fileMap.end()) { FileSegmentQueue queue; if (params.size > 0) { - queue.push(FileWriteInfo(filename, params.offset, data, params.size)); + queue.emplace(filename, params.offset, data, params.size); } FileInfo info; info.fileSegQueue = queue; @@ -100,7 +100,7 @@ void FilesystemMock::createOrAddToFile(FileOpParams params, const uint8_t *data) fileMap.emplace(filename, info); } else { FileInfo &info = iter->second; - info.fileSegQueue.push(FileWriteInfo(filename, params.offset, data, params.size)); + info.fileSegQueue.emplace(filename, params.offset, data, params.size); if (data == nullptr) { return; } @@ -149,7 +149,7 @@ bool FilesystemMock::isDirectory(const char *path) { return false; } bool FilesystemMock::getFileSize(FilesystemParams params, size_t &fileSize) { std::string filename(params.path); auto iter = fileMap.find(filename); - if (iter == fileMap.end()) { + if (iter != fileMap.end()) { fileSize = iter->second.fileRaw.size(); return true; }