176 lines
7.5 KiB
C++
176 lines
7.5 KiB
C++
|
#include <catch2/catch_test_macros.hpp>
|
||
|
|
||
|
#include "fsfw/cfdp/pdu/FileDataDeserializer.h"
|
||
|
#include "fsfw/cfdp/pdu/FileDataSerializer.h"
|
||
|
#include "fsfw/globalfunctions/arrayprinter.h"
|
||
|
#include "fsfw/serviceinterface.h"
|
||
|
|
||
|
#include <array>
|
||
|
|
||
|
TEST_CASE( "File Data PDU" , "[FileDataPdu]") {
|
||
|
using namespace cfdp;
|
||
|
|
||
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||
|
std::array<uint8_t, 128> fileBuffer = {};
|
||
|
std::array<uint8_t, 256> fileDataBuffer = {};
|
||
|
uint8_t* buffer = fileDataBuffer.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(TransmissionModes::ACKNOWLEDGED, seqNum, sourceId, destId);
|
||
|
|
||
|
for(uint8_t idx = 0; idx < 10; idx++) {
|
||
|
fileBuffer[idx] = idx;
|
||
|
}
|
||
|
FileSize offset(50);
|
||
|
FileDataInfo info(offset, fileBuffer.data(), 10);
|
||
|
|
||
|
SECTION("Serialization") {
|
||
|
FileDataSerializer serializer(pduConf, info);
|
||
|
result = serializer.serialize(&buffer, &sz, fileDataBuffer.size(),
|
||
|
SerializeIF::Endianness::NETWORK);
|
||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||
|
REQUIRE(sz == 24);
|
||
|
// 10 file bytes plus 4 byte offset
|
||
|
REQUIRE(((fileDataBuffer[1] << 8) | fileDataBuffer[2]) == 14);
|
||
|
// File Data -> Fourth bit is one
|
||
|
REQUIRE(fileDataBuffer[0] == 0b00110000);
|
||
|
uint32_t offsetRaw = 0;
|
||
|
buffer = fileDataBuffer.data();
|
||
|
result = SerializeAdapter::deSerialize(&offsetRaw, buffer + 10, nullptr,
|
||
|
SerializeIF::Endianness::NETWORK);
|
||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||
|
REQUIRE(offsetRaw == 50);
|
||
|
buffer = fileDataBuffer.data() + 14;
|
||
|
for(size_t idx = 0; idx < 10; idx++) {
|
||
|
REQUIRE(buffer[idx] == idx);
|
||
|
}
|
||
|
|
||
|
REQUIRE(info.hasSegmentMetadata() == false);
|
||
|
info.addSegmentMetadataInfo(cfdp::RecordContinuationState::CONTAINS_START_AND_END,
|
||
|
fileBuffer.data(), 10);
|
||
|
REQUIRE(info.hasSegmentMetadata() == true);
|
||
|
REQUIRE(info.getSegmentationControl() ==
|
||
|
cfdp::SegmentationControl::NO_RECORD_BOUNDARIES_PRESERVATION);
|
||
|
info.setSegmentationControl(cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION);
|
||
|
serializer.update();
|
||
|
REQUIRE(serializer.getSegmentationControl() ==
|
||
|
cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION);
|
||
|
buffer = fileDataBuffer.data();
|
||
|
sz = 0;
|
||
|
serializer.setSegmentationControl(cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION);
|
||
|
|
||
|
result = serializer.serialize(&buffer, &sz, fileDataBuffer.size(),
|
||
|
SerializeIF::Endianness::NETWORK);
|
||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||
|
REQUIRE(((fileDataBuffer[1] << 8) | fileDataBuffer[2]) == 25);
|
||
|
// First bit: Seg Ctrl is set
|
||
|
// Bits 1 to 3 length of enitity IDs is 2
|
||
|
// Bit 4: Segment metadata flag is set
|
||
|
// Bit 5 to seven: length of transaction seq num is 2
|
||
|
REQUIRE(fileDataBuffer[3] == 0b10101010);
|
||
|
REQUIRE((fileDataBuffer[10] >> 6) & 0b11 ==
|
||
|
cfdp::RecordContinuationState::CONTAINS_START_AND_END);
|
||
|
// Segment metadata length
|
||
|
REQUIRE((fileDataBuffer[10] & 0x3f) == 10);
|
||
|
buffer = fileDataBuffer.data() + 11;
|
||
|
// Check segment metadata
|
||
|
for(size_t idx = 0; idx < 10; idx++) {
|
||
|
REQUIRE(buffer[idx] == idx);
|
||
|
}
|
||
|
// Check filedata
|
||
|
buffer = fileDataBuffer.data() + 25;
|
||
|
for(size_t idx = 0; idx < 10; idx++) {
|
||
|
REQUIRE(buffer[idx] == idx);
|
||
|
}
|
||
|
|
||
|
for(size_t invalidStartSz = 1; invalidStartSz < sz; invalidStartSz ++) {
|
||
|
buffer = fileDataBuffer.data();
|
||
|
sz = 0;
|
||
|
result = serializer.serialize(&buffer, &invalidStartSz, sz,
|
||
|
SerializeIF::Endianness::NETWORK);
|
||
|
REQUIRE(result != HasReturnvaluesIF::RETURN_OK);
|
||
|
}
|
||
|
|
||
|
info.setSegmentMetadataFlag(true);
|
||
|
REQUIRE(info.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT);
|
||
|
info.setSegmentMetadataFlag(false);
|
||
|
REQUIRE(info.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::NOT_PRESENT);
|
||
|
info.setRecordContinuationState(cfdp::RecordContinuationState::CONTAINS_END_NO_START);
|
||
|
info.setSegmentMetadataLen(10);
|
||
|
info.setSegmentMetadata(nullptr);
|
||
|
info.setFileData(nullptr, 0);
|
||
|
}
|
||
|
|
||
|
SECTION("Deserialization") {
|
||
|
FileDataSerializer serializer(pduConf, info);
|
||
|
result = serializer.serialize(&buffer, &sz, fileDataBuffer.size(),
|
||
|
SerializeIF::Endianness::NETWORK);
|
||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||
|
|
||
|
FileSize emptyOffset;
|
||
|
FileDataInfo emptyInfo(emptyOffset);
|
||
|
FileDataDeserializer deserializer(fileDataBuffer.data(), fileDataBuffer.size(), emptyInfo);
|
||
|
result = deserializer.parseData();
|
||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||
|
REQUIRE(deserializer.getWholePduSize() == 24);
|
||
|
REQUIRE(deserializer.getPduDataFieldLen() == 14);
|
||
|
REQUIRE(deserializer.getSegmentationControl() ==
|
||
|
cfdp::SegmentationControl::NO_RECORD_BOUNDARIES_PRESERVATION);
|
||
|
REQUIRE(deserializer.getSegmentMetadataFlag() ==
|
||
|
cfdp::SegmentMetadataFlag::NOT_PRESENT);
|
||
|
|
||
|
REQUIRE(emptyInfo.getOffset().getSize() == 50);
|
||
|
REQUIRE(emptyInfo.hasSegmentMetadata() == false);
|
||
|
size_t emptyFileSize = 0;
|
||
|
const uint8_t* fileData = emptyInfo.getFileData(&emptyFileSize);
|
||
|
REQUIRE(emptyFileSize == 10);
|
||
|
for(size_t idx = 0; idx < 10; idx++) {
|
||
|
REQUIRE(fileData[idx] == idx);
|
||
|
}
|
||
|
|
||
|
deserializer.setEndianness(SerializeIF::Endianness::NETWORK);
|
||
|
|
||
|
info.addSegmentMetadataInfo(cfdp::RecordContinuationState::CONTAINS_START_AND_END,
|
||
|
fileBuffer.data(), 10);
|
||
|
serializer.update();
|
||
|
buffer = fileDataBuffer.data();
|
||
|
sz = 0;
|
||
|
result = serializer.serialize(&buffer, &sz, fileDataBuffer.size(),
|
||
|
SerializeIF::Endianness::NETWORK);
|
||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||
|
|
||
|
result = deserializer.parseData();
|
||
|
REQUIRE(result == HasReturnvaluesIF::RETURN_OK);
|
||
|
|
||
|
REQUIRE(emptyInfo.getOffset().getSize() == 50);
|
||
|
REQUIRE(emptyInfo.hasSegmentMetadata() == true);
|
||
|
REQUIRE(emptyInfo.getRecordContinuationState() ==
|
||
|
cfdp::RecordContinuationState::CONTAINS_START_AND_END);
|
||
|
emptyFileSize = 0;
|
||
|
fileData = emptyInfo.getFileData(&emptyFileSize);
|
||
|
REQUIRE(emptyFileSize == 10);
|
||
|
for(size_t idx = 0; idx < 10; idx++) {
|
||
|
REQUIRE(fileData[idx] == idx);
|
||
|
}
|
||
|
size_t segmentMetadataLen = 0;
|
||
|
fileData = emptyInfo.getSegmentMetadata(&segmentMetadataLen);
|
||
|
REQUIRE(segmentMetadataLen == 10);
|
||
|
for(size_t idx = 0; idx < 10; idx++) {
|
||
|
REQUIRE(fileData[idx] == idx);
|
||
|
}
|
||
|
for(size_t invalidPduField = 0; invalidPduField < 24; invalidPduField++) {
|
||
|
fileDataBuffer[1] = (invalidPduField >> 8) & 0xff;
|
||
|
fileDataBuffer[2] = invalidPduField & 0xff;
|
||
|
result = deserializer.parseData();
|
||
|
// Starting at 15, the file data is parsed. There is not leading file data length
|
||
|
// field to the parser can't check whether the remaining length is valid
|
||
|
if(invalidPduField < 15) {
|
||
|
REQUIRE(result != HasReturnvaluesIF::RETURN_OK);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|