add CFDP fault handler mock
This commit is contained in:
189
unittests/cfdp/pdu/testFinishedPdu.cpp
Normal file
189
unittests/cfdp/pdu/testFinishedPdu.cpp
Normal file
@ -0,0 +1,189 @@
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/cfdp/pdu/FinishedPduDeserializer.h"
|
||||
#include "fsfw/cfdp/pdu/FinishedPduSerializer.h"
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
|
||||
TEST_CASE("Finished PDU", "[cfdp][pdu]") {
|
||||
using namespace cfdp;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
std::array<uint8_t, 256> fnBuffer = {};
|
||||
uint8_t* buffer = fnBuffer.data();
|
||||
size_t sz = 0;
|
||||
EntityId destId(WidthInBytes::TWO_BYTES, 2);
|
||||
TransactionSeqNum seqNum(WidthInBytes::TWO_BYTES, 15);
|
||||
EntityId sourceId(WidthInBytes::TWO_BYTES, 1);
|
||||
PduConfig pduConf(sourceId, destId, TransmissionModes::ACKNOWLEDGED, seqNum);
|
||||
|
||||
cfdp::Lv emptyFsMsg;
|
||||
FinishedInfo info(cfdp::ConditionCode::INACTIVITY_DETECTED,
|
||||
cfdp::FinishedDeliveryCode::DATA_INCOMPLETE,
|
||||
cfdp::FinishedFileStatus::DISCARDED_DELIBERATELY);
|
||||
|
||||
SECTION("Serialize") {
|
||||
FinishPduSerializer serializer(pduConf, info);
|
||||
result = serializer.serialize(&buffer, &sz, fnBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||
REQUIRE(serializer.getSerializedSize() == 12);
|
||||
REQUIRE(((fnBuffer[1] << 8) | fnBuffer[2]) == 2);
|
||||
REQUIRE(fnBuffer[10] == cfdp::FileDirectives::FINISH);
|
||||
REQUIRE(((fnBuffer[sz - 1] >> 4) & 0x0f) == cfdp::ConditionCode::INACTIVITY_DETECTED);
|
||||
REQUIRE(((fnBuffer[sz - 1] >> 2) & 0x01) == cfdp::FinishedDeliveryCode::DATA_INCOMPLETE);
|
||||
REQUIRE((fnBuffer[sz - 1] & 0b11) == cfdp::FinishedFileStatus::DISCARDED_DELIBERATELY);
|
||||
REQUIRE(sz == 12);
|
||||
|
||||
// Add a filestore response
|
||||
std::string firstName = "hello.txt";
|
||||
cfdp::Lv firstNameLv(reinterpret_cast<const uint8_t*>(firstName.data()), firstName.size());
|
||||
FilestoreResponseTlv response(cfdp::FilestoreActionCode::DELETE_FILE,
|
||||
cfdp::FSR_APPEND_FILE_1_NOT_EXISTS, firstNameLv, nullptr);
|
||||
FilestoreResponseTlv* responsePtr = &response;
|
||||
REQUIRE(response.getSerializedSize() == 14);
|
||||
size_t len = 1;
|
||||
info.setFilestoreResponsesArray(&responsePtr, &len, &len);
|
||||
serializer.updateDirectiveFieldLen();
|
||||
REQUIRE(serializer.getSerializedSize() == 12 + 14);
|
||||
sz = 0;
|
||||
buffer = fnBuffer.data();
|
||||
result = serializer.serialize(&buffer, &sz, fnBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||
REQUIRE(serializer.getSerializedSize() == 12 + 14);
|
||||
REQUIRE(serializer.getPduDataFieldLen() == 16);
|
||||
|
||||
// Add two filestore responses and a fault location parameter
|
||||
std::string secondName = "hello2.txt";
|
||||
cfdp::Lv secondNameLv(reinterpret_cast<const uint8_t*>(secondName.data()), secondName.size());
|
||||
FilestoreResponseTlv response2(cfdp::FilestoreActionCode::DENY_FILE, cfdp::FSR_SUCCESS,
|
||||
secondNameLv, nullptr);
|
||||
REQUIRE(response2.getSerializedSize() == 15);
|
||||
len = 2;
|
||||
std::array<FilestoreResponseTlv*, 2> responses{&response, &response2};
|
||||
info.setFilestoreResponsesArray(responses.data(), &len, &len);
|
||||
serializer.updateDirectiveFieldLen();
|
||||
|
||||
EntityIdTlv faultLoc(destId);
|
||||
REQUIRE(faultLoc.getSerializedSize() == 4);
|
||||
info.setFaultLocation(&faultLoc);
|
||||
serializer.updateDirectiveFieldLen();
|
||||
sz = 0;
|
||||
buffer = fnBuffer.data();
|
||||
result = serializer.serialize(&buffer, &sz, fnBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||
info.setConditionCode(cfdp::ConditionCode::FILESTORE_REJECTION);
|
||||
REQUIRE(serializer.getSerializedSize() == 12 + 14 + 15 + 4);
|
||||
REQUIRE(sz == 12 + 14 + 15 + 4);
|
||||
info.setFileStatus(cfdp::FinishedFileStatus::DISCARDED_FILESTORE_REJECTION);
|
||||
REQUIRE(info.getFileStatus() == cfdp::FinishedFileStatus::DISCARDED_FILESTORE_REJECTION);
|
||||
info.setDeliveryCode(cfdp::FinishedDeliveryCode::DATA_INCOMPLETE);
|
||||
REQUIRE(info.getDeliveryCode() == cfdp::FinishedDeliveryCode::DATA_INCOMPLETE);
|
||||
for (size_t maxSz = 0; maxSz < 45; maxSz++) {
|
||||
sz = 0;
|
||||
buffer = fnBuffer.data();
|
||||
result = serializer.serialize(&buffer, &sz, maxSz, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result != HasReturnvaluesIF::RETURN_OK);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Deserialize") {
|
||||
FinishedInfo emptyInfo;
|
||||
FinishPduSerializer serializer(pduConf, info);
|
||||
result = serializer.serialize(&buffer, &sz, fnBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||
FinishPduDeserializer deserializer(fnBuffer.data(), fnBuffer.size(), emptyInfo);
|
||||
result = deserializer.parseData();
|
||||
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||
REQUIRE(emptyInfo.getFileStatus() == cfdp::FinishedFileStatus::DISCARDED_DELIBERATELY);
|
||||
REQUIRE(emptyInfo.getConditionCode() == cfdp::ConditionCode::INACTIVITY_DETECTED);
|
||||
REQUIRE(emptyInfo.getDeliveryCode() == cfdp::FinishedDeliveryCode::DATA_INCOMPLETE);
|
||||
|
||||
// Add a filestore response
|
||||
sz = 0;
|
||||
buffer = fnBuffer.data();
|
||||
std::string firstName = "hello.txt";
|
||||
cfdp::Lv firstNameLv(reinterpret_cast<const uint8_t*>(firstName.data()), firstName.size());
|
||||
FilestoreResponseTlv response(cfdp::FilestoreActionCode::DELETE_FILE, cfdp::FSR_NOT_PERFORMED,
|
||||
firstNameLv, nullptr);
|
||||
FilestoreResponseTlv* responsePtr = &response;
|
||||
size_t len = 1;
|
||||
info.setFilestoreResponsesArray(&responsePtr, &len, &len);
|
||||
serializer.updateDirectiveFieldLen();
|
||||
REQUIRE(serializer.getPduDataFieldLen() == 16);
|
||||
result = serializer.serialize(&buffer, &sz, fnBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||
FilestoreResponseTlv emptyResponse(firstNameLv, nullptr);
|
||||
responsePtr = &emptyResponse;
|
||||
emptyInfo.setFilestoreResponsesArray(&responsePtr, nullptr, &len);
|
||||
FinishPduDeserializer deserializer2(fnBuffer.data(), fnBuffer.size(), emptyInfo);
|
||||
result = deserializer2.parseData();
|
||||
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||
REQUIRE(emptyInfo.getFsResponsesLen() == 1);
|
||||
FilestoreResponseTlv** responseArray = nullptr;
|
||||
emptyInfo.getFilestoreResonses(&responseArray, nullptr, nullptr);
|
||||
REQUIRE(responseArray[0]->getActionCode() == cfdp::FilestoreActionCode::DELETE_FILE);
|
||||
REQUIRE(responseArray[0]->getStatusCode() == cfdp::FSR_NOT_PERFORMED);
|
||||
auto& fileNameRef = responseArray[0]->getFirstFileName();
|
||||
size_t stringSize = 0;
|
||||
const char* string = reinterpret_cast<const char*>(fileNameRef.getValue(&stringSize));
|
||||
std::string firstFileName(string, stringSize);
|
||||
REQUIRE(firstFileName == "hello.txt");
|
||||
|
||||
// Add two filestore responses and a fault location parameter
|
||||
std::string secondName = "hello2.txt";
|
||||
cfdp::Lv secondNameLv(reinterpret_cast<const uint8_t*>(secondName.data()), secondName.size());
|
||||
FilestoreResponseTlv response2(cfdp::FilestoreActionCode::DENY_FILE, cfdp::FSR_SUCCESS,
|
||||
secondNameLv, nullptr);
|
||||
REQUIRE(response2.getSerializedSize() == 15);
|
||||
len = 2;
|
||||
std::array<FilestoreResponseTlv*, 2> responses{&response, &response2};
|
||||
info.setFilestoreResponsesArray(responses.data(), &len, &len);
|
||||
serializer.updateDirectiveFieldLen();
|
||||
|
||||
EntityIdTlv faultLoc(destId);
|
||||
info.setFaultLocation(&faultLoc);
|
||||
serializer.updateDirectiveFieldLen();
|
||||
sz = 0;
|
||||
buffer = fnBuffer.data();
|
||||
result = serializer.serialize(&buffer, &sz, fnBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||
EntityId emptyId;
|
||||
EntityIdTlv emptyFaultLoc(emptyId);
|
||||
emptyInfo.setFaultLocation(&emptyFaultLoc);
|
||||
response.setFilestoreMessage(&emptyFsMsg);
|
||||
emptyInfo.setFilestoreResponsesArray(responses.data(), &len, &len);
|
||||
response2.setFilestoreMessage(&emptyFsMsg);
|
||||
FinishPduDeserializer deserializer3(fnBuffer.data(), fnBuffer.size(), emptyInfo);
|
||||
result = deserializer3.parseData();
|
||||
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||||
auto& infoRef = deserializer3.getInfo();
|
||||
REQUIRE(deserializer3.getWholePduSize() == 45);
|
||||
|
||||
size_t invalidMaxLen = 1;
|
||||
emptyInfo.setFilestoreResponsesArray(responses.data(), &len, &invalidMaxLen);
|
||||
result = deserializer3.parseData();
|
||||
REQUIRE(result == cfdp::FINISHED_CANT_PARSE_FS_RESPONSES);
|
||||
emptyInfo.setFilestoreResponsesArray(nullptr, nullptr, nullptr);
|
||||
result = deserializer3.parseData();
|
||||
REQUIRE(result == cfdp::FINISHED_CANT_PARSE_FS_RESPONSES);
|
||||
|
||||
// Clear condition code
|
||||
auto tmp = fnBuffer[11];
|
||||
fnBuffer[11] = fnBuffer[11] & ~0xf0;
|
||||
fnBuffer[11] = fnBuffer[11] | (cfdp::ConditionCode::NO_ERROR << 4);
|
||||
emptyInfo.setFilestoreResponsesArray(responses.data(), &len, &len);
|
||||
result = deserializer3.parseData();
|
||||
REQUIRE(result == cfdp::INVALID_TLV_TYPE);
|
||||
|
||||
fnBuffer[11] = tmp;
|
||||
// Invalid TLV type, should be entity ID
|
||||
fnBuffer[sz - 4] = cfdp::TlvTypes::FILESTORE_REQUEST;
|
||||
result = deserializer3.parseData();
|
||||
REQUIRE(result == cfdp::INVALID_TLV_TYPE);
|
||||
|
||||
for (size_t maxSz = 0; maxSz < 45; maxSz++) {
|
||||
FinishPduDeserializer faultyDeser(fnBuffer.data(), maxSz, emptyInfo);
|
||||
result = faultyDeser.parseData();
|
||||
REQUIRE(result != HasReturnvaluesIF::RETURN_OK);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user