Merge remote-tracking branch 'upstream/mueller/new-cfdp-update-with-handlers' into cfdp-integration
This commit is contained in:
@ -1,18 +1,12 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
CatchDefinitions.cpp
|
||||
CatchFactory.cpp
|
||||
printChar.cpp
|
||||
testVersion.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE CatchDefinitions.cpp CatchFactory.cpp
|
||||
printChar.cpp testVersion.cpp)
|
||||
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
CatchRunner.cpp
|
||||
CatchSetup.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE CatchRunner.cpp CatchSetup.cpp)
|
||||
|
||||
add_subdirectory(testcfg)
|
||||
add_subdirectory(mocks)
|
||||
|
||||
add_subdirectory(tcdistributor)
|
||||
add_subdirectory(action)
|
||||
add_subdirectory(power)
|
||||
add_subdirectory(util)
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include <fsfw/objectmanager/ObjectManager.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
|
||||
StorageManagerIF* tglob::getIpcStoreHandle() {
|
||||
if (ObjectManager::instance() != nullptr) {
|
||||
return ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <fsfw/returnvalues/returnvalue.h>
|
||||
#include <fsfw/storagemanager/StorageManagerIF.h>
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
|
||||
namespace tconst {
|
||||
static constexpr MessageQueueId_t testQueueId = 42;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "CatchDefinitions.h"
|
||||
#include "CatchFactory.h"
|
||||
#include "fsfw/FSFW.h"
|
||||
|
||||
#ifdef GCOV
|
||||
#include <gcov.h>
|
||||
|
@ -1,3 +1 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
TestActionHelper.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE TestActionHelper.cpp)
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include "mocks/MessageQueueMock.h"
|
||||
|
||||
TEST_CASE("Action Helper", "[ActionHelper]") {
|
||||
TEST_CASE("Action Helper", "[action]") {
|
||||
ActionHelperOwnerMockBase testDhMock;
|
||||
// TODO: Setting another number here breaks the test. Find out why
|
||||
MessageQueueMock testMqMock(MessageQueueIF::NO_QUEUE);
|
||||
|
@ -1,12 +1,5 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
testCfdp.cpp
|
||||
testTlvsLvs.cpp
|
||||
testAckPdu.cpp
|
||||
testEofPdu.cpp
|
||||
testNakPdu.cpp
|
||||
testFinishedPdu.cpp
|
||||
testPromptPdu.cpp
|
||||
testKeepAlivePdu.cpp
|
||||
testMetadataPdu.cpp
|
||||
testFileData.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE testCfdp.cpp testOtherTlvs.cpp
|
||||
testTlv.cpp testLvs.cpp)
|
||||
|
||||
add_subdirectory(handler)
|
||||
add_subdirectory(pdu)
|
||||
|
3
unittests/cfdp/handler/CMakeLists.txt
Normal file
3
unittests/cfdp/handler/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
target_sources(
|
||||
${FSFW_TEST_TGT} PRIVATE testDistributor.cpp testDestHandler.cpp
|
||||
testSourceHandler.cpp testFaultHandler.cpp)
|
244
unittests/cfdp/handler/testDestHandler.cpp
Normal file
244
unittests/cfdp/handler/testDestHandler.cpp
Normal file
@ -0,0 +1,244 @@
|
||||
#include <etl/crc32.h>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <random>
|
||||
#include <utility>
|
||||
|
||||
#include "fsfw/cfdp.h"
|
||||
#include "fsfw/cfdp/pdu/EofPduCreator.h"
|
||||
#include "fsfw/cfdp/pdu/FileDataCreator.h"
|
||||
#include "fsfw/cfdp/pdu/MetadataPduCreator.h"
|
||||
#include "mocks/AcceptsTmMock.h"
|
||||
#include "mocks/EventReportingProxyMock.h"
|
||||
#include "mocks/FilesystemMock.h"
|
||||
#include "mocks/MessageQueueMock.h"
|
||||
#include "mocks/StorageManagerMock.h"
|
||||
#include "mocks/cfdp/FaultHandlerMock.h"
|
||||
#include "mocks/cfdp/RemoteConfigTableMock.h"
|
||||
#include "mocks/cfdp/UserMock.h"
|
||||
|
||||
TEST_CASE("CFDP Dest Handler", "[cfdp]") {
|
||||
using namespace cfdp;
|
||||
using namespace returnvalue;
|
||||
MessageQueueId_t destQueueId = 2;
|
||||
AcceptsTmMock tmReceiver(destQueueId);
|
||||
MessageQueueMock mqMock(destQueueId);
|
||||
EntityId localId = EntityId(UnsignedByteField<uint16_t>(2));
|
||||
EntityId remoteId = EntityId(UnsignedByteField<uint16_t>(3));
|
||||
FaultHandlerMock fhMock;
|
||||
LocalEntityCfg localEntityCfg(localId, IndicationCfg(), fhMock);
|
||||
FilesystemMock fsMock;
|
||||
UserMock userMock(fsMock);
|
||||
RemoteConfigTableMock remoteCfgTableMock;
|
||||
PacketInfoList<64> packetInfoList;
|
||||
LostSegmentsList<128> lostSegmentsList;
|
||||
DestHandlerParams dp(localEntityCfg, userMock, remoteCfgTableMock, packetInfoList,
|
||||
lostSegmentsList);
|
||||
EventReportingProxyMock eventReporterMock;
|
||||
LocalPool::LocalPoolConfig storeCfg = {{10, 32}, {10, 64}, {10, 128}, {10, 1024}};
|
||||
StorageManagerMock tcStore(2, storeCfg);
|
||||
StorageManagerMock tmStore(3, storeCfg);
|
||||
FsfwParams fp(tmReceiver, &mqMock, &eventReporterMock);
|
||||
RemoteEntityCfg cfg(remoteId);
|
||||
remoteCfgTableMock.addRemoteConfig(cfg);
|
||||
fp.tcStore = &tcStore;
|
||||
fp.tmStore = &tmStore;
|
||||
uint8_t* buf = nullptr;
|
||||
size_t serLen = 0;
|
||||
store_address_t storeId;
|
||||
PduConfig conf;
|
||||
auto destHandler = DestHandler(dp, fp);
|
||||
CHECK(destHandler.initialize() == OK);
|
||||
|
||||
auto metadataPreparation = [&](FileSize cfdpFileSize, ChecksumType checksumType) {
|
||||
std::string srcNameString = "hello.txt";
|
||||
std::string destNameString = "hello-cpy.txt";
|
||||
StringLv srcName(srcNameString);
|
||||
StringLv destName(destNameString);
|
||||
MetadataInfo info(false, checksumType, cfdpFileSize, srcName, destName);
|
||||
TransactionSeqNum seqNum(UnsignedByteField<uint16_t>(1));
|
||||
conf.sourceId = remoteId;
|
||||
conf.destId = localId;
|
||||
conf.mode = TransmissionMode::UNACKNOWLEDGED;
|
||||
conf.seqNum = seqNum;
|
||||
MetadataPduCreator metadataCreator(conf, info);
|
||||
REQUIRE(tcStore.getFreeElement(&storeId, metadataCreator.getSerializedSize(), &buf) == OK);
|
||||
REQUIRE(metadataCreator.serialize(buf, serLen, metadataCreator.getSerializedSize()) == OK);
|
||||
PacketInfo packetInfo(metadataCreator.getPduType(), storeId,
|
||||
metadataCreator.getDirectiveCode());
|
||||
packetInfoList.push_back(packetInfo);
|
||||
};
|
||||
|
||||
auto metadataCheck = [&](const cfdp::DestHandler::FsmResult& res, const char* sourceName,
|
||||
const char* destName, size_t fileLen) {
|
||||
REQUIRE(res.result == OK);
|
||||
REQUIRE(res.callStatus == CallStatus::CALL_AGAIN);
|
||||
REQUIRE(res.errors == 0);
|
||||
// Assert that the packet was deleted after handling
|
||||
REQUIRE(not tcStore.hasDataAtId(storeId));
|
||||
REQUIRE(packetInfoList.empty());
|
||||
REQUIRE(userMock.metadataRecvd.size() == 1);
|
||||
auto& idMetadataPair = userMock.metadataRecvd.back();
|
||||
REQUIRE(idMetadataPair.first == destHandler.getTransactionId());
|
||||
REQUIRE(idMetadataPair.second.sourceId.getValue() == 3);
|
||||
REQUIRE(idMetadataPair.second.fileSize == fileLen);
|
||||
REQUIRE(strcmp(idMetadataPair.second.destFileName, destName) == 0);
|
||||
REQUIRE(strcmp(idMetadataPair.second.sourceFileName, sourceName) == 0);
|
||||
userMock.metadataRecvd.pop();
|
||||
REQUIRE(fsMock.fileMap.find(destName) != fsMock.fileMap.end());
|
||||
REQUIRE(res.result == OK);
|
||||
REQUIRE(res.state == CfdpStates::BUSY_CLASS_1_NACKED);
|
||||
REQUIRE(res.step == DestHandler::TransactionStep::RECEIVING_FILE_DATA_PDUS);
|
||||
};
|
||||
|
||||
auto eofPreparation = [&](FileSize cfdpFileSize, uint32_t crc) {
|
||||
EofInfo eofInfo(cfdp::ConditionCode::NO_ERROR, crc, std::move(cfdpFileSize));
|
||||
EofPduCreator eofCreator(conf, eofInfo);
|
||||
REQUIRE(tcStore.getFreeElement(&storeId, eofCreator.getSerializedSize(), &buf) == OK);
|
||||
REQUIRE(eofCreator.serialize(buf, serLen, eofCreator.getSerializedSize()) == OK);
|
||||
PacketInfo packetInfo(eofCreator.getPduType(), storeId, eofCreator.getDirectiveCode());
|
||||
packetInfoList.push_back(packetInfo);
|
||||
};
|
||||
|
||||
auto eofCheck = [&](const cfdp::DestHandler::FsmResult& res, const TransactionId& id) {
|
||||
REQUIRE(res.result == OK);
|
||||
REQUIRE(res.state == CfdpStates::IDLE);
|
||||
REQUIRE(res.errors == 0);
|
||||
REQUIRE(res.step == DestHandler::TransactionStep::IDLE);
|
||||
// Assert that the packet was deleted after handling
|
||||
REQUIRE(not tcStore.hasDataAtId(storeId));
|
||||
REQUIRE(packetInfoList.empty());
|
||||
REQUIRE(userMock.eofsRevd.size() == 1);
|
||||
auto& eofId = userMock.eofsRevd.back();
|
||||
CHECK(eofId == id);
|
||||
REQUIRE(userMock.finishedRecvd.size() == 1);
|
||||
auto& idParamPair = userMock.finishedRecvd.back();
|
||||
CHECK(idParamPair.first == id);
|
||||
CHECK(idParamPair.second.condCode == ConditionCode::NO_ERROR);
|
||||
};
|
||||
|
||||
auto fileDataPduCheck = [&](const cfdp::DestHandler::FsmResult& res,
|
||||
const std::vector<store_address_t>& idsToCheck) {
|
||||
REQUIRE(res.result == OK);
|
||||
REQUIRE(res.state == CfdpStates::BUSY_CLASS_1_NACKED);
|
||||
REQUIRE(res.step == DestHandler::TransactionStep::RECEIVING_FILE_DATA_PDUS);
|
||||
for (const auto id : idsToCheck) {
|
||||
REQUIRE(not tcStore.hasDataAtId(id));
|
||||
}
|
||||
REQUIRE(packetInfoList.empty());
|
||||
};
|
||||
|
||||
SECTION("State") {
|
||||
CHECK(destHandler.getCfdpState() == CfdpStates::IDLE);
|
||||
CHECK(destHandler.getTransactionStep() == DestHandler::TransactionStep::IDLE);
|
||||
}
|
||||
|
||||
SECTION("Idle State Machine Iteration") {
|
||||
auto res = destHandler.performStateMachine();
|
||||
CHECK(res.result == OK);
|
||||
CHECK(res.callStatus == CallStatus::CALL_AFTER_DELAY);
|
||||
CHECK(res.errors == 0);
|
||||
CHECK(destHandler.getCfdpState() == CfdpStates::IDLE);
|
||||
CHECK(destHandler.getTransactionStep() == DestHandler::TransactionStep::IDLE);
|
||||
}
|
||||
|
||||
SECTION("Empty File Transfer") {
|
||||
const DestHandler::FsmResult& res = destHandler.performStateMachine();
|
||||
CHECK(res.result == OK);
|
||||
FileSize cfdpFileSize(0);
|
||||
metadataPreparation(cfdpFileSize, ChecksumType::NULL_CHECKSUM);
|
||||
destHandler.performStateMachine();
|
||||
metadataCheck(res, "hello.txt", "hello-cpy.txt", 0);
|
||||
destHandler.performStateMachine();
|
||||
REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY);
|
||||
auto transactionId = destHandler.getTransactionId();
|
||||
eofPreparation(cfdpFileSize, 0);
|
||||
// After EOF, operation is done because no closure was requested
|
||||
destHandler.performStateMachine();
|
||||
eofCheck(res, transactionId);
|
||||
}
|
||||
|
||||
SECTION("Small File Transfer") {
|
||||
const DestHandler::FsmResult& res = destHandler.performStateMachine();
|
||||
CHECK(res.result == OK);
|
||||
std::string fileData = "hello test data";
|
||||
etl::crc32 crcCalc;
|
||||
crcCalc.add(fileData.begin(), fileData.end());
|
||||
uint32_t crc32 = crcCalc.value();
|
||||
FileSize cfdpFileSize(fileData.size());
|
||||
metadataPreparation(cfdpFileSize, ChecksumType::CRC_32);
|
||||
destHandler.performStateMachine();
|
||||
metadataCheck(res, "hello.txt", "hello-cpy.txt", fileData.size());
|
||||
destHandler.performStateMachine();
|
||||
REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY);
|
||||
auto transactionId = destHandler.getTransactionId();
|
||||
FileSize offset(0);
|
||||
FileDataInfo fdPduInfo(offset, reinterpret_cast<const uint8_t*>(fileData.data()),
|
||||
fileData.size());
|
||||
FileDataCreator fdPduCreator(conf, fdPduInfo);
|
||||
REQUIRE(tcStore.getFreeElement(&storeId, fdPduCreator.getSerializedSize(), &buf) == OK);
|
||||
REQUIRE(fdPduCreator.serialize(buf, serLen, fdPduCreator.getSerializedSize()) == OK);
|
||||
PacketInfo packetInfo(fdPduCreator.getPduType(), storeId, std::nullopt);
|
||||
packetInfoList.push_back(packetInfo);
|
||||
destHandler.performStateMachine();
|
||||
fileDataPduCheck(res, {storeId});
|
||||
eofPreparation(cfdpFileSize, crc32);
|
||||
// After EOF, operation is done because no closure was requested
|
||||
destHandler.performStateMachine();
|
||||
eofCheck(res, transactionId);
|
||||
}
|
||||
|
||||
SECTION("Segmented File Transfer") {
|
||||
const DestHandler::FsmResult& res = destHandler.performStateMachine();
|
||||
CHECK(res.result == OK);
|
||||
std::random_device dev;
|
||||
std::mt19937 rng(dev());
|
||||
std::uniform_int_distribution<std::mt19937::result_type> distU8(0, 255);
|
||||
std::array<uint8_t, 1024> largerFileData{};
|
||||
for (auto& val : largerFileData) {
|
||||
val = distU8(rng);
|
||||
}
|
||||
etl::crc32 crcCalc;
|
||||
crcCalc.add(largerFileData.begin(), largerFileData.end());
|
||||
uint32_t crc32 = crcCalc.value();
|
||||
FileSize cfdpFileSize(largerFileData.size());
|
||||
metadataPreparation(cfdpFileSize, ChecksumType::CRC_32);
|
||||
destHandler.performStateMachine();
|
||||
metadataCheck(res, "hello.txt", "hello-cpy.txt", largerFileData.size());
|
||||
destHandler.performStateMachine();
|
||||
REQUIRE(res.callStatus == CallStatus::CALL_AFTER_DELAY);
|
||||
auto transactionId = destHandler.getTransactionId();
|
||||
|
||||
std::vector<store_address_t> idsToCheck;
|
||||
{
|
||||
FileSize offset(0);
|
||||
FileDataInfo fdPduInfo(offset, reinterpret_cast<const uint8_t*>(largerFileData.data()),
|
||||
largerFileData.size() / 2);
|
||||
FileDataCreator fdPduCreator(conf, fdPduInfo);
|
||||
REQUIRE(tcStore.getFreeElement(&storeId, fdPduCreator.getSerializedSize(), &buf) == OK);
|
||||
REQUIRE(fdPduCreator.serialize(buf, serLen, fdPduCreator.getSerializedSize()) == OK);
|
||||
PacketInfo packetInfo(fdPduCreator.getPduType(), storeId, std::nullopt);
|
||||
idsToCheck.push_back(storeId);
|
||||
packetInfoList.push_back(packetInfo);
|
||||
}
|
||||
|
||||
{
|
||||
FileSize offset(512);
|
||||
FileDataInfo fdPduInfo(offset, reinterpret_cast<const uint8_t*>(largerFileData.data() + 512),
|
||||
largerFileData.size() / 2);
|
||||
FileDataCreator fdPduCreator(conf, fdPduInfo);
|
||||
REQUIRE(tcStore.getFreeElement(&storeId, fdPduCreator.getSerializedSize(), &buf) == OK);
|
||||
REQUIRE(fdPduCreator.serialize(buf, serLen, fdPduCreator.getSerializedSize()) == OK);
|
||||
PacketInfo packetInfo(fdPduCreator.getPduType(), storeId, std::nullopt);
|
||||
idsToCheck.push_back(storeId);
|
||||
packetInfoList.push_back(packetInfo);
|
||||
}
|
||||
|
||||
destHandler.performStateMachine();
|
||||
fileDataPduCheck(res, idsToCheck);
|
||||
eofPreparation(cfdpFileSize, crc32);
|
||||
// After EOF, operation is done because no closure was requested
|
||||
destHandler.performStateMachine();
|
||||
eofCheck(res, transactionId);
|
||||
}
|
||||
}
|
99
unittests/cfdp/handler/testDistributor.cpp
Normal file
99
unittests/cfdp/handler/testDistributor.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/cfdp/CfdpDistributor.h"
|
||||
#include "fsfw/cfdp/pdu/MetadataPduCreator.h"
|
||||
#include "fsfw/cfdp/tlv/StringLv.h"
|
||||
#include "fsfw/storagemanager/LocalPool.h"
|
||||
#include "fsfw/tcdistribution/definitions.h"
|
||||
#include "mocks/AcceptsTcMock.h"
|
||||
#include "mocks/MessageQueueMock.h"
|
||||
#include "mocks/StorageManagerMock.h"
|
||||
|
||||
TEST_CASE("CFDP Distributor", "[cfdp][distributor]") {
|
||||
LocalPool::LocalPoolConfig cfg = {{5, 32}, {2, 64}};
|
||||
StorageManagerMock pool(objects::NO_OBJECT, cfg);
|
||||
auto queue = MessageQueueMock(1);
|
||||
CfdpDistribCfg distribCfg(1, pool, &queue);
|
||||
auto distributor = CfdpDistributor(distribCfg);
|
||||
auto obswEntityId = cfdp::EntityId(UnsignedByteField<uint16_t>(2));
|
||||
auto groundEntityId = cfdp::EntityId(UnsignedByteField<uint16_t>(1));
|
||||
MessageQueueId_t receiverQueueId = 3;
|
||||
auto tcAcceptor = AcceptsTcMock("CFDP Receiver", 0, receiverQueueId);
|
||||
|
||||
// Set up Metadata PDU for generate test data.
|
||||
cfdp::FileSize fileSize(12);
|
||||
const cfdp::EntityId& sourceId(groundEntityId);
|
||||
const cfdp::EntityId& destId(obswEntityId);
|
||||
cfdp::TransactionSeqNum seqNum(UnsignedByteField<uint16_t>(12));
|
||||
auto pduConf = PduConfig(sourceId, destId, cfdp::TransmissionMode::UNACKNOWLEDGED, seqNum);
|
||||
std::string sourceFileString = "hello.txt";
|
||||
cfdp::StringLv sourceFileName(sourceFileString);
|
||||
std::string destFileString = "hello2.txt";
|
||||
cfdp::StringLv destFileName(destFileString);
|
||||
MetadataInfo metadataInfo(false, cfdp::ChecksumType::CRC_32, fileSize, sourceFileName,
|
||||
destFileName);
|
||||
MetadataPduCreator creator(pduConf, metadataInfo);
|
||||
uint8_t* dataPtr = nullptr;
|
||||
|
||||
SECTION("State") {
|
||||
CHECK(distributor.initialize() == returnvalue::OK);
|
||||
CHECK(std::strcmp(distributor.getName(), "CFDP Distributor") == 0);
|
||||
CHECK(distributor.getIdentifier() == 0);
|
||||
CHECK(distributor.getRequestQueue() == queue.getId());
|
||||
}
|
||||
|
||||
SECTION("Packet Forwarding") {
|
||||
CHECK(distributor.initialize() == returnvalue::OK);
|
||||
CHECK(distributor.registerTcDestination(obswEntityId, tcAcceptor) == returnvalue::OK);
|
||||
size_t serLen = 0;
|
||||
store_address_t storeId;
|
||||
CHECK(pool.LocalPool::getFreeElement(&storeId, creator.getSerializedSize(), &dataPtr) ==
|
||||
returnvalue::OK);
|
||||
REQUIRE(creator.SerializeIF::serializeBe(dataPtr, serLen, creator.getSerializedSize()) ==
|
||||
returnvalue::OK);
|
||||
TmTcMessage msg(storeId);
|
||||
queue.addReceivedMessage(msg);
|
||||
CHECK(distributor.performOperation(0) == returnvalue::OK);
|
||||
CHECK(queue.wasMessageSent());
|
||||
CHECK(queue.numberOfSentMessages() == 1);
|
||||
// The packet is forwarded, with no need to delete the data
|
||||
CHECK(pool.hasDataAtId(storeId));
|
||||
TmTcMessage sentMsg;
|
||||
CHECK(queue.getNextSentMessage(receiverQueueId, sentMsg) == returnvalue::OK);
|
||||
CHECK(sentMsg.getStorageId() == storeId);
|
||||
}
|
||||
|
||||
SECTION("No Destination found") {
|
||||
CHECK(distributor.initialize() == returnvalue::OK);
|
||||
size_t serLen = 0;
|
||||
store_address_t storeId;
|
||||
CHECK(pool.LocalPool::getFreeElement(&storeId, creator.getSerializedSize(), &dataPtr) ==
|
||||
returnvalue::OK);
|
||||
REQUIRE(creator.SerializeIF::serializeBe(dataPtr, serLen, creator.getSerializedSize()) ==
|
||||
returnvalue::OK);
|
||||
TmTcMessage msg(storeId);
|
||||
queue.addReceivedMessage(msg);
|
||||
CHECK(distributor.performOperation(0) == tmtcdistrib::NO_DESTINATION_FOUND);
|
||||
}
|
||||
|
||||
SECTION("Getting data fails") {
|
||||
pool.nextModifyDataCallFails.first = true;
|
||||
pool.nextModifyDataCallFails.second = StorageManagerIF::DATA_DOES_NOT_EXIST;
|
||||
size_t serLen = 0;
|
||||
store_address_t storeId;
|
||||
CHECK(distributor.registerTcDestination(obswEntityId, tcAcceptor) == returnvalue::OK);
|
||||
CHECK(pool.LocalPool::getFreeElement(&storeId, creator.getSerializedSize(), &dataPtr) ==
|
||||
returnvalue::OK);
|
||||
REQUIRE(creator.SerializeIF::serializeBe(dataPtr, serLen, creator.getSerializedSize()) ==
|
||||
returnvalue::OK);
|
||||
TmTcMessage msg(storeId);
|
||||
queue.addReceivedMessage(msg);
|
||||
CHECK(distributor.performOperation(0) == StorageManagerIF::DATA_DOES_NOT_EXIST);
|
||||
}
|
||||
|
||||
SECTION("Duplicate registration") {
|
||||
CHECK(distributor.initialize() == returnvalue::OK);
|
||||
CHECK(distributor.registerTcDestination(obswEntityId, tcAcceptor) == returnvalue::OK);
|
||||
CHECK(distributor.registerTcDestination(obswEntityId, tcAcceptor) == returnvalue::FAILED);
|
||||
}
|
||||
}
|
89
unittests/cfdp/handler/testFaultHandler.cpp
Normal file
89
unittests/cfdp/handler/testFaultHandler.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "mocks/cfdp/FaultHandlerMock.h"
|
||||
|
||||
TEST_CASE("CFDP Fault Handler", "[cfdp]") {
|
||||
using namespace cfdp;
|
||||
auto fhMock = FaultHandlerMock();
|
||||
cfdp::FaultHandlerCode fhCode;
|
||||
cfdp::TransactionId id;
|
||||
|
||||
SECTION("State") {
|
||||
// Verify initial condition
|
||||
CHECK(fhMock.getFaultHandler(ConditionCode::UNSUPPORTED_CHECKSUM_TYPE, fhCode));
|
||||
CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR);
|
||||
CHECK(fhMock.getFaultHandler(ConditionCode::POSITIVE_ACK_LIMIT_REACHED, fhCode));
|
||||
CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR);
|
||||
CHECK(fhMock.getFaultHandler(ConditionCode::KEEP_ALIVE_LIMIT_REACHED, fhCode));
|
||||
CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR);
|
||||
CHECK(fhMock.getFaultHandler(ConditionCode::INVALID_TRANSMISSION_MODE, fhCode));
|
||||
CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR);
|
||||
CHECK(fhMock.getFaultHandler(ConditionCode::FILESTORE_REJECTION, fhCode));
|
||||
CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR);
|
||||
CHECK(fhMock.getFaultHandler(ConditionCode::FILE_CHECKSUM_FAILURE, fhCode));
|
||||
CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR);
|
||||
CHECK(fhMock.getFaultHandler(ConditionCode::FILE_SIZE_ERROR, fhCode));
|
||||
CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR);
|
||||
CHECK(fhMock.getFaultHandler(ConditionCode::NAK_LIMIT_REACHED, fhCode));
|
||||
CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR);
|
||||
CHECK(fhMock.getFaultHandler(ConditionCode::INACTIVITY_DETECTED, fhCode));
|
||||
CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR);
|
||||
CHECK(fhMock.getFaultHandler(ConditionCode::CHECK_LIMIT_REACHED, fhCode));
|
||||
CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR);
|
||||
}
|
||||
|
||||
SECTION("Call Handler, Ignore Fault") {
|
||||
auto& info = fhMock.getFhInfo(FaultHandlerCode::IGNORE_ERROR);
|
||||
CHECK(fhMock.reportFault(id, ConditionCode::CHECK_LIMIT_REACHED));
|
||||
CHECK(info.callCount == 1);
|
||||
CHECK(info.condCodes.back() == ConditionCode::CHECK_LIMIT_REACHED);
|
||||
fhMock.reportFault(id, ConditionCode::FILE_CHECKSUM_FAILURE);
|
||||
CHECK(info.callCount == 2);
|
||||
CHECK(info.condCodes.back() == ConditionCode::FILE_CHECKSUM_FAILURE);
|
||||
}
|
||||
|
||||
SECTION("Invalid Reported Code") { CHECK(not fhMock.reportFault(id, ConditionCode::NO_ERROR)); }
|
||||
|
||||
SECTION("Invalid FH code") {
|
||||
CHECK(not fhMock.setFaultHandler(ConditionCode::KEEP_ALIVE_LIMIT_REACHED,
|
||||
FaultHandlerCode::RESERVED));
|
||||
CHECK(fhMock.getFaultHandler(ConditionCode::KEEP_ALIVE_LIMIT_REACHED, fhCode));
|
||||
CHECK(fhCode == FaultHandlerCode::IGNORE_ERROR);
|
||||
CHECK(not fhMock.setFaultHandler(ConditionCode::NO_ERROR, FaultHandlerCode::IGNORE_ERROR));
|
||||
CHECK(not fhMock.getFaultHandler(ConditionCode::NO_ERROR, fhCode));
|
||||
}
|
||||
|
||||
SECTION("Set Other Fault Handler") {
|
||||
CHECK(fhMock.setFaultHandler(ConditionCode::FILE_CHECKSUM_FAILURE,
|
||||
FaultHandlerCode::NOTICE_OF_CANCELLATION));
|
||||
CHECK(fhMock.setFaultHandler(ConditionCode::INACTIVITY_DETECTED,
|
||||
FaultHandlerCode::ABANDON_TRANSACTION));
|
||||
CHECK(fhMock.setFaultHandler(ConditionCode::KEEP_ALIVE_LIMIT_REACHED,
|
||||
FaultHandlerCode::NOTICE_OF_SUSPENSION));
|
||||
auto& ignoreInfo = fhMock.getFhInfo(FaultHandlerCode::IGNORE_ERROR);
|
||||
auto& cancellationInfo = fhMock.getFhInfo(FaultHandlerCode::NOTICE_OF_CANCELLATION);
|
||||
auto& suspensionInfo = fhMock.getFhInfo(FaultHandlerCode::NOTICE_OF_SUSPENSION);
|
||||
auto& abandonInfo = fhMock.getFhInfo(FaultHandlerCode::ABANDON_TRANSACTION);
|
||||
|
||||
CHECK(fhMock.reportFault(id, ConditionCode::FILE_CHECKSUM_FAILURE));
|
||||
CHECK(cancellationInfo.callCount == 1);
|
||||
CHECK(cancellationInfo.condCodes.back() == ConditionCode::FILE_CHECKSUM_FAILURE);
|
||||
CHECK(ignoreInfo.callCount == 0);
|
||||
CHECK(suspensionInfo.callCount == 0);
|
||||
CHECK(abandonInfo.callCount == 0);
|
||||
|
||||
CHECK(fhMock.reportFault(id, ConditionCode::INACTIVITY_DETECTED));
|
||||
CHECK(cancellationInfo.callCount == 1);
|
||||
CHECK(ignoreInfo.callCount == 0);
|
||||
CHECK(suspensionInfo.callCount == 0);
|
||||
CHECK(abandonInfo.callCount == 1);
|
||||
CHECK(abandonInfo.condCodes.back() == ConditionCode::INACTIVITY_DETECTED);
|
||||
|
||||
CHECK(fhMock.reportFault(id, ConditionCode::KEEP_ALIVE_LIMIT_REACHED));
|
||||
CHECK(cancellationInfo.callCount == 1);
|
||||
CHECK(ignoreInfo.callCount == 0);
|
||||
CHECK(suspensionInfo.callCount == 1);
|
||||
CHECK(suspensionInfo.condCodes.back() == ConditionCode::KEEP_ALIVE_LIMIT_REACHED);
|
||||
CHECK(abandonInfo.callCount == 1);
|
||||
}
|
||||
}
|
3
unittests/cfdp/handler/testSourceHandler.cpp
Normal file
3
unittests/cfdp/handler/testSourceHandler.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
TEST_CASE("CFDP Source Handler", "[cfdp]") {}
|
13
unittests/cfdp/pdu/CMakeLists.txt
Normal file
13
unittests/cfdp/pdu/CMakeLists.txt
Normal file
@ -0,0 +1,13 @@
|
||||
target_sources(
|
||||
${FSFW_TEST_TGT}
|
||||
PRIVATE testAckPdu.cpp
|
||||
testAckPdu.cpp
|
||||
testEofPdu.cpp
|
||||
testNakPdu.cpp
|
||||
testFinishedPdu.cpp
|
||||
testPromptPdu.cpp
|
||||
testKeepAlivePdu.cpp
|
||||
testMetadataPdu.cpp
|
||||
testFileData.cpp
|
||||
testCfdpHeader.cpp
|
||||
testFileDirective.cpp)
|
100
unittests/cfdp/pdu/testAckPdu.cpp
Normal file
100
unittests/cfdp/pdu/testAckPdu.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/cfdp/pdu/AckPduCreator.h"
|
||||
#include "fsfw/cfdp/pdu/AckPduReader.h"
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
|
||||
TEST_CASE("ACK PDU", "[cfdp][pdu]") {
|
||||
using namespace cfdp;
|
||||
ReturnValue_t result;
|
||||
std::array<uint8_t, 256> buf = {};
|
||||
uint8_t* bufptr = buf.data();
|
||||
size_t maxsz = buf.size();
|
||||
size_t sz = 0;
|
||||
auto seqNum = TransactionSeqNum(WidthInBytes::TWO_BYTES, 15);
|
||||
auto sourceId = EntityId(WidthInBytes::TWO_BYTES, 1);
|
||||
auto destId = EntityId(WidthInBytes::TWO_BYTES, 2);
|
||||
auto pduConf = PduConfig(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum);
|
||||
AckInfo ackInfo(FileDirective::EOF_DIRECTIVE, ConditionCode::NO_ERROR,
|
||||
AckTransactionStatus::ACTIVE);
|
||||
auto ackSerializer = AckPduCreator(ackInfo, pduConf);
|
||||
result = ackSerializer.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
SECTION("Serialize") {
|
||||
REQUIRE(buf[sz - 3] == cfdp::FileDirective::ACK);
|
||||
REQUIRE((buf[sz - 2] >> 4) == FileDirective::EOF_DIRECTIVE);
|
||||
REQUIRE((buf[sz - 2] & 0x0f) == 0);
|
||||
REQUIRE(buf[sz - 1] == AckTransactionStatus::ACTIVE);
|
||||
ackInfo.setAckedDirective(FileDirective::FINISH);
|
||||
ackInfo.setAckedConditionCode(ConditionCode::FILESTORE_REJECTION);
|
||||
ackInfo.setTransactionStatus(AckTransactionStatus::TERMINATED);
|
||||
auto ackSerializer2 = AckPduCreator(ackInfo, pduConf);
|
||||
bufptr = buf.data();
|
||||
sz = 0;
|
||||
result = ackSerializer2.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(buf[sz - 3] == cfdp::FileDirective::ACK);
|
||||
REQUIRE((buf[sz - 2] >> 4) == FileDirective::FINISH);
|
||||
REQUIRE((buf[sz - 2] & 0x0f) == 0b0001);
|
||||
REQUIRE((buf[sz - 1] >> 4) == ConditionCode::FILESTORE_REJECTION);
|
||||
REQUIRE((buf[sz - 1] & 0b11) == AckTransactionStatus::TERMINATED);
|
||||
|
||||
bufptr = buf.data();
|
||||
sz = 0;
|
||||
ackInfo.setAckedDirective(FileDirective::KEEP_ALIVE);
|
||||
auto ackSerializer3 = AckPduCreator(ackInfo, pduConf);
|
||||
result = ackSerializer3.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK);
|
||||
// Invalid file directive
|
||||
REQUIRE(result != returnvalue::OK);
|
||||
|
||||
ackInfo.setAckedDirective(FileDirective::FINISH);
|
||||
// buffer too small
|
||||
result = ackSerializer.serialize(&bufptr, &sz, 8, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == SerializeIF::BUFFER_TOO_SHORT);
|
||||
}
|
||||
|
||||
SECTION("Deserialize") {
|
||||
AckInfo ackInfo2;
|
||||
auto reader = AckPduReader(buf.data(), sz, ackInfo2);
|
||||
result = reader.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(ackInfo2.getAckedDirective() == FileDirective::EOF_DIRECTIVE);
|
||||
REQUIRE(ackInfo2.getAckedConditionCode() == ConditionCode::NO_ERROR);
|
||||
REQUIRE(ackInfo2.getDirectiveSubtypeCode() == 0);
|
||||
REQUIRE(ackInfo2.getTransactionStatus() == AckTransactionStatus::ACTIVE);
|
||||
|
||||
AckInfo newInfo = AckInfo(FileDirective::FINISH, ConditionCode::FILESTORE_REJECTION,
|
||||
AckTransactionStatus::TERMINATED);
|
||||
auto ackSerializer2 = AckPduCreator(newInfo, pduConf);
|
||||
bufptr = buf.data();
|
||||
sz = 0;
|
||||
result = ackSerializer2.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
auto reader2 = AckPduReader(buf.data(), sz, ackInfo2);
|
||||
result = reader2.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(ackInfo2.getAckedDirective() == FileDirective::FINISH);
|
||||
REQUIRE(ackInfo2.getAckedConditionCode() == ConditionCode::FILESTORE_REJECTION);
|
||||
REQUIRE(ackInfo2.getDirectiveSubtypeCode() == 0b0001);
|
||||
REQUIRE(ackInfo2.getTransactionStatus() == AckTransactionStatus::TERMINATED);
|
||||
|
||||
uint8_t prevVal = buf[sz - 2];
|
||||
buf[sz - 2] = FileDirective::INVALID_DIRECTIVE << 4;
|
||||
result = reader2.parseData();
|
||||
REQUIRE(result == cfdp::INVALID_ACK_DIRECTIVE_FIELDS);
|
||||
buf[sz - 2] = FileDirective::FINISH << 4 | 0b1111;
|
||||
result = reader2.parseData();
|
||||
REQUIRE(result == cfdp::INVALID_ACK_DIRECTIVE_FIELDS);
|
||||
buf[sz - 2] = prevVal;
|
||||
buf[sz - 3] = cfdp::FileDirective::INVALID_DIRECTIVE;
|
||||
result = reader2.parseData();
|
||||
REQUIRE(result == cfdp::INVALID_DIRECTIVE_FIELD);
|
||||
buf[sz - 3] = cfdp::FileDirective::ACK;
|
||||
auto maxSizeTooSmall = AckPduReader(buf.data(), sz - 2, ackInfo2);
|
||||
result = maxSizeTooSmall.parseData();
|
||||
REQUIRE(result == SerializeIF::STREAM_TOO_SHORT);
|
||||
}
|
||||
}
|
327
unittests/cfdp/pdu/testCfdpHeader.cpp
Normal file
327
unittests/cfdp/pdu/testCfdpHeader.cpp
Normal file
@ -0,0 +1,327 @@
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/cfdp/pdu/FinishedInfo.h"
|
||||
#include "fsfw/cfdp/pdu/FinishedPduCreator.h"
|
||||
#include "fsfw/cfdp/pdu/HeaderCreator.h"
|
||||
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
|
||||
using namespace returnvalue;
|
||||
|
||||
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 =
|
||||
PduConfig(sourceId, destId, cfdp::TransmissionMode::ACKNOWLEDGED, seqNum, false);
|
||||
uint8_t* serTarget = serBuf.data();
|
||||
const uint8_t* deserTarget = serTarget;
|
||||
size_t serSize = 0;
|
||||
auto creator = HeaderCreator(pduConf, cfdp::PduType::FILE_DIRECTIVE, 0);
|
||||
|
||||
SECTION("Header State") {
|
||||
REQUIRE(seqNum.getSerializedSize() == 1);
|
||||
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);
|
||||
REQUIRE(creator.getPduType() == cfdp::PduType::FILE_DIRECTIVE);
|
||||
REQUIRE(creator.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::NOT_PRESENT);
|
||||
REQUIRE(creator.getSegmentationControl() == false);
|
||||
REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::ACKNOWLEDGED);
|
||||
cfdp::TransactionSeqNum seqNumLocal;
|
||||
creator.getTransactionSeqNum(seqNumLocal);
|
||||
REQUIRE(seqNumLocal.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
|
||||
REQUIRE(seqNumLocal.getValue() == 2);
|
||||
cfdp::EntityId sourceDestId;
|
||||
creator.getSourceId(sourceDestId);
|
||||
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
|
||||
REQUIRE(sourceDestId.getValue() == 0);
|
||||
creator.getDestId(sourceDestId);
|
||||
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
|
||||
REQUIRE(sourceDestId.getValue() == 1);
|
||||
}
|
||||
|
||||
SECTION("Deserialization fails") {
|
||||
const uint8_t** dummyPtr = nullptr;
|
||||
REQUIRE(creator.deSerialize(dummyPtr, &serSize, SerializeIF::Endianness::NETWORK) ==
|
||||
returnvalue::FAILED);
|
||||
}
|
||||
|
||||
SECTION("Serialization fails") {
|
||||
REQUIRE(creator.serialize(nullptr, &serSize, serBuf.size(), SerializeIF::Endianness::NETWORK) ==
|
||||
returnvalue::FAILED);
|
||||
}
|
||||
|
||||
SECTION("Buffer Too Short") {
|
||||
for (uint8_t idx = 0; idx < 7; idx++) {
|
||||
result = creator.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::BIG);
|
||||
REQUIRE(result == static_cast<int>(SerializeIF::BUFFER_TOO_SHORT));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Set Data Field Len") {
|
||||
// Set PDU data field len
|
||||
creator.setPduDataFieldLen(0x0ff0);
|
||||
REQUIRE(creator.getPduDataFieldLen() == 0x0ff0);
|
||||
REQUIRE(creator.getSerializedSize() == 7);
|
||||
REQUIRE(creator.getWholePduSize() == 7 + 0x0ff0);
|
||||
serTarget = serBuf.data();
|
||||
serSize = 0;
|
||||
result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG);
|
||||
REQUIRE(serBuf[1] == 0x0f);
|
||||
REQUIRE(serBuf[2] == 0xf0);
|
||||
}
|
||||
|
||||
SECTION("Serialize with Fields Flipped") {
|
||||
pduConf.crcFlag = true;
|
||||
pduConf.largeFile = true;
|
||||
pduConf.direction = cfdp::Direction::TOWARDS_SENDER;
|
||||
pduConf.mode = cfdp::TransmissionMode::UNACKNOWLEDGED;
|
||||
creator.setSegmentationControl(cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION);
|
||||
creator.setPduType(cfdp::PduType::FILE_DATA);
|
||||
creator.setSegmentMetadataFlag(cfdp::SegmentMetadataFlag::PRESENT);
|
||||
serTarget = serBuf.data();
|
||||
serSize = 0;
|
||||
|
||||
SECTION("Regular") {
|
||||
// Everything except version bit flipped to one now
|
||||
REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(),
|
||||
SerializeIF::Endianness::BIG) == returnvalue::OK);
|
||||
CHECK(serBuf[0] == 0x3f);
|
||||
CHECK(serBuf[3] == 0x99);
|
||||
REQUIRE(creator.getCrcFlag() == true);
|
||||
REQUIRE(creator.getDirection() == cfdp::Direction::TOWARDS_SENDER);
|
||||
REQUIRE(creator.getLargeFileFlag() == true);
|
||||
REQUIRE(creator.getLenEntityIds() == 1);
|
||||
REQUIRE(creator.getLenSeqNum() == 1);
|
||||
REQUIRE(creator.getPduType() == cfdp::PduType::FILE_DATA);
|
||||
REQUIRE(creator.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT);
|
||||
REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED);
|
||||
REQUIRE(creator.getSegmentationControl() == true);
|
||||
}
|
||||
|
||||
SECTION("Other variable sized fields") {
|
||||
pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
|
||||
pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
|
||||
pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
|
||||
REQUIRE(pduConf.sourceId.getSerializedSize() == 4);
|
||||
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);
|
||||
REQUIRE(creator.getPduType() == cfdp::PduType::FILE_DATA);
|
||||
REQUIRE(creator.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT);
|
||||
REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED);
|
||||
REQUIRE(creator.getSegmentationControl() == true);
|
||||
// Last three bits are 2 now (length of seq number) and bit 1 to bit 3 is 4 (len entity IDs)
|
||||
REQUIRE(serBuf[3] == 0b11001010);
|
||||
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.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
|
||||
pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
|
||||
pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
|
||||
for (uint8_t idx = 0; idx < 14; idx++) {
|
||||
REQUIRE(creator.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::BIG) ==
|
||||
SerializeIF::BUFFER_TOO_SHORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Invalid Variable Sized Fields") {
|
||||
result = pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 0xfff);
|
||||
REQUIRE(result == returnvalue::FAILED);
|
||||
result = pduConf.sourceId.setValue(cfdp::WidthInBytes::TWO_BYTES, 0xfffff);
|
||||
REQUIRE(result == returnvalue::FAILED);
|
||||
result = pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xfffffffff);
|
||||
REQUIRE(result == returnvalue::FAILED);
|
||||
}
|
||||
|
||||
SECTION("Header Serialization") {
|
||||
result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
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
|
||||
REQUIRE(serBuf[3] == 0b00010001);
|
||||
// Source ID
|
||||
REQUIRE(serBuf[4] == 0);
|
||||
// Transaction Seq Number
|
||||
REQUIRE(serBuf[5] == 2);
|
||||
// Dest ID
|
||||
REQUIRE(serBuf[6] == 1);
|
||||
|
||||
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.setValue(cfdp::WidthInBytes::ONE_BYTE, 1);
|
||||
serTarget = serBuf.data();
|
||||
serSize = 1;
|
||||
result = pduConf.sourceId.serialize(&serTarget, &serSize, 1, SerializeIF::Endianness::MACHINE);
|
||||
REQUIRE(result == static_cast<int>(SerializeIF::BUFFER_TOO_SHORT));
|
||||
}
|
||||
|
||||
SECTION("Header Deserialization 0") {
|
||||
REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG) ==
|
||||
returnvalue::OK);
|
||||
REQUIRE(serBuf[1] == 0);
|
||||
REQUIRE(serBuf[2] == 0);
|
||||
// Entity and Transaction Sequence number are 1 byte large
|
||||
REQUIRE(serBuf[3] == 0b00010001);
|
||||
REQUIRE(serSize == 7);
|
||||
// Deser call not strictly necessary
|
||||
auto reader = PduHeaderReader(serBuf.data(), serBuf.size());
|
||||
|
||||
ReturnValue_t serResult = reader.parseData();
|
||||
REQUIRE(serResult == returnvalue::OK);
|
||||
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);
|
||||
REQUIRE(reader.getPduType() == cfdp::PduType::FILE_DIRECTIVE);
|
||||
REQUIRE(reader.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::NOT_PRESENT);
|
||||
REQUIRE(reader.getSegmentationControl() == false);
|
||||
REQUIRE(reader.getTransmissionMode() == cfdp::TransmissionMode::ACKNOWLEDGED);
|
||||
// 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);
|
||||
}
|
||||
|
||||
SECTION("Header Deserialization 1") {
|
||||
pduConf.crcFlag = true;
|
||||
pduConf.largeFile = true;
|
||||
pduConf.direction = cfdp::Direction::TOWARDS_SENDER;
|
||||
pduConf.mode = cfdp::TransmissionMode::UNACKNOWLEDGED;
|
||||
creator.setSegmentationControl(cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION);
|
||||
creator.setPduType(cfdp::PduType::FILE_DATA);
|
||||
creator.setSegmentMetadataFlag(cfdp::SegmentMetadataFlag::PRESENT);
|
||||
result = pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
result = pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
result = pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
serTarget = serBuf.data();
|
||||
serSize = 0;
|
||||
result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG);
|
||||
PduHeaderReader reader(serBuf.data(), serBuf.size());
|
||||
REQUIRE(reader.parseData() == returnvalue::OK);
|
||||
// Everything except version bit flipped to one now
|
||||
REQUIRE(serBuf[0] == 0x3f);
|
||||
REQUIRE(serBuf[3] == 0b11001010);
|
||||
REQUIRE(reader.getWholePduSize() == 14);
|
||||
|
||||
REQUIRE(reader.getCrcFlag() == true);
|
||||
REQUIRE(reader.getDirection() == cfdp::Direction::TOWARDS_SENDER);
|
||||
REQUIRE(reader.getLargeFileFlag() == true);
|
||||
REQUIRE(reader.getLenEntityIds() == 4);
|
||||
REQUIRE(reader.getLenSeqNum() == 2);
|
||||
REQUIRE(reader.getPduType() == cfdp::PduType::FILE_DATA);
|
||||
REQUIRE(reader.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT);
|
||||
REQUIRE(reader.getSegmentationControl() == true);
|
||||
REQUIRE(reader.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED);
|
||||
// Again, no data field set because this is a header only
|
||||
REQUIRE(reader.getPduDataField() == nullptr);
|
||||
|
||||
cfdp::TransactionSeqNum seqNumLocal;
|
||||
reader.getTransactionSeqNum(seqNumLocal);
|
||||
REQUIRE(seqNumLocal.getWidth() == cfdp::WidthInBytes::TWO_BYTES);
|
||||
REQUIRE(seqNumLocal.getValue() == 0x0fff);
|
||||
cfdp::EntityId sourceDestId;
|
||||
reader.getSourceId(sourceDestId);
|
||||
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::FOUR_BYTES);
|
||||
REQUIRE(sourceDestId.getValue() == 0xff00ff00);
|
||||
reader.getDestId(sourceDestId);
|
||||
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::FOUR_BYTES);
|
||||
REQUIRE(sourceDestId.getValue() == 0x00ff00ff);
|
||||
CHECK(reader.setReadOnlyData(nullptr, -1) != returnvalue::OK);
|
||||
REQUIRE(reader.getHeaderSize() == 14);
|
||||
|
||||
SECTION("Manipulate Source Dest ID") {
|
||||
serTarget = serBuf.data();
|
||||
serSize = 0;
|
||||
pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 22);
|
||||
pduConf.destId.setValue(cfdp::WidthInBytes::ONE_BYTE, 48);
|
||||
result = creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG);
|
||||
reader.getSourceId(sourceDestId);
|
||||
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
|
||||
REQUIRE(sourceDestId.getValue() == 22);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/cfdp/pdu/EofPduDeserializer.h"
|
||||
#include "fsfw/cfdp/pdu/EofPduSerializer.h"
|
||||
#include "fsfw/cfdp/pdu/EofPduCreator.h"
|
||||
#include "fsfw/cfdp/pdu/EofPduReader.h"
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
|
||||
TEST_CASE("EOF PDU", "[EofPdu]") {
|
||||
TEST_CASE("EOF PDU", "[cfdp][pdu]") {
|
||||
using namespace cfdp;
|
||||
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
@ -20,9 +20,9 @@ TEST_CASE("EOF PDU", "[EofPdu]") {
|
||||
TransactionSeqNum seqNum(WidthInBytes::TWO_BYTES, 15);
|
||||
EntityId sourceId(WidthInBytes::TWO_BYTES, 1);
|
||||
|
||||
PduConfig pduConf(TransmissionModes::ACKNOWLEDGED, seqNum, sourceId, destId);
|
||||
PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum);
|
||||
|
||||
auto eofSerializer = EofPduSerializer(pduConf, eofInfo);
|
||||
auto eofSerializer = EofPduCreator(pduConf, eofInfo);
|
||||
SECTION("Serialize") {
|
||||
result = eofSerializer.serialize(&bufPtr, &sz, buf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
@ -37,7 +37,7 @@ TEST_CASE("EOF PDU", "[EofPdu]") {
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(fileSizeVal == 12);
|
||||
REQUIRE(buf[sz - 10] == cfdp::FileDirectives::EOF_DIRECTIVE);
|
||||
REQUIRE(buf[sz - 10] == cfdp::FileDirective::EOF_DIRECTIVE);
|
||||
REQUIRE(buf[sz - 9] == 0x00);
|
||||
REQUIRE(sz == 20);
|
||||
|
||||
@ -45,20 +45,20 @@ TEST_CASE("EOF PDU", "[EofPdu]") {
|
||||
eofInfo.setFileSize(0x10ffffff10, true);
|
||||
pduConf.largeFile = true;
|
||||
// Should serialize with fault location now
|
||||
auto serializeWithFaultLocation = EofPduSerializer(pduConf, eofInfo);
|
||||
auto serializeWithFaultLocation = EofPduCreator(pduConf, eofInfo);
|
||||
bufPtr = buf.data();
|
||||
sz = 0;
|
||||
result = serializeWithFaultLocation.serialize(&bufPtr, &sz, buf.size(),
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(sz == 28);
|
||||
REQUIRE(buf[10] == cfdp::FileDirectives::EOF_DIRECTIVE);
|
||||
REQUIRE(buf[10] == cfdp::FileDirective::EOF_DIRECTIVE);
|
||||
REQUIRE(buf[11] >> 4 == cfdp::ConditionCode::FILESTORE_REJECTION);
|
||||
uint64_t fileSizeLarge = 0;
|
||||
result = SerializeAdapter::deSerialize(&fileSizeLarge, buf.data() + 16, nullptr,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(fileSizeLarge == 0x10ffffff10);
|
||||
REQUIRE(buf[sz - 4] == cfdp::TlvTypes::ENTITY_ID);
|
||||
REQUIRE(buf[sz - 4] == cfdp::TlvType::ENTITY_ID);
|
||||
// width of entity ID is 2
|
||||
REQUIRE(buf[sz - 3] == 2);
|
||||
uint16_t entityIdRaw = 0;
|
||||
@ -83,7 +83,7 @@ TEST_CASE("EOF PDU", "[EofPdu]") {
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
EntityIdTlv tlv(destId);
|
||||
EofInfo emptyInfo(&tlv);
|
||||
auto deserializer = EofPduDeserializer(buf.data(), buf.size(), emptyInfo);
|
||||
auto deserializer = EofPduReader(buf.data(), buf.size(), emptyInfo);
|
||||
result = deserializer.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(emptyInfo.getConditionCode() == cfdp::ConditionCode::NO_ERROR);
|
||||
@ -94,23 +94,23 @@ TEST_CASE("EOF PDU", "[EofPdu]") {
|
||||
eofInfo.setFileSize(0x10ffffff10, true);
|
||||
pduConf.largeFile = true;
|
||||
// Should serialize with fault location now
|
||||
auto serializeWithFaultLocation = EofPduSerializer(pduConf, eofInfo);
|
||||
auto serializeWithFaultLocation = EofPduCreator(pduConf, eofInfo);
|
||||
bufPtr = buf.data();
|
||||
sz = 0;
|
||||
result = serializeWithFaultLocation.serialize(&bufPtr, &sz, buf.size(),
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
auto deserializer2 = EofPduDeserializer(buf.data(), buf.size(), emptyInfo);
|
||||
auto deserializer2 = EofPduReader(buf.data(), buf.size(), emptyInfo);
|
||||
result = deserializer2.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(emptyInfo.getConditionCode() == cfdp::ConditionCode::FILESTORE_REJECTION);
|
||||
REQUIRE(emptyInfo.getChecksum() == 5);
|
||||
REQUIRE(emptyInfo.getFileSize().getSize() == 0x10ffffff10);
|
||||
REQUIRE(emptyInfo.getFaultLoc()->getType() == cfdp::TlvTypes::ENTITY_ID);
|
||||
REQUIRE(emptyInfo.getFaultLoc()->getType() == cfdp::TlvType::ENTITY_ID);
|
||||
REQUIRE(emptyInfo.getFaultLoc()->getSerializedSize() == 4);
|
||||
uint16_t destId = emptyInfo.getFaultLoc()->getEntityId().getValue();
|
||||
REQUIRE(destId == 2);
|
||||
for (size_t maxSz = 0; maxSz < deserializer2.getWholePduSize() - 1; maxSz++) {
|
||||
auto invalidDeser = EofPduDeserializer(buf.data(), maxSz, emptyInfo);
|
||||
auto invalidDeser = EofPduReader(buf.data(), maxSz, emptyInfo);
|
||||
result = invalidDeser.parseData();
|
||||
REQUIRE(result != returnvalue::OK);
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/cfdp/pdu/FileDataDeserializer.h"
|
||||
#include "fsfw/cfdp/pdu/FileDataSerializer.h"
|
||||
#include "fsfw/cfdp/pdu/FileDataCreator.h"
|
||||
#include "fsfw/cfdp/pdu/FileDataReader.h"
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
#include "fsfw/serviceinterface.h"
|
||||
|
||||
TEST_CASE("File Data PDU", "[FileDataPdu]") {
|
||||
TEST_CASE("File Data PDU", "[cfdp][pdu]") {
|
||||
using namespace cfdp;
|
||||
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
@ -17,7 +17,7 @@ TEST_CASE("File Data PDU", "[FileDataPdu]") {
|
||||
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);
|
||||
PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum);
|
||||
|
||||
for (uint8_t idx = 0; idx < 10; idx++) {
|
||||
fileBuffer[idx] = idx;
|
||||
@ -26,7 +26,7 @@ TEST_CASE("File Data PDU", "[FileDataPdu]") {
|
||||
FileDataInfo info(offset, fileBuffer.data(), 10);
|
||||
|
||||
SECTION("Serialization") {
|
||||
FileDataSerializer serializer(pduConf, info);
|
||||
FileDataCreator serializer(pduConf, info);
|
||||
result =
|
||||
serializer.serialize(&buffer, &sz, fileDataBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
@ -102,14 +102,14 @@ TEST_CASE("File Data PDU", "[FileDataPdu]") {
|
||||
}
|
||||
|
||||
SECTION("Deserialization") {
|
||||
FileDataSerializer serializer(pduConf, info);
|
||||
FileDataCreator serializer(pduConf, info);
|
||||
result =
|
||||
serializer.serialize(&buffer, &sz, fileDataBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
FileSize emptyOffset;
|
||||
FileDataInfo emptyInfo(emptyOffset);
|
||||
FileDataDeserializer deserializer(fileDataBuffer.data(), fileDataBuffer.size(), emptyInfo);
|
||||
FileDataReader deserializer(fileDataBuffer.data(), fileDataBuffer.size(), emptyInfo);
|
||||
result = deserializer.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(deserializer.getWholePduSize() == 24);
|
85
unittests/cfdp/pdu/testFileDirective.cpp
Normal file
85
unittests/cfdp/pdu/testFileDirective.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
|
||||
|
||||
TEST_CASE("CFDP File Directive", "[cfdp][pdu]") {
|
||||
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 =
|
||||
PduConfig(sourceId, destId, cfdp::TransmissionMode::ACKNOWLEDGED, seqNum, false);
|
||||
uint8_t* serTarget = serBuf.data();
|
||||
const uint8_t* deserTarget = serTarget;
|
||||
size_t serSize = 0;
|
||||
auto fdSer = FileDirectiveCreator(pduConf, FileDirective::ACK, 4);
|
||||
|
||||
SECTION("Serialization") {
|
||||
REQUIRE(fdSer.getSerializedSize() == 8);
|
||||
serTarget = serBuf.data();
|
||||
serSize = 0;
|
||||
result = fdSer.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
// Only version bits are set
|
||||
REQUIRE(serBuf[0] == 0b00100000);
|
||||
// PDU data field length is 5 (4 + Directive code octet)
|
||||
REQUIRE(serBuf[1] == 0);
|
||||
REQUIRE(serBuf[2] == 5);
|
||||
// Entity and Transaction Sequence number are 1 byte large
|
||||
REQUIRE(serBuf[3] == 0b00010001);
|
||||
// Source ID
|
||||
REQUIRE(serBuf[4] == 0);
|
||||
// Transaction Seq Number
|
||||
REQUIRE(serBuf[5] == 2);
|
||||
// Dest ID
|
||||
REQUIRE(serBuf[6] == 1);
|
||||
REQUIRE(serBuf[7] == FileDirective::ACK);
|
||||
}
|
||||
|
||||
SECTION("Serialization fails") {
|
||||
REQUIRE(fdSer.serialize(nullptr, nullptr, 85, SerializeIF::Endianness::NETWORK) ==
|
||||
returnvalue::FAILED);
|
||||
}
|
||||
|
||||
SECTION("Buffer Too Short") {
|
||||
for (uint8_t idx = 0; idx < 8; idx++) {
|
||||
serTarget = serBuf.data();
|
||||
serSize = 0;
|
||||
REQUIRE(fdSer.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::NETWORK) ==
|
||||
SerializeIF::BUFFER_TOO_SHORT);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Deserialize") {
|
||||
CHECK(fdSer.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::NETWORK) ==
|
||||
returnvalue::OK);
|
||||
serTarget = serBuf.data();
|
||||
|
||||
REQUIRE(fdSer.deSerialize(&deserTarget, &serSize, SerializeIF::Endianness::NETWORK) ==
|
||||
returnvalue::FAILED);
|
||||
deserTarget = serBuf.data();
|
||||
CHECK(serSize == 8);
|
||||
auto fdDeser = FileDirectiveReader(deserTarget, serBuf.size());
|
||||
REQUIRE(fdDeser.isNull());
|
||||
REQUIRE(not fdDeser);
|
||||
REQUIRE(fdDeser.getEndianness() == SerializeIF::Endianness::NETWORK);
|
||||
fdDeser.setEndianness(SerializeIF::Endianness::MACHINE);
|
||||
REQUIRE(fdDeser.getEndianness() == SerializeIF::Endianness::MACHINE);
|
||||
fdDeser.setEndianness(SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(fdDeser.parseData() == returnvalue::OK);
|
||||
REQUIRE(not fdDeser.isNull());
|
||||
REQUIRE(fdDeser);
|
||||
REQUIRE(fdDeser.getFileDirective() == FileDirective::ACK);
|
||||
REQUIRE(fdDeser.getPduDataFieldLen() == 5);
|
||||
REQUIRE(fdDeser.getHeaderSize() == 8);
|
||||
REQUIRE(fdDeser.getPduType() == cfdp::PduType::FILE_DIRECTIVE);
|
||||
|
||||
serBuf[7] = 0xff;
|
||||
// Invalid file directive
|
||||
REQUIRE(fdDeser.parseData() == cfdp::INVALID_DIRECTIVE_FIELD);
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/cfdp/pdu/FinishedPduDeserializer.h"
|
||||
#include "fsfw/cfdp/pdu/FinishedPduSerializer.h"
|
||||
#include "fsfw/cfdp/pdu/FinishedPduCreator.h"
|
||||
#include "fsfw/cfdp/pdu/FinishedPduReader.h"
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
|
||||
TEST_CASE("Finished PDU", "[FinishedPdu]") {
|
||||
TEST_CASE("Finished PDU", "[cfdp][pdu]") {
|
||||
using namespace cfdp;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
std::array<uint8_t, 256> fnBuffer = {};
|
||||
@ -14,28 +14,28 @@ TEST_CASE("Finished PDU", "[FinishedPdu]") {
|
||||
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);
|
||||
PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum);
|
||||
|
||||
cfdp::Lv emptyFsMsg;
|
||||
FinishedInfo info(cfdp::ConditionCode::INACTIVITY_DETECTED,
|
||||
cfdp::FinishedDeliveryCode::DATA_INCOMPLETE,
|
||||
cfdp::FinishedFileStatus::DISCARDED_DELIBERATELY);
|
||||
cfdp::FileDeliveryCode::DATA_INCOMPLETE,
|
||||
cfdp::FileDeliveryStatus::DISCARDED_DELIBERATELY);
|
||||
|
||||
SECTION("Serialize") {
|
||||
FinishPduSerializer serializer(pduConf, info);
|
||||
FinishPduCreator serializer(pduConf, info);
|
||||
result = serializer.serialize(&buffer, &sz, fnBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(serializer.getSerializedSize() == 12);
|
||||
REQUIRE(((fnBuffer[1] << 8) | fnBuffer[2]) == 2);
|
||||
REQUIRE(fnBuffer[10] == cfdp::FileDirectives::FINISH);
|
||||
REQUIRE(fnBuffer[10] == cfdp::FileDirective::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(((fnBuffer[sz - 1] >> 2) & 0x01) == cfdp::FileDeliveryCode::DATA_INCOMPLETE);
|
||||
REQUIRE((fnBuffer[sz - 1] & 0b11) == cfdp::FileDeliveryStatus::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());
|
||||
cfdp::StringLv firstNameLv(firstName);
|
||||
FilestoreResponseTlv response(cfdp::FilestoreActionCode::DELETE_FILE,
|
||||
cfdp::FSR_APPEND_FILE_1_NOT_EXISTS, firstNameLv, nullptr);
|
||||
FilestoreResponseTlv* responsePtr = &response;
|
||||
@ -53,7 +53,7 @@ TEST_CASE("Finished PDU", "[FinishedPdu]") {
|
||||
|
||||
// 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());
|
||||
cfdp::StringLv secondNameLv(secondName);
|
||||
FilestoreResponseTlv response2(cfdp::FilestoreActionCode::DENY_FILE, cfdp::FSR_SUCCESS,
|
||||
secondNameLv, nullptr);
|
||||
REQUIRE(response2.getSerializedSize() == 15);
|
||||
@ -73,10 +73,10 @@ TEST_CASE("Finished PDU", "[FinishedPdu]") {
|
||||
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);
|
||||
info.setFileStatus(cfdp::FileDeliveryStatus::DISCARDED_FILESTORE_REJECTION);
|
||||
REQUIRE(info.getFileStatus() == cfdp::FileDeliveryStatus::DISCARDED_FILESTORE_REJECTION);
|
||||
info.setDeliveryCode(cfdp::FileDeliveryCode::DATA_INCOMPLETE);
|
||||
REQUIRE(info.getDeliveryCode() == cfdp::FileDeliveryCode::DATA_INCOMPLETE);
|
||||
for (size_t maxSz = 0; maxSz < 45; maxSz++) {
|
||||
sz = 0;
|
||||
buffer = fnBuffer.data();
|
||||
@ -87,21 +87,21 @@ TEST_CASE("Finished PDU", "[FinishedPdu]") {
|
||||
|
||||
SECTION("Deserialize") {
|
||||
FinishedInfo emptyInfo;
|
||||
FinishPduSerializer serializer(pduConf, info);
|
||||
FinishPduCreator serializer(pduConf, info);
|
||||
result = serializer.serialize(&buffer, &sz, fnBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
FinishPduDeserializer deserializer(fnBuffer.data(), fnBuffer.size(), emptyInfo);
|
||||
FinishPduReader deserializer(fnBuffer.data(), fnBuffer.size(), emptyInfo);
|
||||
result = deserializer.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(emptyInfo.getFileStatus() == cfdp::FinishedFileStatus::DISCARDED_DELIBERATELY);
|
||||
REQUIRE(emptyInfo.getFileStatus() == cfdp::FileDeliveryStatus::DISCARDED_DELIBERATELY);
|
||||
REQUIRE(emptyInfo.getConditionCode() == cfdp::ConditionCode::INACTIVITY_DETECTED);
|
||||
REQUIRE(emptyInfo.getDeliveryCode() == cfdp::FinishedDeliveryCode::DATA_INCOMPLETE);
|
||||
REQUIRE(emptyInfo.getDeliveryCode() == cfdp::FileDeliveryCode::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());
|
||||
cfdp::StringLv firstNameLv(firstName);
|
||||
FilestoreResponseTlv response(cfdp::FilestoreActionCode::DELETE_FILE, cfdp::FSR_NOT_PERFORMED,
|
||||
firstNameLv, nullptr);
|
||||
FilestoreResponseTlv* responsePtr = &response;
|
||||
@ -114,7 +114,7 @@ TEST_CASE("Finished PDU", "[FinishedPdu]") {
|
||||
FilestoreResponseTlv emptyResponse(firstNameLv, nullptr);
|
||||
responsePtr = &emptyResponse;
|
||||
emptyInfo.setFilestoreResponsesArray(&responsePtr, nullptr, &len);
|
||||
FinishPduDeserializer deserializer2(fnBuffer.data(), fnBuffer.size(), emptyInfo);
|
||||
FinishPduReader deserializer2(fnBuffer.data(), fnBuffer.size(), emptyInfo);
|
||||
result = deserializer2.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(emptyInfo.getFsResponsesLen() == 1);
|
||||
@ -130,7 +130,7 @@ TEST_CASE("Finished PDU", "[FinishedPdu]") {
|
||||
|
||||
// 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());
|
||||
cfdp::StringLv secondNameLv(secondName);
|
||||
FilestoreResponseTlv response2(cfdp::FilestoreActionCode::DENY_FILE, cfdp::FSR_SUCCESS,
|
||||
secondNameLv, nullptr);
|
||||
REQUIRE(response2.getSerializedSize() == 15);
|
||||
@ -152,7 +152,7 @@ TEST_CASE("Finished PDU", "[FinishedPdu]") {
|
||||
response.setFilestoreMessage(&emptyFsMsg);
|
||||
emptyInfo.setFilestoreResponsesArray(responses.data(), &len, &len);
|
||||
response2.setFilestoreMessage(&emptyFsMsg);
|
||||
FinishPduDeserializer deserializer3(fnBuffer.data(), fnBuffer.size(), emptyInfo);
|
||||
FinishPduReader deserializer3(fnBuffer.data(), fnBuffer.size(), emptyInfo);
|
||||
result = deserializer3.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
auto& infoRef = deserializer3.getInfo();
|
||||
@ -176,12 +176,12 @@ TEST_CASE("Finished PDU", "[FinishedPdu]") {
|
||||
|
||||
fnBuffer[11] = tmp;
|
||||
// Invalid TLV type, should be entity ID
|
||||
fnBuffer[sz - 4] = cfdp::TlvTypes::FILESTORE_REQUEST;
|
||||
fnBuffer[sz - 4] = cfdp::TlvType::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);
|
||||
FinishPduReader faultyDeser(fnBuffer.data(), maxSz, emptyInfo);
|
||||
result = faultyDeser.parseData();
|
||||
REQUIRE(result != returnvalue::OK);
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/cfdp/pdu/KeepAlivePduDeserializer.h"
|
||||
#include "fsfw/cfdp/pdu/KeepAlivePduSerializer.h"
|
||||
#include "fsfw/cfdp/pdu/KeepAlivePduCreator.h"
|
||||
#include "fsfw/cfdp/pdu/KeepAlivePduReader.h"
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
|
||||
TEST_CASE("Keep Alive PDU", "[KeepAlivePdu]") {
|
||||
TEST_CASE("Keep Alive PDU", "[cfdp][pdu]") {
|
||||
using namespace cfdp;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
std::array<uint8_t, 256> kaBuffer = {};
|
||||
@ -14,15 +14,15 @@ TEST_CASE("Keep Alive PDU", "[KeepAlivePdu]") {
|
||||
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);
|
||||
PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum);
|
||||
|
||||
FileSize progress(0x50);
|
||||
|
||||
SECTION("Serialize") {
|
||||
KeepAlivePduSerializer serializer(pduConf, progress);
|
||||
KeepAlivePduCreator serializer(pduConf, progress);
|
||||
result = serializer.serialize(&buffer, &sz, kaBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(kaBuffer[10] == cfdp::FileDirectives::KEEP_ALIVE);
|
||||
REQUIRE(kaBuffer[10] == cfdp::FileDirective::KEEP_ALIVE);
|
||||
uint32_t fsRaw = 0;
|
||||
result = SerializeAdapter::deSerialize(&fsRaw, kaBuffer.data() + 11, nullptr,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
@ -55,25 +55,27 @@ TEST_CASE("Keep Alive PDU", "[KeepAlivePdu]") {
|
||||
}
|
||||
|
||||
SECTION("Deserialize") {
|
||||
KeepAlivePduSerializer serializer(pduConf, progress);
|
||||
KeepAlivePduCreator serializer(pduConf, progress);
|
||||
result = serializer.serialize(&buffer, &sz, kaBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
// Set another file size
|
||||
progress.setFileSize(200, false);
|
||||
KeepAlivePduDeserializer deserializer(kaBuffer.data(), kaBuffer.size(), progress);
|
||||
result = deserializer.parseData();
|
||||
KeepAlivePduReader reader(kaBuffer.data(), kaBuffer.size(), progress);
|
||||
result = reader.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
auto& progRef = deserializer.getProgress();
|
||||
auto& progRef = reader.getProgress();
|
||||
// Should have been overwritten
|
||||
REQUIRE(progRef.getSize() == 0x50);
|
||||
sz = deserializer.getWholePduSize();
|
||||
sz = reader.getWholePduSize();
|
||||
|
||||
// invalid max size
|
||||
for (size_t invalidMaxSz = 0; invalidMaxSz < sz; invalidMaxSz++) {
|
||||
deserializer.setData(kaBuffer.data(), invalidMaxSz);
|
||||
result = deserializer.parseData();
|
||||
REQUIRE(result != returnvalue::OK);
|
||||
ReturnValue_t setResult = reader.setReadOnlyData(kaBuffer.data(), invalidMaxSz);
|
||||
if (setResult == returnvalue::OK) {
|
||||
result = reader.parseData();
|
||||
REQUIRE(result != returnvalue::OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
#include <fsfw/cfdp/tlv/MessageToUserTlv.h>
|
||||
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include "fsfw/cfdp/pdu/MetadataPduDeserializer.h"
|
||||
#include "fsfw/cfdp/pdu/MetadataPduSerializer.h"
|
||||
#include "fsfw/cfdp/pdu/MetadataPduCreator.h"
|
||||
#include "fsfw/cfdp/pdu/MetadataPduReader.h"
|
||||
#include "fsfw/cfdp/tlv/FilestoreResponseTlv.h"
|
||||
#include "fsfw/cfdp/tlv/MessageToUserTlv.h"
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
|
||||
TEST_CASE("Metadata PDU", "[MetadataPdu]") {
|
||||
TEST_CASE("Metadata PDU", "[cfdp][pdu]") {
|
||||
using namespace cfdp;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
std::array<uint8_t, 256> mdBuffer = {};
|
||||
@ -17,12 +17,11 @@ TEST_CASE("Metadata PDU", "[MetadataPdu]") {
|
||||
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);
|
||||
PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum);
|
||||
|
||||
std::string firstFileName = "hello.txt";
|
||||
cfdp::Lv sourceFileName(reinterpret_cast<const uint8_t*>(firstFileName.data()),
|
||||
firstFileName.size());
|
||||
cfdp::Lv destFileName(nullptr, 0);
|
||||
cfdp::StringLv sourceFileName(firstFileName);
|
||||
cfdp::StringLv destFileName;
|
||||
FileSize fileSize(35);
|
||||
MetadataInfo info(false, ChecksumType::MODULAR, fileSize, sourceFileName, destFileName);
|
||||
|
||||
@ -39,7 +38,7 @@ TEST_CASE("Metadata PDU", "[MetadataPdu]") {
|
||||
REQUIRE(options[1]->getSerializedSize() == 5);
|
||||
|
||||
SECTION("Serialize") {
|
||||
MetadataPduSerializer serializer(pduConf, info);
|
||||
MetadataPduCreator serializer(pduConf, info);
|
||||
result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(serializer.getWholePduSize() == 27);
|
||||
@ -47,7 +46,7 @@ TEST_CASE("Metadata PDU", "[MetadataPdu]") {
|
||||
REQUIRE(info.getDestFileName().getSerializedSize() == 1);
|
||||
REQUIRE(info.getSerializedSize() == 16);
|
||||
REQUIRE((mdBuffer[1] << 8 | mdBuffer[2]) == 17);
|
||||
REQUIRE(mdBuffer[10] == FileDirectives::METADATA);
|
||||
REQUIRE(mdBuffer[10] == FileDirective::METADATA);
|
||||
// no closure requested and checksum type is modular => 0x00
|
||||
REQUIRE(mdBuffer[11] == 0x00);
|
||||
uint32_t fileSizeRaw = 0;
|
||||
@ -68,11 +67,10 @@ TEST_CASE("Metadata PDU", "[MetadataPdu]") {
|
||||
REQUIRE(mdBuffer[26] == 0);
|
||||
|
||||
std::string otherFileName = "hello2.txt";
|
||||
cfdp::Lv otherFileNameLv(reinterpret_cast<const uint8_t*>(otherFileName.data()),
|
||||
otherFileName.size());
|
||||
cfdp::StringLv otherFileNameLv(otherFileName.data(), otherFileName.size());
|
||||
info.setSourceFileName(otherFileNameLv);
|
||||
size_t sizeOfOptions = options.size();
|
||||
info.setOptionsArray(options.data(), &sizeOfOptions, &sizeOfOptions);
|
||||
info.setOptionsArray(options.data(), sizeOfOptions, sizeOfOptions);
|
||||
REQUIRE(info.getMaxOptionsLen() == 2);
|
||||
info.setMaxOptionsLen(3);
|
||||
REQUIRE(info.getMaxOptionsLen() == 3);
|
||||
@ -115,22 +113,22 @@ TEST_CASE("Metadata PDU", "[MetadataPdu]") {
|
||||
}
|
||||
|
||||
SECTION("Deserialize") {
|
||||
MetadataPduSerializer serializer(pduConf, info);
|
||||
MetadataPduCreator serializer(pduConf, info);
|
||||
result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
MetadataPduDeserializer deserializer(mdBuffer.data(), mdBuffer.size(), info);
|
||||
MetadataPduReader deserializer(mdBuffer.data(), mdBuffer.size(), info);
|
||||
result = deserializer.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
size_t fullSize = deserializer.getWholePduSize();
|
||||
for (size_t maxSz = 0; maxSz < fullSize; maxSz++) {
|
||||
MetadataPduDeserializer invalidSzDeser(mdBuffer.data(), maxSz, info);
|
||||
MetadataPduReader invalidSzDeser(mdBuffer.data(), maxSz, info);
|
||||
result = invalidSzDeser.parseData();
|
||||
REQUIRE(result != returnvalue::OK);
|
||||
}
|
||||
size_t sizeOfOptions = options.size();
|
||||
size_t maxSize = 4;
|
||||
info.setOptionsArray(options.data(), &sizeOfOptions, &maxSize);
|
||||
info.setOptionsArray(options.data(), sizeOfOptions, maxSize);
|
||||
REQUIRE(info.getOptionsLen() == 2);
|
||||
info.setChecksumType(cfdp::ChecksumType::CRC_32C);
|
||||
info.setClosureRequested(true);
|
||||
@ -142,12 +140,12 @@ TEST_CASE("Metadata PDU", "[MetadataPdu]") {
|
||||
result = serializer.serialize(&buffer, &sz, mdBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
MetadataPduDeserializer deserializer2(mdBuffer.data(), mdBuffer.size(), info);
|
||||
MetadataPduReader deserializer2(mdBuffer.data(), mdBuffer.size(), info);
|
||||
result = deserializer2.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(options[0]->getType() == cfdp::TlvTypes::FILESTORE_RESPONSE);
|
||||
REQUIRE(options[0]->getType() == cfdp::TlvType::FILESTORE_RESPONSE);
|
||||
REQUIRE(options[0]->getSerializedSize() == 14);
|
||||
REQUIRE(options[1]->getType() == cfdp::TlvTypes::MSG_TO_USER);
|
||||
REQUIRE(options[1]->getType() == cfdp::TlvType::MSG_TO_USER);
|
||||
REQUIRE(options[1]->getSerializedSize() == 5);
|
||||
|
||||
for (size_t invalidFieldLen = 0; invalidFieldLen < 36; invalidFieldLen++) {
|
||||
@ -167,13 +165,15 @@ TEST_CASE("Metadata PDU", "[MetadataPdu]") {
|
||||
}
|
||||
mdBuffer[1] = (36 >> 8) & 0xff;
|
||||
mdBuffer[2] = 36 & 0xff;
|
||||
info.setOptionsArray(nullptr, nullptr, nullptr);
|
||||
info.setOptionsArray(nullptr, std::nullopt, std::nullopt);
|
||||
REQUIRE(deserializer2.parseData() == cfdp::METADATA_CANT_PARSE_OPTIONS);
|
||||
info.setOptionsArray(options.data(), &sizeOfOptions, nullptr);
|
||||
info.setOptionsArray(options.data(), sizeOfOptions, std::nullopt);
|
||||
for (size_t maxSz = 0; maxSz < 46; maxSz++) {
|
||||
MetadataPduDeserializer invalidSzDeser(mdBuffer.data(), maxSz, info);
|
||||
result = invalidSzDeser.parseData();
|
||||
REQUIRE(result == SerializeIF::STREAM_TOO_SHORT);
|
||||
MetadataPduReader invalidSzDeser(mdBuffer.data(), maxSz, info);
|
||||
if (not invalidSzDeser.isNull()) {
|
||||
result = invalidSzDeser.parseData();
|
||||
REQUIRE(result == SerializeIF::STREAM_TOO_SHORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/cfdp/pdu/NakPduDeserializer.h"
|
||||
#include "fsfw/cfdp/pdu/NakPduSerializer.h"
|
||||
#include "fsfw/cfdp/pdu/NakPduCreator.h"
|
||||
#include "fsfw/cfdp/pdu/NakPduReader.h"
|
||||
#include "fsfw/cfdp/pdu/PduConfig.h"
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
|
||||
TEST_CASE("NAK PDU", "[NakPdu]") {
|
||||
TEST_CASE("NAK PDU", "[cfdp][pdu]") {
|
||||
using namespace cfdp;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
std::array<uint8_t, 256> nakBuffer = {};
|
||||
@ -15,21 +15,21 @@ TEST_CASE("NAK PDU", "[NakPdu]") {
|
||||
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);
|
||||
PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum);
|
||||
|
||||
FileSize startOfScope(50);
|
||||
FileSize endOfScope(1050);
|
||||
NakInfo info(startOfScope, endOfScope);
|
||||
SECTION("Serializer") {
|
||||
NakPduSerializer serializer(pduConf, info);
|
||||
NakPduCreator serializer(pduConf, info);
|
||||
result = serializer.serialize(&buffer, &sz, nakBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(serializer.getSerializedSize() == 19);
|
||||
REQUIRE(serializer.FileDirectiveSerializer::getSerializedSize() == 11);
|
||||
REQUIRE(serializer.FileDirectiveCreator::getSerializedSize() == 11);
|
||||
REQUIRE(sz == 19);
|
||||
REQUIRE(serializer.getPduDataFieldLen() == 9);
|
||||
REQUIRE(((nakBuffer[1] << 8) | nakBuffer[2]) == 0x09);
|
||||
REQUIRE(nakBuffer[10] == cfdp::FileDirectives::NAK);
|
||||
REQUIRE(nakBuffer[10] == cfdp::FileDirective::NAK);
|
||||
uint32_t scope = 0;
|
||||
result = SerializeAdapter::deSerialize(&scope, nakBuffer.data() + 11, nullptr,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
@ -87,13 +87,13 @@ TEST_CASE("NAK PDU", "[NakPdu]") {
|
||||
}
|
||||
|
||||
SECTION("Deserializer") {
|
||||
NakPduSerializer serializer(pduConf, info);
|
||||
NakPduCreator serializer(pduConf, info);
|
||||
result = serializer.serialize(&buffer, &sz, nakBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
info.getStartOfScope().setFileSize(0, false);
|
||||
info.getEndOfScope().setFileSize(0, false);
|
||||
NakPduDeserializer deserializer(nakBuffer.data(), nakBuffer.size(), info);
|
||||
NakPduReader deserializer(nakBuffer.data(), nakBuffer.size(), info);
|
||||
result = deserializer.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(deserializer.getWholePduSize() == 19);
|
||||
@ -112,7 +112,7 @@ TEST_CASE("NAK PDU", "[NakPdu]") {
|
||||
result = serializer.serialize(&buffer, &sz, nakBuffer.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
NakPduDeserializer deserializeWithSegReqs(nakBuffer.data(), nakBuffer.size(), info);
|
||||
NakPduReader deserializeWithSegReqs(nakBuffer.data(), nakBuffer.size(), info);
|
||||
result = deserializeWithSegReqs.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
NakInfo::SegmentRequest* segReqsPtr = nullptr;
|
||||
@ -126,14 +126,14 @@ TEST_CASE("NAK PDU", "[NakPdu]") {
|
||||
REQUIRE(deserializeWithSegReqs.getPduDataFieldLen() == 25);
|
||||
REQUIRE(info.getSegmentRequestsLen() == 2);
|
||||
for (size_t idx = 0; idx < 34; idx++) {
|
||||
NakPduDeserializer faultyDeserializer(nakBuffer.data(), idx, info);
|
||||
NakPduReader faultyDeserializer(nakBuffer.data(), idx, info);
|
||||
result = faultyDeserializer.parseData();
|
||||
REQUIRE(result != returnvalue::OK);
|
||||
}
|
||||
for (size_t pduFieldLen = 0; pduFieldLen < 25; pduFieldLen++) {
|
||||
nakBuffer[1] = (pduFieldLen >> 8) & 0xff;
|
||||
nakBuffer[2] = pduFieldLen & 0xff;
|
||||
NakPduDeserializer faultyDeserializer(nakBuffer.data(), nakBuffer.size(), info);
|
||||
NakPduReader faultyDeserializer(nakBuffer.data(), nakBuffer.size(), info);
|
||||
result = faultyDeserializer.parseData();
|
||||
if (pduFieldLen == 9) {
|
||||
REQUIRE(info.getSegmentRequestsLen() == 0);
|
@ -1,11 +1,11 @@
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/cfdp/pdu/PromptPduDeserializer.h"
|
||||
#include "fsfw/cfdp/pdu/PromptPduSerializer.h"
|
||||
#include "fsfw/cfdp/pdu/PromptPduCreator.h"
|
||||
#include "fsfw/cfdp/pdu/PromptPduReader.h"
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
|
||||
TEST_CASE("Prompt PDU", "[PromptPdu]") {
|
||||
TEST_CASE("Prompt PDU", "[cfdp][pdu]") {
|
||||
using namespace cfdp;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
std::array<uint8_t, 256> rawBuf = {};
|
||||
@ -14,17 +14,17 @@ TEST_CASE("Prompt PDU", "[PromptPdu]") {
|
||||
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);
|
||||
PduConfig pduConf(sourceId, destId, TransmissionMode::ACKNOWLEDGED, seqNum);
|
||||
|
||||
SECTION("Serialize") {
|
||||
PromptPduSerializer serializer(pduConf, cfdp::PromptResponseRequired::PROMPT_KEEP_ALIVE);
|
||||
PromptPduCreator serializer(pduConf, cfdp::PromptResponseRequired::PROMPT_KEEP_ALIVE);
|
||||
result = serializer.serialize(&buffer, &sz, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(serializer.getWholePduSize() == 12);
|
||||
REQUIRE(sz == 12);
|
||||
REQUIRE(serializer.getPduDataFieldLen() == 2);
|
||||
REQUIRE(rawBuf[10] == FileDirectives::PROMPT);
|
||||
REQUIRE((rawBuf[sz - 1] >> 7) & 0x01 == cfdp::PromptResponseRequired::PROMPT_KEEP_ALIVE);
|
||||
REQUIRE(rawBuf[10] == FileDirective::PROMPT);
|
||||
REQUIRE(((rawBuf[sz - 1] >> 7) & 0x01) == cfdp::PromptResponseRequired::PROMPT_KEEP_ALIVE);
|
||||
|
||||
for (size_t invalidMaxSz = 0; invalidMaxSz < sz; invalidMaxSz++) {
|
||||
uint8_t* buffer = rawBuf.data();
|
||||
@ -41,25 +41,29 @@ TEST_CASE("Prompt PDU", "[PromptPdu]") {
|
||||
}
|
||||
|
||||
SECTION("Deserialize") {
|
||||
PromptPduSerializer serializer(pduConf, cfdp::PromptResponseRequired::PROMPT_KEEP_ALIVE);
|
||||
PromptPduCreator serializer(pduConf, cfdp::PromptResponseRequired::PROMPT_KEEP_ALIVE);
|
||||
result = serializer.serialize(&buffer, &sz, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
PromptPduDeserializer deserializer(rawBuf.data(), rawBuf.size());
|
||||
PromptPduReader deserializer(rawBuf.data(), rawBuf.size());
|
||||
result = deserializer.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(deserializer.getPromptResponseRequired() ==
|
||||
cfdp::PromptResponseRequired::PROMPT_KEEP_ALIVE);
|
||||
sz = deserializer.getWholePduSize();
|
||||
// Set invalid size
|
||||
rawBuf[2] = 1;
|
||||
result = deserializer.parseData();
|
||||
size_t sz2 = deserializer.getWholePduSize();
|
||||
REQUIRE(result == SerializeIF::STREAM_TOO_SHORT);
|
||||
rawBuf[2] = 2;
|
||||
|
||||
for (size_t invalidMaxSz = 0; invalidMaxSz < sz; invalidMaxSz++) {
|
||||
deserializer.setData(rawBuf.data(), invalidMaxSz);
|
||||
result = deserializer.parseData();
|
||||
REQUIRE(result != returnvalue::OK);
|
||||
ReturnValue_t setResult = deserializer.setReadOnlyData(rawBuf.data(), invalidMaxSz);
|
||||
if (setResult == returnvalue::OK) {
|
||||
result = deserializer.parseData();
|
||||
REQUIRE(result != returnvalue::OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/cfdp/pdu/AckPduDeserializer.h"
|
||||
#include "fsfw/cfdp/pdu/AckPduSerializer.h"
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
|
||||
TEST_CASE("ACK PDU", "[AckPdu]") {
|
||||
using namespace cfdp;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
std::array<uint8_t, 256> buf = {};
|
||||
uint8_t* bufptr = buf.data();
|
||||
size_t maxsz = buf.size();
|
||||
size_t sz = 0;
|
||||
auto seqNum = TransactionSeqNum(WidthInBytes::TWO_BYTES, 15);
|
||||
auto sourceId = EntityId(WidthInBytes::TWO_BYTES, 1);
|
||||
auto destId = EntityId(WidthInBytes::TWO_BYTES, 2);
|
||||
auto pduConf = PduConfig(TransmissionModes::ACKNOWLEDGED, seqNum, sourceId, destId);
|
||||
AckInfo ackInfo(FileDirectives::EOF_DIRECTIVE, ConditionCode::NO_ERROR,
|
||||
AckTransactionStatus::ACTIVE);
|
||||
auto ackSerializer = AckPduSerializer(ackInfo, pduConf);
|
||||
result = ackSerializer.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
SECTION("Serialize") {
|
||||
REQUIRE(buf.data()[sz - 3] == cfdp::FileDirectives::ACK);
|
||||
REQUIRE((buf.data()[sz - 2] >> 4) == FileDirectives::EOF_DIRECTIVE);
|
||||
REQUIRE((buf.data()[sz - 2] & 0x0f) == 0);
|
||||
REQUIRE(buf.data()[sz - 1] == AckTransactionStatus::ACTIVE);
|
||||
ackInfo.setAckedDirective(FileDirectives::FINISH);
|
||||
ackInfo.setAckedConditionCode(ConditionCode::FILESTORE_REJECTION);
|
||||
ackInfo.setTransactionStatus(AckTransactionStatus::TERMINATED);
|
||||
auto ackSerializer2 = AckPduSerializer(ackInfo, pduConf);
|
||||
bufptr = buf.data();
|
||||
sz = 0;
|
||||
result = ackSerializer2.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(buf.data()[sz - 3] == cfdp::FileDirectives::ACK);
|
||||
REQUIRE((buf.data()[sz - 2] >> 4) == FileDirectives::FINISH);
|
||||
REQUIRE((buf.data()[sz - 2] & 0x0f) == 0b0001);
|
||||
REQUIRE((buf.data()[sz - 1] >> 4) == ConditionCode::FILESTORE_REJECTION);
|
||||
REQUIRE((buf.data()[sz - 1] & 0b11) == AckTransactionStatus::TERMINATED);
|
||||
|
||||
bufptr = buf.data();
|
||||
sz = 0;
|
||||
ackInfo.setAckedDirective(FileDirectives::KEEP_ALIVE);
|
||||
auto ackSerializer3 = AckPduSerializer(ackInfo, pduConf);
|
||||
result = ackSerializer3.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK);
|
||||
// Invalid file directive
|
||||
REQUIRE(result != returnvalue::OK);
|
||||
|
||||
ackInfo.setAckedDirective(FileDirectives::FINISH);
|
||||
// buffer too small
|
||||
result = ackSerializer.serialize(&bufptr, &sz, 8, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == SerializeIF::BUFFER_TOO_SHORT);
|
||||
}
|
||||
|
||||
SECTION("Deserialize") {
|
||||
AckInfo ackInfo;
|
||||
auto reader = AckPduDeserializer(buf.data(), sz, ackInfo);
|
||||
result = reader.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(ackInfo.getAckedDirective() == FileDirectives::EOF_DIRECTIVE);
|
||||
REQUIRE(ackInfo.getAckedConditionCode() == ConditionCode::NO_ERROR);
|
||||
REQUIRE(ackInfo.getDirectiveSubtypeCode() == 0);
|
||||
REQUIRE(ackInfo.getTransactionStatus() == AckTransactionStatus::ACTIVE);
|
||||
|
||||
AckInfo newInfo = AckInfo(FileDirectives::FINISH, ConditionCode::FILESTORE_REJECTION,
|
||||
AckTransactionStatus::TERMINATED);
|
||||
auto ackSerializer2 = AckPduSerializer(newInfo, pduConf);
|
||||
bufptr = buf.data();
|
||||
sz = 0;
|
||||
result = ackSerializer2.serialize(&bufptr, &sz, maxsz, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
auto reader2 = AckPduDeserializer(buf.data(), sz, ackInfo);
|
||||
result = reader2.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(ackInfo.getAckedDirective() == FileDirectives::FINISH);
|
||||
REQUIRE(ackInfo.getAckedConditionCode() == ConditionCode::FILESTORE_REJECTION);
|
||||
REQUIRE(ackInfo.getDirectiveSubtypeCode() == 0b0001);
|
||||
REQUIRE(ackInfo.getTransactionStatus() == AckTransactionStatus::TERMINATED);
|
||||
|
||||
uint8_t prevVal = buf[sz - 2];
|
||||
buf[sz - 2] = FileDirectives::INVALID_DIRECTIVE << 4;
|
||||
result = reader2.parseData();
|
||||
REQUIRE(result == cfdp::INVALID_ACK_DIRECTIVE_FIELDS);
|
||||
buf[sz - 2] = FileDirectives::FINISH << 4 | 0b1111;
|
||||
result = reader2.parseData();
|
||||
REQUIRE(result == cfdp::INVALID_ACK_DIRECTIVE_FIELDS);
|
||||
buf[sz - 2] = prevVal;
|
||||
buf[sz - 3] = cfdp::FileDirectives::INVALID_DIRECTIVE;
|
||||
result = reader2.parseData();
|
||||
REQUIRE(result == cfdp::INVALID_DIRECTIVE_FIELDS);
|
||||
buf[sz - 3] = cfdp::FileDirectives::ACK;
|
||||
auto maxSizeTooSmall = AckPduDeserializer(buf.data(), sz - 2, ackInfo);
|
||||
result = maxSizeTooSmall.parseData();
|
||||
REQUIRE(result == SerializeIF::STREAM_TOO_SHORT);
|
||||
}
|
||||
}
|
@ -2,301 +2,27 @@
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <cstring>
|
||||
|
||||
#include "CatchDefinitions.h"
|
||||
#include "fsfw/cfdp/FileSize.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveDeserializer.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveSerializer.h"
|
||||
#include "fsfw/cfdp/pdu/HeaderDeserializer.h"
|
||||
#include "fsfw/cfdp/pdu/HeaderSerializer.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveCreator.h"
|
||||
#include "fsfw/cfdp/pdu/FileDirectiveReader.h"
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
#include "fsfw/serialize/SerializeAdapter.h"
|
||||
|
||||
TEST_CASE("CFDP Base", "[CfdpBase]") {
|
||||
TEST_CASE("CFDP Base", "[cfdp]") {
|
||||
using namespace cfdp;
|
||||
std::array<uint8_t, 32> serBuf;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
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 =
|
||||
PduConfig(cfdp::TransmissionModes::ACKNOWLEDGED, seqNum, sourceId, destId, false);
|
||||
PduConfig(sourceId, destId, cfdp::TransmissionMode::ACKNOWLEDGED, seqNum, false);
|
||||
uint8_t* serTarget = serBuf.data();
|
||||
const uint8_t* deserTarget = serTarget;
|
||||
size_t serSize = 0;
|
||||
|
||||
SECTION("Header Serialization") {
|
||||
auto headerSerializer = HeaderSerializer(pduConf, cfdp::PduType::FILE_DIRECTIVE, 0);
|
||||
const uint8_t** dummyPtr = nullptr;
|
||||
ReturnValue_t deserResult =
|
||||
headerSerializer.deSerialize(dummyPtr, &serSize, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(deserResult == returnvalue::FAILED);
|
||||
deserResult = headerSerializer.serialize(nullptr, &serSize, serBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(deserResult == returnvalue::FAILED);
|
||||
REQUIRE(seqNum.getSerializedSize() == 1);
|
||||
|
||||
REQUIRE(headerSerializer.getPduDataFieldLen() == 0);
|
||||
REQUIRE(headerSerializer.getSerializedSize() == 7);
|
||||
REQUIRE(headerSerializer.getWholePduSize() == 7);
|
||||
REQUIRE(headerSerializer.getCrcFlag() == false);
|
||||
REQUIRE(headerSerializer.getDirection() == cfdp::Direction::TOWARDS_RECEIVER);
|
||||
REQUIRE(headerSerializer.getLargeFileFlag() == false);
|
||||
REQUIRE(headerSerializer.getLenEntityIds() == 1);
|
||||
REQUIRE(headerSerializer.getLenSeqNum() == 1);
|
||||
REQUIRE(headerSerializer.getPduType() == cfdp::PduType::FILE_DIRECTIVE);
|
||||
REQUIRE(headerSerializer.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::NOT_PRESENT);
|
||||
REQUIRE(headerSerializer.getSegmentationControl() == false);
|
||||
REQUIRE(headerSerializer.getTransmissionMode() == cfdp::TransmissionModes::ACKNOWLEDGED);
|
||||
|
||||
cfdp::TransactionSeqNum seqNumLocal;
|
||||
headerSerializer.getTransactionSeqNum(seqNumLocal);
|
||||
REQUIRE(seqNumLocal.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
|
||||
REQUIRE(seqNumLocal.getValue() == 2);
|
||||
cfdp::EntityId sourceDestId;
|
||||
headerSerializer.getSourceId(sourceDestId);
|
||||
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
|
||||
REQUIRE(sourceDestId.getValue() == 0);
|
||||
headerSerializer.getDestId(sourceDestId);
|
||||
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
|
||||
REQUIRE(sourceDestId.getValue() == 1);
|
||||
|
||||
result = headerSerializer.serialize(&serTarget, &serSize, serBuf.size(),
|
||||
SerializeIF::Endianness::BIG);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
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
|
||||
REQUIRE(serBuf[3] == 0b00010001);
|
||||
// Source ID
|
||||
REQUIRE(serBuf[4] == 0);
|
||||
// Transaction Seq Number
|
||||
REQUIRE(serBuf[5] == 2);
|
||||
// Dest ID
|
||||
REQUIRE(serBuf[6] == 1);
|
||||
|
||||
for (uint8_t idx = 0; idx < 7; idx++) {
|
||||
ReturnValue_t result =
|
||||
headerSerializer.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::BIG);
|
||||
REQUIRE(result == static_cast<int>(SerializeIF::BUFFER_TOO_SHORT));
|
||||
}
|
||||
|
||||
// Set PDU data field len
|
||||
headerSerializer.setPduDataFieldLen(0x0ff0);
|
||||
REQUIRE(headerSerializer.getPduDataFieldLen() == 0x0ff0);
|
||||
REQUIRE(headerSerializer.getSerializedSize() == 7);
|
||||
REQUIRE(headerSerializer.getWholePduSize() == 7 + 0x0ff0);
|
||||
serTarget = serBuf.data();
|
||||
serSize = 0;
|
||||
result = headerSerializer.serialize(&serTarget, &serSize, serBuf.size(),
|
||||
SerializeIF::Endianness::BIG);
|
||||
REQUIRE(serBuf[1] == 0x0f);
|
||||
REQUIRE(serBuf[2] == 0xf0);
|
||||
|
||||
pduConf.crcFlag = true;
|
||||
pduConf.largeFile = true;
|
||||
pduConf.direction = cfdp::Direction::TOWARDS_SENDER;
|
||||
pduConf.mode = cfdp::TransmissionModes::UNACKNOWLEDGED;
|
||||
headerSerializer.setSegmentationControl(
|
||||
cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION);
|
||||
headerSerializer.setPduType(cfdp::PduType::FILE_DATA);
|
||||
headerSerializer.setSegmentMetadataFlag(cfdp::SegmentMetadataFlag::PRESENT);
|
||||
serTarget = serBuf.data();
|
||||
serSize = 0;
|
||||
result = headerSerializer.serialize(&serTarget, &serSize, serBuf.size(),
|
||||
SerializeIF::Endianness::BIG);
|
||||
|
||||
// Everything except version bit flipped to one now
|
||||
REQUIRE(serBuf[0] == 0x3f);
|
||||
REQUIRE(serBuf[3] == 0x99);
|
||||
pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
|
||||
pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
|
||||
pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
|
||||
REQUIRE(pduConf.sourceId.getSerializedSize() == 4);
|
||||
REQUIRE(headerSerializer.getSerializedSize() == 14);
|
||||
serTarget = serBuf.data();
|
||||
serSize = 0;
|
||||
result = headerSerializer.serialize(&serTarget, &serSize, serBuf.size(),
|
||||
SerializeIF::Endianness::BIG);
|
||||
|
||||
for (uint8_t idx = 0; idx < 14; idx++) {
|
||||
ReturnValue_t result =
|
||||
headerSerializer.serialize(&serTarget, &serSize, idx, SerializeIF::Endianness::BIG);
|
||||
REQUIRE(result == static_cast<int>(SerializeIF::BUFFER_TOO_SHORT));
|
||||
}
|
||||
REQUIRE(headerSerializer.getCrcFlag() == true);
|
||||
REQUIRE(headerSerializer.getDirection() == cfdp::Direction::TOWARDS_SENDER);
|
||||
REQUIRE(headerSerializer.getLargeFileFlag() == true);
|
||||
REQUIRE(headerSerializer.getLenEntityIds() == 4);
|
||||
REQUIRE(headerSerializer.getLenSeqNum() == 2);
|
||||
REQUIRE(headerSerializer.getPduType() == cfdp::PduType::FILE_DATA);
|
||||
REQUIRE(headerSerializer.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT);
|
||||
REQUIRE(headerSerializer.getTransmissionMode() == cfdp::TransmissionModes::UNACKNOWLEDGED);
|
||||
REQUIRE(headerSerializer.getSegmentationControl() == true);
|
||||
// Last three bits are 2 now (length of seq number) and bit 1 to bit 3 is 4 (len entity IDs)
|
||||
REQUIRE(serBuf[3] == 0b11001010);
|
||||
uint32_t entityId = 0;
|
||||
size_t deSerSize = 0;
|
||||
SerializeAdapter::deSerialize(&entityId, serBuf.data() + 4, &deSerSize,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(deSerSize == 4);
|
||||
REQUIRE(entityId == 0xff00ff00);
|
||||
uint16_t seqNum = 0;
|
||||
SerializeAdapter::deSerialize(&seqNum, serBuf.data() + 8, &deSerSize,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(deSerSize == 2);
|
||||
REQUIRE(seqNum == 0x0fff);
|
||||
SerializeAdapter::deSerialize(&entityId, serBuf.data() + 10, &deSerSize,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(deSerSize == 4);
|
||||
REQUIRE(entityId == 0x00ff00ff);
|
||||
|
||||
result = pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 0xfff);
|
||||
REQUIRE(result == returnvalue::FAILED);
|
||||
result = pduConf.sourceId.setValue(cfdp::WidthInBytes::TWO_BYTES, 0xfffff);
|
||||
REQUIRE(result == returnvalue::FAILED);
|
||||
result = pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xfffffffff);
|
||||
REQUIRE(result == returnvalue::FAILED);
|
||||
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.setValue(cfdp::WidthInBytes::ONE_BYTE, 1);
|
||||
serTarget = serBuf.data();
|
||||
serSize = 1;
|
||||
result = pduConf.sourceId.serialize(&serTarget, &serSize, 1, SerializeIF::Endianness::MACHINE);
|
||||
REQUIRE(result == static_cast<int>(SerializeIF::BUFFER_TOO_SHORT));
|
||||
}
|
||||
|
||||
SECTION("Header Deserialization") {
|
||||
// We unittested the serializer before, so we can use it now to generate valid raw CFDP
|
||||
// data
|
||||
auto headerSerializer = HeaderSerializer(pduConf, cfdp::PduType::FILE_DIRECTIVE, 0);
|
||||
ReturnValue_t result = headerSerializer.serialize(&serTarget, &serSize, serBuf.size(),
|
||||
SerializeIF::Endianness::BIG);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(serBuf[1] == 0);
|
||||
REQUIRE(serBuf[2] == 0);
|
||||
// Entity and Transaction Sequence number are 1 byte large
|
||||
REQUIRE(serBuf[3] == 0b00010001);
|
||||
REQUIRE(serSize == 7);
|
||||
// Deser call not strictly necessary
|
||||
auto headerDeser = HeaderDeserializer(serBuf.data(), serBuf.size());
|
||||
|
||||
ReturnValue_t serResult = headerDeser.parseData();
|
||||
REQUIRE(serResult == returnvalue::OK);
|
||||
REQUIRE(headerDeser.getPduDataFieldLen() == 0);
|
||||
REQUIRE(headerDeser.getHeaderSize() == 7);
|
||||
REQUIRE(headerDeser.getWholePduSize() == 7);
|
||||
REQUIRE(headerDeser.getCrcFlag() == false);
|
||||
REQUIRE(headerDeser.getDirection() == cfdp::Direction::TOWARDS_RECEIVER);
|
||||
REQUIRE(headerDeser.getLargeFileFlag() == false);
|
||||
REQUIRE(headerDeser.getLenEntityIds() == 1);
|
||||
REQUIRE(headerDeser.getLenSeqNum() == 1);
|
||||
REQUIRE(headerDeser.getPduType() == cfdp::PduType::FILE_DIRECTIVE);
|
||||
REQUIRE(headerDeser.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::NOT_PRESENT);
|
||||
REQUIRE(headerDeser.getSegmentationControl() == false);
|
||||
REQUIRE(headerDeser.getTransmissionMode() == cfdp::TransmissionModes::ACKNOWLEDGED);
|
||||
|
||||
pduConf.crcFlag = true;
|
||||
pduConf.largeFile = true;
|
||||
pduConf.direction = cfdp::Direction::TOWARDS_SENDER;
|
||||
pduConf.mode = cfdp::TransmissionModes::UNACKNOWLEDGED;
|
||||
headerSerializer.setSegmentationControl(
|
||||
cfdp::SegmentationControl::RECORD_BOUNDARIES_PRESERVATION);
|
||||
headerSerializer.setPduType(cfdp::PduType::FILE_DATA);
|
||||
headerSerializer.setSegmentMetadataFlag(cfdp::SegmentMetadataFlag::PRESENT);
|
||||
result = pduConf.seqNum.setValue(cfdp::WidthInBytes::TWO_BYTES, 0x0fff);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
result = pduConf.sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0xff00ff00);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
result = pduConf.destId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 0x00ff00ff);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
serTarget = serBuf.data();
|
||||
serSize = 0;
|
||||
result = headerSerializer.serialize(&serTarget, &serSize, serBuf.size(),
|
||||
SerializeIF::Endianness::BIG);
|
||||
headerDeser = HeaderDeserializer(serBuf.data(), serBuf.size());
|
||||
|
||||
result = headerDeser.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
// Everything except version bit flipped to one now
|
||||
REQUIRE(serBuf[0] == 0x3f);
|
||||
REQUIRE(serBuf[3] == 0b11001010);
|
||||
REQUIRE(headerDeser.getWholePduSize() == 14);
|
||||
|
||||
REQUIRE(headerDeser.getCrcFlag() == true);
|
||||
REQUIRE(headerDeser.getDirection() == cfdp::Direction::TOWARDS_SENDER);
|
||||
REQUIRE(headerDeser.getLargeFileFlag() == true);
|
||||
REQUIRE(headerDeser.getLenEntityIds() == 4);
|
||||
REQUIRE(headerDeser.getLenSeqNum() == 2);
|
||||
REQUIRE(headerDeser.getPduType() == cfdp::PduType::FILE_DATA);
|
||||
REQUIRE(headerDeser.getSegmentMetadataFlag() == cfdp::SegmentMetadataFlag::PRESENT);
|
||||
REQUIRE(headerDeser.getSegmentationControl() == true);
|
||||
REQUIRE(headerDeser.getTransmissionMode() == cfdp::TransmissionModes::UNACKNOWLEDGED);
|
||||
|
||||
cfdp::TransactionSeqNum seqNumLocal;
|
||||
headerDeser.getTransactionSeqNum(seqNumLocal);
|
||||
REQUIRE(seqNumLocal.getWidth() == cfdp::WidthInBytes::TWO_BYTES);
|
||||
REQUIRE(seqNumLocal.getValue() == 0x0fff);
|
||||
cfdp::EntityId sourceDestId;
|
||||
headerDeser.getSourceId(sourceDestId);
|
||||
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::FOUR_BYTES);
|
||||
REQUIRE(sourceDestId.getValue() == 0xff00ff00);
|
||||
headerDeser.getDestId(sourceDestId);
|
||||
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::FOUR_BYTES);
|
||||
REQUIRE(sourceDestId.getValue() == 0x00ff00ff);
|
||||
|
||||
size_t deSerSize = headerDeser.getWholePduSize();
|
||||
serTarget = serBuf.data();
|
||||
const uint8_t** serTargetConst = const_cast<const uint8_t**>(&serTarget);
|
||||
result = headerDeser.parseData();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
headerDeser.setData(nullptr, -1);
|
||||
REQUIRE(headerDeser.getHeaderSize() == 0);
|
||||
headerDeser.setData(serBuf.data(), serBuf.size());
|
||||
|
||||
serTarget = serBuf.data();
|
||||
serSize = 0;
|
||||
pduConf.sourceId.setValue(cfdp::WidthInBytes::ONE_BYTE, 22);
|
||||
pduConf.destId.setValue(cfdp::WidthInBytes::ONE_BYTE, 48);
|
||||
result = headerSerializer.serialize(&serTarget, &serSize, serBuf.size(),
|
||||
SerializeIF::Endianness::BIG);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(headerDeser.getWholePduSize() == 8);
|
||||
headerDeser.setData(serBuf.data(), serBuf.size());
|
||||
|
||||
headerDeser.getSourceId(sourceDestId);
|
||||
REQUIRE(sourceDestId.getWidth() == cfdp::WidthInBytes::ONE_BYTE);
|
||||
REQUIRE(sourceDestId.getValue() == 22);
|
||||
}
|
||||
|
||||
SECTION("File Directive") {
|
||||
auto fdSer = FileDirectiveSerializer(pduConf, FileDirectives::ACK, 4);
|
||||
auto fdSer = FileDirectiveCreator(pduConf, FileDirective::ACK, 4);
|
||||
REQUIRE(fdSer.getSerializedSize() == 8);
|
||||
serTarget = serBuf.data();
|
||||
serSize = 0;
|
||||
@ -315,7 +41,7 @@ TEST_CASE("CFDP Base", "[CfdpBase]") {
|
||||
REQUIRE(serBuf[5] == 2);
|
||||
// Dest ID
|
||||
REQUIRE(serBuf[6] == 1);
|
||||
REQUIRE(serBuf[7] == FileDirectives::ACK);
|
||||
REQUIRE(serBuf[7] == FileDirective::ACK);
|
||||
|
||||
serTarget = serBuf.data();
|
||||
size_t deserSize = 20;
|
||||
@ -333,31 +59,30 @@ TEST_CASE("CFDP Base", "[CfdpBase]") {
|
||||
|
||||
deserTarget = serBuf.data();
|
||||
deserSize = 0;
|
||||
auto fdDeser = FileDirectiveDeserializer(deserTarget, serBuf.size());
|
||||
auto fdDeser = FileDirectiveReader(deserTarget, serBuf.size());
|
||||
REQUIRE(fdDeser.getEndianness() == SerializeIF::Endianness::NETWORK);
|
||||
fdDeser.setEndianness(SerializeIF::Endianness::MACHINE);
|
||||
REQUIRE(fdDeser.getEndianness() == SerializeIF::Endianness::MACHINE);
|
||||
fdDeser.setEndianness(SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(fdDeser.parseData() == returnvalue::OK);
|
||||
REQUIRE(fdDeser.getFileDirective() == FileDirectives::ACK);
|
||||
REQUIRE(fdDeser.getFileDirective() == FileDirective::ACK);
|
||||
REQUIRE(fdDeser.getPduDataFieldLen() == 5);
|
||||
REQUIRE(fdDeser.getHeaderSize() == 8);
|
||||
REQUIRE(fdDeser.getPduType() == cfdp::PduType::FILE_DIRECTIVE);
|
||||
|
||||
serBuf[7] = 0xff;
|
||||
// Invalid file directive
|
||||
REQUIRE(fdDeser.parseData() == cfdp::INVALID_DIRECTIVE_FIELDS);
|
||||
REQUIRE(fdDeser.parseData() == cfdp::INVALID_DIRECTIVE_FIELD);
|
||||
}
|
||||
|
||||
SECTION("FileSize") {
|
||||
SECTION("File Size") {
|
||||
std::array<uint8_t, 8> fssBuf = {};
|
||||
uint8_t* buffer = fssBuf.data();
|
||||
size_t size = 0;
|
||||
cfdp::FileSize fss;
|
||||
REQUIRE(fss.getSize() == 0);
|
||||
fss.setFileSize(0x20, false);
|
||||
ReturnValue_t result =
|
||||
fss.serialize(&buffer, &size, fssBuf.size(), SerializeIF::Endianness::MACHINE);
|
||||
result = fss.serialize(&buffer, &size, fssBuf.size(), SerializeIF::Endianness::MACHINE);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
uint32_t fileSize = 0;
|
||||
result = SerializeAdapter::deSerialize(&fileSize, fssBuf.data(), nullptr,
|
||||
@ -365,4 +90,16 @@ TEST_CASE("CFDP Base", "[CfdpBase]") {
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(fileSize == 0x20);
|
||||
}
|
||||
|
||||
SECTION("Var Length Field") {
|
||||
VarLenField defaultField;
|
||||
CHECK(defaultField.getValue() == 0);
|
||||
CHECK(defaultField.getWidth() == WidthInBytes::ONE_BYTE);
|
||||
VarLenField explicitField(WidthInBytes::FOUR_BYTES, 12);
|
||||
CHECK(explicitField.getWidth() == WidthInBytes::FOUR_BYTES);
|
||||
CHECK(explicitField.getValue() == 12);
|
||||
VarLenField fromUnsignedByteField(UnsignedByteField<uint16_t>(12));
|
||||
CHECK(fromUnsignedByteField.getWidth() == WidthInBytes::TWO_BYTES);
|
||||
CHECK(fromUnsignedByteField.getValue() == 12);
|
||||
}
|
||||
}
|
||||
|
116
unittests/cfdp/testLvs.cpp
Normal file
116
unittests/cfdp/testLvs.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/cfdp.h"
|
||||
#include "fsfw/cfdp/VarLenFields.h"
|
||||
|
||||
TEST_CASE("CFDP LV", "[cfdp][lv]") {
|
||||
using namespace cfdp;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
std::array<uint8_t, 255> rawBuf{};
|
||||
uint8_t* serPtr = rawBuf.data();
|
||||
const uint8_t* deserPtr = rawBuf.data();
|
||||
size_t deserSize = 0;
|
||||
cfdp::EntityId sourceId = EntityId(cfdp::WidthInBytes::TWO_BYTES, 0x0ff0);
|
||||
|
||||
SECTION("LV Serialization") {
|
||||
std::array<uint8_t, 8> lvRawBuf{};
|
||||
serPtr = lvRawBuf.data();
|
||||
REQUIRE(sourceId.serialize(&serPtr, &deserSize, lvRawBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK) == returnvalue::OK);
|
||||
REQUIRE(deserSize == 2);
|
||||
|
||||
auto lv = cfdp::Lv(lvRawBuf.data(), 2);
|
||||
REQUIRE(lv.getSerializedSize() == 3);
|
||||
|
||||
SECTION("Copy") {
|
||||
auto lvCopy = cfdp::Lv(lv);
|
||||
REQUIRE(lvCopy.getSerializedSize() == 3);
|
||||
REQUIRE(lv.getValue(nullptr) == lvCopy.getValue(nullptr));
|
||||
}
|
||||
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
REQUIRE(lv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK) ==
|
||||
returnvalue::OK);
|
||||
REQUIRE(deserSize == 3);
|
||||
REQUIRE(rawBuf[0] == 2);
|
||||
uint16_t sourceIdRaw = 0;
|
||||
REQUIRE(SerializeAdapter::deSerialize(&sourceIdRaw, rawBuf.data() + 1, &deserSize,
|
||||
SerializeIF::Endianness::BIG) == returnvalue::OK);
|
||||
REQUIRE(sourceIdRaw == 0x0ff0);
|
||||
}
|
||||
|
||||
SECTION("Empty Serialization") {
|
||||
auto lvEmpty = Lv();
|
||||
REQUIRE(lvEmpty.getSerializedSize() == 1);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
result =
|
||||
lvEmpty.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(deserSize == 1);
|
||||
deserPtr = rawBuf.data();
|
||||
result = lvEmpty.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::BIG);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(lvEmpty.getSerializedSize() == 1);
|
||||
}
|
||||
|
||||
SECTION("Uninit LV") {
|
||||
std::array<uint8_t, 8> lvRawBuf{};
|
||||
serPtr = lvRawBuf.data();
|
||||
REQUIRE(sourceId.serialize(&serPtr, &deserSize, lvRawBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK) == returnvalue::OK);
|
||||
auto lv = cfdp::Lv(lvRawBuf.data(), 2);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
result = lv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
Lv uninitLv;
|
||||
deserPtr = rawBuf.data();
|
||||
deserSize = 3;
|
||||
result = uninitLv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::BIG);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(uninitLv.getSerializedSize() == 3);
|
||||
const uint8_t* storedValue = uninitLv.getValue(nullptr);
|
||||
uint16_t sourceIdRaw = 0;
|
||||
REQUIRE(SerializeAdapter::deSerialize(&sourceIdRaw, storedValue, &deserSize,
|
||||
SerializeIF::Endianness::BIG) == returnvalue::OK);
|
||||
REQUIRE(sourceIdRaw == 0x0ff0);
|
||||
}
|
||||
|
||||
SECTION("Invalid Input") {
|
||||
Lv uninitLv;
|
||||
REQUIRE(uninitLv.deSerialize(nullptr, nullptr, SerializeIF::Endianness::BIG) ==
|
||||
returnvalue::FAILED);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
REQUIRE(uninitLv.serialize(&serPtr, &deserSize, 0, SerializeIF::Endianness::BIG) ==
|
||||
SerializeIF::BUFFER_TOO_SHORT);
|
||||
REQUIRE(uninitLv.serialize(nullptr, nullptr, 12, SerializeIF::Endianness::BIG));
|
||||
deserSize = 0;
|
||||
REQUIRE(uninitLv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::BIG) ==
|
||||
SerializeIF::STREAM_TOO_SHORT);
|
||||
}
|
||||
|
||||
SECTION("String LV String") {
|
||||
std::string filename = "hello.txt";
|
||||
StringLv sourceFileName(filename);
|
||||
REQUIRE(sourceFileName.getSerializedSize() == 1 + filename.size());
|
||||
REQUIRE(sourceFileName.serializeBe(rawBuf.data(), deserSize, rawBuf.size()) == returnvalue::OK);
|
||||
REQUIRE(rawBuf[0] == filename.size());
|
||||
std::string filenameFromRaw(reinterpret_cast<const char*>(rawBuf.data() + 1), filename.size());
|
||||
REQUIRE(filenameFromRaw == filename);
|
||||
}
|
||||
|
||||
SECTION("String LV Const Char") {
|
||||
const char filename[] = "hello.txt";
|
||||
StringLv sourceFileName(filename, sizeof(filename) - 1);
|
||||
REQUIRE(sourceFileName.getSerializedSize() == 1 + sizeof(filename) - 1);
|
||||
REQUIRE(sourceFileName.serializeBe(rawBuf.data(), deserSize, rawBuf.size()) == returnvalue::OK);
|
||||
REQUIRE(rawBuf[0] == sizeof(filename) - 1);
|
||||
rawBuf[deserSize] = '\0';
|
||||
const char* filenameFromRaw = reinterpret_cast<const char*>(rawBuf.data() + 1);
|
||||
REQUIRE(std::strcmp(filename, filenameFromRaw) == 0);
|
||||
}
|
||||
}
|
137
unittests/cfdp/testOtherTlvs.cpp
Normal file
137
unittests/cfdp/testOtherTlvs.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
#include <fsfw/cfdp/tlv/EntityIdTlv.h>
|
||||
#include <fsfw/cfdp/tlv/FaultHandlerOverrideTlv.h>
|
||||
#include <fsfw/cfdp/tlv/FilestoreRequestTlv.h>
|
||||
#include <fsfw/cfdp/tlv/FilestoreResponseTlv.h>
|
||||
#include <fsfw/cfdp/tlv/FlowLabelTlv.h>
|
||||
#include <fsfw/cfdp/tlv/MessageToUserTlv.h>
|
||||
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <string>
|
||||
|
||||
#include "fsfw/cfdp/pdu/PduConfig.h"
|
||||
#include "fsfw/cfdp/tlv/Lv.h"
|
||||
#include "fsfw/cfdp/tlv/Tlv.h"
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
|
||||
TEST_CASE("CFDP Other TLVs", "[cfdp][tlv]") {
|
||||
using namespace cfdp;
|
||||
ReturnValue_t result;
|
||||
std::array<uint8_t, 255> rawBuf{};
|
||||
uint8_t* serPtr = rawBuf.data();
|
||||
const uint8_t* deserPtr = rawBuf.data();
|
||||
size_t deserSize = 0;
|
||||
cfdp::EntityId sourceId = EntityId(cfdp::WidthInBytes::TWO_BYTES, 0x0ff0);
|
||||
|
||||
SECTION("Filestore Response TLV") {
|
||||
std::string name = "hello.txt";
|
||||
cfdp::StringLv firstName(name);
|
||||
std::string name2 = "hello2.txt";
|
||||
cfdp::StringLv secondName(name2);
|
||||
std::string msg = "12345";
|
||||
cfdp::Lv fsMsg(reinterpret_cast<const uint8_t*>(msg.data()), msg.size());
|
||||
FilestoreResponseTlv response(cfdp::FilestoreActionCode::APPEND_FILE, cfdp::FSR_SUCCESS,
|
||||
firstName, &fsMsg);
|
||||
response.setSecondFileName(&secondName);
|
||||
REQUIRE(response.getLengthField() == 10 + 11 + 6 + 1);
|
||||
REQUIRE(response.getSerializedSize() == response.getLengthField() + 2);
|
||||
|
||||
cfdp::Tlv rawResponse;
|
||||
std::array<uint8_t, 128> serBuf = {};
|
||||
result = response.convertToTlv(rawResponse, serBuf.data(), serBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(rawResponse.getType() == cfdp::TlvType::FILESTORE_RESPONSE);
|
||||
cfdp::StringLv emptyMsg;
|
||||
cfdp::StringLv emptySecondName;
|
||||
FilestoreResponseTlv emptyTlv(firstName, &emptyMsg);
|
||||
emptyTlv.setSecondFileName(&emptySecondName);
|
||||
result = emptyTlv.deSerialize(rawResponse, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(emptyTlv.getActionCode() == cfdp::FilestoreActionCode::APPEND_FILE);
|
||||
REQUIRE(emptyTlv.getStatusCode() == cfdp::FSR_SUCCESS);
|
||||
size_t firstNameLen = 0;
|
||||
const char* firstNamePtr =
|
||||
reinterpret_cast<const char*>(emptyTlv.getFirstFileName().getValue(&firstNameLen));
|
||||
auto helloString = std::string(firstNamePtr, firstNameLen);
|
||||
REQUIRE(helloString == "hello.txt");
|
||||
}
|
||||
|
||||
SECTION("Filestore Request TLV") {
|
||||
std::string name = "hello.txt";
|
||||
cfdp::StringLv firstName(name);
|
||||
std::string name2 = "hello2.txt";
|
||||
cfdp::StringLv secondName(name2);
|
||||
FilestoreRequestTlv request(cfdp::FilestoreActionCode::APPEND_FILE, firstName);
|
||||
|
||||
// second name not set yet
|
||||
REQUIRE(request.getLengthField() == 10 + 1);
|
||||
REQUIRE(request.getSerializedSize() == request.getLengthField() + 2);
|
||||
|
||||
std::array<uint8_t, 128> serBuf = {};
|
||||
uint8_t* ptr = serBuf.data();
|
||||
size_t sz = 0;
|
||||
result = request.serialize(&ptr, &sz, serBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == cfdp::FILESTORE_REQUIRES_SECOND_FILE);
|
||||
|
||||
ptr = serBuf.data();
|
||||
sz = 0;
|
||||
request.setSecondFileName(&secondName);
|
||||
size_t expectedSz = request.getLengthField();
|
||||
REQUIRE(expectedSz == 10 + 11 + 1);
|
||||
REQUIRE(request.getSerializedSize() == expectedSz + 2);
|
||||
result = request.serialize(&ptr, &sz, serBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(sz == expectedSz + 2);
|
||||
|
||||
FilestoreRequestTlv emptyRequest(firstName);
|
||||
emptyRequest.setSecondFileName(&secondName);
|
||||
const uint8_t* constptr = serBuf.data();
|
||||
result = emptyRequest.deSerialize(&constptr, &sz, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
cfdp::Tlv rawRequest;
|
||||
ptr = serBuf.data();
|
||||
sz = 0;
|
||||
result = request.convertToTlv(rawRequest, serBuf.data(), serBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(rawRequest.getType() == cfdp::TlvType::FILESTORE_REQUEST);
|
||||
|
||||
emptyRequest.setActionCode(cfdp::FilestoreActionCode::DELETE_FILE);
|
||||
result = emptyRequest.deSerialize(rawRequest, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(emptyRequest.getType() == cfdp::TlvType::FILESTORE_REQUEST);
|
||||
REQUIRE(emptyRequest.getActionCode() == cfdp::FilestoreActionCode::APPEND_FILE);
|
||||
}
|
||||
|
||||
SECTION("Other") {
|
||||
MessageToUserTlv emptyTlv;
|
||||
uint8_t flowLabel = 1;
|
||||
FlowLabelTlv flowLabelTlv(&flowLabel, 1);
|
||||
|
||||
FaultHandlerOverrideTlv faultOverrideTlv(cfdp::ConditionCode::FILESTORE_REJECTION,
|
||||
cfdp::FaultHandlerCode::NOTICE_OF_CANCELLATION);
|
||||
size_t sz = 0;
|
||||
result =
|
||||
faultOverrideTlv.serialize(&serPtr, &sz, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(faultOverrideTlv.getSerializedSize() == 3);
|
||||
REQUIRE(sz == 3);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
FaultHandlerOverrideTlv emptyOverrideTlv;
|
||||
result = emptyOverrideTlv.deSerialize(&deserPtr, &sz, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
EntityId entId(cfdp::WidthInBytes::TWO_BYTES, 0x42);
|
||||
EntityId emptyId;
|
||||
EntityIdTlv idTlv(emptyId);
|
||||
serPtr = rawBuf.data();
|
||||
result = idTlv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
cfdp::Tlv rawTlv(cfdp::TlvType::ENTITY_ID, rawBuf.data() + 2, 2);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
deserPtr = rawBuf.data();
|
||||
result = idTlv.deSerialize(rawTlv, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
}
|
||||
}
|
128
unittests/cfdp/testTlv.cpp
Normal file
128
unittests/cfdp/testTlv.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/cfdp.h"
|
||||
#include "fsfw/cfdp/VarLenFields.h"
|
||||
|
||||
TEST_CASE("CFDP TLV", "[cfdp][tlv]") {
|
||||
using namespace cfdp;
|
||||
ReturnValue_t result;
|
||||
std::array<uint8_t, 255> rawBuf{};
|
||||
uint8_t* serPtr = rawBuf.data();
|
||||
const uint8_t* deserPtr = rawBuf.data();
|
||||
size_t deserSize = 0;
|
||||
cfdp::EntityId sourceId = EntityId(cfdp::WidthInBytes::TWO_BYTES, 0x0ff0);
|
||||
|
||||
SECTION("Entity ID Serialization") {
|
||||
REQUIRE(sourceId.serialize(&serPtr, &deserSize, rawBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK) == returnvalue::OK);
|
||||
REQUIRE(deserSize == 2);
|
||||
}
|
||||
|
||||
SECTION("TLV Serialization") {
|
||||
std::array<uint8_t, 8> tlvBuf{};
|
||||
REQUIRE(sourceId.serializeBe(tlvBuf.data(), deserSize, tlvBuf.size()) == returnvalue::OK);
|
||||
auto tlv = Tlv(TlvType::ENTITY_ID, tlvBuf.data(), deserSize);
|
||||
REQUIRE(tlv.getSerializedSize() == 4);
|
||||
REQUIRE(tlv.getLengthField() == 2);
|
||||
deserSize = 0;
|
||||
REQUIRE(tlv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK) ==
|
||||
returnvalue::OK);
|
||||
REQUIRE(deserSize == 4);
|
||||
REQUIRE(rawBuf[0] == TlvType::ENTITY_ID);
|
||||
REQUIRE(rawBuf[1] == 2);
|
||||
uint16_t entityId = 0;
|
||||
REQUIRE(SerializeAdapter::deSerialize(&entityId, rawBuf.data() + 2, &deserSize,
|
||||
SerializeIF::Endianness::NETWORK) == returnvalue::OK);
|
||||
REQUIRE(entityId == 0x0ff0);
|
||||
}
|
||||
|
||||
SECTION("TLV Other Value") {
|
||||
auto tlv = Tlv(TlvType::ENTITY_ID, rawBuf.data(), deserSize);
|
||||
// Set new value
|
||||
sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 12);
|
||||
REQUIRE(sourceId.serialize(&serPtr, &deserSize, rawBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK) == returnvalue::OK);
|
||||
tlv.setValue(rawBuf.data(), cfdp::WidthInBytes::FOUR_BYTES);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
result = tlv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(rawBuf[0] == TlvType::ENTITY_ID);
|
||||
REQUIRE(rawBuf[1] == 4);
|
||||
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
}
|
||||
|
||||
SECTION("TLV Invalid") {
|
||||
auto tlvInvalid = Tlv(cfdp::TlvType::INVALID_TLV, rawBuf.data(), 0);
|
||||
REQUIRE(tlvInvalid.serialize(&serPtr, &deserSize, rawBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK) != returnvalue::OK);
|
||||
tlvInvalid = Tlv(cfdp::TlvType::ENTITY_ID, nullptr, 3);
|
||||
REQUIRE(tlvInvalid.serialize(&serPtr, &deserSize, rawBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK) != returnvalue::OK);
|
||||
REQUIRE(tlvInvalid.serialize(&serPtr, &deserSize, 0, SerializeIF::Endianness::NETWORK) !=
|
||||
returnvalue::OK);
|
||||
REQUIRE(tlvInvalid.getSerializedSize() == 0);
|
||||
REQUIRE(tlvInvalid.serialize(nullptr, nullptr, 0, SerializeIF::Endianness::NETWORK) !=
|
||||
returnvalue::OK);
|
||||
}
|
||||
|
||||
SECTION("TLV Zero Length Field") {
|
||||
Tlv zeroLenField(TlvType::FAULT_HANDLER, nullptr, 0);
|
||||
REQUIRE(zeroLenField.getSerializedSize() == 2);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
REQUIRE(zeroLenField.serialize(&serPtr, &deserSize, rawBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK) == returnvalue::OK);
|
||||
REQUIRE(rawBuf[0] == TlvType::FAULT_HANDLER);
|
||||
REQUIRE(rawBuf[1] == 0);
|
||||
}
|
||||
|
||||
SECTION("TLV Deserialization") {
|
||||
// Serialization was tested before, generate raw data now
|
||||
std::array<uint8_t, 8> tlvRawBuf{};
|
||||
serPtr = tlvRawBuf.data();
|
||||
result =
|
||||
sourceId.serialize(&serPtr, &deserSize, tlvRawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
auto tlvSerialization = Tlv(TlvType::ENTITY_ID, tlvRawBuf.data(), deserSize);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
result = tlvSerialization.serialize(&serPtr, &deserSize, rawBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
Tlv tlv;
|
||||
deserPtr = rawBuf.data();
|
||||
result = tlv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(tlv.getSerializedSize() == 4);
|
||||
REQUIRE(tlv.getType() == TlvType::ENTITY_ID);
|
||||
deserPtr = tlv.getValue();
|
||||
uint16_t entityId = 0;
|
||||
deserSize = 0;
|
||||
SerializeAdapter::deSerialize(&entityId, deserPtr, &deserSize,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(entityId == 0x0ff0);
|
||||
|
||||
REQUIRE(tlv.deSerialize(nullptr, nullptr, SerializeIF::Endianness::NETWORK) != returnvalue::OK);
|
||||
deserPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
REQUIRE(tlv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK) ==
|
||||
SerializeIF::STREAM_TOO_SHORT);
|
||||
// Set invalid TLV
|
||||
rawBuf[0] = TlvType::INVALID_TLV;
|
||||
deserSize = 4;
|
||||
REQUIRE(tlv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK) !=
|
||||
returnvalue::OK);
|
||||
|
||||
Tlv zeroLenField(TlvType::FAULT_HANDLER, nullptr, 0);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
REQUIRE(zeroLenField.serialize(&serPtr, &deserSize, rawBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK) == returnvalue::OK);
|
||||
deserPtr = rawBuf.data();
|
||||
result = zeroLenField.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(zeroLenField.getSerializedSize() == 2);
|
||||
REQUIRE(deserSize == 0);
|
||||
}
|
||||
}
|
@ -1,327 +0,0 @@
|
||||
#include <fsfw/cfdp/tlv/EntityIdTlv.h>
|
||||
#include <fsfw/cfdp/tlv/FaultHandlerOverrideTlv.h>
|
||||
#include <fsfw/cfdp/tlv/FilestoreRequestTlv.h>
|
||||
#include <fsfw/cfdp/tlv/FilestoreResponseTlv.h>
|
||||
#include <fsfw/cfdp/tlv/FlowLabelTlv.h>
|
||||
#include <fsfw/cfdp/tlv/MessageToUserTlv.h>
|
||||
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <string>
|
||||
|
||||
#include "fsfw/cfdp/pdu/PduConfig.h"
|
||||
#include "fsfw/cfdp/tlv/Lv.h"
|
||||
#include "fsfw/cfdp/tlv/Tlv.h"
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
|
||||
TEST_CASE("CFDP TLV LV", "[CfdpTlvLv]") {
|
||||
using namespace cfdp;
|
||||
int result = returnvalue::OK;
|
||||
std::array<uint8_t, 255> rawBuf;
|
||||
uint8_t* serPtr = rawBuf.data();
|
||||
const uint8_t* deserPtr = rawBuf.data();
|
||||
size_t deserSize = 0;
|
||||
cfdp::EntityId sourceId = EntityId(cfdp::WidthInBytes::TWO_BYTES, 0x0ff0);
|
||||
|
||||
SECTION("TLV Serialization") {
|
||||
std::array<uint8_t, 8> tlvRawBuf;
|
||||
serPtr = tlvRawBuf.data();
|
||||
result =
|
||||
sourceId.serialize(&serPtr, &deserSize, tlvRawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(deserSize == 2);
|
||||
auto tlv = Tlv(TlvTypes::ENTITY_ID, tlvRawBuf.data(), deserSize);
|
||||
REQUIRE(tlv.getSerializedSize() == 4);
|
||||
REQUIRE(tlv.getLengthField() == 2);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
result = tlv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(deserSize == 4);
|
||||
REQUIRE(rawBuf[0] == TlvTypes::ENTITY_ID);
|
||||
REQUIRE(rawBuf[1] == 2);
|
||||
uint16_t entityId = 0;
|
||||
SerializeAdapter::deSerialize(&entityId, rawBuf.data() + 2, &deserSize,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(entityId == 0x0ff0);
|
||||
|
||||
// Set new value
|
||||
sourceId.setValue(cfdp::WidthInBytes::FOUR_BYTES, 12);
|
||||
serPtr = tlvRawBuf.data();
|
||||
deserSize = 0;
|
||||
result =
|
||||
sourceId.serialize(&serPtr, &deserSize, tlvRawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
tlv.setValue(tlvRawBuf.data(), cfdp::WidthInBytes::FOUR_BYTES);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
result = tlv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(rawBuf[0] == TlvTypes::ENTITY_ID);
|
||||
REQUIRE(rawBuf[1] == 4);
|
||||
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
auto tlvInvalid = Tlv(cfdp::TlvTypes::INVALID_TLV, tlvRawBuf.data(), 0);
|
||||
REQUIRE(tlvInvalid.serialize(&serPtr, &deserSize, rawBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK) != returnvalue::OK);
|
||||
tlvInvalid = Tlv(cfdp::TlvTypes::ENTITY_ID, nullptr, 3);
|
||||
REQUIRE(tlvInvalid.serialize(&serPtr, &deserSize, rawBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK) != returnvalue::OK);
|
||||
REQUIRE(tlvInvalid.serialize(&serPtr, &deserSize, 0, SerializeIF::Endianness::NETWORK) !=
|
||||
returnvalue::OK);
|
||||
REQUIRE(tlvInvalid.getSerializedSize() == 0);
|
||||
REQUIRE(tlvInvalid.serialize(nullptr, nullptr, 0, SerializeIF::Endianness::NETWORK) !=
|
||||
returnvalue::OK);
|
||||
|
||||
Tlv zeroLenField(TlvTypes::FAULT_HANDLER, nullptr, 0);
|
||||
REQUIRE(zeroLenField.getSerializedSize() == 2);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
REQUIRE(zeroLenField.serialize(&serPtr, &deserSize, rawBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK) == returnvalue::OK);
|
||||
REQUIRE(rawBuf[0] == TlvTypes::FAULT_HANDLER);
|
||||
REQUIRE(rawBuf[1] == 0);
|
||||
}
|
||||
|
||||
SECTION("TLV Deserialization") {
|
||||
// Serialization was tested before, generate raw data now
|
||||
std::array<uint8_t, 8> tlvRawBuf;
|
||||
serPtr = tlvRawBuf.data();
|
||||
result =
|
||||
sourceId.serialize(&serPtr, &deserSize, tlvRawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
auto tlvSerialization = Tlv(TlvTypes::ENTITY_ID, tlvRawBuf.data(), deserSize);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
result = tlvSerialization.serialize(&serPtr, &deserSize, rawBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
Tlv tlv;
|
||||
deserPtr = rawBuf.data();
|
||||
result = tlv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(tlv.getSerializedSize() == 4);
|
||||
REQUIRE(tlv.getType() == TlvTypes::ENTITY_ID);
|
||||
deserPtr = tlv.getValue();
|
||||
uint16_t entityId = 0;
|
||||
deserSize = 0;
|
||||
SerializeAdapter::deSerialize(&entityId, deserPtr, &deserSize,
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(entityId == 0x0ff0);
|
||||
|
||||
REQUIRE(tlv.deSerialize(nullptr, nullptr, SerializeIF::Endianness::NETWORK) != returnvalue::OK);
|
||||
deserPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
REQUIRE(tlv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK) ==
|
||||
SerializeIF::STREAM_TOO_SHORT);
|
||||
// Set invalid TLV
|
||||
rawBuf[0] = TlvTypes::INVALID_TLV;
|
||||
deserSize = 4;
|
||||
REQUIRE(tlv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK) !=
|
||||
returnvalue::OK);
|
||||
|
||||
Tlv zeroLenField(TlvTypes::FAULT_HANDLER, nullptr, 0);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
REQUIRE(zeroLenField.serialize(&serPtr, &deserSize, rawBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK) == returnvalue::OK);
|
||||
deserPtr = rawBuf.data();
|
||||
result = zeroLenField.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(zeroLenField.getSerializedSize() == 2);
|
||||
REQUIRE(deserSize == 0);
|
||||
}
|
||||
|
||||
SECTION("LV Serialization") {
|
||||
std::array<uint8_t, 8> lvRawBuf;
|
||||
serPtr = lvRawBuf.data();
|
||||
result =
|
||||
sourceId.serialize(&serPtr, &deserSize, lvRawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(deserSize == 2);
|
||||
auto lv = cfdp::Lv(lvRawBuf.data(), 2);
|
||||
auto lvCopy = cfdp::Lv(lv);
|
||||
REQUIRE(lv.getSerializedSize() == 3);
|
||||
REQUIRE(lvCopy.getSerializedSize() == 3);
|
||||
REQUIRE(lv.getValue(nullptr) == lvCopy.getValue(nullptr));
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
result = lv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(deserSize == 3);
|
||||
REQUIRE(rawBuf[0] == 2);
|
||||
uint16_t sourceId = 0;
|
||||
result = SerializeAdapter::deSerialize(&sourceId, rawBuf.data() + 1, &deserSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
REQUIRE(sourceId == 0x0ff0);
|
||||
|
||||
auto lvEmpty = Lv(nullptr, 0);
|
||||
REQUIRE(lvEmpty.getSerializedSize() == 1);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
result =
|
||||
lvEmpty.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(deserSize == 1);
|
||||
}
|
||||
|
||||
SECTION("LV Deserialization") {
|
||||
std::array<uint8_t, 8> lvRawBuf;
|
||||
serPtr = lvRawBuf.data();
|
||||
result =
|
||||
sourceId.serialize(&serPtr, &deserSize, lvRawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
auto lv = cfdp::Lv(lvRawBuf.data(), 2);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
result = lv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
Lv uninitLv;
|
||||
deserPtr = rawBuf.data();
|
||||
deserSize = 3;
|
||||
result = uninitLv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::BIG);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(uninitLv.getSerializedSize() == 3);
|
||||
const uint8_t* storedValue = uninitLv.getValue(nullptr);
|
||||
uint16_t sourceId = 0;
|
||||
result = SerializeAdapter::deSerialize(&sourceId, storedValue, &deserSize,
|
||||
SerializeIF::Endianness::BIG);
|
||||
REQUIRE(sourceId == 0x0ff0);
|
||||
|
||||
auto lvEmpty = Lv(nullptr, 0);
|
||||
REQUIRE(lvEmpty.getSerializedSize() == 1);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
result =
|
||||
lvEmpty.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(deserSize == 1);
|
||||
deserPtr = rawBuf.data();
|
||||
result = uninitLv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::BIG);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(uninitLv.getSerializedSize() == 1);
|
||||
|
||||
REQUIRE(uninitLv.deSerialize(nullptr, nullptr, SerializeIF::Endianness::BIG) ==
|
||||
returnvalue::FAILED);
|
||||
serPtr = rawBuf.data();
|
||||
deserSize = 0;
|
||||
REQUIRE(uninitLv.serialize(&serPtr, &deserSize, 0, SerializeIF::Endianness::BIG) ==
|
||||
SerializeIF::BUFFER_TOO_SHORT);
|
||||
REQUIRE(uninitLv.serialize(nullptr, nullptr, 12, SerializeIF::Endianness::BIG));
|
||||
deserSize = 0;
|
||||
REQUIRE(uninitLv.deSerialize(&deserPtr, &deserSize, SerializeIF::Endianness::BIG) ==
|
||||
SerializeIF::STREAM_TOO_SHORT);
|
||||
}
|
||||
|
||||
SECTION("Filestore Response TLV") {
|
||||
std::string name = "hello.txt";
|
||||
cfdp::Lv firstName(reinterpret_cast<const uint8_t*>(name.data()), name.size());
|
||||
std::string name2 = "hello2.txt";
|
||||
cfdp::Lv secondName(reinterpret_cast<const uint8_t*>(name2.data()), name2.size());
|
||||
std::string msg = "12345";
|
||||
cfdp::Lv fsMsg(reinterpret_cast<const uint8_t*>(msg.data()), msg.size());
|
||||
FilestoreResponseTlv response(cfdp::FilestoreActionCode::APPEND_FILE, cfdp::FSR_SUCCESS,
|
||||
firstName, &fsMsg);
|
||||
response.setSecondFileName(&secondName);
|
||||
REQUIRE(response.getLengthField() == 10 + 11 + 6 + 1);
|
||||
REQUIRE(response.getSerializedSize() == response.getLengthField() + 2);
|
||||
|
||||
cfdp::Tlv rawResponse;
|
||||
std::array<uint8_t, 128> serBuf = {};
|
||||
result = response.convertToTlv(rawResponse, serBuf.data(), serBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(rawResponse.getType() == cfdp::TlvTypes::FILESTORE_RESPONSE);
|
||||
cfdp::Lv emptyMsg;
|
||||
cfdp::Lv emptySecondName;
|
||||
FilestoreResponseTlv emptyTlv(firstName, &emptyMsg);
|
||||
emptyTlv.setSecondFileName(&emptySecondName);
|
||||
result = emptyTlv.deSerialize(rawResponse, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(emptyTlv.getActionCode() == cfdp::FilestoreActionCode::APPEND_FILE);
|
||||
REQUIRE(emptyTlv.getStatusCode() == cfdp::FSR_SUCCESS);
|
||||
size_t firstNameLen = 0;
|
||||
const char* firstNamePtr =
|
||||
reinterpret_cast<const char*>(emptyTlv.getFirstFileName().getValue(&firstNameLen));
|
||||
auto helloString = std::string(firstNamePtr, firstNameLen);
|
||||
REQUIRE(helloString == "hello.txt");
|
||||
}
|
||||
|
||||
SECTION("Filestore Request TLV") {
|
||||
std::string name = "hello.txt";
|
||||
cfdp::Lv firstName(reinterpret_cast<const uint8_t*>(name.data()), name.size());
|
||||
std::string name2 = "hello2.txt";
|
||||
cfdp::Lv secondName(reinterpret_cast<const uint8_t*>(name2.data()), name2.size());
|
||||
FilestoreRequestTlv request(cfdp::FilestoreActionCode::APPEND_FILE, firstName);
|
||||
|
||||
// second name not set yet
|
||||
REQUIRE(request.getLengthField() == 10 + 1);
|
||||
REQUIRE(request.getSerializedSize() == request.getLengthField() + 2);
|
||||
|
||||
std::array<uint8_t, 128> serBuf = {};
|
||||
uint8_t* ptr = serBuf.data();
|
||||
size_t sz = 0;
|
||||
result = request.serialize(&ptr, &sz, serBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == cfdp::FILESTORE_REQUIRES_SECOND_FILE);
|
||||
|
||||
ptr = serBuf.data();
|
||||
sz = 0;
|
||||
request.setSecondFileName(&secondName);
|
||||
size_t expectedSz = request.getLengthField();
|
||||
REQUIRE(expectedSz == 10 + 11 + 1);
|
||||
REQUIRE(request.getSerializedSize() == expectedSz + 2);
|
||||
result = request.serialize(&ptr, &sz, serBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(sz == expectedSz + 2);
|
||||
|
||||
FilestoreRequestTlv emptyRequest(firstName);
|
||||
emptyRequest.setSecondFileName(&secondName);
|
||||
const uint8_t* constptr = serBuf.data();
|
||||
result = emptyRequest.deSerialize(&constptr, &sz, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
cfdp::Tlv rawRequest;
|
||||
ptr = serBuf.data();
|
||||
sz = 0;
|
||||
result = request.convertToTlv(rawRequest, serBuf.data(), serBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(rawRequest.getType() == cfdp::TlvTypes::FILESTORE_REQUEST);
|
||||
|
||||
emptyRequest.setActionCode(cfdp::FilestoreActionCode::DELETE_FILE);
|
||||
result = emptyRequest.deSerialize(rawRequest, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
REQUIRE(emptyRequest.getType() == cfdp::TlvTypes::FILESTORE_REQUEST);
|
||||
REQUIRE(emptyRequest.getActionCode() == cfdp::FilestoreActionCode::APPEND_FILE);
|
||||
}
|
||||
|
||||
SECTION("Other") {
|
||||
MessageToUserTlv emptyTlv;
|
||||
uint8_t flowLabel = 1;
|
||||
FlowLabelTlv flowLabelTlv(&flowLabel, 1);
|
||||
|
||||
FaultHandlerOverrideTlv faultOverrideTlv(cfdp::ConditionCode::FILESTORE_REJECTION,
|
||||
cfdp::FaultHandlerCode::NOTICE_OF_CANCELLATION);
|
||||
size_t sz = 0;
|
||||
ReturnValue_t result =
|
||||
faultOverrideTlv.serialize(&serPtr, &sz, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(faultOverrideTlv.getSerializedSize() == 3);
|
||||
REQUIRE(sz == 3);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
FaultHandlerOverrideTlv emptyOverrideTlv;
|
||||
result = emptyOverrideTlv.deSerialize(&deserPtr, &sz, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
EntityId entId(cfdp::WidthInBytes::TWO_BYTES, 0x42);
|
||||
EntityId emptyId;
|
||||
EntityIdTlv idTlv(emptyId);
|
||||
serPtr = rawBuf.data();
|
||||
result = idTlv.serialize(&serPtr, &deserSize, rawBuf.size(), SerializeIF::Endianness::NETWORK);
|
||||
cfdp::Tlv rawTlv(cfdp::TlvTypes::ENTITY_ID, rawBuf.data() + 2, 2);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
deserPtr = rawBuf.data();
|
||||
result = idTlv.deSerialize(rawTlv, SerializeIF::Endianness::NETWORK);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
}
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
RingBufferTest.cpp
|
||||
TestArrayList.cpp
|
||||
TestDynamicFifo.cpp
|
||||
TestFifo.cpp
|
||||
TestFixedArrayList.cpp
|
||||
TestFixedMap.cpp
|
||||
TestFixedOrderedMultimap.cpp
|
||||
TestPlacementFactory.cpp
|
||||
)
|
||||
target_sources(
|
||||
${FSFW_TEST_TGT}
|
||||
PRIVATE RingBufferTest.cpp
|
||||
TestArrayList.cpp
|
||||
TestDynamicFifo.cpp
|
||||
TestFifo.cpp
|
||||
TestFixedArrayList.cpp
|
||||
TestFixedMap.cpp
|
||||
TestFixedOrderedMultimap.cpp
|
||||
TestPlacementFactory.cpp)
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "CatchDefinitions.h"
|
||||
|
||||
TEST_CASE("Ring Buffer Test", "[RingBufferTest]") {
|
||||
TEST_CASE("Ring Buffer Test", "[containers]") {
|
||||
uint8_t testData[13] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
|
||||
uint8_t readBuffer[10] = {13, 13, 13, 13, 13, 13, 13, 13, 13, 13};
|
||||
SimpleRingBuffer ringBuffer(10, false, 5);
|
||||
|
@ -8,7 +8,7 @@
|
||||
/**
|
||||
* @brief Array List test
|
||||
*/
|
||||
TEST_CASE("Array List", "[ArrayListTest]") {
|
||||
TEST_CASE("Array List", "[containers]") {
|
||||
// perform set-up here
|
||||
ArrayList<uint16_t> list(20);
|
||||
struct TestClass {
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include "CatchDefinitions.h"
|
||||
|
||||
TEST_CASE("Dynamic Fifo Tests", "[TestDynamicFifo]") {
|
||||
TEST_CASE("Dynamic Fifo Tests", "[containers]") {
|
||||
INFO("Dynamic Fifo Tests");
|
||||
struct Test {
|
||||
uint64_t number1;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include "CatchDefinitions.h"
|
||||
|
||||
TEST_CASE("Static Fifo Tests", "[TestFifo]") {
|
||||
TEST_CASE("Static Fifo Tests", "[containers]") {
|
||||
INFO("Fifo Tests");
|
||||
struct Test {
|
||||
uint64_t number1;
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "CatchDefinitions.h"
|
||||
|
||||
TEST_CASE("FixedArrayList Tests", "[TestFixedArrayList]") {
|
||||
TEST_CASE("FixedArrayList Tests", "[containers]") {
|
||||
INFO("FixedArrayList Tests");
|
||||
using testList = FixedArrayList<uint32_t, 260, uint16_t>;
|
||||
testList list;
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
template class FixedMap<unsigned int, unsigned short>;
|
||||
|
||||
TEST_CASE("FixedMap Tests", "[TestFixedMap]") {
|
||||
TEST_CASE("FixedMap Tests", "[containers]") {
|
||||
INFO("FixedMap Tests");
|
||||
|
||||
FixedMap<unsigned int, unsigned short> map(30);
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include "CatchDefinitions.h"
|
||||
|
||||
TEST_CASE("FixedOrderedMultimap Tests", "[TestFixedOrderedMultimap]") {
|
||||
TEST_CASE("FixedOrderedMultimap Tests", "[containers]") {
|
||||
INFO("FixedOrderedMultimap Tests");
|
||||
|
||||
FixedOrderedMultimap<unsigned int, unsigned short> map(30);
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#include "CatchDefinitions.h"
|
||||
|
||||
TEST_CASE("PlacementFactory Tests", "[TestPlacementFactory]") {
|
||||
TEST_CASE("PlacementFactory Tests", "[containers]") {
|
||||
INFO("PlacementFactory Tests");
|
||||
|
||||
LocalPool::LocalPoolConfig poolCfg = {
|
||||
|
@ -1,6 +1,3 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
testLocalPoolVariable.cpp
|
||||
testLocalPoolVector.cpp
|
||||
testDataSet.cpp
|
||||
testLocalPoolManager.cpp
|
||||
)
|
||||
target_sources(
|
||||
${FSFW_TEST_TGT} PRIVATE testLocalPoolVariable.cpp testLocalPoolVector.cpp
|
||||
testDataSet.cpp testLocalPoolManager.cpp)
|
||||
|
@ -1,4 +1,2 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
DeviceHandlerCommander.cpp
|
||||
TestDeviceHandlerBase.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE DeviceHandlerCommander.cpp
|
||||
TestDeviceHandlerBase.cpp)
|
||||
|
@ -1,7 +1,3 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
testDleEncoder.cpp
|
||||
testOpDivider.cpp
|
||||
testBitutil.cpp
|
||||
testCRC.cpp
|
||||
testTimevalOperations.cpp
|
||||
)
|
||||
target_sources(
|
||||
${FSFW_TEST_TGT} PRIVATE testDleEncoder.cpp testOpDivider.cpp testBitutil.cpp
|
||||
testCRC.cpp testTimevalOperations.cpp)
|
||||
|
@ -1,3 +1,2 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
testCommandExecutor.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE testCommandExecutor.cpp
|
||||
testHostFilesystem.cpp testFsMock.cpp)
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
static const char TEST_FILE_NAME[] = "/tmp/fsfw-unittest-test.txt";
|
||||
|
||||
TEST_CASE("Command Executor", "[cmd-exec]") {
|
||||
TEST_CASE("Command Executor", "[hal][linux]") {
|
||||
// Check blocking mode first
|
||||
CommandExecutor cmdExecutor(1024);
|
||||
std::string cmd = "echo \"test\" >> " + std::string(TEST_FILE_NAME);
|
||||
|
49
unittests/hal/testFsMock.cpp
Normal file
49
unittests/hal/testFsMock.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/serialize/SerializeIF.h"
|
||||
#include "mocks/FilesystemMock.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
TEST_CASE("Filesystem Mock", "[mocks]") {
|
||||
auto fsMock = FilesystemMock();
|
||||
|
||||
SECTION("Create File") {
|
||||
FilesystemParams params("hello.txt");
|
||||
CHECK(fsMock.createFile(params) == returnvalue::OK);
|
||||
auto iter = fsMock.fileMap.find("hello.txt");
|
||||
REQUIRE(iter != fsMock.fileMap.end());
|
||||
FilesystemMock::FileInfo &stats = iter->second;
|
||||
CHECK(stats.fileSegQueue.empty());
|
||||
CHECK(stats.fileRaw.empty());
|
||||
}
|
||||
|
||||
SECTION("Write to File") {
|
||||
std::string testData = "test data";
|
||||
FileOpParams params("hello.txt", testData.size());
|
||||
CHECK(fsMock.writeToFile(params, reinterpret_cast<const uint8_t *>(testData.data())) ==
|
||||
returnvalue::OK);
|
||||
auto iter = fsMock.fileMap.find("hello.txt");
|
||||
REQUIRE(iter != fsMock.fileMap.end());
|
||||
FilesystemMock::FileInfo &stats = iter->second;
|
||||
CHECK(not stats.fileSegQueue.empty());
|
||||
CHECK(not stats.fileRaw.empty());
|
||||
auto &segment = stats.fileSegQueue.back();
|
||||
CHECK(segment.offset == 0);
|
||||
CHECK(std::string(reinterpret_cast<const char *>(segment.data.data()), segment.data.size()) ==
|
||||
testData);
|
||||
CHECK(std::string(reinterpret_cast<const char *>(stats.fileRaw.data()), segment.data.size()) ==
|
||||
testData);
|
||||
}
|
||||
|
||||
SECTION("Create Directory") {
|
||||
FilesystemParams params("hello");
|
||||
CHECK(fsMock.createDirectory(params) == returnvalue::OK);
|
||||
REQUIRE(not fsMock.dirMap.empty());
|
||||
auto iter = fsMock.dirMap.find("hello");
|
||||
REQUIRE(iter != fsMock.dirMap.end());
|
||||
auto &dirInfo = iter->second;
|
||||
CHECK(dirInfo.createCallCount == 1);
|
||||
CHECK(dirInfo.delCallCount == 0);
|
||||
}
|
||||
}
|
228
unittests/hal/testHostFilesystem.cpp
Normal file
228
unittests/hal/testHostFilesystem.cpp
Normal file
@ -0,0 +1,228 @@
|
||||
#include <etl/crc32.h>
|
||||
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <random>
|
||||
|
||||
#include "fsfw/serialize/SerializeIF.h"
|
||||
#include "fsfw_hal/host/HostFilesystem.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
TEST_CASE("Host Filesystem", "[hal][host]") {
|
||||
namespace fs = filesystem;
|
||||
auto hostFs = HostFilesystem();
|
||||
auto tmpDir = fs::temp_directory_path();
|
||||
fs::path file0 = tmpDir / "hello.txt";
|
||||
fs::path file1 = tmpDir / "hello2.txt";
|
||||
fs::path dir0 = tmpDir / "test_dir";
|
||||
fs::path fileInDir0 = dir0 / "hello.txt";
|
||||
fs::path dirWithParent = dir0 / "test_dir";
|
||||
|
||||
REQUIRE_NOTHROW(fs::remove(file0));
|
||||
REQUIRE_NOTHROW(fs::remove(file1));
|
||||
REQUIRE_NOTHROW(fs::remove_all(dir0));
|
||||
|
||||
SECTION("Create file") {
|
||||
FilesystemParams params(file0.c_str());
|
||||
REQUIRE(hostFs.createFile(params) == returnvalue::OK);
|
||||
CHECK(fs::is_regular_file(file0));
|
||||
REQUIRE(fs::exists(file0));
|
||||
}
|
||||
|
||||
SECTION("Remove File") {
|
||||
FilesystemParams params(file0.c_str());
|
||||
REQUIRE(hostFs.createFile(params) == returnvalue::OK);
|
||||
CHECK(fs::is_regular_file(file0));
|
||||
REQUIRE(fs::exists(file0));
|
||||
REQUIRE(hostFs.removeFile(file0.c_str()) == returnvalue::OK);
|
||||
REQUIRE(not fs::exists(file0));
|
||||
}
|
||||
|
||||
SECTION("Create Directory") {
|
||||
FilesystemParams params(dir0.c_str());
|
||||
REQUIRE(hostFs.createDirectory(params) == returnvalue::OK);
|
||||
CHECK(fs::is_directory(dir0));
|
||||
REQUIRE(fs::exists(dir0));
|
||||
}
|
||||
|
||||
SECTION("Remove Directory") {
|
||||
FilesystemParams params(dir0.c_str());
|
||||
REQUIRE(hostFs.createDirectory(params) == returnvalue::OK);
|
||||
REQUIRE(fs::exists(dir0));
|
||||
REQUIRE(hostFs.removeDirectory(params) == returnvalue::OK);
|
||||
REQUIRE(not fs::exists(dir0));
|
||||
}
|
||||
|
||||
SECTION("Rename File") {
|
||||
FilesystemParams params(file0.c_str());
|
||||
REQUIRE(hostFs.createFile(params) == returnvalue::OK);
|
||||
CHECK(fs::is_regular_file(file0));
|
||||
REQUIRE(fs::exists(file0));
|
||||
REQUIRE(hostFs.rename(file0.c_str(), file1.c_str()) == returnvalue::OK);
|
||||
}
|
||||
|
||||
SECTION("Write To File") {
|
||||
std::string data = "hello world!";
|
||||
FileOpParams params(file0.c_str(), data.size());
|
||||
REQUIRE(hostFs.createFile(params.fsParams) == returnvalue::OK);
|
||||
CHECK(fs::is_regular_file(file0));
|
||||
REQUIRE(fs::exists(file0));
|
||||
CHECK(hostFs.writeToFile(params, reinterpret_cast<const uint8_t*>(data.c_str())) ==
|
||||
returnvalue::OK);
|
||||
CHECK(fs::file_size(file0) == data.size());
|
||||
ifstream ifile(file0);
|
||||
std::array<char, 524> readBuf{};
|
||||
ifile.read(readBuf.data(), sizeof(readBuf));
|
||||
std::string readBackString(readBuf.data());
|
||||
CHECK(data == readBackString);
|
||||
}
|
||||
|
||||
SECTION("Write To File, Check Not Truncated") {
|
||||
std::random_device dev;
|
||||
std::mt19937 rng(dev());
|
||||
std::uniform_int_distribution<std::mt19937::result_type> distU8(1, 255);
|
||||
std::array<uint8_t, 512> randData{};
|
||||
for (uint8_t& byte : randData) {
|
||||
byte = distU8(rng);
|
||||
}
|
||||
FileOpParams params(file0.c_str(), randData.size() - 256);
|
||||
REQUIRE(hostFs.createFile(params.fsParams) == returnvalue::OK);
|
||||
CHECK(fs::is_regular_file(file0));
|
||||
REQUIRE(fs::exists(file0));
|
||||
// Write first file chunk
|
||||
CHECK(hostFs.writeToFile(params, randData.cbegin()) == returnvalue::OK);
|
||||
params.offset = 256;
|
||||
CHECK(hostFs.writeToFile(params, randData.cbegin() + 256) == returnvalue::OK);
|
||||
std::ifstream rf(file0, ios::binary);
|
||||
std::array<uint8_t, 512> readBack{};
|
||||
REQUIRE(std::filesystem::file_size(file0) == 512);
|
||||
rf.read(reinterpret_cast<char*>(readBack.data()), readBack.size());
|
||||
for (size_t i = 0; i < 512; i++) {
|
||||
CHECK(randData[i] == readBack[i]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Read From File") {
|
||||
std::string data = "hello world!";
|
||||
FileOpParams params(file0.c_str(), data.size());
|
||||
REQUIRE(hostFs.createFile(params.fsParams) == returnvalue::OK);
|
||||
CHECK(fs::is_regular_file(file0));
|
||||
ofstream of(file0);
|
||||
of.write(data.c_str(), static_cast<unsigned int>(data.size()));
|
||||
of.close();
|
||||
CHECK(fs::file_size(file0) == data.size());
|
||||
REQUIRE(fs::exists(file0));
|
||||
std::array<uint8_t, 256> readBuf{};
|
||||
uint8_t* readPtr = readBuf.data();
|
||||
size_t readSize = 0;
|
||||
CHECK(hostFs.readFromFile(params, &readPtr, readSize, readBuf.size()) == returnvalue::OK);
|
||||
std::string readBackString(reinterpret_cast<const char*>(readBuf.data()));
|
||||
CHECK(readSize == data.size());
|
||||
CHECK(data == readBackString);
|
||||
}
|
||||
|
||||
SECTION("Invalid Input does not crash") {
|
||||
FileOpParams params(nullptr, 10);
|
||||
REQUIRE(hostFs.createFile(params.fsParams) != returnvalue::OK);
|
||||
REQUIRE(hostFs.createDirectory(params.fsParams) != returnvalue::OK);
|
||||
REQUIRE(hostFs.createFile(params.fsParams) != returnvalue::OK);
|
||||
REQUIRE(hostFs.removeDirectory(params.fsParams) != returnvalue::OK);
|
||||
REQUIRE(hostFs.removeFile(nullptr) != returnvalue::OK);
|
||||
REQUIRE(hostFs.rename(nullptr, nullptr) != returnvalue::OK);
|
||||
REQUIRE(hostFs.writeToFile(params, nullptr) != returnvalue::OK);
|
||||
size_t readLen = 0;
|
||||
REQUIRE(hostFs.readFromFile(params, nullptr, readLen, 20) != returnvalue::OK);
|
||||
}
|
||||
|
||||
SECTION("Create File but already exists") {
|
||||
FilesystemParams params(file0.c_str());
|
||||
REQUIRE(hostFs.createFile(params) == returnvalue::OK);
|
||||
REQUIRE(hostFs.createFile(params) == HasFileSystemIF::FILE_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
SECTION("Remove File but does not exist") {
|
||||
REQUIRE(hostFs.removeFile(file0.c_str()) == HasFileSystemIF::FILE_DOES_NOT_EXIST);
|
||||
}
|
||||
|
||||
SECTION("Create Directory but already exists") {
|
||||
FileOpParams params(file0.c_str(), 12);
|
||||
REQUIRE(hostFs.createDirectory(params.fsParams) == returnvalue::OK);
|
||||
REQUIRE(hostFs.createDirectory(params.fsParams) == HasFileSystemIF::DIRECTORY_ALREADY_EXISTS);
|
||||
}
|
||||
|
||||
SECTION("Remove Directory but does not exist") {
|
||||
FilesystemParams params(dir0.c_str());
|
||||
REQUIRE(hostFs.removeDirectory(params) == HasFileSystemIF::DIRECTORY_DOES_NOT_EXIST);
|
||||
}
|
||||
|
||||
SECTION("Remove Directory but is file") {
|
||||
ofstream of(file0);
|
||||
FilesystemParams params(file0.c_str());
|
||||
REQUIRE(hostFs.removeDirectory(params) == HasFileSystemIF::NOT_A_DIRECTORY);
|
||||
}
|
||||
|
||||
SECTION("Read from file but does not exist") {
|
||||
std::string data = "hello world!";
|
||||
FileOpParams params(file0.c_str(), data.size());
|
||||
std::array<uint8_t, 10> readBuf{};
|
||||
uint8_t* readPtr = readBuf.data();
|
||||
size_t readSize = 0;
|
||||
CHECK(hostFs.readFromFile(params, &readPtr, readSize, readBuf.size()) ==
|
||||
HasFileSystemIF::FILE_DOES_NOT_EXIST);
|
||||
}
|
||||
|
||||
SECTION("Write to file but does not exist") {
|
||||
std::string data = "hello world!";
|
||||
FileOpParams params(file0.c_str(), data.size());
|
||||
CHECK(hostFs.writeToFile(params, reinterpret_cast<const uint8_t*>(data.c_str())) ==
|
||||
HasFileSystemIF::FILE_DOES_NOT_EXIST);
|
||||
}
|
||||
|
||||
SECTION("Remove recursively") {
|
||||
fs::create_directory(dir0.c_str());
|
||||
ofstream of(fileInDir0);
|
||||
CHECK(fs::is_directory(dir0));
|
||||
CHECK(fs::is_regular_file(fileInDir0));
|
||||
REQUIRE(hostFs.removeDirectory(FilesystemParams(dir0.c_str()), true) == returnvalue::OK);
|
||||
CHECK(not fs::is_directory(dir0));
|
||||
CHECK(not fs::is_regular_file(fileInDir0));
|
||||
}
|
||||
|
||||
SECTION("Non-Recursive Removal Fails") {
|
||||
fs::create_directory(dir0.c_str());
|
||||
ofstream of(fileInDir0);
|
||||
CHECK(fs::is_directory(dir0));
|
||||
CHECK(fs::is_regular_file(fileInDir0));
|
||||
REQUIRE(hostFs.removeDirectory(FilesystemParams(dir0.c_str())) ==
|
||||
HasFileSystemIF::DIRECTORY_NOT_EMPTY);
|
||||
}
|
||||
|
||||
SECTION("Create directory with parent directory") {
|
||||
CHECK(hostFs.createDirectory(FilesystemParams(dirWithParent.c_str()), true) == returnvalue::OK);
|
||||
CHECK(fs::is_directory(dir0));
|
||||
CHECK(fs::is_directory(dirWithParent));
|
||||
}
|
||||
|
||||
SECTION("Read but provided buffer too small") {
|
||||
std::string data = "hello world!";
|
||||
FileOpParams params(file0.c_str(), data.size());
|
||||
ofstream of(file0);
|
||||
of.write(data.c_str(), static_cast<unsigned int>(data.size()));
|
||||
of.close();
|
||||
CHECK(fs::file_size(file0) == data.size());
|
||||
REQUIRE(fs::exists(file0));
|
||||
std::array<uint8_t, 15> readBuf{};
|
||||
uint8_t* readPtr = readBuf.data();
|
||||
size_t readSize = 0;
|
||||
CHECK(hostFs.readFromFile(params, &readPtr, readSize, 5) == SerializeIF::BUFFER_TOO_SHORT);
|
||||
readSize = 10;
|
||||
CHECK(hostFs.readFromFile(params, &readPtr, readSize, readBuf.size()) ==
|
||||
SerializeIF::BUFFER_TOO_SHORT);
|
||||
}
|
||||
|
||||
REQUIRE_NOTHROW(fs::remove(file0));
|
||||
REQUIRE_NOTHROW(fs::remove(file1));
|
||||
REQUIRE_NOTHROW(fs::remove_all(dir0));
|
||||
}
|
@ -1,3 +1 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
TestInternalErrorReporter.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE TestInternalErrorReporter.cpp)
|
||||
|
8
unittests/mocks/AcceptsTcMock.cpp
Normal file
8
unittests/mocks/AcceptsTcMock.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "AcceptsTcMock.h"
|
||||
|
||||
AcceptsTcMock::AcceptsTcMock(const char* name, uint32_t id, MessageQueueId_t queueId)
|
||||
: name(name), id(id), queueId(queueId) {}
|
||||
|
||||
const char* AcceptsTcMock::getName() const { return name; }
|
||||
uint32_t AcceptsTcMock::getIdentifier() const { return id; }
|
||||
MessageQueueId_t AcceptsTcMock::getRequestQueue() const { return queueId; }
|
20
unittests/mocks/AcceptsTcMock.h
Normal file
20
unittests/mocks/AcceptsTcMock.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef FSFW_TESTS_ACCEPTSTCMOCK_H
|
||||
#define FSFW_TESTS_ACCEPTSTCMOCK_H
|
||||
|
||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
||||
|
||||
class AcceptsTcMock : public AcceptsTelecommandsIF {
|
||||
public:
|
||||
AcceptsTcMock(const char* name, uint32_t id, MessageQueueId_t queueId);
|
||||
[[nodiscard]] const char* getName() const override;
|
||||
[[nodiscard]] uint32_t getIdentifier() const override;
|
||||
[[nodiscard]] MessageQueueId_t getRequestQueue() const override;
|
||||
|
||||
const char* name;
|
||||
uint32_t id;
|
||||
MessageQueueId_t queueId;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // FSFW_TESTS_ACCEPTSTCMOCK_H
|
@ -9,3 +9,5 @@ AcceptsTmMock::AcceptsTmMock(MessageQueueId_t queueToReturn)
|
||||
MessageQueueId_t AcceptsTmMock::getReportReceptionQueue(uint8_t virtualChannel) {
|
||||
return returnedQueue;
|
||||
}
|
||||
|
||||
const char* AcceptsTmMock::getName() const { return "TM Acceptor Mock"; }
|
||||
|
@ -10,6 +10,7 @@ class AcceptsTmMock : public SystemObject, public AcceptsTelemetryIF {
|
||||
explicit AcceptsTmMock(MessageQueueId_t queueToReturn);
|
||||
|
||||
MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) override;
|
||||
const char* getName() const override;
|
||||
|
||||
MessageQueueId_t returnedQueue;
|
||||
};
|
||||
|
@ -1,14 +1,21 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
PowerSwitcherMock.cpp
|
||||
DeviceHandlerMock.cpp
|
||||
DeviceFdirMock.cpp
|
||||
CookieIFMock.cpp
|
||||
ComIFMock.cpp
|
||||
MessageQueueMock.cpp
|
||||
InternalErrorReporterMock.cpp
|
||||
LocalPoolOwnerBase.cpp
|
||||
PusVerificationReporterMock.cpp
|
||||
PusServiceBaseMock.cpp
|
||||
AcceptsTmMock.cpp
|
||||
PusDistributorMock.cpp
|
||||
)
|
||||
target_sources(
|
||||
${FSFW_TEST_TGT}
|
||||
PRIVATE PowerSwitcherMock.cpp
|
||||
DeviceHandlerMock.cpp
|
||||
DeviceFdirMock.cpp
|
||||
CookieIFMock.cpp
|
||||
ComIFMock.cpp
|
||||
MessageQueueMock.cpp
|
||||
InternalErrorReporterMock.cpp
|
||||
LocalPoolOwnerBase.cpp
|
||||
PusVerificationReporterMock.cpp
|
||||
PusServiceBaseMock.cpp
|
||||
AcceptsTmMock.cpp
|
||||
PusDistributorMock.cpp
|
||||
CcsdsCheckerMock.cpp
|
||||
AcceptsTcMock.cpp
|
||||
StorageManagerMock.cpp
|
||||
FilesystemMock.cpp
|
||||
EventReportingProxyMock.cpp)
|
||||
|
||||
add_subdirectory(cfdp)
|
||||
|
10
unittests/mocks/CcsdsCheckerMock.cpp
Normal file
10
unittests/mocks/CcsdsCheckerMock.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "CcsdsCheckerMock.h"
|
||||
|
||||
CcsdsCheckerMock::CcsdsCheckerMock() = default;
|
||||
|
||||
ReturnValue_t CcsdsCheckerMock::checkPacket(const SpacePacketReader& currentPacket,
|
||||
size_t packetLen) {
|
||||
checkCallCount++;
|
||||
checkedPacketLen = packetLen;
|
||||
return nextResult;
|
||||
}
|
16
unittests/mocks/CcsdsCheckerMock.h
Normal file
16
unittests/mocks/CcsdsCheckerMock.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef FSFW_TESTS_CCSDSCHECKERMOCK_H
|
||||
#define FSFW_TESTS_CCSDSCHECKERMOCK_H
|
||||
|
||||
#include "fsfw/tcdistribution/CcsdsPacketCheckIF.h"
|
||||
class CcsdsCheckerMock : public CcsdsPacketCheckIF {
|
||||
public:
|
||||
CcsdsCheckerMock();
|
||||
unsigned int checkCallCount = 0;
|
||||
size_t checkedPacketLen = 0;
|
||||
ReturnValue_t nextResult = returnvalue::OK;
|
||||
ReturnValue_t checkPacket(const SpacePacketReader& currentPacket, size_t packetLen) override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // FSFW_TESTS_CCSDSCHECKERMOCK_H
|
6
unittests/mocks/EventReportingProxyMock.cpp
Normal file
6
unittests/mocks/EventReportingProxyMock.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "EventReportingProxyMock.h"
|
||||
|
||||
void EventReportingProxyMock::forwardEvent(Event event, uint32_t parameter1,
|
||||
uint32_t parameter2) const {
|
||||
eventQueue.emplace(event, parameter1, parameter2);
|
||||
}
|
21
unittests/mocks/EventReportingProxyMock.h
Normal file
21
unittests/mocks/EventReportingProxyMock.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef FSFW_TESTS_EVENTREPORTPROXYMOCK_H
|
||||
#define FSFW_TESTS_EVENTREPORTPROXYMOCK_H
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include "fsfw/events/EventReportingProxyIF.h"
|
||||
|
||||
class EventReportingProxyMock : public EventReportingProxyIF {
|
||||
public:
|
||||
void forwardEvent(Event event, uint32_t parameter1, uint32_t parameter2) const override;
|
||||
|
||||
struct EventInfo {
|
||||
EventInfo(Event event, uint32_t p1, uint32_t p2) : event(event), p1(p1), p2(p2) {}
|
||||
|
||||
Event event;
|
||||
uint32_t p1;
|
||||
uint32_t p2;
|
||||
};
|
||||
mutable std::queue<EventInfo> eventQueue;
|
||||
};
|
||||
#endif // FSFW_TESTS_EVENTREPORTPROXYMOCK_H
|
140
unittests/mocks/FilesystemMock.cpp
Normal file
140
unittests/mocks/FilesystemMock.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
#include "FilesystemMock.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
#include "fsfw/serialize/SerializeIF.h"
|
||||
|
||||
ReturnValue_t FilesystemMock::feedFile(const std::string &filename, std::ifstream &file) {
|
||||
if (not std::filesystem::exists(filename)) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
size_t fileSize = std::filesystem::file_size(filename);
|
||||
FileOpParams params(filename.c_str(), fileSize);
|
||||
std::vector<uint8_t> rawData(fileSize);
|
||||
file.read(reinterpret_cast<char *>(rawData.data()), static_cast<unsigned int>(rawData.size()));
|
||||
createOrAddToFile(params, rawData.data());
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FilesystemMock::writeToFile(FileOpParams params, const uint8_t *data) {
|
||||
createOrAddToFile(params, data);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FilesystemMock::readFromFile(FileOpParams params, uint8_t **buffer, size_t &readSize,
|
||||
size_t maxSize) {
|
||||
std::string filename(params.path());
|
||||
auto iter = fileMap.find(filename);
|
||||
if (iter == fileMap.end()) {
|
||||
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
|
||||
} else {
|
||||
FileInfo &info = iter->second;
|
||||
size_t readLen = params.size;
|
||||
if (params.offset + params.size > info.fileRaw.size()) {
|
||||
if (params.offset > info.fileRaw.size()) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
readLen = info.fileRaw.size() - params.offset;
|
||||
}
|
||||
if (readSize + readLen > maxSize) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
std::copy(info.fileRaw.data() + params.offset, info.fileRaw.data() + readLen, *buffer);
|
||||
*buffer += readLen;
|
||||
readSize += readLen;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FilesystemMock::createFile(FilesystemParams params, const uint8_t *data,
|
||||
size_t size) {
|
||||
FileOpParams params2(params.path, size);
|
||||
createOrAddToFile(params2, data);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FilesystemMock::removeFile(const char *path, FileSystemArgsIF *args) {
|
||||
std::string filename(path);
|
||||
auto iter = fileMap.find(filename);
|
||||
if (iter == fileMap.end()) {
|
||||
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
|
||||
} else {
|
||||
fileMap.erase(iter);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t FilesystemMock::createDirectory(FilesystemParams params, bool createParentDirs) {
|
||||
std::string dirPath = params.path;
|
||||
dirMap[dirPath].createCallCount++;
|
||||
dirMap[dirPath].wihParentDir.push(createParentDirs);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FilesystemMock::removeDirectory(FilesystemParams params, bool deleteRecurively) {
|
||||
std::string dirPath = params.path;
|
||||
dirMap[dirPath].delCallCount++;
|
||||
dirMap[dirPath].recursiveDeletion.push(deleteRecurively);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FilesystemMock::rename(const char *oldPath, const char *newPath,
|
||||
FileSystemArgsIF *args) {
|
||||
renameQueue.push(RenameInfo(oldPath, newPath));
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void FilesystemMock::createOrAddToFile(FileOpParams params, const uint8_t *data) {
|
||||
std::string filename(params.path());
|
||||
auto iter = fileMap.find(filename);
|
||||
if (iter == fileMap.end()) {
|
||||
FileSegmentQueue queue;
|
||||
if (params.size > 0) {
|
||||
queue.push(FileWriteInfo(filename, params.offset, data, params.size));
|
||||
}
|
||||
FileInfo info;
|
||||
info.fileSegQueue = queue;
|
||||
if (data != nullptr) {
|
||||
info.fileRaw.insert(info.fileRaw.end(), data, data + params.size);
|
||||
}
|
||||
fileMap.emplace(filename, info);
|
||||
} else {
|
||||
FileInfo &info = iter->second;
|
||||
info.fileSegQueue.push(FileWriteInfo(filename, params.offset, data, params.size));
|
||||
if (data == nullptr) {
|
||||
return;
|
||||
}
|
||||
// Easiest case: append data to the end
|
||||
if (params.offset == info.fileRaw.size()) {
|
||||
info.fileRaw.insert(info.fileRaw.end(), data, data + params.size);
|
||||
} else {
|
||||
size_t totalNewLen = params.offset + params.size;
|
||||
if (totalNewLen > info.fileRaw.size()) {
|
||||
info.fileRaw.resize(params.offset + params.size);
|
||||
}
|
||||
std::copy(data, data + params.size,
|
||||
info.fileRaw.begin() + static_cast<unsigned int>(params.offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FilesystemMock::reset() {
|
||||
fileMap.clear();
|
||||
dirMap.clear();
|
||||
std::queue<RenameInfo> empty;
|
||||
std::swap(renameQueue, empty);
|
||||
}
|
||||
|
||||
bool FilesystemMock::fileExists(FilesystemParams params) {
|
||||
std::string filename(params.path);
|
||||
auto iter = fileMap.find(filename);
|
||||
if (iter == fileMap.end()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ReturnValue_t FilesystemMock::truncateFile(FilesystemParams params) {
|
||||
truncateCalledOnFile = params.path;
|
||||
return returnvalue::OK;
|
||||
}
|
81
unittests/mocks/FilesystemMock.h
Normal file
81
unittests/mocks/FilesystemMock.h
Normal file
@ -0,0 +1,81 @@
|
||||
#ifndef FSFW_MOCKS_FILESYSTEMMOCK_H
|
||||
#define FSFW_MOCKS_FILESYSTEMMOCK_H
|
||||
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "fsfw/filesystem.h"
|
||||
|
||||
/**
|
||||
* This mock models a filesystem in the RAM. It can be used to verify correct behaviour of
|
||||
* a component using a filesystem without relying on an actual OS filesystem implementation.
|
||||
*
|
||||
* Please note that this object does not actually check paths for validity. The file API was
|
||||
* built in a way to allow reading a file back after it was written while also remembering
|
||||
* the specific file segments which were inserted in write calls.
|
||||
*/
|
||||
class FilesystemMock : public HasFileSystemIF {
|
||||
public:
|
||||
struct FileWriteInfo {
|
||||
FileWriteInfo(std::string filename, size_t offset, const uint8_t *data, size_t len)
|
||||
: filename(std::move(filename)), offset(offset) {
|
||||
this->data.insert(this->data.end(), data, data + len);
|
||||
}
|
||||
std::string filename;
|
||||
size_t offset;
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
using FileSegmentQueue = std::queue<FileWriteInfo>;
|
||||
|
||||
struct FileInfo {
|
||||
FileSegmentQueue fileSegQueue;
|
||||
std::vector<uint8_t> fileRaw;
|
||||
};
|
||||
|
||||
std::map<std::string, FileInfo> fileMap;
|
||||
|
||||
struct DirInfo {
|
||||
size_t createCallCount = 0;
|
||||
size_t delCallCount = 0;
|
||||
std::queue<bool> wihParentDir;
|
||||
std::queue<bool> recursiveDeletion;
|
||||
};
|
||||
std::map<std::string, DirInfo> dirMap;
|
||||
|
||||
struct RenameInfo {
|
||||
RenameInfo(std::string oldName, std::string newName)
|
||||
: oldName(std::move(oldName)), newName(std::move(newName)) {}
|
||||
|
||||
std::string oldName;
|
||||
std::string newName;
|
||||
};
|
||||
std::queue<RenameInfo> renameQueue;
|
||||
std::string truncateCalledOnFile;
|
||||
ReturnValue_t feedFile(const std::string &filename, std::ifstream &file);
|
||||
|
||||
bool fileExists(FilesystemParams params) override;
|
||||
ReturnValue_t truncateFile(FilesystemParams params) override;
|
||||
|
||||
ReturnValue_t writeToFile(FileOpParams params, const uint8_t *data) override;
|
||||
ReturnValue_t readFromFile(FileOpParams params, uint8_t **buffer, size_t &readSize,
|
||||
size_t maxSize) override;
|
||||
ReturnValue_t createFile(FilesystemParams params, const uint8_t *data, size_t size) override;
|
||||
ReturnValue_t removeFile(const char *path, FileSystemArgsIF *args) override;
|
||||
ReturnValue_t createDirectory(FilesystemParams params, bool createParentDirs) override;
|
||||
ReturnValue_t removeDirectory(FilesystemParams params, bool deleteRecurively) override;
|
||||
ReturnValue_t rename(const char *oldPath, const char *newPath, FileSystemArgsIF *args) override;
|
||||
|
||||
void reset();
|
||||
|
||||
using HasFileSystemIF::createDirectory;
|
||||
using HasFileSystemIF::createFile;
|
||||
using HasFileSystemIF::readFromFile;
|
||||
|
||||
private:
|
||||
void createOrAddToFile(FileOpParams params, const uint8_t *data);
|
||||
};
|
||||
|
||||
#endif // FSFW_MOCKS_FILESYSTEMMOCK_H
|
@ -5,8 +5,8 @@ PusDistributorMock::PusDistributorMock() : SystemObject(objects::NO_OBJECT, fals
|
||||
PusDistributorMock::PusDistributorMock(object_id_t registeredId)
|
||||
: SystemObject(registeredId, true) {}
|
||||
|
||||
ReturnValue_t PusDistributorMock::registerService(AcceptsTelecommandsIF *service) {
|
||||
ReturnValue_t PusDistributorMock::registerService(const AcceptsTelecommandsIF& service) {
|
||||
registerCallCount++;
|
||||
lastServiceArg = service;
|
||||
registeredServies.push_back(&service);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -1,16 +1,18 @@
|
||||
#ifndef FSFW_TESTS_PUSDISTRIBUTORMOCK_H
|
||||
#define FSFW_TESTS_PUSDISTRIBUTORMOCK_H
|
||||
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/tcdistribution/PUSDistributorIF.h"
|
||||
#include <vector>
|
||||
|
||||
class PusDistributorMock : public SystemObject, public PUSDistributorIF {
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/tcdistribution/PusDistributorIF.h"
|
||||
|
||||
class PusDistributorMock : public SystemObject, public PusDistributorIF {
|
||||
public:
|
||||
PusDistributorMock();
|
||||
explicit PusDistributorMock(object_id_t registeredId);
|
||||
unsigned int registerCallCount = 0;
|
||||
AcceptsTelecommandsIF* lastServiceArg = nullptr;
|
||||
ReturnValue_t registerService(AcceptsTelecommandsIF* service) override;
|
||||
std::vector<const AcceptsTelecommandsIF*> registeredServies;
|
||||
ReturnValue_t registerService(const AcceptsTelecommandsIF& service) override;
|
||||
};
|
||||
|
||||
#endif // FSFW_TESTS_PUSDISTRIBUTORMOCK_H
|
||||
|
81
unittests/mocks/StorageManagerMock.cpp
Normal file
81
unittests/mocks/StorageManagerMock.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "StorageManagerMock.h"
|
||||
|
||||
ReturnValue_t StorageManagerMock::addData(store_address_t *storageId, const uint8_t *data,
|
||||
size_t size, bool ignoreFault) {
|
||||
if (nextAddDataCallFails.first) {
|
||||
return nextAddDataCallFails.second;
|
||||
}
|
||||
return LocalPool::addData(storageId, data, size, ignoreFault);
|
||||
}
|
||||
ReturnValue_t StorageManagerMock::deleteData(store_address_t packet_id) {
|
||||
if (nextDeleteDataCallFails.first) {
|
||||
return nextDeleteDataCallFails.second;
|
||||
}
|
||||
return LocalPool::deleteData(packet_id);
|
||||
}
|
||||
|
||||
ReturnValue_t StorageManagerMock::deleteData(uint8_t *buffer, size_t size,
|
||||
store_address_t *storeId) {
|
||||
if (nextDeleteDataCallFails.first) {
|
||||
return nextDeleteDataCallFails.second;
|
||||
}
|
||||
return LocalPool::deleteData(buffer, size, storeId);
|
||||
}
|
||||
|
||||
ReturnValue_t StorageManagerMock::getData(store_address_t packet_id, const uint8_t **packet_ptr,
|
||||
size_t *size) {
|
||||
return LocalPool::getData(packet_id, packet_ptr, size);
|
||||
}
|
||||
|
||||
ReturnValue_t StorageManagerMock::modifyData(store_address_t packet_id, uint8_t **packet_ptr,
|
||||
size_t *size) {
|
||||
if (nextModifyDataCallFails.first) {
|
||||
return nextModifyDataCallFails.second;
|
||||
}
|
||||
return LocalPool::modifyData(packet_id, packet_ptr, size);
|
||||
}
|
||||
|
||||
ReturnValue_t StorageManagerMock::getFreeElement(store_address_t *storageId, size_t size,
|
||||
uint8_t **p_data, bool ignoreFault) {
|
||||
if (nextFreeElementCallFails.first) {
|
||||
return nextFreeElementCallFails.second;
|
||||
}
|
||||
return LocalPool::getFreeElement(storageId, size, p_data, ignoreFault);
|
||||
}
|
||||
|
||||
bool StorageManagerMock::hasDataAtId(store_address_t storeId) const {
|
||||
return LocalPool::hasDataAtId(storeId);
|
||||
}
|
||||
void StorageManagerMock::clearStore() { return LocalPool::clearStore(); }
|
||||
|
||||
void StorageManagerMock::clearSubPool(uint8_t poolIndex) {
|
||||
return LocalPool::clearSubPool(poolIndex);
|
||||
}
|
||||
|
||||
void StorageManagerMock::getFillCount(uint8_t *buffer, uint8_t *bytesWritten) {
|
||||
return LocalPool::getFillCount(buffer, bytesWritten);
|
||||
}
|
||||
|
||||
size_t StorageManagerMock::getTotalSize(size_t *additionalSize) {
|
||||
return LocalPool::getTotalSize(additionalSize);
|
||||
}
|
||||
|
||||
StorageManagerIF::max_subpools_t StorageManagerMock::getNumberOfSubPools() const {
|
||||
return LocalPool::getNumberOfSubPools();
|
||||
}
|
||||
|
||||
void StorageManagerMock::reset() {
|
||||
clearStore();
|
||||
nextAddDataCallFails.first = false;
|
||||
nextAddDataCallFails.second = returnvalue::OK;
|
||||
nextModifyDataCallFails.first = false;
|
||||
nextModifyDataCallFails.second = returnvalue::OK;
|
||||
nextDeleteDataCallFails.first = false;
|
||||
nextDeleteDataCallFails.second = returnvalue::OK;
|
||||
nextFreeElementCallFails.first = false;
|
||||
nextFreeElementCallFails.second = returnvalue::OK;
|
||||
}
|
||||
|
||||
StorageManagerMock::StorageManagerMock(object_id_t setObjectId,
|
||||
const LocalPool::LocalPoolConfig &poolConfig)
|
||||
: LocalPool(setObjectId, poolConfig) {}
|
40
unittests/mocks/StorageManagerMock.h
Normal file
40
unittests/mocks/StorageManagerMock.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef FSFW_TESTS_STORAGEMANAGERMOCK_H
|
||||
#define FSFW_TESTS_STORAGEMANAGERMOCK_H
|
||||
|
||||
#include "fsfw/storagemanager/LocalPool.h"
|
||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||
|
||||
class StorageManagerMock : public LocalPool {
|
||||
public:
|
||||
StorageManagerMock(object_id_t setObjectId, const LocalPoolConfig &poolConfig);
|
||||
|
||||
ReturnValue_t addData(store_address_t *storageId, const uint8_t *data, size_t size,
|
||||
bool ignoreFault) override;
|
||||
ReturnValue_t deleteData(store_address_t packet_id) override;
|
||||
ReturnValue_t deleteData(uint8_t *buffer, size_t size, store_address_t *storeId) override;
|
||||
ReturnValue_t getData(store_address_t packet_id, const uint8_t **packet_ptr,
|
||||
size_t *size) override;
|
||||
ReturnValue_t modifyData(store_address_t packet_id, uint8_t **packet_ptr, size_t *size) override;
|
||||
ReturnValue_t getFreeElement(store_address_t *storageId, size_t size, uint8_t **p_data,
|
||||
bool ignoreFault) override;
|
||||
[[nodiscard]] bool hasDataAtId(store_address_t storeId) const override;
|
||||
void clearStore() override;
|
||||
void clearSubPool(uint8_t poolIndex) override;
|
||||
void getFillCount(uint8_t *buffer, uint8_t *bytesWritten) override;
|
||||
size_t getTotalSize(size_t *additionalSize) override;
|
||||
[[nodiscard]] max_subpools_t getNumberOfSubPools() const override;
|
||||
|
||||
std::pair<bool, ReturnValue_t> nextAddDataCallFails;
|
||||
/**
|
||||
* This can be used to make both the modify and get API call fail. This is because generally,
|
||||
* the pool implementation get functions will use the modify API internally.
|
||||
*/
|
||||
std::pair<bool, ReturnValue_t> nextModifyDataCallFails;
|
||||
std::pair<bool, ReturnValue_t> nextDeleteDataCallFails;
|
||||
std::pair<bool, ReturnValue_t> nextFreeElementCallFails;
|
||||
|
||||
using LocalPool::getFreeElement;
|
||||
|
||||
void reset();
|
||||
};
|
||||
#endif // FSFW_TESTS_STORAGEMANAGERMOCK_H
|
2
unittests/mocks/cfdp/CMakeLists.txt
Normal file
2
unittests/mocks/cfdp/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE FaultHandlerMock.cpp UserMock.cpp
|
||||
RemoteConfigTableMock.cpp)
|
42
unittests/mocks/cfdp/FaultHandlerMock.cpp
Normal file
42
unittests/mocks/cfdp/FaultHandlerMock.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "FaultHandlerMock.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
void FaultHandlerMock::noticeOfSuspensionCb(TransactionId& id, cfdp::ConditionCode code) {
|
||||
auto& info = fhInfoMap.at(cfdp::FaultHandlerCode::NOTICE_OF_SUSPENSION);
|
||||
info.callCount++;
|
||||
info.condCodes.push(code);
|
||||
}
|
||||
|
||||
void FaultHandlerMock::noticeOfCancellationCb(TransactionId& id, cfdp::ConditionCode code) {
|
||||
auto& info = fhInfoMap.at(cfdp::FaultHandlerCode::NOTICE_OF_CANCELLATION);
|
||||
info.callCount++;
|
||||
info.condCodes.push(code);
|
||||
}
|
||||
|
||||
void FaultHandlerMock::abandonCb(TransactionId& id, cfdp::ConditionCode code) {
|
||||
auto& info = fhInfoMap.at(cfdp::FaultHandlerCode::ABANDON_TRANSACTION);
|
||||
info.callCount++;
|
||||
info.condCodes.push(code);
|
||||
}
|
||||
|
||||
void FaultHandlerMock::ignoreCb(TransactionId& id, cfdp::ConditionCode code) {
|
||||
auto& info = fhInfoMap.at(cfdp::FaultHandlerCode::IGNORE_ERROR);
|
||||
info.callCount++;
|
||||
info.condCodes.push(code);
|
||||
}
|
||||
|
||||
FaultHandlerMock::FaultInfo& FaultHandlerMock::getFhInfo(cfdp::FaultHandlerCode fhCode) {
|
||||
return fhInfoMap.at(fhCode);
|
||||
}
|
||||
|
||||
void FaultHandlerMock::reset() { fhInfoMap.clear(); }
|
||||
|
||||
bool FaultHandlerMock::faultCbWasCalled() const {
|
||||
return std::any_of(fhInfoMap.begin(), fhInfoMap.end(),
|
||||
[](const std::pair<cfdp::FaultHandlerCode, FaultInfo>& pair) {
|
||||
return pair.second.callCount > 0;
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace cfdp
|
37
unittests/mocks/cfdp/FaultHandlerMock.h
Normal file
37
unittests/mocks/cfdp/FaultHandlerMock.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef FSFW_TESTS_FAULTHANDLERMOCK_H
|
||||
#define FSFW_TESTS_FAULTHANDLERMOCK_H
|
||||
|
||||
#include <map>
|
||||
#include <queue>
|
||||
|
||||
#include "fsfw/cfdp/handler/FaultHandlerBase.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
class FaultHandlerMock : public FaultHandlerBase {
|
||||
public:
|
||||
struct FaultInfo {
|
||||
size_t callCount = 0;
|
||||
std::queue<cfdp::ConditionCode> condCodes;
|
||||
};
|
||||
|
||||
void noticeOfSuspensionCb(TransactionId& id, ConditionCode code) override;
|
||||
void noticeOfCancellationCb(TransactionId& id, ConditionCode code) override;
|
||||
void abandonCb(TransactionId& id,ConditionCode code) override;
|
||||
void ignoreCb(TransactionId& id, ConditionCode code) override;
|
||||
|
||||
FaultInfo& getFhInfo(FaultHandlerCode fhCode);
|
||||
[[nodiscard]] bool faultCbWasCalled() const;
|
||||
void reset();
|
||||
|
||||
private:
|
||||
std::map<cfdp::FaultHandlerCode, FaultInfo> fhInfoMap = {
|
||||
std::pair{cfdp::FaultHandlerCode::IGNORE_ERROR, FaultInfo()},
|
||||
std::pair{cfdp::FaultHandlerCode::NOTICE_OF_CANCELLATION, FaultInfo()},
|
||||
std::pair{cfdp::FaultHandlerCode::NOTICE_OF_SUSPENSION, FaultInfo()},
|
||||
std::pair{cfdp::FaultHandlerCode::ABANDON_TRANSACTION, FaultInfo()}};
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
||||
#endif // FSFW_TESTS_FAULTHANDLERMOCK_H
|
15
unittests/mocks/cfdp/RemoteConfigTableMock.cpp
Normal file
15
unittests/mocks/cfdp/RemoteConfigTableMock.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "RemoteConfigTableMock.h"
|
||||
|
||||
void cfdp::RemoteConfigTableMock::addRemoteConfig(const cfdp::RemoteEntityCfg& cfg) {
|
||||
remoteCfgTable.emplace(cfg.remoteId, cfg);
|
||||
}
|
||||
|
||||
bool cfdp::RemoteConfigTableMock::getRemoteCfg(const cfdp::EntityId& remoteId,
|
||||
cfdp::RemoteEntityCfg** cfg) {
|
||||
auto iter = remoteCfgTable.find(remoteId);
|
||||
if (iter == remoteCfgTable.end()) {
|
||||
return false;
|
||||
}
|
||||
*cfg = &iter->second;
|
||||
return true;
|
||||
}
|
20
unittests/mocks/cfdp/RemoteConfigTableMock.h
Normal file
20
unittests/mocks/cfdp/RemoteConfigTableMock.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef FSFW_TESTS_CFDP_REMOTCONFIGTABLEMOCK_H
|
||||
#define FSFW_TESTS_CFDP_REMOTCONFIGTABLEMOCK_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "fsfw/cfdp/handler/RemoteConfigTableIF.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
class RemoteConfigTableMock : public RemoteConfigTableIF {
|
||||
public:
|
||||
void addRemoteConfig(const RemoteEntityCfg& cfg);
|
||||
bool getRemoteCfg(const cfdp::EntityId& remoteId, cfdp::RemoteEntityCfg** cfg) override;
|
||||
|
||||
std::map<EntityId, RemoteEntityCfg> remoteCfgTable;
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
||||
#endif // FSFW_TESTS_CFDP_REMOTCONFIGTABLEMOCK_H
|
35
unittests/mocks/cfdp/UserMock.cpp
Normal file
35
unittests/mocks/cfdp/UserMock.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include "UserMock.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
cfdp::UserMock::UserMock(HasFileSystemIF& vfs) : UserBase(vfs) {}
|
||||
|
||||
void UserMock::transactionIndication(const TransactionId& id) {}
|
||||
void UserMock::eofSentIndication(const TransactionId& id) {}
|
||||
void UserMock::abandonedIndication(const TransactionId& id, cfdp::ConditionCode code,
|
||||
uint64_t progress) {}
|
||||
|
||||
void UserMock::eofRecvIndication(const TransactionId& id) { eofsRevd.push(id); }
|
||||
|
||||
void UserMock::transactionFinishedIndication(const TransactionFinishedParams& finishedParams) {
|
||||
finishedRecvd.push({finishedParams.id, finishedParams});
|
||||
}
|
||||
|
||||
void UserMock::metadataRecvdIndication(const MetadataRecvdParams& params) {
|
||||
metadataRecvd.push({params.id, params});
|
||||
}
|
||||
|
||||
void UserMock::fileSegmentRecvdIndication(const FileSegmentRecvdParams& params) {}
|
||||
void UserMock::reportIndication(const TransactionId& id, StatusReportIF& report) {}
|
||||
void UserMock::suspendedIndication(const TransactionId& id, ConditionCode code) {}
|
||||
void UserMock::resumedIndication(const TransactionId& id, size_t progress) {}
|
||||
void UserMock::faultIndication(const TransactionId& id, cfdp::ConditionCode code, size_t progress) {
|
||||
}
|
||||
|
||||
void UserMock::reset() {
|
||||
std::queue<TransactionId>().swap(eofsRevd);
|
||||
std::queue<std::pair<TransactionId, cfdp::MetadataRecvdParams>>().swap(metadataRecvd);
|
||||
std::queue<std::pair<TransactionId, cfdp::TransactionFinishedParams>>().swap(finishedRecvd);
|
||||
}
|
||||
|
||||
} // namespace cfdp
|
34
unittests/mocks/cfdp/UserMock.h
Normal file
34
unittests/mocks/cfdp/UserMock.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef FSFW_TESTS_CFDP_USERMOCK_H
|
||||
#define FSFW_TESTS_CFDP_USERMOCK_H
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include "fsfw/cfdp/handler/UserBase.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
class UserMock : public UserBase {
|
||||
public:
|
||||
explicit UserMock(HasFileSystemIF& vfs);
|
||||
|
||||
void transactionIndication(const TransactionId& id) override;
|
||||
void eofSentIndication(const TransactionId& id) override;
|
||||
void abandonedIndication(const TransactionId& id, ConditionCode code, size_t progress) override;
|
||||
void eofRecvIndication(const TransactionId& id) override;
|
||||
void transactionFinishedIndication(const TransactionFinishedParams& params) override;
|
||||
void metadataRecvdIndication(const MetadataRecvdParams& params) override;
|
||||
void fileSegmentRecvdIndication(const FileSegmentRecvdParams& params) override;
|
||||
void reportIndication(const TransactionId& id, StatusReportIF& report) override;
|
||||
void suspendedIndication(const TransactionId& id, ConditionCode code) override;
|
||||
void resumedIndication(const TransactionId& id, size_t progress) override;
|
||||
void faultIndication(const TransactionId& id, ConditionCode code, size_t progress) override;
|
||||
|
||||
std::queue<std::pair<TransactionId, MetadataRecvdParams>> metadataRecvd;
|
||||
std::queue<TransactionId> eofsRevd;
|
||||
std::queue<std::pair<TransactionId, TransactionFinishedParams>> finishedRecvd;
|
||||
void reset();
|
||||
};
|
||||
|
||||
} // namespace cfdp
|
||||
|
||||
#endif // FSFW_TESTS_CFDP_USERMOCK_H
|
@ -1,5 +1,2 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
testMq.cpp
|
||||
TestSemaphore.cpp
|
||||
TestClock.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE testMq.cpp TestSemaphore.cpp
|
||||
TestClock.cpp)
|
||||
|
@ -1,3 +1 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
testPowerSwitcher.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE testPowerSwitcher.cpp)
|
||||
|
@ -1,3 +1 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
testService11.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE testService11.cpp)
|
||||
|
@ -1,6 +1,3 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
testSerialBufferAdapter.cpp
|
||||
testSerializeAdapter.cpp
|
||||
testSerialLinkedPacket.cpp
|
||||
testSerializeIF.cpp
|
||||
)
|
||||
target_sources(
|
||||
${FSFW_TEST_TGT} PRIVATE testSerialBufferAdapter.cpp testSerializeAdapter.cpp
|
||||
testSerialLinkedPacket.cpp testSerializeIF.cpp)
|
||||
|
@ -1,4 +1 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
testAccessor.cpp
|
||||
testPool.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE testAccessor.cpp testPool.cpp)
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
TEST_CASE("Pool Accessor", "[pool-accessor]") {
|
||||
LocalPool::LocalPoolConfig poolCfg = {{1, 10}};
|
||||
LocalPool SimplePool = LocalPool(0, poolCfg);
|
||||
LocalPool simplePool = LocalPool(0, poolCfg);
|
||||
std::array<uint8_t, 20> testDataArray{};
|
||||
std::array<uint8_t, 20> receptionArray{};
|
||||
store_address_t testStoreId;
|
||||
@ -20,9 +20,9 @@ TEST_CASE("Pool Accessor", "[pool-accessor]") {
|
||||
size_t size = 10;
|
||||
|
||||
SECTION("Simple tests getter functions") {
|
||||
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
auto resultPair = SimplePool.getData(testStoreId);
|
||||
auto resultPair = simplePool.getData(testStoreId);
|
||||
REQUIRE(resultPair.first == returnvalue::OK);
|
||||
resultPair.second.getDataCopy(receptionArray.data(), 20);
|
||||
CHECK(resultPair.second.getId() == testStoreId);
|
||||
@ -38,18 +38,18 @@ TEST_CASE("Pool Accessor", "[pool-accessor]") {
|
||||
}
|
||||
|
||||
{
|
||||
auto resultPairLoc = SimplePool.getData(testStoreId);
|
||||
auto resultPairLoc = simplePool.getData(testStoreId);
|
||||
REQUIRE(resultPairLoc.first == returnvalue::OK);
|
||||
// data should be deleted when accessor goes out of scope.
|
||||
}
|
||||
resultPair = SimplePool.getData(testStoreId);
|
||||
resultPair = simplePool.getData(testStoreId);
|
||||
REQUIRE(resultPair.first == (int)StorageManagerIF::DATA_DOES_NOT_EXIST);
|
||||
|
||||
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
{
|
||||
ConstStorageAccessor constAccessor(testStoreId);
|
||||
result = SimplePool.getData(testStoreId, constAccessor);
|
||||
result = simplePool.getData(testStoreId, constAccessor);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
constAccessor.getDataCopy(receptionArray.data(), 20);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
@ -57,17 +57,17 @@ TEST_CASE("Pool Accessor", "[pool-accessor]") {
|
||||
}
|
||||
// likewise, data should be deleted when accessor gets out of scope.
|
||||
}
|
||||
resultPair = SimplePool.getData(testStoreId);
|
||||
resultPair = simplePool.getData(testStoreId);
|
||||
REQUIRE(resultPair.first == (int)StorageManagerIF::DATA_DOES_NOT_EXIST);
|
||||
|
||||
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
{
|
||||
resultPair = SimplePool.getData(testStoreId);
|
||||
resultPair = simplePool.getData(testStoreId);
|
||||
REQUIRE(resultPair.first == returnvalue::OK);
|
||||
resultPair.second.release();
|
||||
// now data should not be deleted anymore
|
||||
}
|
||||
resultPair = SimplePool.getData(testStoreId);
|
||||
resultPair = simplePool.getData(testStoreId);
|
||||
REQUIRE(resultPair.first == returnvalue::OK);
|
||||
resultPair.second.getDataCopy(receptionArray.data(), 20);
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
@ -76,11 +76,11 @@ TEST_CASE("Pool Accessor", "[pool-accessor]") {
|
||||
}
|
||||
|
||||
SECTION("Simple tests modify functions") {
|
||||
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
{
|
||||
StorageAccessor accessor(testStoreId);
|
||||
result = SimplePool.modifyData(testStoreId, accessor);
|
||||
result = simplePool.modifyData(testStoreId, accessor);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
CHECK(accessor.getId() == testStoreId);
|
||||
CHECK(accessor.size() == 10);
|
||||
@ -94,13 +94,13 @@ TEST_CASE("Pool Accessor", "[pool-accessor]") {
|
||||
}
|
||||
// data should be deleted when accessor goes out of scope
|
||||
}
|
||||
auto resultPair = SimplePool.getData(testStoreId);
|
||||
auto resultPair = simplePool.getData(testStoreId);
|
||||
REQUIRE(resultPair.first == (int)StorageManagerIF::DATA_DOES_NOT_EXIST);
|
||||
|
||||
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
{
|
||||
auto resultPairLoc = SimplePool.modifyData(testStoreId);
|
||||
auto resultPairLoc = simplePool.modifyData(testStoreId);
|
||||
REQUIRE(resultPairLoc.first == returnvalue::OK);
|
||||
CHECK(resultPairLoc.second.getId() == testStoreId);
|
||||
CHECK(resultPairLoc.second.size() == 10);
|
||||
@ -116,22 +116,22 @@ TEST_CASE("Pool Accessor", "[pool-accessor]") {
|
||||
resultPairLoc.second.release();
|
||||
// data should not be deleted when accessor goes out of scope
|
||||
}
|
||||
resultPair = SimplePool.getData(testStoreId);
|
||||
resultPair = simplePool.getData(testStoreId);
|
||||
REQUIRE(resultPair.first == returnvalue::OK);
|
||||
}
|
||||
|
||||
SECTION("Write tests") {
|
||||
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
{
|
||||
auto resultPair = SimplePool.modifyData(testStoreId);
|
||||
auto resultPair = simplePool.modifyData(testStoreId);
|
||||
REQUIRE(resultPair.first == returnvalue::OK);
|
||||
testDataArray[9] = 42;
|
||||
resultPair.second.write(testDataArray.data(), 10, 0);
|
||||
// now data should not be deleted
|
||||
resultPair.second.release();
|
||||
}
|
||||
auto resultConstPair = SimplePool.getData(testStoreId);
|
||||
auto resultConstPair = simplePool.getData(testStoreId);
|
||||
REQUIRE(resultConstPair.first == returnvalue::OK);
|
||||
|
||||
resultConstPair.second.getDataCopy(receptionArray.data(), 10);
|
||||
@ -140,7 +140,7 @@ TEST_CASE("Pool Accessor", "[pool-accessor]") {
|
||||
}
|
||||
CHECK(receptionArray[9] == 42);
|
||||
|
||||
auto resultPair = SimplePool.modifyData(testStoreId);
|
||||
auto resultPair = simplePool.modifyData(testStoreId);
|
||||
REQUIRE(resultPair.first == returnvalue::OK);
|
||||
result = resultPair.second.write(testDataArray.data(), 20, 0);
|
||||
REQUIRE(result == returnvalue::FAILED);
|
||||
@ -150,7 +150,7 @@ TEST_CASE("Pool Accessor", "[pool-accessor]") {
|
||||
std::memset(testDataArray.data(), 42, 5);
|
||||
result = resultPair.second.write(testDataArray.data(), 5, 5);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
resultConstPair = SimplePool.getData(testStoreId);
|
||||
resultConstPair = simplePool.getData(testStoreId);
|
||||
resultPair.second.getDataCopy(receptionArray.data(), 20);
|
||||
for (size_t i = 5; i < 10; i++) {
|
||||
CHECK(receptionArray[i] == 42);
|
||||
@ -158,7 +158,7 @@ TEST_CASE("Pool Accessor", "[pool-accessor]") {
|
||||
}
|
||||
|
||||
SECTION("Operators") {
|
||||
result = SimplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
result = simplePool.addData(&testStoreId, testDataArray.data(), size);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
{
|
||||
StorageAccessor accessor(testStoreId);
|
||||
@ -169,7 +169,7 @@ TEST_CASE("Pool Accessor", "[pool-accessor]") {
|
||||
size_t size = 6;
|
||||
result = accessor.write(data.data(), data.size());
|
||||
REQUIRE(result == returnvalue::FAILED);
|
||||
result = SimplePool.modifyData(testStoreId, accessor2);
|
||||
result = simplePool.modifyData(testStoreId, accessor2);
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
CHECK(accessor2.getId() == testStoreId);
|
||||
CHECK(accessor2.size() == 10);
|
||||
|
1
unittests/tcdistributor/CMakeLists.txt
Normal file
1
unittests/tcdistributor/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE testCcsdsDistributor.cpp)
|
169
unittests/tcdistributor/testCcsdsDistributor.cpp
Normal file
169
unittests/tcdistributor/testCcsdsDistributor.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
#include <array>
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "fsfw/storagemanager/LocalPool.h"
|
||||
#include "fsfw/tcdistribution/CcsdsDistributor.h"
|
||||
#include "fsfw/tmtcpacket/ccsds/SpacePacketCreator.h"
|
||||
#include "mocks/AcceptsTcMock.h"
|
||||
#include "mocks/CcsdsCheckerMock.h"
|
||||
#include "mocks/MessageQueueMock.h"
|
||||
|
||||
TEST_CASE("CCSDS Distributor", "[ccsds][tmtcdistrib]") {
|
||||
LocalPool::LocalPoolConfig cfg = {{5, 32}, {2, 64}};
|
||||
LocalPool pool(objects::NO_OBJECT, cfg);
|
||||
auto queue = MessageQueueMock(1);
|
||||
auto checkerMock = CcsdsCheckerMock();
|
||||
uint16_t unregisteredApid = 0;
|
||||
uint16_t defaultApid = 4;
|
||||
MessageQueueId_t defaultQueueId = 5;
|
||||
auto ccsdsDistrib = CcsdsDistributor(defaultApid, 1, &pool, &queue, &checkerMock);
|
||||
uint32_t tcAcceptorApid = 1;
|
||||
MessageQueueId_t tcAcceptorQueueId = 3;
|
||||
|
||||
auto tcAcceptorMock = AcceptsTcMock("TC Receiver Dummy", tcAcceptorApid, tcAcceptorQueueId);
|
||||
auto defReceiverMock = AcceptsTcMock("Default Receiver Dummy", defaultApid, defaultQueueId);
|
||||
auto packetId = PacketId(ccsds::PacketType::TC, true, 0);
|
||||
auto psc = PacketSeqCtrl(ccsds::SequenceFlags::FIRST_SEGMENT, 0x34);
|
||||
auto spParams = SpacePacketParams(packetId, psc, 0x16);
|
||||
SpacePacketCreator spCreator(spParams);
|
||||
std::array<uint8_t, 32> buf{};
|
||||
|
||||
auto createSpacePacket = [&](uint16_t apid, TmTcMessage& msg, uint8_t* dataField = nullptr,
|
||||
size_t dataFieldLen = 1) {
|
||||
store_address_t storeId{};
|
||||
spCreator.setApid(tcAcceptorApid);
|
||||
spCreator.setCcsdsLenFromTotalDataFieldLen(dataFieldLen);
|
||||
uint8_t* dataPtr;
|
||||
REQUIRE(pool.getFreeElement(&storeId, spCreator.getSerializedSize() + dataFieldLen, &dataPtr) ==
|
||||
returnvalue::OK);
|
||||
size_t serLen = 0;
|
||||
REQUIRE(spCreator.SerializeIF::serializeBe(dataPtr, serLen, ccsds::HEADER_LEN) ==
|
||||
returnvalue::OK);
|
||||
REQUIRE(spCreator.SerializeIF::serializeBe(buf.data(), serLen, ccsds::HEADER_LEN) ==
|
||||
returnvalue::OK);
|
||||
if (dataField == nullptr) {
|
||||
dataPtr[ccsds::HEADER_LEN] = 0;
|
||||
buf[ccsds::HEADER_LEN] = 0;
|
||||
} else {
|
||||
std::memcpy(dataPtr + ccsds::HEADER_LEN, dataField, dataFieldLen);
|
||||
std::memcpy(buf.data() + ccsds::HEADER_LEN, dataField, dataFieldLen);
|
||||
}
|
||||
msg.setStorageId(storeId);
|
||||
};
|
||||
|
||||
SECTION("State") {
|
||||
CHECK(ccsdsDistrib.initialize() == returnvalue::OK);
|
||||
CHECK(ccsdsDistrib.getRequestQueue() == 1);
|
||||
CHECK(ccsdsDistrib.getIdentifier() == 0);
|
||||
CHECK(ccsdsDistrib.getObjectId() == 1);
|
||||
REQUIRE(ccsdsDistrib.getName() != nullptr);
|
||||
CHECK(std::strcmp(ccsdsDistrib.getName(), "CCSDS Distributor") == 0);
|
||||
}
|
||||
|
||||
SECTION("Basic Forwarding") {
|
||||
CcsdsDistributor::DestInfo info(tcAcceptorMock, false);
|
||||
REQUIRE(ccsdsDistrib.registerApplication(info) == returnvalue::OK);
|
||||
TmTcMessage message;
|
||||
createSpacePacket(tcAcceptorApid, message);
|
||||
store_address_t storeId = message.getStorageId();
|
||||
queue.addReceivedMessage(message);
|
||||
REQUIRE(ccsdsDistrib.performOperation(0) == returnvalue::OK);
|
||||
CHECK(checkerMock.checkedPacketLen == 7);
|
||||
CHECK(checkerMock.checkCallCount == 1);
|
||||
CHECK(queue.wasMessageSent());
|
||||
CHECK(queue.numberOfSentMessages() == 1);
|
||||
// The packet is forwarded, with no need to delete the data
|
||||
CHECK(pool.hasDataAtId(storeId));
|
||||
TmTcMessage sentMsg;
|
||||
CHECK(queue.getNextSentMessage(tcAcceptorQueueId, sentMsg) == returnvalue::OK);
|
||||
CHECK(sentMsg.getStorageId() == storeId);
|
||||
auto accessor = pool.getData(storeId);
|
||||
CHECK(accessor.first == returnvalue::OK);
|
||||
CHECK(accessor.second.size() == ccsds::HEADER_LEN + 1);
|
||||
for (size_t i = 0; i < ccsds::HEADER_LEN; i++) {
|
||||
CHECK(accessor.second.data()[i] == buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Forwarding to Default Destination, but not registered") {
|
||||
TmTcMessage message;
|
||||
createSpacePacket(unregisteredApid, message);
|
||||
store_address_t storeId = message.getStorageId();
|
||||
message.setStorageId(storeId);
|
||||
queue.addReceivedMessage(message);
|
||||
REQUIRE(ccsdsDistrib.performOperation(0) == TcDistributorBase::DESTINATION_NOT_FOUND);
|
||||
}
|
||||
|
||||
SECTION("Forward to Default Handler") {
|
||||
CcsdsDistributor::DestInfo info(defReceiverMock, false);
|
||||
ccsdsDistrib.registerApplication(info);
|
||||
TmTcMessage message;
|
||||
createSpacePacket(defaultApid, message);
|
||||
store_address_t storeId = message.getStorageId();
|
||||
message.setStorageId(storeId);
|
||||
queue.addReceivedMessage(message);
|
||||
REQUIRE(ccsdsDistrib.performOperation(0) == returnvalue::OK);
|
||||
CHECK(checkerMock.checkedPacketLen == 7);
|
||||
CHECK(checkerMock.checkCallCount == 1);
|
||||
CHECK(queue.wasMessageSent());
|
||||
CHECK(queue.numberOfSentMessages() == 1);
|
||||
// The packet is forwarded, with no need to delete the data
|
||||
CHECK(pool.hasDataAtId(storeId));
|
||||
TmTcMessage sentMsg;
|
||||
CHECK(queue.getNextSentMessage(defaultQueueId, sentMsg) == returnvalue::OK);
|
||||
CHECK(sentMsg.getStorageId() == storeId);
|
||||
auto accessor = pool.getData(storeId);
|
||||
CHECK(accessor.first == returnvalue::OK);
|
||||
CHECK(accessor.second.size() == ccsds::HEADER_LEN + 1);
|
||||
for (size_t i = 0; i < ccsds::HEADER_LEN; i++) {
|
||||
CHECK(accessor.second.data()[i] == buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Remove CCSDS header") {
|
||||
uint16_t tgtApid = 0;
|
||||
MessageQueueId_t tgtQueueId = MessageQueueIF::NO_QUEUE;
|
||||
SECTION("Default destination") {
|
||||
CcsdsDistributor::DestInfo info(defReceiverMock, true);
|
||||
tgtApid = defaultApid;
|
||||
tgtQueueId = defaultQueueId;
|
||||
REQUIRE(ccsdsDistrib.registerApplication(info) == returnvalue::OK);
|
||||
}
|
||||
SECTION("Specific destination") {
|
||||
CcsdsDistributor::DestInfo info(tcAcceptorMock, true);
|
||||
tgtApid = tcAcceptorApid;
|
||||
tgtQueueId = tcAcceptorQueueId;
|
||||
REQUIRE(ccsdsDistrib.registerApplication(info) == returnvalue::OK);
|
||||
}
|
||||
TmTcMessage message;
|
||||
std::array<uint8_t, 5> dataField = {0, 1, 2, 3, 4};
|
||||
createSpacePacket(tgtApid, message, dataField.data(), 5);
|
||||
store_address_t storeId = message.getStorageId();
|
||||
message.setStorageId(storeId);
|
||||
queue.addReceivedMessage(message);
|
||||
REQUIRE(ccsdsDistrib.performOperation(0) == returnvalue::OK);
|
||||
CHECK(checkerMock.checkedPacketLen == 11);
|
||||
CHECK(checkerMock.checkCallCount == 1);
|
||||
// Data was deleted from old slot to re-store without the header
|
||||
CHECK(not pool.hasDataAtId(storeId));
|
||||
TmTcMessage sentMsg;
|
||||
CHECK(queue.getNextSentMessage(tgtQueueId, sentMsg) == returnvalue::OK);
|
||||
CHECK(sentMsg.getStorageId() != storeId);
|
||||
auto accessor = pool.getData(sentMsg.getStorageId());
|
||||
CHECK(accessor.first == returnvalue::OK);
|
||||
CHECK(accessor.second.size() == 5);
|
||||
// Verify correctness of data field
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
CHECK(accessor.second.data()[i] == i);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Invalid Space Packet, Too Short") {
|
||||
store_address_t storeId{};
|
||||
std::array<uint8_t, 4> data = {1, 2, 3, 4};
|
||||
pool.addData(&storeId, data.data(), data.size());
|
||||
TmTcMessage message(storeId);
|
||||
queue.addReceivedMessage(message);
|
||||
REQUIRE(ccsdsDistrib.performOperation(0) == SerializeIF::STREAM_TOO_SHORT);
|
||||
}
|
||||
}
|
@ -1,23 +1,16 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
ipc/MissionMessageTypes.cpp
|
||||
pollingsequence/PollingSequenceFactory.cpp
|
||||
)
|
||||
target_sources(
|
||||
${FSFW_TEST_TGT} PRIVATE ipc/MissionMessageTypes.cpp
|
||||
pollingsequence/PollingSequenceFactory.cpp)
|
||||
|
||||
# Add include paths for the executable
|
||||
target_include_directories(${FSFW_TEST_TGT} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
target_include_directories(${FSFW_TEST_TGT} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
# If a special translation file for object IDs exists, compile it.
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp")
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
objects/translateObjects.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE objects/translateObjects.cpp)
|
||||
endif()
|
||||
|
||||
# If a special translation file for events exists, compile it.
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/objects/translateObjects.cpp")
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
events/translateEvents.cpp
|
||||
)
|
||||
endif()
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE events/translateEvents.cpp)
|
||||
endif()
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
#include <fsfw/tasks/FixedTimeslotTaskIF.h>
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "tests/TestsConfig.h"
|
||||
|
||||
ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) {
|
||||
@ -20,7 +21,7 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence)
|
||||
if (thisSequence->checkSequence() == returnvalue::OK) {
|
||||
return returnvalue::OK;
|
||||
} else {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "pst::pollingSequenceInitDefault: Sequence invalid!" << std::endl;
|
||||
#else
|
||||
sif::printError("pst::pollingSequenceInitDefault: Sequence invalid!");
|
||||
|
@ -1,4 +1 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
TestCountdown.cpp
|
||||
TestCCSDSTime.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE TestCountdown.cpp TestCCSDSTime.cpp)
|
||||
|
@ -1,10 +1,10 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
testCcsdsCreator.cpp
|
||||
testCcsdsReader.cpp
|
||||
testPusTcCreator.cpp
|
||||
testPusTcReader.cpp
|
||||
testPusTmCreator.cpp
|
||||
testPusTmReader.cpp
|
||||
testCcsds.cpp
|
||||
testZcTmWriter.cpp
|
||||
)
|
||||
target_sources(
|
||||
${FSFW_TEST_TGT}
|
||||
PRIVATE testCcsdsCreator.cpp
|
||||
testCcsdsReader.cpp
|
||||
testPusTcCreator.cpp
|
||||
testPusTcReader.cpp
|
||||
testPusTmCreator.cpp
|
||||
testPusTmReader.cpp
|
||||
testCcsds.cpp
|
||||
testZcTmWriter.cpp)
|
||||
|
@ -39,7 +39,8 @@ TEST_CASE("CCSDS Creator", "[ccsds-creator]") {
|
||||
SECTION("Deserialization Fails") {
|
||||
serLen = 6;
|
||||
const uint8_t* readOnlyPtr = buf.data();
|
||||
REQUIRE(base.deSerialize(&readOnlyPtr, &serLen, SerializeIF::Endianness::BIG) ==
|
||||
auto& ser = dynamic_cast<SerializeIF&>(base);
|
||||
REQUIRE(ser.deSerialize(&readOnlyPtr, &serLen, SerializeIF::Endianness::BIG) ==
|
||||
returnvalue::FAILED);
|
||||
}
|
||||
|
||||
@ -64,7 +65,7 @@ TEST_CASE("CCSDS Creator", "[ccsds-creator]") {
|
||||
base.setApid(static_cast<int>(std::pow(2, 11)) - 1);
|
||||
base.setSeqCount(static_cast<int>(std::pow(2, 14)) - 1);
|
||||
base.setSeqFlags(ccsds::SequenceFlags::UNSEGMENTED);
|
||||
base.setDataLen(static_cast<int>(std::pow(2, 16)) - 1);
|
||||
base.setDataLenField(static_cast<int>(std::pow(2, 16)) - 1);
|
||||
REQUIRE(base.isValid());
|
||||
REQUIRE(base.serializeBe(&bufPtr, &serLen, buf.size()) == returnvalue::OK);
|
||||
CHECK(buf[0] == 0x1F);
|
||||
@ -75,6 +76,15 @@ TEST_CASE("CCSDS Creator", "[ccsds-creator]") {
|
||||
CHECK(buf[5] == 0xFF);
|
||||
}
|
||||
|
||||
SECTION("Setting data length 0 is ignored") {
|
||||
SpacePacketCreator creator = SpacePacketCreator(
|
||||
ccsds::PacketType::TC, true, 0xFFFF, ccsds::SequenceFlags::FIRST_SEGMENT, 0x34, 0x22);
|
||||
creator.setCcsdsLenFromTotalDataFieldLen(0);
|
||||
REQUIRE(creator.getPacketDataLen() == 0x22);
|
||||
creator.setCcsdsLenFromTotalDataFieldLen(1);
|
||||
REQUIRE(creator.getPacketDataLen() == 0x00);
|
||||
}
|
||||
|
||||
SECTION("Invalid APID") {
|
||||
SpacePacketCreator creator = SpacePacketCreator(
|
||||
ccsds::PacketType::TC, true, 0xFFFF, ccsds::SequenceFlags::FIRST_SEGMENT, 0x34, 0x16);
|
||||
|
@ -64,7 +64,7 @@ TEST_CASE("CCSDS Reader", "[ccsds-reader]") {
|
||||
SECTION("Invalid Size") {
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
REQUIRE(reader.setReadOnlyData(buf.data(), i) == SerializeIF::STREAM_TOO_SHORT);
|
||||
REQUIRE(not reader.isNull());
|
||||
REQUIRE(reader.isNull());
|
||||
REQUIRE(reader.getPacketData() == nullptr);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,2 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
testStoreHelper.cpp
|
||||
testSendHelper.cpp
|
||||
testStoreAndSendHelper.cpp
|
||||
testPsb.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE testStoreHelper.cpp testSendHelper.cpp
|
||||
testStoreAndSendHelper.cpp testPsb.cpp)
|
||||
|
@ -194,7 +194,7 @@ TEST_CASE("Pus Service Base", "[pus-service-base]") {
|
||||
REQUIRE(PsbMock::getStaticPusDistributor() == distributorId);
|
||||
REQUIRE(psb2.initialize() == returnvalue::OK);
|
||||
REQUIRE(pusDistrib.registerCallCount == 1);
|
||||
REQUIRE(pusDistrib.lastServiceArg == &psb2);
|
||||
REQUIRE(pusDistrib.registeredServies.front() == &psb2);
|
||||
}
|
||||
|
||||
SECTION("Auto Initialize Packet Destination") {
|
||||
|
@ -1,4 +1 @@
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE
|
||||
testUnsignedByteField.cpp
|
||||
testDataWrapper.cpp
|
||||
)
|
||||
target_sources(${FSFW_TEST_TGT} PRIVATE testUnsignedByteField.cpp)
|
||||
|
Reference in New Issue
Block a user