CFDP SOURCE handler #157

Merged
muellerr merged 107 commits from cfdp-source-handler into develop 2023-10-19 10:59:55 +02:00
2 changed files with 46 additions and 36 deletions
Showing only changes of commit 22df8f6147 - Show all commits

View File

@ -134,7 +134,7 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
} }
SECTION("Idle State Machine Iteration") { SECTION("Idle State Machine Iteration") {
auto res = destHandler.performStateMachine(); auto res = destHandler.stateMachine();
CHECK(res.result == OK); CHECK(res.result == OK);
CHECK(res.callStatus == CallStatus::CALL_AFTER_DELAY); CHECK(res.callStatus == CallStatus::CALL_AFTER_DELAY);
CHECK(res.errors == 0); CHECK(res.errors == 0);
@ -143,23 +143,23 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
} }
SECTION("Empty File Transfer") { SECTION("Empty File Transfer") {
const DestHandler::FsmResult& res = destHandler.performStateMachine(); const DestHandler::FsmResult& res = destHandler.stateMachine();
CHECK(res.result == OK); CHECK(res.result == OK);
Fss cfdpFileSize(0); Fss cfdpFileSize(0);
metadataPreparation(cfdpFileSize, ChecksumType::NULL_CHECKSUM); metadataPreparation(cfdpFileSize, ChecksumType::NULL_CHECKSUM);
destHandler.performStateMachine(); destHandler.stateMachine();
metadataCheck(res, "hello.txt", "hello-cpy.txt", 0); metadataCheck(res, "hello.txt", "hello-cpy.txt", 0);
destHandler.performStateMachine(); destHandler.stateMachine();
REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY); REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY);
auto transactionId = destHandler.getTransactionId(); auto transactionId = destHandler.getTransactionId();
eofPreparation(cfdpFileSize, 0); eofPreparation(cfdpFileSize, 0);
// After EOF, operation is done because no closure was requested // After EOF, operation is done because no closure was requested
destHandler.performStateMachine(); destHandler.stateMachine();
eofCheck(res, transactionId); eofCheck(res, transactionId);
} }
SECTION("Small File Transfer") { SECTION("Small File Transfer") {
const DestHandler::FsmResult& res = destHandler.performStateMachine(); const DestHandler::FsmResult& res = destHandler.stateMachine();
CHECK(res.result == OK); CHECK(res.result == OK);
std::string fileData = "hello test data"; std::string fileData = "hello test data";
etl::crc32 crcCalc; etl::crc32 crcCalc;
@ -167,9 +167,9 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
uint32_t crc32 = crcCalc.value(); uint32_t crc32 = crcCalc.value();
Fss cfdpFileSize(fileData.size()); Fss cfdpFileSize(fileData.size());
metadataPreparation(cfdpFileSize, ChecksumType::CRC_32); metadataPreparation(cfdpFileSize, ChecksumType::CRC_32);
destHandler.performStateMachine(); destHandler.stateMachine();
metadataCheck(res, "hello.txt", "hello-cpy.txt", fileData.size()); metadataCheck(res, "hello.txt", "hello-cpy.txt", fileData.size());
destHandler.performStateMachine(); destHandler.stateMachine();
REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY); REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY);
auto transactionId = destHandler.getTransactionId(); auto transactionId = destHandler.getTransactionId();
Fss offset(0); Fss offset(0);
@ -180,16 +180,16 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
REQUIRE(fdPduCreator.serialize(buf, serLen, fdPduCreator.getSerializedSize()) == OK); REQUIRE(fdPduCreator.serialize(buf, serLen, fdPduCreator.getSerializedSize()) == OK);
PacketInfo packetInfo(fdPduCreator.getPduType(), storeId, std::nullopt); PacketInfo packetInfo(fdPduCreator.getPduType(), storeId, std::nullopt);
packetInfoList.push_back(packetInfo); packetInfoList.push_back(packetInfo);
destHandler.performStateMachine(); destHandler.stateMachine();
fileDataPduCheck(res, {storeId}); fileDataPduCheck(res, {storeId});
eofPreparation(cfdpFileSize, crc32); eofPreparation(cfdpFileSize, crc32);
// After EOF, operation is done because no closure was requested // After EOF, operation is done because no closure was requested
destHandler.performStateMachine(); destHandler.stateMachine();
eofCheck(res, transactionId); eofCheck(res, transactionId);
} }
SECTION("Segmented File Transfer") { SECTION("Segmented File Transfer") {
const DestHandler::FsmResult& res = destHandler.performStateMachine(); const DestHandler::FsmResult& res = destHandler.stateMachine();
CHECK(res.result == OK); CHECK(res.result == OK);
std::random_device dev; std::random_device dev;
std::mt19937 rng(dev()); std::mt19937 rng(dev());
@ -203,9 +203,9 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
uint32_t crc32 = crcCalc.value(); uint32_t crc32 = crcCalc.value();
Fss cfdpFileSize(largerFileData.size()); Fss cfdpFileSize(largerFileData.size());
metadataPreparation(cfdpFileSize, ChecksumType::CRC_32); metadataPreparation(cfdpFileSize, ChecksumType::CRC_32);
destHandler.performStateMachine(); destHandler.stateMachine();
metadataCheck(res, "hello.txt", "hello-cpy.txt", largerFileData.size()); metadataCheck(res, "hello.txt", "hello-cpy.txt", largerFileData.size());
destHandler.performStateMachine(); destHandler.stateMachine();
REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY); REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY);
auto transactionId = destHandler.getTransactionId(); auto transactionId = destHandler.getTransactionId();
@ -234,11 +234,11 @@ TEST_CASE("CFDP Dest Handler", "[cfdp]") {
packetInfoList.push_back(packetInfo); packetInfoList.push_back(packetInfo);
} }
destHandler.performStateMachine(); destHandler.stateMachine();
fileDataPduCheck(res, idsToCheck); fileDataPduCheck(res, idsToCheck);
eofPreparation(cfdpFileSize, crc32); eofPreparation(cfdpFileSize, crc32);
// After EOF, operation is done because no closure was requested // After EOF, operation is done because no closure was requested
destHandler.performStateMachine(); destHandler.stateMachine();
eofCheck(res, transactionId); eofCheck(res, transactionId);
} }
} }

View File

@ -63,7 +63,7 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
PutRequest putRequest(remoteId, srcNameLv, destNameLv); PutRequest putRequest(remoteId, srcNameLv, destNameLv);
CHECK(sourceHandler.initialize() == OK); CHECK(sourceHandler.initialize() == OK);
auto onePduSentCheck = [&](SourceHandler::FsmResult& fsmResult, TmTcMessage& tmtcMessage, auto onePduSentCheck = [&](const SourceHandler::FsmResult& fsmResult, TmTcMessage& tmtcMessage,
const uint8_t** pduPtr) { const uint8_t** pduPtr) {
CHECK(fsmResult.errors == 0); CHECK(fsmResult.errors == 0);
CHECK(fsmResult.packetsSent == 1); CHECK(fsmResult.packetsSent == 1);
@ -74,8 +74,8 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
*pduPtr = accessor.second.data(); *pduPtr = accessor.second.data();
return std::move(accessor); return std::move(accessor);
}; };
auto genericMetadataCheck = [&](SourceHandler::FsmResult& fsmResult, size_t expectedFileSize, auto genericMetadataCheck = [&](const SourceHandler::FsmResult& fsmResult,
uint16_t expectedSeqNum) { size_t expectedFileSize, uint16_t expectedSeqNum) {
CHECK(fsmResult.errors == 0); CHECK(fsmResult.errors == 0);
TmTcMessage tmtcMessage; TmTcMessage tmtcMessage;
const uint8_t* pduPtr; const uint8_t* pduPtr;
@ -108,7 +108,7 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
CHECK(!metadataInfo.isClosureRequested()); CHECK(!metadataInfo.isClosureRequested());
mqMock.clearMessages(); mqMock.clearMessages();
}; };
auto genericEofCheck = [&](SourceHandler::FsmResult& fsmResult, size_t expectedFileSize, auto genericEofCheck = [&](const SourceHandler::FsmResult& fsmResult, size_t expectedFileSize,
uint32_t expectedChecksum, uint16_t expectedSeqNum) { uint32_t expectedChecksum, uint16_t expectedSeqNum) {
CHECK(fsmResult.errors == 0); CHECK(fsmResult.errors == 0);
TmTcMessage tmtcMessage; TmTcMessage tmtcMessage;
@ -126,12 +126,19 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
auto transactionId = TransactionId(localId, seqNum); auto transactionId = TransactionId(localId, seqNum);
CHECK(userMock.eofSentRecvd.size() == 1); CHECK(userMock.eofSentRecvd.size() == 1);
CHECK(userMock.eofSentRecvd.back() == transactionId); CHECK(userMock.eofSentRecvd.back() == transactionId);
CHECK(userMock.finishedRecvd.size() == 1);
CHECK(userMock.finishedRecvd.back().first == transactionId);
CHECK(eofInfo.getChecksum() == expectedChecksum); CHECK(eofInfo.getChecksum() == expectedChecksum);
CHECK(eofInfo.getConditionCode() == ConditionCode::NO_ERROR); CHECK(eofInfo.getConditionCode() == ConditionCode::NO_ERROR);
CHECK(eofInfo.getFileSize().value() == expectedFileSize); CHECK(eofInfo.getFileSize().value() == expectedFileSize);
}; };
auto genericNoticeOfCompletionCheck = [&](const SourceHandler::FsmResult& fsmResult,
uint16_t expectedSeqNum) {
CHECK(userMock.finishedRecvd.size() == 1);
CHECK(userMock.finishedRecvd.back().first ==
TransactionId(localId, TransactionSeqNum(cfdp::WidthInBytes::TWO_BYTES, expectedSeqNum)));
CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE);
CHECK(sourceHandler.getState() == CfdpState::IDLE);
};
SECTION("Test Basic") { SECTION("Test Basic") {
CHECK(sourceHandler.getState() == CfdpState::IDLE); CHECK(sourceHandler.getState() == CfdpState::IDLE);
CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE); CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE);
@ -141,16 +148,17 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK); CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK);
size_t expectedFileSize = 0; size_t expectedFileSize = 0;
SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine(); const SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine();
// Verify metadata PDU was sent. // Verify metadata PDU was sent.
genericMetadataCheck(fsmResult, expectedFileSize, 0); genericMetadataCheck(fsmResult, expectedFileSize, 0);
fsmResult = sourceHandler.stateMachine(); sourceHandler.stateMachine();
// Verify EOF PDU was sent. No file data PDU is sent for an empty file and the checksum is 0. // Verify EOF PDU was sent. No file data PDU is sent for an empty file and the checksum is 0.
genericEofCheck(fsmResult, expectedFileSize, 0, 0); genericEofCheck(fsmResult, expectedFileSize, 0, 0);
CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE); // Verify notice of completion.
CHECK(sourceHandler.getState() == CfdpState::IDLE); sourceHandler.stateMachine();
genericNoticeOfCompletionCheck(fsmResult, 0);
} }
SECTION("Transfer small file") { SECTION("Transfer small file") {
@ -161,13 +169,13 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
FileOpParams params(srcFileName.c_str(), expectedFileSize); FileOpParams params(srcFileName.c_str(), expectedFileSize);
fsMock.writeToFile(params, reinterpret_cast<const uint8_t*>(fileContent.data())); fsMock.writeToFile(params, reinterpret_cast<const uint8_t*>(fileContent.data()));
CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK); CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK);
SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine(); const SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine();
// Verify metadata PDU was sent. // Verify metadata PDU was sent.
genericMetadataCheck(fsmResult, expectedFileSize, expectedSeqNum); genericMetadataCheck(fsmResult, expectedFileSize, expectedSeqNum);
// Verify that a small file data PDU was sent. // Verify that a small file data PDU was sent.
fsmResult = sourceHandler.stateMachine(); sourceHandler.stateMachine();
TmTcMessage tmtcMessage; TmTcMessage tmtcMessage;
const uint8_t* pduPtr; const uint8_t* pduPtr;
auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr); auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr);
@ -185,15 +193,16 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
CHECK(dataReadBack == fileContent); CHECK(dataReadBack == fileContent);
mqMock.clearMessages(); mqMock.clearMessages();
fsmResult = sourceHandler.stateMachine(); sourceHandler.stateMachine();
etl::crc32 crcCalc; etl::crc32 crcCalc;
crcCalc.add(fileContent.data(), fileContent.data() + fileContent.size()); crcCalc.add(fileContent.data(), fileContent.data() + fileContent.size());
// Verify EOF PDU was sent. // Verify EOF PDU was sent.
genericEofCheck(fsmResult, expectedFileSize, crcCalc.value(), expectedSeqNum); genericEofCheck(fsmResult, expectedFileSize, crcCalc.value(), expectedSeqNum);
CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE); // Verify notice of completion.
CHECK(sourceHandler.getState() == CfdpState::IDLE); sourceHandler.stateMachine();
genericNoticeOfCompletionCheck(fsmResult, expectedSeqNum);
} }
SECTION("Transfer two segment file") { SECTION("Transfer two segment file") {
@ -212,12 +221,12 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
FileOpParams params(srcFileName.c_str(), expectedFileSize); FileOpParams params(srcFileName.c_str(), expectedFileSize);
fsMock.writeToFile(params, reinterpret_cast<const uint8_t*>(largerFileData.data())); fsMock.writeToFile(params, reinterpret_cast<const uint8_t*>(largerFileData.data()));
CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK); CHECK(sourceHandler.transactionStart(putRequest, cfg) == OK);
SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine(); const SourceHandler::FsmResult& fsmResult = sourceHandler.stateMachine();
// Verify metadata PDU was sent. // Verify metadata PDU was sent.
genericMetadataCheck(fsmResult, expectedFileSize, expectedSeqNum); genericMetadataCheck(fsmResult, expectedFileSize, expectedSeqNum);
// Check first file data PDU. It should have the maximum file segment size. // Check first file data PDU. It should have the maximum file segment size.
fsmResult = sourceHandler.stateMachine(); sourceHandler.stateMachine();
TmTcMessage tmtcMessage; TmTcMessage tmtcMessage;
const uint8_t* pduPtr; const uint8_t* pduPtr;
FileDataInfo fdInfo; FileDataInfo fdInfo;
@ -239,7 +248,7 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
mqMock.clearMessages(); mqMock.clearMessages();
// Check second file data PDU. // Check second file data PDU.
fsmResult = sourceHandler.stateMachine(); sourceHandler.stateMachine();
auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr); auto accessor = onePduSentCheck(fsmResult, tmtcMessage, &pduPtr);
FileDataReader fdReader(pduPtr, accessor.second.size(), fdInfo); FileDataReader fdReader(pduPtr, accessor.second.size(), fdInfo);
// 10 byte PDU header, 4 byte offset, remaining file data (400 - 255 == 145). // 10 byte PDU header, 4 byte offset, remaining file data (400 - 255 == 145).
@ -256,14 +265,15 @@ TEST_CASE("CFDP Source Handler", "[cfdp]") {
mqMock.clearMessages(); mqMock.clearMessages();
// Check EOF and verify checksum. // Check EOF and verify checksum.
fsmResult = sourceHandler.stateMachine(); sourceHandler.stateMachine();
etl::crc32 crcCalc; etl::crc32 crcCalc;
crcCalc.add(largerFileData.data(), largerFileData.data() + largerFileData.size()); crcCalc.add(largerFileData.data(), largerFileData.data() + largerFileData.size());
// Verify EOF PDU was sent. // Verify EOF PDU was sent.
genericEofCheck(fsmResult, expectedFileSize, crcCalc.value(), expectedSeqNum); genericEofCheck(fsmResult, expectedFileSize, crcCalc.value(), expectedSeqNum);
CHECK(sourceHandler.getStep() == SourceHandler::TransactionStep::IDLE); // Verify notice of completion.
CHECK(sourceHandler.getState() == CfdpState::IDLE); sourceHandler.stateMachine();
genericNoticeOfCompletionCheck(fsmResult, expectedSeqNum);
} }
} }