fsfw/unittests/cfdp/pdu/testCfdpHeader.cpp

328 lines
15 KiB
C++
Raw Permalink Normal View History

2022-08-03 13:23:49 +02:00
#include <array>
#include <catch2/catch_test_macros.hpp>
2022-09-08 11:08:40 +02:00
#include "fsfw/cfdp/pdu/FinishedInfo.h"
#include "fsfw/cfdp/pdu/FinishedPduCreator.h"
2022-08-03 15:22:39 +02:00
#include "fsfw/cfdp/pdu/HeaderCreator.h"
2024-05-24 14:29:42 +02:00
#include "fsfw/cfdp/pdu/HeaderReader.h"
2022-08-22 16:35:53 +02:00
#include "fsfw/returnvalues/returnvalue.h"
2022-08-03 13:23:49 +02:00
2022-09-08 11:08:40 +02:00
using namespace returnvalue;
2022-08-03 13:23:49 +02:00
TEST_CASE("CFDP Header", "[cfdp]") {
using namespace cfdp;
std::array<uint8_t, 32> serBuf{};
ReturnValue_t result;
cfdp::TransactionSeqNum seqNum = TransactionSeqNum(cfdp::WidthInBytes::ONE_BYTE, 2);
cfdp::EntityId sourceId = EntityId(cfdp::WidthInBytes::ONE_BYTE, 0);
cfdp::EntityId destId = EntityId(cfdp::WidthInBytes::ONE_BYTE, 1);
PduConfig pduConf =
2022-09-15 18:41:15 +02:00
PduConfig(sourceId, destId, cfdp::TransmissionMode::ACKNOWLEDGED, seqNum, false);
2022-08-03 13:23:49 +02:00
uint8_t* serTarget = serBuf.data();
const uint8_t* deserTarget = serTarget;
size_t serSize = 0;
2022-09-15 18:41:15 +02:00
auto creator = HeaderCreator(pduConf, cfdp::PduType::FILE_DIRECTIVE, 0);
2022-08-03 13:23:49 +02:00
2022-08-09 11:17:57 +02:00
SECTION("Header State") {
2022-08-03 13:23:49 +02:00
REQUIRE(seqNum.getSerializedSize() == 1);
2022-09-08 11:08:40 +02:00
REQUIRE(creator.getPduDataFieldLen() == 0);
REQUIRE(creator.getSerializedSize() == 7);
REQUIRE(creator.getWholePduSize() == 7);
REQUIRE(creator.getCrcFlag() == false);
REQUIRE(creator.getDirection() == cfdp::Direction::TOWARDS_RECEIVER);
REQUIRE(creator.getLargeFileFlag() == false);
REQUIRE(creator.getLenEntityIds() == 1);
REQUIRE(creator.getLenSeqNum() == 1);
2022-09-15 18:41:15 +02:00
REQUIRE(creator.getPduType() == cfdp::PduType::FILE_DIRECTIVE);
2022-09-08 11:08:40 +02:00
REQUIRE(creator.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::NOT_PRESENT);
REQUIRE(creator.getSegmentationControl() == false);
2022-09-15 18:41:15 +02:00
REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::ACKNOWLEDGED);
2022-08-03 13:23:49 +02:00
cfdp::TransactionSeqNum seqNumLocal;
2022-09-08 11:08:40 +02:00
creator.getTransactionSeqNum(seqNumLocal);
2022-08-03 13:23:49 +02:00
REQUIRE(seqNumLocal.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
REQUIRE(seqNumLocal.getValue() == 2);
cfdp::EntityId sourceDestId;
2022-09-08 11:08:40 +02:00
creator.getSourceId(sourceDestId);
2022-08-03 13:23:49 +02:00
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
REQUIRE(sourceDestId.getValue() == 0);
2022-09-08 11:08:40 +02:00
creator.getDestId(sourceDestId);
2022-08-03 13:23:49 +02:00
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
REQUIRE(sourceDestId.getValue() == 1);
2022-08-09 11:17:57 +02:00
}
2022-08-03 13:23:49 +02:00
2022-08-09 11:17:57 +02:00
SECTION("Deserialization fails") {
const uint8_t** dummyPtr = nullptr;
2022-09-08 11:08:40 +02:00
REQUIRE(creator.deSerialize(dummyPtr, &serSize, SerializeIF::Endianness::NETWORK) ==
2022-08-22 16:35:53 +02:00
returnvalue::FAILED);
2022-08-09 11:17:57 +02:00
}
2022-08-03 13:23:49 +02:00
2022-08-09 11:17:57 +02:00
SECTION("Serialization fails") {
2022-09-08 11:08:40 +02:00
REQUIRE(creator.serialize(nullptr, &serSize, serBuf.size(), SerializeIF::Endianness::NETWORK) ==
returnvalue::FAILED);
2022-08-09 11:17:57 +02:00
}
SECTION("Buffer Too Short") {
2022-08-03 13:23:49 +02:00
for (uint8_t idx = 0; idx < 7; idx++) {
2022-09-08 11:08:40 +02:00
result = creator.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::BIG);
2022-08-03 13:23:49 +02:00
REQUIRE(result == static_cast<int>(SerializeIF::BUFFER_TOO_SHORT));
}
2022-08-09 11:17:57 +02:00
}
2022-08-03 13:23:49 +02:00
2022-08-09 11:17:57 +02:00
SECTION("Set Data Field Len") {
2022-08-03 13:23:49 +02:00
// Set PDU data field len
2022-09-08 11:08:40 +02:00
creator.setPduDataFieldLen(0x0ff0);
REQUIRE(creator.getPduDataFieldLen() == 0x0ff0);
REQUIRE(creator.getSerializedSize() == 7);
REQUIRE(creator.getWholePduSize() == 7 + 0x0ff0);
2022-08-03 13:23:49 +02:00
serTarget = serBuf.data();
serSize = 0;
2022-09-08 11:08:40 +02:00
result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG);
2022-08-03 13:23:49 +02:00
REQUIRE(serBuf[1] == 0x0f);
REQUIRE(serBuf[2] == 0xf0);
2022-08-09 11:17:57 +02:00
}
2022-08-03 13:23:49 +02:00
2022-08-09 11:17:57 +02:00
SECTION("Serialize with Fields Flipped") {
2022-08-03 13:23:49 +02:00
pduConf.crcFlag = true;
pduConf.largeFile = true;
pduConf.direction = cfdp::Direction::TOWARDS_SENDER;
2022-09-15 18:41:15 +02:00
pduConf.mode = cfdp::TransmissionMode::UNACKNOWLEDGED;
2022-09-08 11:08:40 +02:00
creator.setSegmentationControl(cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION);
2022-09-15 18:41:15 +02:00
creator.setPduType(cfdp::PduType::FILE_DATA);
2022-09-08 11:08:40 +02:00
creator.setSegmentMetadataFlag(cfdp::SegmentMetadataFlag::PRESENT);
2022-08-03 13:23:49 +02:00
serTarget = serBuf.data();
serSize = 0;
2022-08-09 11:17:57 +02:00
SECTION("Regular") {
// Everything except version bit flipped to one now
2022-09-08 11:08:40 +02:00
REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(),
SerializeIF::Endianness::BIG) == returnvalue::OK);
2022-08-09 11:17:57 +02:00
CHECK(serBuf[0] == 0x3f);
2023-05-15 16:02:55 +02:00
CHECK(serBuf[3] == 0x88);
2022-09-08 11:08:40 +02:00
REQUIRE(creator.getCrcFlag() == true);
REQUIRE(creator.getDirection() == cfdp::Direction::TOWARDS_SENDER);
REQUIRE(creator.getLargeFileFlag() == true);
REQUIRE(creator.getLenEntityIds() == 1);
REQUIRE(creator.getLenSeqNum() == 1);
2022-09-15 18:41:15 +02:00
REQUIRE(creator.getPduType() == cfdp::PduType::FILE_DATA);
2022-09-08 11:08:40 +02:00
REQUIRE(creator.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT);
2022-09-15 18:41:15 +02:00
REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED);
2022-09-08 11:08:40 +02:00
REQUIRE(creator.getSegmentationControl() == true);
2022-08-09 11:17:57 +02:00
}
2022-08-03 13:23:49 +02:00
2022-08-09 11:17:57 +02:00
SECTION("Other variable sized fields") {
pduConf.seqNum.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
2022-08-09 11:17:57 +02:00
REQUIRE(pduConf.sourceId.getSerializedSize() == 4);
2022-09-08 11:08:40 +02:00
REQUIRE(creator.getSerializedSize() == 14);
REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(),
SerializeIF::Endianness::BIG) == returnvalue::OK);
REQUIRE(creator.getCrcFlag() == true);
REQUIRE(creator.getDirection() == cfdp::Direction::TOWARDS_SENDER);
REQUIRE(creator.getLargeFileFlag() == true);
REQUIRE(creator.getLenEntityIds() == 4);
REQUIRE(creator.getLenSeqNum() == 2);
2022-09-15 18:41:15 +02:00
REQUIRE(creator.getPduType() == cfdp::PduType::FILE_DATA);
2022-09-08 11:08:40 +02:00
REQUIRE(creator.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT);
2022-09-15 18:41:15 +02:00
REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED);
2022-09-08 11:08:40 +02:00
REQUIRE(creator.getSegmentationControl() == true);
2022-08-09 11:17:57 +02:00
// Last three bits are 2 now (length of seq number) and bit 1 to bit 3 is 4 (len entity IDs)
2023-05-15 16:02:55 +02:00
REQUIRE(serBuf[3] == 0b10111001);
2022-08-09 11:17:57 +02:00
uint32_t entityId = 0;
size_t deSerSize = 0;
SerializeAdapter::deSerialize(&entityId, serBuf.data() + 4, &deSerSize,
SerializeIF::Endianness::NETWORK);
CHECK(deSerSize == 4);
CHECK(entityId == 0xff00ff00);
uint16_t seqNumRaw = 0;
SerializeAdapter::deSerialize(&seqNumRaw, serBuf.data() + 8, &deSerSize,
SerializeIF::Endianness::NETWORK);
CHECK(deSerSize == 2);
CHECK(seqNumRaw == 0x0fff);
SerializeAdapter::deSerialize(&entityId, serBuf.data() + 10, &deSerSize,
SerializeIF::Endianness::NETWORK);
CHECK(deSerSize == 4);
CHECK(entityId == 0x00ff00ff);
}
SECTION("Buffer Too Short") {
pduConf.seqNum.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
2022-08-09 11:17:57 +02:00
for (uint8_t idx = 0; idx < 14; idx++) {
2022-09-08 11:08:40 +02:00
REQUIRE(creator.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::BIG) ==
SerializeIF::BUFFER_TOO_SHORT);
2022-08-09 11:17:57 +02:00
}
2022-08-03 13:23:49 +02:00
}
2022-08-09 11:17:57 +02:00
}
2022-08-03 13:23:49 +02:00
2022-08-09 11:17:57 +02:00
SECTION("Invalid Variable Sized Fields") {
result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 0xfff);
2022-08-22 16:35:53 +02:00
REQUIRE(result == returnvalue::FAILED);
result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0xfffff);
2022-08-22 16:35:53 +02:00
REQUIRE(result == returnvalue::FAILED);
result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xfffffffff);
2022-08-22 16:35:53 +02:00
REQUIRE(result == returnvalue::FAILED);
2022-08-09 11:17:57 +02:00
}
SECTION("Header Serialization") {
2022-09-08 11:08:40 +02:00
result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG);
2022-08-22 16:35:53 +02:00
REQUIRE(result == returnvalue::OK);
2022-08-09 11:17:57 +02:00
REQUIRE(serSize == 7);
// Only version bits are set
REQUIRE(serBuf[0] == 0b00100000);
// PDU data field length is 0
REQUIRE(serBuf[1] == 0);
REQUIRE(serBuf[2] == 0);
// Entity and Transaction Sequence number are 1 byte large
2023-05-15 16:02:55 +02:00
REQUIRE(serBuf[3] == 0b00000000);
2022-08-09 11:17:57 +02:00
// Source ID
REQUIRE(serBuf[4] == 0);
// Transaction Seq Number
REQUIRE(serBuf[5] == 2);
// Dest ID
REQUIRE(serBuf[6] == 1);
2022-08-03 13:23:49 +02:00
uint8_t oneByteSourceId = 32;
serTarget = &oneByteSourceId;
size_t deserLen = 1;
pduConf.sourceId.deSerialize(cfdp::WidthInBytes::ONE_BYTE,
const_cast<const uint8_t**>(&serTarget), &deserLen,
SerializeIF::Endianness::MACHINE);
REQUIRE(pduConf.sourceId.getValue() == 32);
uint16_t twoByteSourceId = 0xf0f0;
serTarget = reinterpret_cast<uint8_t*>(&twoByteSourceId);
deserLen = 2;
pduConf.sourceId.deSerialize(cfdp::WidthInBytes::TWO_BYTES,
const_cast<const uint8_t**>(&serTarget), &deserLen,
SerializeIF::Endianness::MACHINE);
REQUIRE(pduConf.sourceId.getValue() == 0xf0f0);
uint32_t fourByteSourceId = 0xf0f0f0f0;
serTarget = reinterpret_cast<uint8_t*>(&fourByteSourceId);
deserLen = 4;
pduConf.sourceId.deSerialize(cfdp::WidthInBytes::FOUR_BYTES,
const_cast<const uint8_t**>(&serTarget), &deserLen,
SerializeIF::Endianness::MACHINE);
REQUIRE(pduConf.sourceId.getValue() == 0xf0f0f0f0);
pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 1);
2022-08-03 13:23:49 +02:00
serTarget = serBuf.data();
serSize = 1;
result = pduConf.sourceId.serialize(&serTarget, &serSize, 1, SerializeIF::Endianness::MACHINE);
REQUIRE(result == static_cast<int>(SerializeIF::BUFFER_TOO_SHORT));
}
2022-09-08 11:08:40 +02:00
SECTION("Header Deserialization 0") {
REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG) ==
returnvalue::OK);
2022-08-03 13:23:49 +02:00
REQUIRE(serBuf[1] == 0);
REQUIRE(serBuf[2] == 0);
// Entity and Transaction Sequence number are 1 byte large
2023-05-15 16:02:55 +02:00
REQUIRE(serBuf[3] == 0b00000000);
2022-08-03 13:23:49 +02:00
REQUIRE(serSize == 7);
// Deser call not strictly necessary
2022-09-08 11:08:40 +02:00
auto reader = PduHeaderReader(serBuf.data(), serBuf.size());
2022-08-03 13:23:49 +02:00
2022-09-08 11:08:40 +02:00
ReturnValue_t serResult = reader.parseData();
2022-08-22 16:35:53 +02:00
REQUIRE(serResult == returnvalue::OK);
2022-09-08 11:08:40 +02:00
REQUIRE(reader.getPduDataFieldLen() == 0);
REQUIRE(reader.getHeaderSize() == 7);
REQUIRE(reader.getWholePduSize() == 7);
REQUIRE(reader.getCrcFlag() == false);
REQUIRE(reader.getDirection() == cfdp::Direction::TOWARDS_RECEIVER);
REQUIRE(reader.getLargeFileFlag() == false);
REQUIRE(reader.getLenEntityIds() == 1);
REQUIRE(reader.getLenSeqNum() == 1);
2022-09-15 18:41:15 +02:00
REQUIRE(reader.getPduType() == cfdp::PduType::FILE_DIRECTIVE);
2022-09-08 11:08:40 +02:00
REQUIRE(reader.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::NOT_PRESENT);
REQUIRE(reader.getSegmentationControl() == false);
2022-09-15 18:41:15 +02:00
REQUIRE(reader.getTransmissionMode() == cfdp::TransmissionMode::ACKNOWLEDGED);
2022-09-08 11:08:40 +02:00
// No PDU data contained, so the PDU data field is empty
REQUIRE(reader.getPduDataField() == nullptr);
size_t deSerSize = reader.getWholePduSize();
serTarget = serBuf.data();
const auto** serTargetConst = const_cast<const uint8_t**>(&serTarget);
result = reader.parseData();
REQUIRE(result == returnvalue::OK);
}
2022-08-03 13:23:49 +02:00
2022-09-08 11:08:40 +02:00
SECTION("Header Deserialization 1") {
2022-08-03 13:23:49 +02:00
pduConf.crcFlag = true;
pduConf.largeFile = true;
pduConf.direction = cfdp::Direction::TOWARDS_SENDER;
2022-09-15 18:41:15 +02:00
pduConf.mode = cfdp::TransmissionMode::UNACKNOWLEDGED;
2022-09-08 11:08:40 +02:00
creator.setSegmentationControl(cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION);
2022-09-15 18:41:15 +02:00
creator.setPduType(cfdp::PduType::FILE_DATA);
2022-09-08 11:08:40 +02:00
creator.setSegmentMetadataFlag(cfdp::SegmentMetadataFlag::PRESENT);
result = pduConf.seqNum.setValueAndWidth(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
2022-08-22 16:35:53 +02:00
REQUIRE(result == returnvalue::OK);
result = pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
2022-08-22 16:35:53 +02:00
REQUIRE(result == returnvalue::OK);
result = pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
2022-08-22 16:35:53 +02:00
REQUIRE(result == returnvalue::OK);
2022-08-03 13:23:49 +02:00
serTarget = serBuf.data();
serSize = 0;
2022-09-08 11:08:40 +02:00
result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG);
PduHeaderReader reader(serBuf.data(), serBuf.size());
REQUIRE(reader.parseData() == returnvalue::OK);
2022-08-03 13:23:49 +02:00
// Everything except version bit flipped to one now
REQUIRE(serBuf[0] == 0x3f);
2023-05-15 16:02:55 +02:00
REQUIRE(serBuf[3] == 0b10111001);
2022-09-08 11:08:40 +02:00
REQUIRE(reader.getWholePduSize() == 14);
2022-08-03 13:23:49 +02:00
2022-09-08 11:08:40 +02:00
REQUIRE(reader.getCrcFlag() == true);
REQUIRE(reader.getDirection() == cfdp::Direction::TOWARDS_SENDER);
REQUIRE(reader.getLargeFileFlag() == true);
REQUIRE(reader.getLenEntityIds() == 4);
REQUIRE(reader.getLenSeqNum() == 2);
2022-09-15 18:41:15 +02:00
REQUIRE(reader.getPduType() == cfdp::PduType::FILE_DATA);
2022-09-08 11:08:40 +02:00
REQUIRE(reader.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT);
REQUIRE(reader.getSegmentationControl() == true);
2022-09-15 18:41:15 +02:00
REQUIRE(reader.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED);
2022-09-08 11:08:40 +02:00
// Again, no data field set because this is a header only
REQUIRE(reader.getPduDataField() == nullptr);
2022-08-03 13:23:49 +02:00
cfdp::TransactionSeqNum seqNumLocal;
2022-09-08 11:08:40 +02:00
reader.getTransactionSeqNum(seqNumLocal);
2022-08-03 13:23:49 +02:00
REQUIRE(seqNumLocal.getWidth() == cfdp::WidthInBytes::TWO_BYTES);
REQUIRE(seqNumLocal.getValue() == 0x0fff);
cfdp::EntityId sourceDestId;
2022-09-08 11:08:40 +02:00
reader.getSourceId(sourceDestId);
2022-08-03 13:23:49 +02:00
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::FOUR_BYTES);
REQUIRE(sourceDestId.getValue() == 0xff00ff00);
2022-09-08 11:08:40 +02:00
reader.getDestId(sourceDestId);
2022-08-03 13:23:49 +02:00
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::FOUR_BYTES);
REQUIRE(sourceDestId.getValue() == 0x00ff00ff);
2022-09-08 11:08:40 +02:00
CHECK(reader.setReadOnlyData(nullptr, -1) != returnvalue::OK);
REQUIRE(reader.getHeaderSize() == 14);
2022-08-03 13:23:49 +02:00
2022-09-08 11:08:40 +02:00
SECTION("Manipulate Source Dest ID") {
serTarget = serBuf.data();
serSize = 0;
pduConf.sourceId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 22);
pduConf.destId.setValueAndWidth(cfdp::WidthInBytes::ONE_BYTE, 48);
2022-09-08 11:08:40 +02:00
result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG);
reader.getSourceId(sourceDestId);
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
REQUIRE(sourceDestId.getValue() == 22);
}
}
2022-08-03 13:23:49 +02:00
2022-09-08 11:08:40 +02:00
SECTION("Verify data field pointer") {
FinishedInfo info(cfdp::ConditionCode::INACTIVITY_DETECTED,
cfdp::FileDeliveryCode::DATA_INCOMPLETE,
cfdp::FileDeliveryStatus::DISCARDED_DELIBERATELY);
FinishPduCreator finishCreator(pduConf, info);
REQUIRE(finishCreator.serialize(serBuf.data(), serSize, serBuf.size()) == OK);
// This PDU contains the directive code and some finishes PDU properties packed into one byte
// in addition to the header
REQUIRE(finishCreator.getSerializedSize() == 9);
PduHeaderReader reader(serBuf.data(), serBuf.size());
REQUIRE(reader.parseData() == returnvalue::OK);
REQUIRE(reader.getPduDataField() == serBuf.data() + 7);
2022-08-03 13:23:49 +02:00
}
}