fsfw/unittests/cfdp/pdu/testMetadataPdu.cpp

225 lines
9.4 KiB
C++
Raw Normal View History

2022-02-02 10:29:30 +01:00
#include <array>
#include <catch2/catch_test_macros.hpp>
2022-08-08 18:36:10 +02:00
#include <iostream>
2022-02-02 10:29:30 +01:00
2022-08-08 17:53:42 +02:00
#include "fsfw/cfdp/pdu/MetadataPduCreator.h"
#include "fsfw/cfdp/pdu/MetadataPduReader.h"
2022-02-02 10:29:30 +01:00
#include "fsfw/cfdp/tlv/FilestoreResponseTlv.h"
2022-08-09 14:55:08 +02:00
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
2022-08-03 13:23:49 +02:00
TEST_CASE("Metadata PDU", "[cfdp][pdu]") {
2022-02-02 10:29:30 +01:00
using namespace cfdp;
2023-07-21 16:09:52 +02:00
ReturnValue_t result;
2022-02-02 10:29:30 +01:00
std::array<uint8_t, 256> mdBuffer = {};
uint8_t* buffer = mdBuffer.data();
size_t sz = 0;
EntityId destId(WidthInBytes::TWO_BYTES, 2);
TransactionSeqNum seqNum(WidthInBytes::TWO_BYTES, 15);
EntityId sourceId(WidthInBytes::TWO_BYTES, 1);
2022-09-15 18:41:15 +02:00
PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum);
2022-02-02 10:29:30 +01:00
std::string firstFileName = "hello.txt";
2022-08-10 10:34:02 +02:00
cfdp::StringLv sourceFileName(firstFileName);
2022-08-23 19:37:30 +02:00
cfdp::StringLv destFileName;
2023-07-19 13:44:52 +02:00
Fss fileSize(35);
2023-07-27 14:55:46 +02:00
MetadataGenericInfo info(false, ChecksumType::MODULAR, fileSize);
2022-02-02 10:29:30 +01:00
FilestoreResponseTlv response(FilestoreActionCode::CREATE_DIRECTORY, FSR_CREATE_NOT_ALLOWED,
sourceFileName, nullptr);
std::array<uint8_t, 3> msg = {0x41, 0x42, 0x43};
cfdp::Tlv responseTlv;
std::array<uint8_t, 64> responseBuf = {};
response.convertToTlv(responseTlv, buffer, responseBuf.size(), SerializeIF::Endianness::MACHINE);
MessageToUserTlv msgToUser(msg.data(), msg.size());
std::array<Tlv*, 2> options{&responseTlv, &msgToUser};
2023-07-21 16:09:52 +02:00
std::array<Tlv, 5> tlvDeser{};
2022-02-02 10:29:30 +01:00
REQUIRE(options[0]->getSerializedSize() == 2 + 1 + 10 + 1);
REQUIRE(options[1]->getSerializedSize() == 5);
auto metadataCheckPartOne = [&]() {
2022-09-15 18:41:15 +02:00
REQUIRE(mdBuffer[10] == FileDirective::METADATA);
2022-02-02 10:29:30 +01:00
// no closure requested and checksum type is modular => 0x00
REQUIRE(mdBuffer[11] == 0x00);
uint32_t fileSizeRaw = 0;
result = SerializeAdapter::deSerialize(&fileSizeRaw, mdBuffer.data() + 12, nullptr,
SerializeIF::Endianness::NETWORK);
2022-08-16 01:08:26 +02:00
REQUIRE(result == returnvalue::OK);
2022-02-02 10:29:30 +01:00
REQUIRE(fileSizeRaw == 35);
REQUIRE(mdBuffer[16] == 9);
REQUIRE(mdBuffer[17] == 'h');
REQUIRE(mdBuffer[18] == 'e');
REQUIRE(mdBuffer[19] == 'l');
REQUIRE(mdBuffer[20] == 'l');
REQUIRE(mdBuffer[21] == 'o');
REQUIRE(mdBuffer[22] == '.');
REQUIRE(mdBuffer[23] == 't');
REQUIRE(mdBuffer[24] == 'x');
REQUIRE(mdBuffer[25] == 't');
};
2023-08-03 15:13:26 +02:00
SECTION("Serialize with empty dest name") {
MetadataPduCreator serializer(pduConf, info, sourceFileName, destFileName, nullptr, 0);
result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
REQUIRE(result == returnvalue::OK);
2023-08-03 15:13:26 +02:00
CHECK(sz == serializer.getSerializedSize());
// 10 byte heater + 1 byte PDU directive field + 1 byte PDU content + FSS field (4) + source
// name field (10) + dest name field (1).
REQUIRE(serializer.getWholePduSize() == 27);
REQUIRE(serializer.getSourceFileName().getSerializedSize() == 10);
REQUIRE(serializer.getDestFileName().getSerializedSize() == 1);
REQUIRE(info.getSerializedSize() == 5);
REQUIRE((mdBuffer[1] << 8 | mdBuffer[2]) == 17);
REQUIRE(serializer.getSerializedSize() == serializer.getWholePduSize());
metadataCheckPartOne();
2022-02-02 10:29:30 +01:00
REQUIRE(mdBuffer[26] == 0);
2023-07-21 16:09:52 +02:00
}
SECTION("Serialize with dest name") {
std::string secondFileName = "hello2.txt";
cfdp::StringLv destFileName2(secondFileName);
MetadataPduCreator serializer(pduConf, info, sourceFileName, destFileName2, nullptr, 0);
result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
REQUIRE(result == returnvalue::OK);
// 10 byte heater + 1 byte PDU directive field + 1 byte PDU content + FSS field (4) + source
// name field (10) + dest name field (11).
REQUIRE(serializer.getWholePduSize() == 37);
2023-08-03 15:13:26 +02:00
CHECK(sz == serializer.getSerializedSize());
REQUIRE((mdBuffer[1] << 8 | mdBuffer[2]) == 27);
REQUIRE(serializer.getSerializedSize() == serializer.getWholePduSize());
metadataCheckPartOne();
// Size of destination name field
REQUIRE(mdBuffer[26] == 10);
REQUIRE(mdBuffer[27] == 'h');
REQUIRE(mdBuffer[28] == 'e');
REQUIRE(mdBuffer[29] == 'l');
REQUIRE(mdBuffer[30] == 'l');
REQUIRE(mdBuffer[31] == 'o');
REQUIRE(mdBuffer[32] == '2');
REQUIRE(mdBuffer[33] == '.');
REQUIRE(mdBuffer[34] == 't');
REQUIRE(mdBuffer[35] == 'x');
REQUIRE(mdBuffer[36] == 't');
}
2023-07-21 16:09:52 +02:00
SECTION("Serialize with 2 options") {
2022-02-02 10:29:30 +01:00
std::string otherFileName = "hello2.txt";
2022-08-23 19:37:30 +02:00
cfdp::StringLv otherFileNameLv(otherFileName.data(), otherFileName.size());
2023-07-27 14:55:46 +02:00
MetadataPduCreator serializer(pduConf, info, otherFileNameLv, destFileName, options.data(),
options.size());
2022-09-15 18:41:15 +02:00
info.setChecksumType(cfdp::ChecksumType::CRC_32C);
2022-02-02 10:29:30 +01:00
info.setClosureRequested(true);
serializer.updateDirectiveFieldLen();
2022-02-02 10:29:30 +01:00
result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
2022-08-16 01:08:26 +02:00
REQUIRE(result == returnvalue::OK);
2022-02-02 10:29:30 +01:00
REQUIRE((mdBuffer[1] << 8 | mdBuffer[2]) == 37);
2022-09-15 18:41:15 +02:00
auto checksumType = static_cast<cfdp::ChecksumType>(mdBuffer[11] & 0x0f);
REQUIRE(checksumType == cfdp::ChecksumType::CRC_32C);
2022-02-02 10:29:30 +01:00
bool closureRequested = mdBuffer[11] >> 6 & 0x01;
REQUIRE(closureRequested == true);
// The size of the two options is 19. Summing up:
// - 11 bytes of source file name
// - 1 byte for dest file name
// - 4 for FSS
// - 1 leading byte.
// - 1 byte for PDU type
// PDU header has 10 bytes.
// I am not going to check the options raw content, those are part of the dedicated
// TLV unittests
REQUIRE(sz == 10 + 37);
for (size_t maxSz = 0; maxSz < sz; maxSz++) {
2023-07-21 16:09:52 +02:00
buffer = mdBuffer.data();
sz = 0;
2022-02-02 10:29:30 +01:00
result = serializer.serialize(&buffer, &sz, maxSz, SerializeIF::Endianness::NETWORK);
REQUIRE(result == SerializeIF::BUFFER_TOO_SHORT);
}
2022-02-02 10:29:30 +01:00
for (size_t initSz = 1; initSz < 47; initSz++) {
2023-07-21 16:09:52 +02:00
buffer = mdBuffer.data();
sz = initSz;
2022-02-02 10:29:30 +01:00
result = serializer.serialize(&buffer, &sz, 46, SerializeIF::Endianness::NETWORK);
REQUIRE(result == SerializeIF::BUFFER_TOO_SHORT);
}
}
2022-02-02 10:29:30 +01:00
SECTION("Deserialize") {
2023-07-27 14:55:46 +02:00
MetadataPduCreator serializer(pduConf, info, sourceFileName, destFileName, nullptr, 0);
2022-02-02 10:29:30 +01:00
result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
2022-08-16 01:08:26 +02:00
REQUIRE(result == returnvalue::OK);
2023-07-21 16:09:52 +02:00
MetadataPduReader deserializer(mdBuffer.data(), mdBuffer.size(), info, nullptr, 0);
2022-02-02 10:29:30 +01:00
result = deserializer.parseData();
2022-08-16 01:08:26 +02:00
REQUIRE(result == returnvalue::OK);
2022-02-02 10:29:30 +01:00
size_t fullSize = deserializer.getWholePduSize();
for (size_t maxSz = 0; maxSz < fullSize; maxSz++) {
2023-07-21 16:09:52 +02:00
MetadataPduReader invalidSzDeser(mdBuffer.data(), maxSz, info, nullptr, 0);
2022-02-02 10:29:30 +01:00
result = invalidSzDeser.parseData();
2022-08-16 01:08:26 +02:00
REQUIRE(result != returnvalue::OK);
2022-02-02 10:29:30 +01:00
}
2023-07-21 16:09:52 +02:00
}
SECTION("Deserialize with 2 options") {
2023-07-27 14:55:46 +02:00
MetadataPduCreator serializer(pduConf, info, sourceFileName, destFileName, options.data(),
options.size());
2022-09-15 18:41:15 +02:00
info.setChecksumType(cfdp::ChecksumType::CRC_32C);
2022-02-02 10:29:30 +01:00
info.setClosureRequested(true);
serializer.updateDirectiveFieldLen();
2022-02-02 10:29:30 +01:00
result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
2022-08-16 01:08:26 +02:00
REQUIRE(result == returnvalue::OK);
2023-07-21 16:09:52 +02:00
MetadataPduReader deserializer2(mdBuffer.data(), mdBuffer.size(), info, tlvDeser.data(),
tlvDeser.max_size());
2022-02-02 10:29:30 +01:00
result = deserializer2.parseData();
2022-08-16 01:08:26 +02:00
REQUIRE(result == returnvalue::OK);
2022-09-15 18:41:15 +02:00
REQUIRE(options[0]->getType() == cfdp::TlvType::FILESTORE_RESPONSE);
2022-02-02 10:29:30 +01:00
REQUIRE(options[0]->getSerializedSize() == 14);
2022-09-15 18:41:15 +02:00
REQUIRE(options[1]->getType() == cfdp::TlvType::MSG_TO_USER);
2022-02-02 10:29:30 +01:00
REQUIRE(options[1]->getSerializedSize() == 5);
2022-02-02 10:29:30 +01:00
for (size_t invalidFieldLen = 0; invalidFieldLen < 36; invalidFieldLen++) {
mdBuffer[1] = (invalidFieldLen >> 8) & 0xff;
mdBuffer[2] = invalidFieldLen & 0xff;
2023-07-21 16:09:52 +02:00
if (invalidFieldLen == 17) {
volatile uint32_t dummy = 0;
}
2022-02-02 10:29:30 +01:00
result = deserializer2.parseData();
if (invalidFieldLen == 17) {
2023-07-21 16:09:52 +02:00
REQUIRE(deserializer2.getNumberOfParsedOptions() == 0);
2022-02-02 10:29:30 +01:00
}
if (invalidFieldLen == 31) {
2023-07-21 16:09:52 +02:00
REQUIRE(deserializer2.getNumberOfParsedOptions() == 1);
2022-02-02 10:29:30 +01:00
}
// This is the precise length where there are no options or one option
if (invalidFieldLen != 17 and invalidFieldLen != 31) {
2022-08-16 01:08:26 +02:00
REQUIRE(result != returnvalue::OK);
2022-02-02 10:29:30 +01:00
}
}
mdBuffer[1] = (36 >> 8) & 0xff;
mdBuffer[2] = 36 & 0xff;
2023-07-21 16:09:52 +02:00
}
SECTION("Can not parse options") {
2023-07-27 14:55:46 +02:00
MetadataPduCreator serializer(pduConf, info, sourceFileName, destFileName, options.data(),
options.size());
2023-07-21 16:09:52 +02:00
info.setChecksumType(cfdp::ChecksumType::CRC_32C);
info.setClosureRequested(true);
buffer = mdBuffer.data();
sz = 0;
serializer.updateDirectiveFieldLen();
2023-07-27 14:55:46 +02:00
// info.setSourceFileName(sourceFileName);
2023-07-21 16:09:52 +02:00
result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
REQUIRE(result == returnvalue::OK);
MetadataPduReader deserializer2(mdBuffer.data(), mdBuffer.size(), info, nullptr, 0);
2022-02-02 10:29:30 +01:00
REQUIRE(deserializer2.parseData() == cfdp::METADATA_CANT_PARSE_OPTIONS);
for (size_t maxSz = 0; maxSz < 46; maxSz++) {
2023-07-21 16:09:52 +02:00
MetadataPduReader invalidSzDeser(mdBuffer.data(), maxSz, info, nullptr, 0);
2022-08-08 18:36:10 +02:00
if (not invalidSzDeser.isNull()) {
result = invalidSzDeser.parseData();
REQUIRE(result == SerializeIF::STREAM_TOO_SHORT);
}
}
2022-02-02 10:29:30 +01:00
}
}