From 6d0fa36f8acf75bcc93e16bf275f270b5ec5fb76 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 25 Jul 2022 19:36:56 +0200 Subject: [PATCH] cleaning up message queue mock and subscription API --- src/fsfw/datapoollocal/HasLocalDataPoolIF.h | 3 +- .../datapoollocal/LocalDataPoolManager.cpp | 77 ++-- src/fsfw/datapoollocal/LocalDataPoolManager.h | 45 +- .../ProvidesDataPoolSubscriptionIF.h | 69 ++- src/fsfw/housekeeping/AcceptsHkPacketsIF.h | 6 +- .../internalerror/InternalErrorReporter.cpp | 5 +- src/fsfw/ipc/MessageQueueBase.h | 8 +- src/fsfw/ipc/MessageQueueMessage.cpp | 36 +- src/fsfw/ipc/MessageQueueMessage.h | 113 ++--- src/fsfw/ipc/MessageQueueMessageIF.h | 32 +- src/fsfw/osal/linux/Clock.cpp | 2 +- src/fsfw/serialize/SerializeIF.h | 4 +- src/fsfw/timemanager/CCSDSTime.h | 2 +- src/fsfw/timemanager/TimeMessage.h | 2 +- src/fsfw/tmtcpacket/pus/tc/PusTcCreator.cpp | 2 +- src/fsfw/tmtcpacket/pus/tc/PusTcCreator.h | 2 +- src/fsfw/tmtcservices/TmSendHelper.cpp | 7 +- src/fsfw/tmtcservices/TmSendHelper.h | 4 +- src/fsfw/tmtcservices/TmStoreHelper.cpp | 7 +- src/fsfw/tmtcservices/TmStoreHelper.h | 1 - unittests/CatchFactory.cpp | 9 +- unittests/action/TestActionHelper.cpp | 12 +- unittests/datapoollocal/CMakeLists.txt | 8 +- .../datapoollocal/LocalPoolManagerTest.cpp | 413 ----------------- .../{DataSetTest.cpp => testDataSet.cpp} | 25 +- .../datapoollocal/testLocalPoolManager.cpp | 430 ++++++++++++++++++ ...ableTest.cpp => testLocalPoolVariable.cpp} | 0 ...VectorTest.cpp => testLocalPoolVector.cpp} | 4 +- unittests/mocks/CdsShortTimestamperMock.h | 4 +- unittests/mocks/HkReceiverMock.h | 10 +- unittests/mocks/InternalErrorReporterMock.cpp | 12 +- unittests/mocks/InternalErrorReporterMock.h | 2 +- .../LocalPoolOwnerBase.cpp | 17 +- .../LocalPoolOwnerBase.h | 64 ++- unittests/mocks/MessageQueueMockBase.cpp | 151 ++++-- unittests/mocks/MessageQueueMockBase.h | 41 +- unittests/serialize/testSerializeIF.cpp | 6 +- unittests/testcfg/objects/systemObjectList.h | 2 +- unittests/tmtcservices/testSendHelper.cpp | 4 +- 39 files changed, 916 insertions(+), 725 deletions(-) delete mode 100644 unittests/datapoollocal/LocalPoolManagerTest.cpp rename unittests/datapoollocal/{DataSetTest.cpp => testDataSet.cpp} (93%) create mode 100644 unittests/datapoollocal/testLocalPoolManager.cpp rename unittests/datapoollocal/{LocalPoolVariableTest.cpp => testLocalPoolVariable.cpp} (100%) rename unittests/datapoollocal/{LocalPoolVectorTest.cpp => testLocalPoolVector.cpp} (98%) rename unittests/{datapoollocal => mocks}/LocalPoolOwnerBase.cpp (90%) rename unittests/{datapoollocal => mocks}/LocalPoolOwnerBase.h (68%) diff --git a/src/fsfw/datapoollocal/HasLocalDataPoolIF.h b/src/fsfw/datapoollocal/HasLocalDataPoolIF.h index acbe16976..b7a6198eb 100644 --- a/src/fsfw/datapoollocal/HasLocalDataPoolIF.h +++ b/src/fsfw/datapoollocal/HasLocalDataPoolIF.h @@ -79,8 +79,7 @@ class HasLocalDataPoolIF { * @param clearMessage If this is set to true, the pool manager will take care of * clearing the store automatically */ - virtual void handleChangedDataset(sid_t sid, - store_address_t storeId = store_address_t::invalid(), + virtual void handleChangedDataset(sid_t sid, store_address_t storeId = store_address_t::invalid(), bool* clearMessage = nullptr) { if (clearMessage != nullptr) { *clearMessage = true; diff --git a/src/fsfw/datapoollocal/LocalDataPoolManager.cpp b/src/fsfw/datapoollocal/LocalDataPoolManager.cpp index 9b7f800f1..2ab737bfd 100644 --- a/src/fsfw/datapoollocal/LocalDataPoolManager.cpp +++ b/src/fsfw/datapoollocal/LocalDataPoolManager.cpp @@ -1,6 +1,5 @@ #include "fsfw/datapoollocal/LocalDataPoolManager.h" -#include #include #include "fsfw/datapoollocal.h" @@ -15,6 +14,7 @@ #include "internal/HasLocalDpIFManagerAttorney.h" #include "internal/LocalPoolDataSetAttorney.h" +// TODO: Get rid of this. This should be a constructor argument, not something hardcoded in any way object_id_t LocalDataPoolManager::defaultHkDestination = objects::PUS_SERVICE_3_HOUSEKEEPING; LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse, @@ -57,7 +57,7 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) { } if (defaultHkDestination != objects::NO_OBJECT) { - AcceptsHkPacketsIF* hkPacketReceiver = + auto* hkPacketReceiver = ObjectManager::instance()->get(defaultHkDestination); if (hkPacketReceiver != nullptr) { hkDestinationId = hkPacketReceiver->getHkQueue(); @@ -335,29 +335,32 @@ void LocalDataPoolManager::resetHkUpdateResetHelper() { } } -ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, bool enableReporting, - float collectionInterval, - bool isDiagnostics, - object_id_t packetDestination) { - AcceptsHkPacketsIF* hkReceiverObject = - ObjectManager::instance()->get(packetDestination); - if (hkReceiverObject == nullptr) { - printWarningOrError(sif::OutputTypes::OUT_WARNING, "subscribeForPeriodicPacket", - QUEUE_OR_DESTINATION_INVALID); - return QUEUE_OR_DESTINATION_INVALID; - } +ReturnValue_t LocalDataPoolManager::subscribeForRegularPeriodicPacket( + subdp::RegularHkPeriodicParams params) { + return subscribeForPeriodicPacket(params); +} +ReturnValue_t LocalDataPoolManager::subscribeForDiagPeriodicPacket( + subdp::DiagnosticsHkPeriodicParams params) { + return subscribeForPeriodicPacket(params); +} + +ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(subdp::ParamsBase& params) { struct HkReceiver hkReceiver; - hkReceiver.dataId.sid = sid; + hkReceiver.dataId.sid = params.sid; hkReceiver.reportingType = ReportingType::PERIODIC; hkReceiver.dataType = DataType::DATA_SET; - hkReceiver.destinationQueue = hkReceiverObject->getHkQueue(); + if (params.receiver == MessageQueueIF::NO_QUEUE) { + hkReceiver.destinationQueue = hkDestinationId; + } else { + hkReceiver.destinationQueue = params.receiver; + } - LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); + LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid); if (dataSet != nullptr) { - LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enableReporting); - LocalPoolDataSetAttorney::setDiagnostic(*dataSet, isDiagnostics); - LocalPoolDataSetAttorney::initializePeriodicHelper(*dataSet, collectionInterval, + LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, params.enableReporting); + LocalPoolDataSetAttorney::setDiagnostic(*dataSet, params.isDiagnostics()); + LocalPoolDataSetAttorney::initializePeriodicHelper(*dataSet, params.collectionInterval, owner->getPeriodicOperationFrequency()); } @@ -365,27 +368,30 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, bool e return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t LocalDataPoolManager::subscribeForUpdatePacket(sid_t sid, bool isDiagnostics, - bool reportingEnabled, - object_id_t packetDestination) { - AcceptsHkPacketsIF* hkReceiverObject = - ObjectManager::instance()->get(packetDestination); - if (hkReceiverObject == nullptr) { - printWarningOrError(sif::OutputTypes::OUT_WARNING, "subscribeForPeriodicPacket", - QUEUE_OR_DESTINATION_INVALID); - return QUEUE_OR_DESTINATION_INVALID; - } +ReturnValue_t LocalDataPoolManager::subscribeForRegularUpdatePacket( + subdp::RegularHkUpdateParams params) { + return subscribeForUpdatePacket(params); +} +ReturnValue_t LocalDataPoolManager::subscribeForDiagUpdatePacket( + subdp::DiagnosticsHkUpdateParams params) { + return subscribeForUpdatePacket(params); +} +ReturnValue_t LocalDataPoolManager::subscribeForUpdatePacket(subdp::ParamsBase& params) { struct HkReceiver hkReceiver; - hkReceiver.dataId.sid = sid; + hkReceiver.dataId.sid = params.sid; hkReceiver.reportingType = ReportingType::UPDATE_HK; hkReceiver.dataType = DataType::DATA_SET; - hkReceiver.destinationQueue = hkReceiverObject->getHkQueue(); + if (params.receiver == MessageQueueIF::NO_QUEUE) { + hkReceiver.destinationQueue = hkDestinationId; + } else { + hkReceiver.destinationQueue = params.receiver; + } - LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); + LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid); if (dataSet != nullptr) { LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, true); - LocalPoolDataSetAttorney::setDiagnostic(*dataSet, isDiagnostics); + LocalPoolDataSetAttorney::setDiagnostic(*dataSet, params.isDiagnostics()); } hkReceivers.push_back(hkReceiver); @@ -639,6 +645,7 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid, /* Error, all destinations invalid */ printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateHousekeepingPacket", QUEUE_OR_DESTINATION_INVALID); + return QUEUE_OR_DESTINATION_INVALID; } destination = hkDestinationId; } @@ -879,3 +886,7 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType, } LocalDataPoolManager* LocalDataPoolManager::getPoolManagerHandle() { return this; } + +void LocalDataPoolManager::setHkDestinationId(MessageQueueId_t hkDestId) { + hkDestinationId = hkDestId; +} diff --git a/src/fsfw/datapoollocal/LocalDataPoolManager.h b/src/fsfw/datapoollocal/LocalDataPoolManager.h index e7ec0b6fa..041a4b059 100644 --- a/src/fsfw/datapoollocal/LocalDataPoolManager.h +++ b/src/fsfw/datapoollocal/LocalDataPoolManager.h @@ -8,6 +8,7 @@ #include "ProvidesDataPoolSubscriptionIF.h" #include "fsfw/datapool/DataSetIF.h" #include "fsfw/datapool/PoolEntry.h" +#include "fsfw/housekeeping/AcceptsHkPacketsIF.h" #include "fsfw/housekeeping/HousekeepingMessage.h" #include "fsfw/housekeeping/HousekeepingPacketDownlink.h" #include "fsfw/housekeeping/PeriodicHousekeepingHelper.h" @@ -80,7 +81,9 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces */ LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse, bool appendValidityBuffer = true); - virtual ~LocalDataPoolManager(); + ~LocalDataPoolManager() override; + + void setHkDestinationId(MessageQueueId_t hkDestId); /** * Assigns the queue to use. Make sure to call this in the #initialize @@ -112,31 +115,6 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces */ virtual ReturnValue_t performHkOperation(); - /** - * @brief Subscribe for the generation of periodic packets. - * @details - * This subscription mechanism will generally be used by the data creator - * to generate housekeeping packets which are downlinked directly. - * @return - */ - ReturnValue_t subscribeForPeriodicPacket( - sid_t sid, bool enableReporting, float collectionInterval, bool isDiagnostics, - object_id_t packetDestination = defaultHkDestination) override; - - /** - * @brief Subscribe for the generation of packets if the dataset - * is marked as changed. - * @details - * This subscription mechanism will generally be used by the data creator. - * @param sid - * @param isDiagnostics - * @param packetDestination - * @return - */ - ReturnValue_t subscribeForUpdatePacket( - sid_t sid, bool reportingEnabled, bool isDiagnostics, - object_id_t packetDestination = defaultHkDestination) override; - /** * @brief Subscribe for a notification message which will be sent * if a dataset has changed. @@ -151,7 +129,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces * Otherwise, only an notification message is sent. * @return */ - ReturnValue_t subscribeForSetUpdateMessage(const uint32_t setId, object_id_t destinationObject, + ReturnValue_t subscribeForSetUpdateMessage(uint32_t setId, object_id_t destinationObject, MessageQueueId_t targetQueueId, bool generateSnapshot) override; @@ -169,7 +147,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces * Otherwise, only an notification message is sent. * @return */ - ReturnValue_t subscribeForVariableUpdateMessage(const lp_id_t localPoolId, + ReturnValue_t subscribeForVariableUpdateMessage(lp_id_t localPoolId, object_id_t destinationObject, MessageQueueId_t targetQueueId, bool generateSnapshot) override; @@ -252,7 +230,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces */ void clearReceiversList(); - object_id_t getCreatorObjectId() const; + [[nodiscard]] object_id_t getCreatorObjectId() const; /** * Get the pointer to the mutex. Can be used to lock the data pool @@ -262,7 +240,14 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces */ MutexIF* getMutexHandle(); - virtual LocalDataPoolManager* getPoolManagerHandle() override; + LocalDataPoolManager* getPoolManagerHandle() override; + ReturnValue_t subscribeForRegularPeriodicPacket(subdp::RegularHkPeriodicParams params) override; + ReturnValue_t subscribeForDiagPeriodicPacket(subdp::DiagnosticsHkPeriodicParams params) override; + ReturnValue_t subscribeForPeriodicPacket(subdp::ParamsBase& params); + + ReturnValue_t subscribeForRegularUpdatePacket(subdp::RegularHkUpdateParams params) override; + ReturnValue_t subscribeForDiagUpdatePacket(subdp::DiagnosticsHkUpdateParams params) override; + ReturnValue_t subscribeForUpdatePacket(subdp::ParamsBase& params); protected: /** Core data structure for the actual pool data */ diff --git a/src/fsfw/datapoollocal/ProvidesDataPoolSubscriptionIF.h b/src/fsfw/datapoollocal/ProvidesDataPoolSubscriptionIF.h index 1f13a09d9..4fa86ef0e 100644 --- a/src/fsfw/datapoollocal/ProvidesDataPoolSubscriptionIF.h +++ b/src/fsfw/datapoollocal/ProvidesDataPoolSubscriptionIF.h @@ -1,14 +1,56 @@ #ifndef FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_ #define FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_ -#include "../ipc/messageQueueDefinitions.h" -#include "../returnvalues/HasReturnvaluesIF.h" +#include "fsfw/housekeeping/AcceptsHkPacketsIF.h" +#include "fsfw/ipc/MessageQueueIF.h" +#include "fsfw/ipc/messageQueueDefinitions.h" +#include "fsfw/returnvalues/HasReturnvaluesIF.h" #include "localPoolDefinitions.h" +namespace subdp { + +struct ParamsBase { + ParamsBase(sid_t sid, bool enableReporting, float collectionInterval, bool diagnostics) + : sid(sid), + enableReporting(enableReporting), + collectionInterval(collectionInterval), + diagnostics(diagnostics) {} + + [[nodiscard]] bool isDiagnostics() const { return diagnostics; } + + sid_t sid; + bool enableReporting; + float collectionInterval; + MessageQueueId_t receiver = MessageQueueIF::NO_QUEUE; + + protected: + bool diagnostics; +}; + +struct RegularHkPeriodicParams : public ParamsBase { + RegularHkPeriodicParams(sid_t sid, bool enableReporting, float collectionInterval) + : ParamsBase(sid, enableReporting, collectionInterval, false) {} +}; + +struct DiagnosticsHkPeriodicParams : public ParamsBase { + DiagnosticsHkPeriodicParams(sid_t sid, bool enableReporting, float collectionInterval) + : ParamsBase(sid, enableReporting, collectionInterval, true) {} +}; + +struct RegularHkUpdateParams : public ParamsBase { + RegularHkUpdateParams(sid_t sid, bool enableReporting) + : ParamsBase(sid, enableReporting, 0.0, false) {} +}; + +struct DiagnosticsHkUpdateParams : public ParamsBase { + DiagnosticsHkUpdateParams(sid_t sid, bool enableReporting) + : ParamsBase(sid, enableReporting, 0.0, true) {} +}; +} // namespace subdp + class ProvidesDataPoolSubscriptionIF { public: - virtual ~ProvidesDataPoolSubscriptionIF(){}; - + virtual ~ProvidesDataPoolSubscriptionIF() = default; /** * @brief Subscribe for the generation of periodic packets. * @details @@ -16,9 +58,11 @@ class ProvidesDataPoolSubscriptionIF { * to generate housekeeping packets which are downlinked directly. * @return */ - virtual ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting, - float collectionInterval, bool isDiagnostics, - object_id_t packetDestination) = 0; + virtual ReturnValue_t subscribeForRegularPeriodicPacket( + subdp::RegularHkPeriodicParams params) = 0; + virtual ReturnValue_t subscribeForDiagPeriodicPacket( + subdp::DiagnosticsHkPeriodicParams params) = 0; + /** * @brief Subscribe for the generation of packets if the dataset * is marked as changed. @@ -29,9 +73,9 @@ class ProvidesDataPoolSubscriptionIF { * @param packetDestination * @return */ - virtual ReturnValue_t subscribeForUpdatePacket(sid_t sid, bool reportingEnabled, - bool isDiagnostics, - object_id_t packetDestination) = 0; + virtual ReturnValue_t subscribeForRegularUpdatePacket(subdp::RegularHkUpdateParams params) = 0; + virtual ReturnValue_t subscribeForDiagUpdatePacket(subdp::DiagnosticsHkUpdateParams params) = 0; + /** * @brief Subscribe for a notification message which will be sent * if a dataset has changed. @@ -46,8 +90,7 @@ class ProvidesDataPoolSubscriptionIF { * Otherwise, only an notification message is sent. * @return */ - virtual ReturnValue_t subscribeForSetUpdateMessage(const uint32_t setId, - object_id_t destinationObject, + virtual ReturnValue_t subscribeForSetUpdateMessage(uint32_t setId, object_id_t destinationObject, MessageQueueId_t targetQueueId, bool generateSnapshot) = 0; /** @@ -64,7 +107,7 @@ class ProvidesDataPoolSubscriptionIF { * only an notification message is sent. * @return */ - virtual ReturnValue_t subscribeForVariableUpdateMessage(const lp_id_t localPoolId, + virtual ReturnValue_t subscribeForVariableUpdateMessage(lp_id_t localPoolId, object_id_t destinationObject, MessageQueueId_t targetQueueId, bool generateSnapshot) = 0; diff --git a/src/fsfw/housekeeping/AcceptsHkPacketsIF.h b/src/fsfw/housekeeping/AcceptsHkPacketsIF.h index 078828290..7648e7edb 100644 --- a/src/fsfw/housekeeping/AcceptsHkPacketsIF.h +++ b/src/fsfw/housekeeping/AcceptsHkPacketsIF.h @@ -1,12 +1,12 @@ #ifndef FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_ #define FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_ -#include "../ipc/MessageQueueMessageIF.h" +#include "fsfw/ipc/MessageQueueMessageIF.h" class AcceptsHkPacketsIF { public: - virtual ~AcceptsHkPacketsIF(){}; - virtual MessageQueueId_t getHkQueue() const = 0; + virtual ~AcceptsHkPacketsIF() = default; + [[nodiscard]] virtual MessageQueueId_t getHkQueue() const = 0; }; #endif /* FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_ */ diff --git a/src/fsfw/internalerror/InternalErrorReporter.cpp b/src/fsfw/internalerror/InternalErrorReporter.cpp index fa16ec3f6..12c5aaeb7 100644 --- a/src/fsfw/internalerror/InternalErrorReporter.cpp +++ b/src/fsfw/internalerror/InternalErrorReporter.cpp @@ -129,8 +129,9 @@ ReturnValue_t InternalErrorReporter::initializeLocalDataPool(localpool::DataPool localDataPoolMap.emplace(errorPoolIds::TM_HITS, new PoolEntry()); localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, new PoolEntry()); localDataPoolMap.emplace(errorPoolIds::STORE_HITS, new PoolEntry()); - poolManager.subscribeForPeriodicPacket(internalErrorSid, false, getPeriodicOperationFrequency(), - true); + poolManager.subscribeForDiagPeriodicPacket(subdp::DiagnosticsHkPeriodicParams( + internalErrorSid, false, + static_cast(getPeriodicOperationFrequency()) / static_cast(1000.0))); internalErrorDataset.setValidity(true, true); return HasReturnvaluesIF::RETURN_OK; } diff --git a/src/fsfw/ipc/MessageQueueBase.h b/src/fsfw/ipc/MessageQueueBase.h index 9c05b1a28..c4de8eeb7 100644 --- a/src/fsfw/ipc/MessageQueueBase.h +++ b/src/fsfw/ipc/MessageQueueBase.h @@ -17,18 +17,18 @@ class MessageQueueBase : public MessageQueueIF { [[nodiscard]] MessageQueueId_t getDefaultDestination() const override; [[nodiscard]] bool isDefaultDestinationSet() const override; ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message, - bool ignoreFault) override; + bool ignoreFault) override; ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override; ReturnValue_t reply(MessageQueueMessageIF* message) override; ReturnValue_t receiveMessage(MessageQueueMessageIF* message, - MessageQueueId_t* receivedFrom) override; + MessageQueueId_t* receivedFrom) override; ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom, - bool ignoreFault = false) override; + bool ignoreFault = false) override; // OSAL specific, forward the abstract function ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override = 0; ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, - MessageQueueId_t sentFrom, bool ignoreFault = false) override = 0; + MessageQueueId_t sentFrom, bool ignoreFault = false) override = 0; protected: MessageQueueId_t id = MessageQueueIF::NO_QUEUE; diff --git a/src/fsfw/ipc/MessageQueueMessage.cpp b/src/fsfw/ipc/MessageQueueMessage.cpp index 6899915ac..6e841c7fa 100644 --- a/src/fsfw/ipc/MessageQueueMessage.cpp +++ b/src/fsfw/ipc/MessageQueueMessage.cpp @@ -10,10 +10,10 @@ MessageQueueMessage::MessageQueueMessage() : messageSize(getMinimumMessageSize() } MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size) - : messageSize(this->HEADER_SIZE + size) { - if (size <= this->MAX_DATA_SIZE) { - memcpy(this->getData(), data, size); - this->messageSize = this->HEADER_SIZE + size; + : messageSize(MessageQueueMessage::HEADER_SIZE + size) { + if (size <= MessageQueueMessage::MAX_DATA_SIZE) { + std::memcpy(internalBuffer + MessageQueueMessage::HEADER_SIZE, data, size); + this->messageSize = MessageQueueMessage::HEADER_SIZE + size; } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "MessageQueueMessage: Passed size larger than maximum" @@ -21,21 +21,23 @@ MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size) << std::endl; #endif memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); - this->messageSize = this->HEADER_SIZE; + this->messageSize = MessageQueueMessage::HEADER_SIZE; } } -MessageQueueMessage::~MessageQueueMessage() {} +MessageQueueMessage::~MessageQueueMessage() = default; const uint8_t* MessageQueueMessage::getBuffer() const { return this->internalBuffer; } uint8_t* MessageQueueMessage::getBuffer() { return this->internalBuffer; } const uint8_t* MessageQueueMessage::getData() const { - return this->internalBuffer + this->HEADER_SIZE; + return this->internalBuffer + MessageQueueMessage::HEADER_SIZE; } -uint8_t* MessageQueueMessage::getData() { return this->internalBuffer + this->HEADER_SIZE; } +uint8_t* MessageQueueMessage::getData() { + return this->internalBuffer + MessageQueueMessage::HEADER_SIZE; +} MessageQueueId_t MessageQueueMessage::getSender() const { MessageQueueId_t temp_id; @@ -58,14 +60,22 @@ void MessageQueueMessage::print(bool printWholeMessage) { } } -void MessageQueueMessage::clear() { memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE); } +void MessageQueueMessage::clear() { + memset(this->getBuffer(), 0, MessageQueueMessage::MAX_MESSAGE_SIZE); +} size_t MessageQueueMessage::getMessageSize() const { return this->messageSize; } -void MessageQueueMessage::setMessageSize(size_t messageSize) { this->messageSize = messageSize; } +void MessageQueueMessage::setMessageSize(size_t messageSize_) { this->messageSize = messageSize_; } -size_t MessageQueueMessage::getMinimumMessageSize() const { return this->MIN_MESSAGE_SIZE; } +size_t MessageQueueMessage::getMinimumMessageSize() const { + return MessageQueueMessage::MIN_MESSAGE_SIZE; +} -size_t MessageQueueMessage::getMaximumMessageSize() const { return this->MAX_MESSAGE_SIZE; } +size_t MessageQueueMessage::getMaximumMessageSize() const { + return MessageQueueMessage::MAX_MESSAGE_SIZE; +} -size_t MessageQueueMessage::getMaximumDataSize() const { return this->MAX_DATA_SIZE; } +size_t MessageQueueMessage::getMaximumDataSize() const { + return MessageQueueMessage::MAX_DATA_SIZE; +} diff --git a/src/fsfw/ipc/MessageQueueMessage.h b/src/fsfw/ipc/MessageQueueMessage.h index 30e50ffe3..a3d596f1d 100644 --- a/src/fsfw/ipc/MessageQueueMessage.h +++ b/src/fsfw/ipc/MessageQueueMessage.h @@ -25,6 +25,30 @@ */ class MessageQueueMessage : public MessageQueueMessageIF { public: + /** + * @brief This constant defines the maximum size of the data content, + * excluding the header. + * @details + * It may be changed if necessary, but in general should be kept + * as small as possible. + */ + static const size_t MAX_DATA_SIZE = 24; + /** + * @brief This constant defines the maximum total size in bytes + * of a sent message. + * @details + * It is the sum of the maximum data and the header size. Be aware that + * this constant is used to define the buffer sizes for every message + * queue in the system. So, a change here may have significant impact on + * the required resources. + */ + static constexpr size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE; + /** + * @brief Defines the minimum size of a message where only the + * header is included + */ + static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE; + /** * @brief The class is initialized empty with this constructor. * @details @@ -50,59 +74,12 @@ class MessageQueueMessage : public MessageQueueMessageIF { * @brief As no memory is allocated in this class, * the destructor is empty. */ - virtual ~MessageQueueMessage(); + ~MessageQueueMessage() override; - /** - * @brief The size information of each message is stored in - * this attribute. - * @details - * It is public to simplify usage and to allow for passing the size - * address as a pointer. Care must be taken when inheriting from this class, - * as every child class is responsible for managing the size information by - * itself. When using the class to receive a message, the size information - * is updated automatically. - * - * Please note that the minimum size is limited by the size of the header - * while the maximum size is limited by the maximum allowed message size. - */ - size_t messageSize; - /** - * @brief This constant defines the maximum size of the data content, - * excluding the header. - * @details - * It may be changed if necessary, but in general should be kept - * as small as possible. - */ - static const size_t MAX_DATA_SIZE = 24; - - /** - * @brief This constant defines the maximum total size in bytes - * of a sent message. - * @details - * It is the sum of the maximum data and the header size. Be aware that - * this constant is used to define the buffer sizes for every message - * queue in the system. So, a change here may have significant impact on - * the required resources. - */ - static constexpr size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE; - /** - * @brief Defines the minimum size of a message where only the - * header is included - */ - static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE; - - private: - /** - * @brief This is the internal buffer that contains the - * actual message data. - */ - uint8_t internalBuffer[MAX_MESSAGE_SIZE]; - - public: /** * @brief This method is used to get the complete data of the message. */ - const uint8_t* getBuffer() const override; + [[nodiscard]] const uint8_t* getBuffer() const override; /** * @brief This method is used to get the complete data of the message. */ @@ -112,7 +89,7 @@ class MessageQueueMessage : public MessageQueueMessageIF { * @details * It shall be used by child classes to add data at the right position. */ - const uint8_t* getData() const override; + [[nodiscard]] const uint8_t* getData() const override; /** * @brief This method is used to fetch the data content of the message. * @details @@ -123,7 +100,7 @@ class MessageQueueMessage : public MessageQueueMessageIF { * @brief This method is used to extract the sender's message * queue id information from a received message. */ - MessageQueueId_t getSender() const override; + [[nodiscard]] MessageQueueId_t getSender() const override; /** * @brief With this method, the whole content * and the message size is set to zero. @@ -138,16 +115,40 @@ class MessageQueueMessage : public MessageQueueMessageIF { */ void setSender(MessageQueueId_t setId) override; - virtual size_t getMessageSize() const override; - virtual void setMessageSize(size_t messageSize) override; - virtual size_t getMinimumMessageSize() const override; - virtual size_t getMaximumMessageSize() const override; - virtual size_t getMaximumDataSize() const override; + [[nodiscard]] size_t getMessageSize() const override; + void setMessageSize(size_t messageSize) override; + [[nodiscard]] size_t getMinimumMessageSize() const override; + [[nodiscard]] size_t getMaximumMessageSize() const override; + [[nodiscard]] size_t getMaximumDataSize() const override; /** * @brief This is a debug method that prints the content. */ void print(bool printWholeMessage); + + /** + * TODO: This really should not be public. If it should be possible to pass size address as a + * pointer, add a getter function returning a const reference to the size + * @brief The size information of each message is stored in + * this attribute. + * @details + * It is public to simplify usage and to allow for passing the size + * address as a pointer. Care must be taken when inheriting from this class, + * as every child class is responsible for managing the size information by + * itself. When using the class to receive a message, the size information + * is updated automatically. + * + * Please note that the minimum size is limited by the size of the header + * while the maximum size is limited by the maximum allowed message size. + */ + size_t messageSize; + + private: + /** + * @brief This is the internal buffer that contains the + * actual message data. + */ + uint8_t internalBuffer[MAX_MESSAGE_SIZE] = {}; }; #endif /* FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ */ diff --git a/src/fsfw/ipc/MessageQueueMessageIF.h b/src/fsfw/ipc/MessageQueueMessageIF.h index dae289260..300a90aba 100644 --- a/src/fsfw/ipc/MessageQueueMessageIF.h +++ b/src/fsfw/ipc/MessageQueueMessageIF.h @@ -14,7 +14,7 @@ class MessageQueueMessageIF { */ static const size_t HEADER_SIZE = sizeof(MessageQueueId_t); - virtual ~MessageQueueMessageIF(){}; + virtual ~MessageQueueMessageIF() = default; /** * @brief With this method, the whole content and the message @@ -29,7 +29,7 @@ class MessageQueueMessageIF { * @brief Get read-only pointer to the complete data of the message. * @return */ - virtual const uint8_t* getBuffer() const = 0; + [[nodiscard]] virtual const uint8_t* getBuffer() const = 0; /** * @brief This method is used to get the complete data of the message. @@ -48,14 +48,14 @@ class MessageQueueMessageIF { * @brief This method is used to extract the sender's message queue id * information from a received message. */ - virtual MessageQueueId_t getSender() const = 0; + [[nodiscard]] virtual MessageQueueId_t getSender() const = 0; /** * @brief This method is used to fetch the data content of the message. * @details * It shall be used by child classes to add data at the right position. */ - virtual const uint8_t* getData() const = 0; + [[nodiscard]] virtual const uint8_t* getData() const = 0; /** * @brief This method is used to fetch the data content of the message. * @details @@ -67,12 +67,28 @@ class MessageQueueMessageIF { * Get constant message size of current message implementation. * @return */ - virtual size_t getMessageSize() const = 0; + [[nodiscard]] virtual size_t getMessageSize() const = 0; + /** + * Sets the current message size of a given message + * @param messageSize + */ virtual void setMessageSize(size_t messageSize) = 0; - virtual size_t getMinimumMessageSize() const = 0; - virtual size_t getMaximumMessageSize() const = 0; - virtual size_t getMaximumDataSize() const = 0; + /** + * Returns the smallest possible message size, including any headers + * @return + */ + [[nodiscard]] virtual size_t getMinimumMessageSize() const = 0; + /** + * Returns the largest possible message size, including any headers + * @return + */ + [[nodiscard]] virtual size_t getMaximumMessageSize() const = 0; + /** + * Returns the largest possible data size without any headers + * @return + */ + [[nodiscard]] virtual size_t getMaximumDataSize() const = 0; }; #endif /* FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ */ diff --git a/src/fsfw/osal/linux/Clock.cpp b/src/fsfw/osal/linux/Clock.cpp index 00596dabb..a173bbc5b 100644 --- a/src/fsfw/osal/linux/Clock.cpp +++ b/src/fsfw/osal/linux/Clock.cpp @@ -2,9 +2,9 @@ #include #include -#include #include +#include #include #include "fsfw/ipc/MutexGuard.h" diff --git a/src/fsfw/serialize/SerializeIF.h b/src/fsfw/serialize/SerializeIF.h index 40e19530c..136bd4192 100644 --- a/src/fsfw/serialize/SerializeIF.h +++ b/src/fsfw/serialize/SerializeIF.h @@ -64,7 +64,7 @@ class SerializeIF { /** * Forwards to regular @serialize call with big (network) endianness */ - virtual ReturnValue_t serializeBe(uint8_t** buffer, size_t* size, size_t maxSize) { + virtual ReturnValue_t serializeBe(uint8_t **buffer, size_t *size, size_t maxSize) { return serialize(buffer, size, maxSize, SerializeIF::Endianness::NETWORK); } /** @@ -105,7 +105,7 @@ class SerializeIF { /** * Forwards to regular @deSerialize call with big (network) endianness */ - virtual ReturnValue_t deSerializeBe(const uint8_t** buffer, size_t* size) { + virtual ReturnValue_t deSerializeBe(const uint8_t **buffer, size_t *size) { return deSerialize(buffer, size, SerializeIF::Endianness::NETWORK); } /** diff --git a/src/fsfw/timemanager/CCSDSTime.h b/src/fsfw/timemanager/CCSDSTime.h index f2841d0c5..3f4361f8e 100644 --- a/src/fsfw/timemanager/CCSDSTime.h +++ b/src/fsfw/timemanager/CCSDSTime.h @@ -6,9 +6,9 @@ #include #include -#include "fsfw/returnvalues/HasReturnvaluesIF.h" #include "Clock.h" #include "clockDefinitions.h" +#include "fsfw/returnvalues/HasReturnvaluesIF.h" bool operator<(const timeval &lhs, const timeval &rhs); bool operator<=(const timeval &lhs, const timeval &rhs); diff --git a/src/fsfw/timemanager/TimeMessage.h b/src/fsfw/timemanager/TimeMessage.h index c5eed13fe..628330365 100644 --- a/src/fsfw/timemanager/TimeMessage.h +++ b/src/fsfw/timemanager/TimeMessage.h @@ -3,8 +3,8 @@ #include -#include "fsfw/ipc/MessageQueueMessage.h" #include "Clock.h" +#include "fsfw/ipc/MessageQueueMessage.h" class TimeMessage : public MessageQueueMessage { protected: diff --git a/src/fsfw/tmtcpacket/pus/tc/PusTcCreator.cpp b/src/fsfw/tmtcpacket/pus/tc/PusTcCreator.cpp index 992ec388c..d6748619b 100644 --- a/src/fsfw/tmtcpacket/pus/tc/PusTcCreator.cpp +++ b/src/fsfw/tmtcpacket/pus/tc/PusTcCreator.cpp @@ -101,7 +101,7 @@ ReturnValue_t PusTcCreator::setRawUserData(const uint8_t *data, size_t len) { return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t PusTcCreator::setSerializableUserData(SerializeIF& serializable) { +ReturnValue_t PusTcCreator::setSerializableUserData(SerializeIF &serializable) { // TODO: Check length field? pusParams.dataWrapper.setSerializable(serializable); updateSpLengthField(); diff --git a/src/fsfw/tmtcpacket/pus/tc/PusTcCreator.h b/src/fsfw/tmtcpacket/pus/tc/PusTcCreator.h index 90b32973f..0f903e7b5 100644 --- a/src/fsfw/tmtcpacket/pus/tc/PusTcCreator.h +++ b/src/fsfw/tmtcpacket/pus/tc/PusTcCreator.h @@ -47,7 +47,7 @@ class PusTcCreator : public PusTcIF, public SerializeIF, public CustomUserDataIF [[nodiscard]] uint8_t getSubService() const override; [[nodiscard]] uint16_t getSourceId() const override; ReturnValue_t setRawUserData(const uint8_t *data, size_t len) override; - ReturnValue_t setSerializableUserData(SerializeIF& serializable) override; + ReturnValue_t setSerializableUserData(SerializeIF &serializable) override; private: ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, diff --git a/src/fsfw/tmtcservices/TmSendHelper.cpp b/src/fsfw/tmtcservices/TmSendHelper.cpp index 2f57433d3..7b464ad84 100644 --- a/src/fsfw/tmtcservices/TmSendHelper.cpp +++ b/src/fsfw/tmtcservices/TmSendHelper.cpp @@ -2,16 +2,17 @@ #include "fsfw/ipc/MessageQueueSenderIF.h" -TmSendHelper::TmSendHelper(MessageQueueIF* queue, InternalErrorReporterIF *reporter, MessageQueueId_t tmtcMsgDest) +TmSendHelper::TmSendHelper(MessageQueueIF *queue, InternalErrorReporterIF *reporter, + MessageQueueId_t tmtcMsgDest) : tmtcMsgDest(tmtcMsgDest), queue(queue), errReporter(reporter) {} TmSendHelper::TmSendHelper(MessageQueueIF *queue, InternalErrorReporterIF *reporter) - : queue(queue), errReporter(reporter) {} + : queue(queue), errReporter(reporter) {} TmSendHelper::TmSendHelper(InternalErrorReporterIF *reporter) : errReporter(reporter) {} ReturnValue_t TmSendHelper::sendPacket(const store_address_t &storeId) { - if(queue == nullptr) { + if (queue == nullptr) { return HasReturnvaluesIF::RETURN_FAILED; } TmTcMessage message(storeId); diff --git a/src/fsfw/tmtcservices/TmSendHelper.h b/src/fsfw/tmtcservices/TmSendHelper.h index 7e11daad2..4cb159dae 100644 --- a/src/fsfw/tmtcservices/TmSendHelper.h +++ b/src/fsfw/tmtcservices/TmSendHelper.h @@ -9,11 +9,11 @@ class TmSendHelper { public: - TmSendHelper(MessageQueueIF* queue, InternalErrorReporterIF* reporter, MessageQueueId_t tmtcMsgDest); + TmSendHelper(MessageQueueIF* queue, InternalErrorReporterIF* reporter, + MessageQueueId_t tmtcMsgDest); TmSendHelper(MessageQueueIF* queue, InternalErrorReporterIF* reporter); explicit TmSendHelper(InternalErrorReporterIF* reporter); - void setMsgQueue(MessageQueueIF* queue); void setMsgDestination(MessageQueueId_t msgDest); void setInternalErrorReporter(InternalErrorReporterIF* reporter); diff --git a/src/fsfw/tmtcservices/TmStoreHelper.cpp b/src/fsfw/tmtcservices/TmStoreHelper.cpp index 87a530efa..eb5385189 100644 --- a/src/fsfw/tmtcservices/TmStoreHelper.cpp +++ b/src/fsfw/tmtcservices/TmStoreHelper.cpp @@ -2,7 +2,7 @@ #include "TmTcMessage.h" -TmStoreHelper::TmStoreHelper(uint16_t defaultApid): tmStore(nullptr) { +TmStoreHelper::TmStoreHelper(uint16_t defaultApid) : tmStore(nullptr) { creator.setApid(defaultApid); } @@ -17,7 +17,6 @@ TmStoreHelper::TmStoreHelper(uint16_t defaultApid, StorageManagerIF& tmStore, creator.setTimeStamper(timeStamper); } - ReturnValue_t TmStoreHelper::preparePacket(uint8_t service, uint8_t subservice, uint16_t counter) { PusTmParams& params = creator.getParams(); params.secHeader.service = service; @@ -33,8 +32,8 @@ void TmStoreHelper::setTmStore(StorageManagerIF& store) { tmStore = &store; } const store_address_t& TmStoreHelper::getCurrentAddr() const { return currentAddr; } ReturnValue_t TmStoreHelper::deletePacket() { - ReturnValue_t result = tmStore->deleteData(currentAddr); - if(result == HasReturnvaluesIF::RETURN_OK) { + ReturnValue_t result = tmStore->deleteData(currentAddr); + if (result == HasReturnvaluesIF::RETURN_OK) { currentAddr = store_address_t::invalid(); } return result; diff --git a/src/fsfw/tmtcservices/TmStoreHelper.h b/src/fsfw/tmtcservices/TmStoreHelper.h index b253361e6..3a868d976 100644 --- a/src/fsfw/tmtcservices/TmStoreHelper.h +++ b/src/fsfw/tmtcservices/TmStoreHelper.h @@ -30,7 +30,6 @@ class TmStoreHelper { ReturnValue_t setSourceDataRaw(const uint8_t* data, size_t len); ReturnValue_t setSourceDataSerializable(SerializeIF& serializable); - ReturnValue_t addPacketToStore(); ReturnValue_t deletePacket(); diff --git a/unittests/CatchFactory.cpp b/unittests/CatchFactory.cpp index 5dce8372f..fdb5fd085 100644 --- a/unittests/CatchFactory.cpp +++ b/unittests/CatchFactory.cpp @@ -10,7 +10,6 @@ #include #include -#include "datapoollocal/LocalPoolOwnerBase.h" #include "mocks/HkReceiverMock.h" #include "tests/TestsConfig.h" @@ -34,8 +33,6 @@ void Factory::produceFrameworkObjects(void* args) { new EventManager(objects::EVENT_MANAGER); new HealthTable(objects::HEALTH_TABLE); new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER); - - new LocalPoolOwnerBase(objects::TEST_LOCAL_POOL_OWNER_BASE); new HkReceiverMock(objects::HK_RECEIVER_MOCK); { @@ -54,6 +51,9 @@ void Factory::produceFrameworkObjects(void* args) { } } +// TODO: Our tests, and the code base in general should really not depend on some arbitrary function +// like this. Instead, this should be more like a general struct containing all important +// object IDs which are then explicitely passed in the object constructor void Factory::setStaticFrameworkObjectIds() { PusServiceBase::packetSource = objects::NO_OBJECT; PusServiceBase::packetDestination = objects::NO_OBJECT; @@ -66,7 +66,8 @@ void Factory::setStaticFrameworkObjectIds() { DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT; DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT; - LocalDataPoolManager::defaultHkDestination = objects::HK_RECEIVER_MOCK; + // TODO: Incredibly ugly, get rid of it + LocalDataPoolManager::defaultHkDestination = objects::NO_OBJECT; DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT; } diff --git a/unittests/action/TestActionHelper.cpp b/unittests/action/TestActionHelper.cpp index dd252d881..952f4572d 100644 --- a/unittests/action/TestActionHelper.cpp +++ b/unittests/action/TestActionHelper.cpp @@ -57,8 +57,7 @@ TEST_CASE("Action Helper", "[ActionHelper]") { step += 1; CHECK(testMqMock.wasMessageSent()); CommandMessage testMessage; - REQUIRE(testMqMock.receiveMessage(&testMessage) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(testMqMock.getNextSentMessage(testMessage) == HasReturnvaluesIF::RETURN_OK); REQUIRE(testMessage.getCommand() == static_cast(ActionMessage::STEP_FAILED)); REQUIRE(testMessage.getParameter() == static_cast(testActionId)); uint32_t parameter2 = ((uint32_t)step << 16) | (uint32_t)status; @@ -72,8 +71,7 @@ TEST_CASE("Action Helper", "[ActionHelper]") { actionHelper.finish(false, testMqMock.getId(), testActionId, status); CHECK(testMqMock.wasMessageSent()); CommandMessage testMessage; - REQUIRE(testMqMock.receiveMessage(&testMessage) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(testMqMock.getNextSentMessage(testMessage) == HasReturnvaluesIF::RETURN_OK); REQUIRE(testMessage.getCommand() == static_cast(ActionMessage::COMPLETION_FAILED)); REQUIRE(ActionMessage::getActionId(&testMessage) == testActionId); REQUIRE(ActionMessage::getReturnCode(&testMessage) == static_cast(status)); @@ -89,8 +87,7 @@ TEST_CASE("Action Helper", "[ActionHelper]") { REQUIRE(ipcStore->getData(toLongParamAddress).first == static_cast(StorageManagerIF::DATA_DOES_NOT_EXIST)); CommandMessage testMessage; - REQUIRE(testMqMock.receiveMessage(&testMessage) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(testMqMock.getNextSentMessage(testMessage) == HasReturnvaluesIF::RETURN_OK); REQUIRE(testMessage.getCommand() == static_cast(ActionMessage::STEP_FAILED)); REQUIRE(ActionMessage::getReturnCode(&testMessage) == 0xAFFE); REQUIRE(ActionMessage::getStep(&testMessage) == 0); @@ -102,8 +99,7 @@ TEST_CASE("Action Helper", "[ActionHelper]") { CHECK(not testDhMock.executeActionCalled); REQUIRE(actionHelper.handleActionMessage(&actionMessage) == retval::CATCH_OK); CommandMessage testMessage; - REQUIRE(testMqMock.receiveMessage(&testMessage) == - static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(testMqMock.getNextSentMessage(testMessage) == HasReturnvaluesIF::RETURN_OK); REQUIRE(testMessage.getCommand() == static_cast(ActionMessage::STEP_FAILED)); REQUIRE(ActionMessage::getReturnCode(&testMessage) == static_cast(StorageManagerIF::ILLEGAL_STORAGE_ID)); diff --git a/unittests/datapoollocal/CMakeLists.txt b/unittests/datapoollocal/CMakeLists.txt index bf465282e..6b8946a26 100644 --- a/unittests/datapoollocal/CMakeLists.txt +++ b/unittests/datapoollocal/CMakeLists.txt @@ -1,7 +1,7 @@ target_sources(${FSFW_TEST_TGT} PRIVATE - LocalPoolVariableTest.cpp - LocalPoolVectorTest.cpp - DataSetTest.cpp - LocalPoolManagerTest.cpp + testLocalPoolVariable.cpp + testLocalPoolVector.cpp + testDataSet.cpp + testLocalPoolManager.cpp LocalPoolOwnerBase.cpp ) diff --git a/unittests/datapoollocal/LocalPoolManagerTest.cpp b/unittests/datapoollocal/LocalPoolManagerTest.cpp deleted file mode 100644 index 6d9f162cc..000000000 --- a/unittests/datapoollocal/LocalPoolManagerTest.cpp +++ /dev/null @@ -1,413 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "CatchDefinitions.h" -#include "LocalPoolOwnerBase.h" - -TEST_CASE("LocalPoolManagerTest", "[LocManTest]") { - LocalPoolOwnerBase* poolOwner = - ObjectManager::instance()->get(objects::TEST_LOCAL_POOL_OWNER_BASE); - REQUIRE(poolOwner != nullptr); - REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); - REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() == retval::CATCH_OK); - - MessageQueueMockBase* poolOwnerMock = poolOwner->getMockQueueHandle(); - REQUIRE(poolOwnerMock != nullptr); - - // MessageQueueIF* hkCommander = QueueFactory::instance()->createMessageQueue(); - CommandMessage messageSent; - uint8_t messagesSent = 0; - - SECTION("BasicTest") { - { - /* For code coverage, should not crash */ - LocalDataPoolManager manager(nullptr, nullptr); - } - auto owner = poolOwner->poolManager.getOwner(); - REQUIRE(owner != nullptr); - CHECK(owner->getObjectId() == objects::TEST_LOCAL_POOL_OWNER_BASE); - - /* Subscribe for message generation on update. */ - REQUIRE(poolOwner->subscribeWrapperSetUpdate() == retval::CATCH_OK); - /* Subscribe for an update message. */ - poolOwner->dataset.setChanged(true); - /* Now the update message should be generated. */ - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent() == true); - - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == - static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); - - /* Should have been reset. */ - CHECK(poolOwner->dataset.hasChanged() == false); - /* Set changed again, result should be the same. */ - poolOwner->dataset.setChanged(true); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == - static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); - - /* Now subscribe for set update HK as well. */ - REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK); - poolOwner->dataset.setChanged(true); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 2); - /* first message sent should be the update notification, considering - the internal list is a vector checked in insertion order. */ - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == - static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); - - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == static_cast(HousekeepingMessage::HK_REPORT)); - /* Clear message to avoid memory leak, our mock won't do it for us (yet) */ - CommandMessageCleaner::clearCommandMessage(&messageSent); - } - - SECTION("SetSnapshotUpdateTest") { - /* Set the variables in the set to certain values. These are checked later. */ - { - PoolReadGuard readHelper(&poolOwner->dataset); - REQUIRE(readHelper.getReadResult() == retval::CATCH_OK); - poolOwner->dataset.localPoolVarUint8.value = 5; - poolOwner->dataset.localPoolVarFloat.value = -12.242; - poolOwner->dataset.localPoolUint16Vec.value[0] = 2; - poolOwner->dataset.localPoolUint16Vec.value[1] = 32; - poolOwner->dataset.localPoolUint16Vec.value[2] = 42932; - } - - /* Subscribe for snapshot generation on update. */ - REQUIRE(poolOwner->subscribeWrapperSetUpdateSnapshot() == retval::CATCH_OK); - poolOwner->dataset.setChanged(true); - - /* Store current time, we are going to check the (approximate) time equality later */ - timeval now; - Clock::getClock_timeval(&now); - - /* Trigger generation of snapshot */ - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - /* Check that snapshot was generated */ - CHECK(messageSent.getCommand() == static_cast(HousekeepingMessage::UPDATE_SNAPSHOT_SET)); - /* Now we deserialize the snapshot into a new dataset instance */ - CCSDSTime::CDS_short cdsShort; - LocalPoolTestDataSet newSet; - HousekeepingSnapshot snapshot(&cdsShort, &newSet); - store_address_t storeId; - HousekeepingMessage::getUpdateSnapshotSetCommand(&messageSent, &storeId); - ConstAccessorPair accessorPair = tglob::getIpcStoreHandle()->getData(storeId); - REQUIRE(accessorPair.first == retval::CATCH_OK); - const uint8_t* readOnlyPtr = accessorPair.second.data(); - size_t sizeToDeserialize = accessorPair.second.size(); - CHECK(newSet.localPoolVarFloat.value == 0); - CHECK(newSet.localPoolVarUint8 == 0); - CHECK(newSet.localPoolUint16Vec.value[0] == 0); - CHECK(newSet.localPoolUint16Vec.value[1] == 0); - CHECK(newSet.localPoolUint16Vec.value[2] == 0); - /* Fill the dataset and timestamp */ - REQUIRE(snapshot.deSerialize(&readOnlyPtr, &sizeToDeserialize, - SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); - /* Now we check that the snapshot is actually correct */ - CHECK(newSet.localPoolVarFloat.value == Catch::Approx(-12.242)); - CHECK(newSet.localPoolVarUint8 == 5); - CHECK(newSet.localPoolUint16Vec.value[0] == 2); - CHECK(newSet.localPoolUint16Vec.value[1] == 32); - CHECK(newSet.localPoolUint16Vec.value[2] == 42932); - - /* Now we check that both times are equal */ - timeval timeFromHK; - auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort); - CHECK(result == HasReturnvaluesIF::RETURN_OK); - timeval difference = timeFromHK - now; - CHECK(timevalOperations::toDouble(difference) < 1.0); - } - - SECTION("VariableSnapshotTest") { - /* Acquire subscription interface */ - ProvidesDataPoolSubscriptionIF* subscriptionIF = poolOwner->getSubscriptionInterface(); - REQUIRE(subscriptionIF != nullptr); - - /* Subscribe for variable snapshot */ - REQUIRE(poolOwner->subscribeWrapperVariableSnapshot(lpool::uint8VarId) == retval::CATCH_OK); - auto poolVar = - dynamic_cast*>(poolOwner->getPoolObjectHandle(lpool::uint8VarId)); - REQUIRE(poolVar != nullptr); - - { - PoolReadGuard rg(poolVar); - CHECK(rg.getReadResult() == retval::CATCH_OK); - poolVar->value = 25; - } - - poolVar->setChanged(true); - /* Store current time, we are going to check the (approximate) time equality later */ - CCSDSTime::CDS_short timeCdsNow; - timeval now; - Clock::getClock_timeval(&now); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - - /* Check update snapshot was sent. */ - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - - /* Should have been reset. */ - CHECK(poolVar->hasChanged() == false); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == - static_cast(HousekeepingMessage::UPDATE_SNAPSHOT_VARIABLE)); - /* Now we deserialize the snapshot into a new dataset instance */ - CCSDSTime::CDS_short cdsShort; - lp_var_t varCopy = lp_var_t(lpool::uint8VarGpid); - HousekeepingSnapshot snapshot(&cdsShort, &varCopy); - store_address_t storeId; - HousekeepingMessage::getUpdateSnapshotVariableCommand(&messageSent, &storeId); - ConstAccessorPair accessorPair = tglob::getIpcStoreHandle()->getData(storeId); - REQUIRE(accessorPair.first == retval::CATCH_OK); - const uint8_t* readOnlyPtr = accessorPair.second.data(); - size_t sizeToDeserialize = accessorPair.second.size(); - CHECK(varCopy.value == 0); - /* Fill the dataset and timestamp */ - REQUIRE(snapshot.deSerialize(&readOnlyPtr, &sizeToDeserialize, - SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); - CHECK(varCopy.value == 25); - - /* Now we check that both times are equal */ - timeval timeFromHK; - auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort); - CHECK(result == HasReturnvaluesIF::RETURN_OK); - timeval difference = timeFromHK - now; - CHECK(timevalOperations::toDouble(difference) < 1.0); - } - - SECTION("VariableNotificationTest") { - /* Acquire subscription interface */ - ProvidesDataPoolSubscriptionIF* subscriptionIF = poolOwner->getSubscriptionInterface(); - REQUIRE(subscriptionIF != nullptr); - - /* Subscribe for variable update */ - REQUIRE(poolOwner->subscribeWrapperVariableUpdate(lpool::uint8VarId) == retval::CATCH_OK); - lp_var_t* poolVar = - dynamic_cast*>(poolOwner->getPoolObjectHandle(lpool::uint8VarId)); - REQUIRE(poolVar != nullptr); - poolVar->setChanged(true); - REQUIRE(poolVar->hasChanged() == true); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - - /* Check update notification was sent. */ - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - /* Should have been reset. */ - CHECK(poolVar->hasChanged() == false); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == - static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE)); - /* Now subscribe for the dataset update (HK and update) again with subscription interface */ - REQUIRE(subscriptionIF->subscribeForSetUpdateMessage(lpool::testSetId, objects::NO_OBJECT, - objects::HK_RECEIVER_MOCK, - false) == retval::CATCH_OK); - REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK); - - poolOwner->dataset.setChanged(true); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - /* Now two messages should be sent. */ - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 2); - poolOwnerMock->clearMessages(true); - - poolOwner->dataset.setChanged(true); - poolVar->setChanged(true); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - /* Now three messages should be sent. */ - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 3); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == - static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE)); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == - static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK); - CHECK(messageSent.getCommand() == static_cast(HousekeepingMessage::HK_REPORT)); - CommandMessageCleaner::clearCommandMessage(&messageSent); - REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == static_cast(MessageQueueIF::EMPTY)); - } - - SECTION("PeriodicHKAndMessaging") { - /* Now we subcribe for a HK periodic generation. Even when it's difficult to simulate - the temporal behaviour correctly the HK manager should generate a HK packet - immediately and the periodic helper depends on HK op function calls anyway instead of - using the clock, so we could also just call performHkOperation multiple times */ - REQUIRE(poolOwner->subscribePeriodicHk(true) == retval::CATCH_OK); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - /* Now HK packet should be sent as message immediately. */ - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - LocalPoolDataSetBase* setHandle = poolOwner->getDataSetHandle(lpool::testSid); - REQUIRE(setHandle != nullptr); - CHECK(poolOwner->poolManager.generateHousekeepingPacket(lpool::testSid, setHandle, false) == - retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - CHECK(setHandle->getReportingEnabled() == true); - CommandMessage hkCmd; - HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - CHECK(setHandle->getReportingEnabled() == false); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, true, false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - CHECK(setHandle->getReportingEnabled() == true); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - CHECK(setHandle->getReportingEnabled() == false); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4, - false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - /* For non-diagnostics and a specified minimum frequency of 0.2 seconds, the - resulting collection interval should be 1.0 second */ - CHECK(poolOwner->dataset.getCollectionInterval() == 1.0); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false); - REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - /* Now HK packet should be sent as message. */ - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setUpdateNotificationSetCommand(&hkCmd, lpool::testSid); - sid_t sidToCheck; - store_address_t storeId; - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - CHECK(poolOwner->changedDataSetCallbackWasCalled(sidToCheck, storeId) == true); - CHECK(sidToCheck == lpool::testSid); - - /* Now we test the handling is the dataset is set to diagnostic */ - poolOwner->dataset.setDiagnostic(true); - - HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == - static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); - /* We still expect a failure message being sent */ - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4, - false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == - static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == - static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, true); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4, - true); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, true, true); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, true); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, false); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == - static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, true); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true); - CHECK(messagesSent == 1); - CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK); - - HousekeepingMessage::setUpdateNotificationVariableCommand(&hkCmd, lpool::uint8VarGpid); - gp_id_t gpidToCheck; - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - CHECK(poolOwner->changedVariableCallbackWasCalled(gpidToCheck, storeId) == true); - CHECK(gpidToCheck == lpool::uint8VarGpid); - - HousekeepingMessage::setUpdateSnapshotSetCommand(&hkCmd, lpool::testSid, - store_address_t::invalid()); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - CHECK(poolOwner->changedDataSetCallbackWasCalled(sidToCheck, storeId) == true); - CHECK(sidToCheck == lpool::testSid); - - HousekeepingMessage::setUpdateSnapshotVariableCommand(&hkCmd, lpool::uint8VarGpid, - store_address_t::invalid()); - CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); - CHECK(poolOwner->changedVariableCallbackWasCalled(gpidToCheck, storeId) == true); - CHECK(gpidToCheck == lpool::uint8VarGpid); - - poolOwner->poolManager.printPoolEntry(lpool::uint8VarId); - } - - /* we need to reset the subscription list because the pool owner - is a global object. */ - CHECK(poolOwner->reset() == retval::CATCH_OK); - poolOwnerMock->clearMessages(true); -} diff --git a/unittests/datapoollocal/DataSetTest.cpp b/unittests/datapoollocal/testDataSet.cpp similarity index 93% rename from unittests/datapoollocal/DataSetTest.cpp rename to unittests/datapoollocal/testDataSet.cpp index c9f023ef4..62bf59bbd 100644 --- a/unittests/datapoollocal/DataSetTest.cpp +++ b/unittests/datapoollocal/testDataSet.cpp @@ -13,11 +13,10 @@ #include "tests/TestsConfig.h" TEST_CASE("DataSetTest", "[DataSetTest]") { - LocalPoolOwnerBase* poolOwner = - ObjectManager::instance()->get(objects::TEST_LOCAL_POOL_OWNER_BASE); - REQUIRE(poolOwner != nullptr); - REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); - REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() == retval::CATCH_OK); + auto queue = MessageQueueMockBase(); + LocalPoolOwnerBase poolOwner(queue, objects::TEST_LOCAL_POOL_OWNER_BASE); + REQUIRE(poolOwner.initializeHkManager() == retval::CATCH_OK); + REQUIRE(poolOwner.initializeHkManagerAfterTaskCreation() == retval::CATCH_OK); LocalPoolStaticTestDataSet localSet; SECTION("BasicTest") { @@ -30,9 +29,9 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { size_t maxSize = localSet.getLocalPoolIdsSerializedSize(true); uint8_t localPoolIdBuff[maxSize]; /* Skip size field */ - lp_id_t* lpIds = reinterpret_cast(localPoolIdBuff + 1); + auto* lpIds = reinterpret_cast(localPoolIdBuff + 1); size_t serSize = 0; - uint8_t* localPoolIdBuffPtr = reinterpret_cast(localPoolIdBuff); + auto* localPoolIdBuffPtr = reinterpret_cast(localPoolIdBuff); /* Test local pool ID serialization */ CHECK(localSet.serializeLocalPoolIds(&localPoolIdBuffPtr, &serSize, maxSize, @@ -200,7 +199,7 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { } /* Common fault test cases */ - LocalPoolObjectBase* variableHandle = poolOwner->getPoolObjectHandle(lpool::uint32VarId); + LocalPoolObjectBase* variableHandle = poolOwner.getPoolObjectHandle(lpool::uint32VarId); CHECK(variableHandle != nullptr); CHECK(localSet.registerVariable(variableHandle) == static_cast(DataSetIF::DATA_SET_FULL)); variableHandle = nullptr; @@ -209,7 +208,7 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { } SECTION("MorePoolVariables") { - LocalDataSet set(poolOwner, 2, 10); + LocalDataSet set(&poolOwner, 2, 10); /* Register same variables again to get more than 8 registered variables */ for (uint8_t idx = 0; idx < 8; idx++) { @@ -234,7 +233,7 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { uint8_t* buffPtr = buffer; CHECK(set.serialize(&buffPtr, &serSize, maxSize, SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); - std::array validityBuffer; + std::array validityBuffer{}; std::memcpy(validityBuffer.data(), buffer + 9 + sizeof(uint16_t) * 3, 2); /* The first 9 variables should be valid */ CHECK(validityBuffer[0] == 0xff); @@ -258,7 +257,7 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { SECTION("SharedDataSet") { object_id_t sharedSetId = objects::SHARED_SET_ID; - SharedLocalDataSet sharedSet(sharedSetId, poolOwner, lpool::testSetId, 5); + SharedLocalDataSet sharedSet(sharedSetId, &poolOwner, lpool::testSetId, 5); localSet.localPoolVarUint8.setReadWriteMode(pool_rwm_t::VAR_WRITE); localSet.localPoolUint16Vec.setReadWriteMode(pool_rwm_t::VAR_WRITE); CHECK(sharedSet.registerVariable(&localSet.localPoolVarUint8) == retval::CATCH_OK); @@ -279,8 +278,4 @@ TEST_CASE("DataSetTest", "[DataSetTest]") { sharedSet.setReadCommitProtectionBehaviour(true); } - - /* we need to reset the subscription list because the pool owner - is a global object. */ - CHECK(poolOwner->reset() == retval::CATCH_OK); } diff --git a/unittests/datapoollocal/testLocalPoolManager.cpp b/unittests/datapoollocal/testLocalPoolManager.cpp new file mode 100644 index 000000000..9c979df2e --- /dev/null +++ b/unittests/datapoollocal/testLocalPoolManager.cpp @@ -0,0 +1,430 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "CatchDefinitions.h" +#include "LocalPoolOwnerBase.h" +#include "mocks/HkReceiverMock.h" + +TEST_CASE("Local Pool Manager Tests", "[LocManTest]") { + const MessageQueueId_t defaultDestId = 1; + const MessageQueueId_t hkDest = defaultDestId; + const MessageQueueId_t subscriberId = 2; + auto hkReceiver = HkReceiverMock(hkDest); + auto queue = MessageQueueMockBase(); + LocalPoolOwnerBase poolOwner(queue, objects::TEST_LOCAL_POOL_OWNER_BASE); + REQUIRE(poolOwner.initializeHkManager() == retval::CATCH_OK); + REQUIRE(poolOwner.initializeHkManagerAfterTaskCreation() == retval::CATCH_OK); + + MessageQueueMockBase& poolOwnerMock = poolOwner.getMockQueueHandle(); + + // TODO: This is ugly. This should be an arbitrary ctor argument. Fix this in the pool + // manager + poolOwnerMock.setDefaultDestination(defaultDestId); + poolOwner.setHkDestId(hkDest); + + auto* hkMan = poolOwner.getHkManagerHandle(); + + CommandMessage messageSent; + + SECTION("Basic Test") { + { + /* For code coverage, should not crash */ + LocalDataPoolManager manager(nullptr, nullptr); + } + auto owner = poolOwner.poolManager.getOwner(); + REQUIRE(owner != nullptr); + CHECK(owner->getObjectId() == objects::TEST_LOCAL_POOL_OWNER_BASE); + + /* Subscribe for message generation on update. */ + REQUIRE(poolOwner.subscribeWrapperSetUpdate(subscriberId) == retval::CATCH_OK); + /* Subscribe for an update message. */ + poolOwner.dataset.setChanged(true); + /* Now the update message should be generated. */ + REQUIRE(poolOwner.poolManager.performHkOperation() == retval::CATCH_OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == retval::CATCH_OK); + CHECK(messageSent.getCommand() == + static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); + + /* Should have been reset. */ + CHECK(poolOwner.dataset.hasChanged() == false); + poolOwnerMock.clearMessages(true); + /* Set changed again, result should be the same. */ + poolOwner.dataset.setChanged(true); + REQUIRE(poolOwner.poolManager.performHkOperation() == retval::CATCH_OK); + + REQUIRE(poolOwnerMock.wasMessageSent() == true); + CHECK(poolOwnerMock.numberOfSentMessage() == 1); + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == retval::CATCH_OK); + CHECK(messageSent.getCommand() == + static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); + + poolOwnerMock.clearMessages(true); + /* Now subscribe for set update HK as well. */ + REQUIRE(poolOwner.subscribeWrapperSetUpdateHk(false, &hkReceiver) == retval::CATCH_OK); + poolOwner.dataset.setChanged(true); + REQUIRE(poolOwner.poolManager.performHkOperation() == retval::CATCH_OK); + REQUIRE(poolOwnerMock.wasMessageSent() == true); + CHECK(poolOwnerMock.numberOfSentMessage() == 2); + // first message sent should be the update notification + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == retval::CATCH_OK); + CHECK(messageSent.getCommand() == + static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); + REQUIRE(poolOwnerMock.getNextSentMessage(messageSent) == retval::CATCH_OK); + CHECK(messageSent.getCommand() == static_cast(HousekeepingMessage::HK_REPORT)); + /* Clear message to avoid memory leak, our mock won't do it for us (yet) */ + CommandMessageCleaner::clearCommandMessage(&messageSent); + } + + SECTION("SetSnapshotUpdateTest") { + /* Set the variables in the set to certain values. These are checked later. */ + { + PoolReadGuard readHelper(&poolOwner.dataset); + REQUIRE(readHelper.getReadResult() == retval::CATCH_OK); + poolOwner.dataset.localPoolVarUint8.value = 5; + poolOwner.dataset.localPoolVarFloat.value = -12.242; + poolOwner.dataset.localPoolUint16Vec.value[0] = 2; + poolOwner.dataset.localPoolUint16Vec.value[1] = 32; + poolOwner.dataset.localPoolUint16Vec.value[2] = 42932; + } + + /* Subscribe for snapshot generation on update. */ + REQUIRE(poolOwner.subscribeWrapperSetUpdateSnapshot(subscriberId) == retval::CATCH_OK); + poolOwner.dataset.setChanged(true); + + /* Store current time, we are going to check the (approximate) time equality later */ + timeval now{}; + Clock::getClock_timeval(&now); + + /* Trigger generation of snapshot */ + REQUIRE(poolOwner.poolManager.performHkOperation() == retval::CATCH_OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessage() == 1); + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == retval::CATCH_OK); + /* Check that snapshot was generated */ + CHECK(messageSent.getCommand() == static_cast(HousekeepingMessage::UPDATE_SNAPSHOT_SET)); + /* Now we deserialize the snapshot into a new dataset instance */ + CCSDSTime::CDS_short cdsShort{}; + LocalPoolTestDataSet newSet; + HousekeepingSnapshot snapshot(&cdsShort, &newSet); + store_address_t storeId; + HousekeepingMessage::getUpdateSnapshotSetCommand(&messageSent, &storeId); + ConstAccessorPair accessorPair = tglob::getIpcStoreHandle()->getData(storeId); + REQUIRE(accessorPair.first == retval::CATCH_OK); + const uint8_t* readOnlyPtr = accessorPair.second.data(); + size_t sizeToDeserialize = accessorPair.second.size(); + CHECK(newSet.localPoolVarFloat.value == 0); + CHECK(newSet.localPoolVarUint8 == 0); + CHECK(newSet.localPoolUint16Vec.value[0] == 0); + CHECK(newSet.localPoolUint16Vec.value[1] == 0); + CHECK(newSet.localPoolUint16Vec.value[2] == 0); + /* Fill the dataset and timestamp */ + REQUIRE(snapshot.deSerialize(&readOnlyPtr, &sizeToDeserialize, + SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); + /* Now we check that the snapshot is actually correct */ + CHECK(newSet.localPoolVarFloat.value == Catch::Approx(-12.242)); + CHECK(newSet.localPoolVarUint8 == 5); + CHECK(newSet.localPoolUint16Vec.value[0] == 2); + CHECK(newSet.localPoolUint16Vec.value[1] == 32); + CHECK(newSet.localPoolUint16Vec.value[2] == 42932); + + /* Now we check that both times are equal */ + timeval timeFromHK{}; + auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort); + CHECK(result == HasReturnvaluesIF::RETURN_OK); + timeval difference = timeFromHK - now; + CHECK(timevalOperations::toDouble(difference) < 1.0); + } + + SECTION("VariableSnapshotTest") { + /* Acquire subscription interface */ + ProvidesDataPoolSubscriptionIF* subscriptionIF = poolOwner.getSubscriptionInterface(); + REQUIRE(subscriptionIF != nullptr); + + /* Subscribe for variable snapshot */ + REQUIRE(poolOwner.subscribeWrapperVariableSnapshot(subscriberId, lpool::uint8VarId) == + retval::CATCH_OK); + auto poolVar = + dynamic_cast*>(poolOwner.getPoolObjectHandle(lpool::uint8VarId)); + REQUIRE(poolVar != nullptr); + + { + PoolReadGuard rg(poolVar); + CHECK(rg.getReadResult() == retval::CATCH_OK); + poolVar->value = 25; + } + + poolVar->setChanged(true); + /* Store current time, we are going to check the (approximate) time equality later */ + CCSDSTime::CDS_short timeCdsNow{}; + timeval now{}; + Clock::getClock_timeval(&now); + REQUIRE(poolOwner.poolManager.performHkOperation() == retval::CATCH_OK); + + /* Check update snapshot was sent. */ + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessage() == 1); + + /* Should have been reset. */ + CHECK(poolVar->hasChanged() == false); + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == retval::CATCH_OK); + CHECK(messageSent.getCommand() == + static_cast(HousekeepingMessage::UPDATE_SNAPSHOT_VARIABLE)); + /* Now we deserialize the snapshot into a new dataset instance */ + CCSDSTime::CDS_short cdsShort{}; + lp_var_t varCopy = lp_var_t(lpool::uint8VarGpid); + HousekeepingSnapshot snapshot(&cdsShort, &varCopy); + store_address_t storeId; + HousekeepingMessage::getUpdateSnapshotVariableCommand(&messageSent, &storeId); + ConstAccessorPair accessorPair = tglob::getIpcStoreHandle()->getData(storeId); + REQUIRE(accessorPair.first == retval::CATCH_OK); + const uint8_t* readOnlyPtr = accessorPair.second.data(); + size_t sizeToDeserialize = accessorPair.second.size(); + CHECK(varCopy.value == 0); + /* Fill the dataset and timestamp */ + REQUIRE(snapshot.deSerialize(&readOnlyPtr, &sizeToDeserialize, + SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); + CHECK(varCopy.value == 25); + + /* Now we check that both times are equal */ + timeval timeFromHK{}; + auto result = CCSDSTime::convertFromCDS(&timeFromHK, &cdsShort); + CHECK(result == HasReturnvaluesIF::RETURN_OK); + timeval difference = timeFromHK - now; + CHECK(timevalOperations::toDouble(difference) < 1.0); + } + + SECTION("VariableNotificationTest") { + /* Acquire subscription interface */ + ProvidesDataPoolSubscriptionIF* subscriptionIF = poolOwner.getSubscriptionInterface(); + REQUIRE(subscriptionIF != nullptr); + + /* Subscribe for variable update */ + REQUIRE(poolOwner.subscribeWrapperVariableUpdate(subscriberId, lpool::uint8VarId) == + retval::CATCH_OK); + auto* poolVar = + dynamic_cast*>(poolOwner.getPoolObjectHandle(lpool::uint8VarId)); + REQUIRE(poolVar != nullptr); + poolVar->setChanged(true); + REQUIRE(poolVar->hasChanged() == true); + REQUIRE(poolOwner.poolManager.performHkOperation() == retval::CATCH_OK); + + /* Check update notification was sent. */ + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessage() == 1); + /* Should have been reset. */ + CHECK(poolVar->hasChanged() == false); + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == retval::CATCH_OK); + CHECK(messageSent.getCommand() == + static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE)); + /* Now subscribe for the dataset update (HK and update) again with subscription interface */ + REQUIRE(subscriptionIF->subscribeForSetUpdateMessage(lpool::testSetId, objects::NO_OBJECT, + subscriberId, false) == retval::CATCH_OK); + REQUIRE(poolOwner.subscribeWrapperSetUpdateHk(false, &hkReceiver) == retval::CATCH_OK); + + poolOwner.dataset.setChanged(true); + poolOwnerMock.clearMessages(); + REQUIRE(poolOwner.poolManager.performHkOperation() == retval::CATCH_OK); + /* Now two messages should be sent. */ + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessage() == 2); + poolOwnerMock.clearMessages(true); + + poolOwner.dataset.setChanged(true); + poolOwnerMock.clearMessages(true); + poolVar->setChanged(true); + REQUIRE(poolOwner.poolManager.performHkOperation() == retval::CATCH_OK); + /* Now three messages should be sent. */ + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessage() == 3); + CHECK(poolOwnerMock.numberOfSentMessage(subscriberId) == 2); + CHECK(poolOwnerMock.numberOfSentMessage(hkDest) == 1); + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == retval::CATCH_OK); + CHECK(messageSent.getCommand() == + static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE)); + REQUIRE(poolOwnerMock.clearLastSentMessage(subscriberId) == HasReturnvaluesIF::RETURN_OK); + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == + HasReturnvaluesIF::RETURN_OK); + CHECK(messageSent.getCommand() == + static_cast(HousekeepingMessage::UPDATE_NOTIFICATION_SET)); + REQUIRE(poolOwnerMock.clearLastSentMessage(subscriberId) == HasReturnvaluesIF::RETURN_OK); + REQUIRE(poolOwnerMock.getNextSentMessage(messageSent) == retval::CATCH_OK); + CHECK(messageSent.getCommand() == static_cast(HousekeepingMessage::HK_REPORT)); + REQUIRE(poolOwnerMock.clearLastSentMessage() == HasReturnvaluesIF::RETURN_OK); + REQUIRE(poolOwnerMock.getNextSentMessage(subscriberId, messageSent) == MessageQueueIF::EMPTY); + REQUIRE(poolOwnerMock.getNextSentMessage(messageSent) == MessageQueueIF::EMPTY); + } + + SECTION("PeriodicHKAndMessaging") { + /* Now we subcribe for a HK periodic generation. Even when it's difficult to simulate + the temporal behaviour correctly the HK manager should generate a HK packet + immediately and the periodic helper depends on HK op function calls anyway instead of + using the clock, so we could also just call performHkOperation multiple times */ + REQUIRE(poolOwner.subscribePeriodicHk(true) == retval::CATCH_OK); + REQUIRE(poolOwner.poolManager.performHkOperation() == retval::CATCH_OK); + /* Now HK packet should be sent as message immediately. */ + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessage() == 1); + CHECK(poolOwnerMock.clearLastSentMessage() == retval::CATCH_OK); + + LocalPoolDataSetBase* setHandle = poolOwner.getDataSetHandle(lpool::testSid); + REQUIRE(setHandle != nullptr); + CHECK(poolOwner.poolManager.generateHousekeepingPacket(lpool::testSid, setHandle, false) == + retval::CATCH_OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessage() == 1); + CHECK(poolOwnerMock.clearLastSentMessage() == retval::CATCH_OK); + + CHECK(setHandle->getReportingEnabled() == true); + CommandMessage hkCmd; + HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + CHECK(setHandle->getReportingEnabled() == false); + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.numberOfSentMessage() == 1); + CHECK(poolOwnerMock.clearLastSentMessage() == retval::CATCH_OK); + + HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, true, false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + CHECK(setHandle->getReportingEnabled() == true); + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.clearLastSentMessage() == retval::CATCH_OK); + + HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + CHECK(setHandle->getReportingEnabled() == false); + REQUIRE(poolOwnerMock.wasMessageSent()); + CHECK(poolOwnerMock.clearLastSentMessage() == retval::CATCH_OK); + + HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4, + false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + /* For non-diagnostics and a specified minimum frequency of 0.2 seconds, the + resulting collection interval should be 1.0 second */ + CHECK(poolOwner.dataset.getCollectionInterval() == 1.0); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessage() == 1); + CHECK(poolOwnerMock.clearLastSentMessage() == retval::CATCH_OK); + + HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false); + REQUIRE(poolOwner.poolManager.performHkOperation() == retval::CATCH_OK); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + /* Now HK packet should be sent as message. */ + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessage() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessage() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setUpdateNotificationSetCommand(&hkCmd, lpool::testSid); + sid_t sidToCheck; + store_address_t storeId; + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + CHECK(poolOwner.changedDataSetCallbackWasCalled(sidToCheck, storeId) == true); + CHECK(sidToCheck == lpool::testSid); + + /* Now we test the handling is the dataset is set to diagnostic */ + poolOwner.dataset.setDiagnostic(true); + + HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == + static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); + /* We still expect a failure message being sent */ + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessage() == 1); + CHECK(poolOwnerMock.clearLastSentMessage() == retval::CATCH_OK); + + HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4, + false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == + static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessage() == 1); + CHECK(poolOwnerMock.clearLastSentMessage() == retval::CATCH_OK); + + HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == + static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessage() == 1); + CHECK(poolOwnerMock.clearLastSentMessage() == retval::CATCH_OK); + + HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, true); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessage() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4, + true); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessage() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, true, true); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessage() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, true); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessage() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, false); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == + static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessage() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, true); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + REQUIRE(poolOwnerMock.wasMessageSent()); + REQUIRE(poolOwnerMock.numberOfSentMessage() == 1); + poolOwnerMock.clearMessages(); + + HousekeepingMessage::setUpdateNotificationVariableCommand(&hkCmd, lpool::uint8VarGpid); + gp_id_t gpidToCheck; + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + CHECK(poolOwner.changedVariableCallbackWasCalled(gpidToCheck, storeId) == true); + CHECK(gpidToCheck == lpool::uint8VarGpid); + + HousekeepingMessage::setUpdateSnapshotSetCommand(&hkCmd, lpool::testSid, + store_address_t::invalid()); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + CHECK(poolOwner.changedDataSetCallbackWasCalled(sidToCheck, storeId) == true); + CHECK(sidToCheck == lpool::testSid); + + HousekeepingMessage::setUpdateSnapshotVariableCommand(&hkCmd, lpool::uint8VarGpid, + store_address_t::invalid()); + CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK); + CHECK(poolOwner.changedVariableCallbackWasCalled(gpidToCheck, storeId) == true); + CHECK(gpidToCheck == lpool::uint8VarGpid); + + poolOwner.poolManager.printPoolEntry(lpool::uint8VarId); + } + + /* we need to reset the subscription list because the pool owner + is a global object. */ + CHECK(poolOwner.reset() == retval::CATCH_OK); + poolOwnerMock.clearMessages(true); +} diff --git a/unittests/datapoollocal/LocalPoolVariableTest.cpp b/unittests/datapoollocal/testLocalPoolVariable.cpp similarity index 100% rename from unittests/datapoollocal/LocalPoolVariableTest.cpp rename to unittests/datapoollocal/testLocalPoolVariable.cpp diff --git a/unittests/datapoollocal/LocalPoolVectorTest.cpp b/unittests/datapoollocal/testLocalPoolVector.cpp similarity index 98% rename from unittests/datapoollocal/LocalPoolVectorTest.cpp rename to unittests/datapoollocal/testLocalPoolVector.cpp index 2235ad39b..331d4e094 100644 --- a/unittests/datapoollocal/LocalPoolVectorTest.cpp +++ b/unittests/datapoollocal/testLocalPoolVector.cpp @@ -4,11 +4,11 @@ #include #include "CatchDefinitions.h" -#include "LocalPoolOwnerBase.h" +#include "mocks/LocalPoolOwnerBase.h" #include "tests/TestsConfig.h" TEST_CASE("LocalPoolVector", "[LocPoolVecTest]") { - LocalPoolOwnerBase* poolOwner = + auto* poolOwner = ObjectManager::instance()->get(objects::TEST_LOCAL_POOL_OWNER_BASE); REQUIRE(poolOwner != nullptr); REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); diff --git a/unittests/mocks/CdsShortTimestamperMock.h b/unittests/mocks/CdsShortTimestamperMock.h index 273cf24c5..784ef7f48 100644 --- a/unittests/mocks/CdsShortTimestamperMock.h +++ b/unittests/mocks/CdsShortTimestamperMock.h @@ -3,8 +3,8 @@ #include -#include "fsfw/timemanager/TimeStamperIF.h" #include "fsfw/timemanager/TimeReaderIF.h" +#include "fsfw/timemanager/TimeStamperIF.h" class CdsShortTimestamperMock : public TimeStamperIF, public TimeReaderIF { public: @@ -75,7 +75,7 @@ class CdsShortTimestamperMock : public TimeStamperIF, public TimeReaderIF { serFailRetval = HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t readTimeStamp(const uint8_t* buffer, size_t maxSize) override { + ReturnValue_t readTimeStamp(const uint8_t *buffer, size_t maxSize) override { return deSerialize(&buffer, &maxSize, SerializeIF::Endianness::NETWORK); } size_t getTimestampLen() override { return getSerializedSize(); } diff --git a/unittests/mocks/HkReceiverMock.h b/unittests/mocks/HkReceiverMock.h index 8d4b49834..33a43a81b 100644 --- a/unittests/mocks/HkReceiverMock.h +++ b/unittests/mocks/HkReceiverMock.h @@ -2,13 +2,15 @@ #define FSFW_UNITTEST_TESTS_MOCKS_HKRECEIVERMOCK_H_ #include -#include -class HkReceiverMock : public SystemObject, public AcceptsHkPacketsIF { +class HkReceiverMock : public AcceptsHkPacketsIF { public: - HkReceiverMock(object_id_t objectId) : SystemObject(objectId) {} + explicit HkReceiverMock(MessageQueueId_t queueId) : queueId(queueId) {} - MessageQueueId_t getHkQueue() const { return MessageQueueIF::NO_QUEUE; } + [[nodiscard]] MessageQueueId_t getHkQueue() const override { return queueId; } + + private: + MessageQueueId_t queueId; }; #endif /* FSFW_UNITTEST_TESTS_MOCKS_HKRECEIVERMOCK_H_ */ diff --git a/unittests/mocks/InternalErrorReporterMock.cpp b/unittests/mocks/InternalErrorReporterMock.cpp index 9988234b2..c7758a13d 100644 --- a/unittests/mocks/InternalErrorReporterMock.cpp +++ b/unittests/mocks/InternalErrorReporterMock.cpp @@ -2,12 +2,6 @@ InternalErrorReporterMock::InternalErrorReporterMock() = default; -void InternalErrorReporterMock::queueMessageNotSent() { - queueMsgNotSentCallCnt++; -} -void InternalErrorReporterMock::lostTm() { - lostTmCallCnt++; -} -void InternalErrorReporterMock::storeFull() { - storeFullCallCnt++; -} +void InternalErrorReporterMock::queueMessageNotSent() { queueMsgNotSentCallCnt++; } +void InternalErrorReporterMock::lostTm() { lostTmCallCnt++; } +void InternalErrorReporterMock::storeFull() { storeFullCallCnt++; } diff --git a/unittests/mocks/InternalErrorReporterMock.h b/unittests/mocks/InternalErrorReporterMock.h index d29216305..f6babe091 100644 --- a/unittests/mocks/InternalErrorReporterMock.h +++ b/unittests/mocks/InternalErrorReporterMock.h @@ -3,7 +3,7 @@ #include "fsfw/internalerror/InternalErrorReporterIF.h" -class InternalErrorReporterMock: public InternalErrorReporterIF { +class InternalErrorReporterMock : public InternalErrorReporterIF { public: unsigned int queueMsgNotSentCallCnt = 0; unsigned int lostTmCallCnt = 0; diff --git a/unittests/datapoollocal/LocalPoolOwnerBase.cpp b/unittests/mocks/LocalPoolOwnerBase.cpp similarity index 90% rename from unittests/datapoollocal/LocalPoolOwnerBase.cpp rename to unittests/mocks/LocalPoolOwnerBase.cpp index 2743e7f71..f269e066a 100644 --- a/unittests/datapoollocal/LocalPoolOwnerBase.cpp +++ b/unittests/mocks/LocalPoolOwnerBase.cpp @@ -1,18 +1,17 @@ #include "LocalPoolOwnerBase.h" -LocalPoolOwnerBase::LocalPoolOwnerBase(object_id_t objectId) - : SystemObject(objectId), poolManager(this, messageQueue), dataset(this, lpool::testSetId) { - messageQueue = new MessageQueueMockBase(); -} +LocalPoolOwnerBase::LocalPoolOwnerBase(MessageQueueIF &queue, object_id_t objectId) + : SystemObject(objectId), + queue(queue), + poolManager(this, &queue), + dataset(this, lpool::testSetId) {} -LocalPoolOwnerBase::~LocalPoolOwnerBase() { - QueueFactory::instance()->deleteMessageQueue(messageQueue); -} +LocalPoolOwnerBase::~LocalPoolOwnerBase() = default; ReturnValue_t LocalPoolOwnerBase::initializeHkManager() { if (not initialized) { initialized = true; - return poolManager.initialize(messageQueue); + return poolManager.initialize(&queue); } return HasReturnvaluesIF::RETURN_OK; } @@ -125,3 +124,5 @@ void LocalPoolOwnerBase::handleChangedPoolVariable(gp_id_t globPoolId, store_add this->changedPoolVariableGpid = globPoolId; this->storeIdForChangedVariable = storeId; } + +void LocalPoolOwnerBase::setHkDestId(MessageQueueId_t id) { poolManager.setHkDestinationId(id); } diff --git a/unittests/datapoollocal/LocalPoolOwnerBase.h b/unittests/mocks/LocalPoolOwnerBase.h similarity index 68% rename from unittests/datapoollocal/LocalPoolOwnerBase.h rename to unittests/mocks/LocalPoolOwnerBase.h index 0bcebc00d..1dcd6cf28 100644 --- a/unittests/datapoollocal/LocalPoolOwnerBase.h +++ b/unittests/mocks/LocalPoolOwnerBase.h @@ -64,26 +64,29 @@ class LocalPoolTestDataSet : public LocalDataSet { class LocalPoolOwnerBase : public SystemObject, public HasLocalDataPoolIF { public: - LocalPoolOwnerBase(object_id_t objectId = objects::TEST_LOCAL_POOL_OWNER_BASE); + explicit LocalPoolOwnerBase(MessageQueueIF& queue, + object_id_t objectId = objects::TEST_LOCAL_POOL_OWNER_BASE); - ~LocalPoolOwnerBase(); + ~LocalPoolOwnerBase() override; - object_id_t getObjectId() const override { return SystemObject::getObjectId(); } + [[nodiscard]] object_id_t getObjectId() const override { return SystemObject::getObjectId(); } ReturnValue_t initializeHkManager(); + void setHkDestId(MessageQueueId_t id); + ReturnValue_t initializeHkManagerAfterTaskCreation(); /** Command queue for housekeeping messages. */ - MessageQueueId_t getCommandQueue() const override { return messageQueue->getId(); } + [[nodiscard]] MessageQueueId_t getCommandQueue() const override { return queue.getId(); } // This is called by initializeAfterTaskCreation of the HK manager. - virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, - LocalDataPoolManager& poolManager) override; + ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; LocalDataPoolManager* getHkManagerHandle() override { return &poolManager; } - dur_millis_t getPeriodicOperationFrequency() const override { return 200; } + [[nodiscard]] dur_millis_t getPeriodicOperationFrequency() const override { return 200; } /** * This function is used by the pool manager to get a valid dataset @@ -91,41 +94,54 @@ class LocalPoolOwnerBase : public SystemObject, public HasLocalDataPoolIF { * @param sid Corresponding structure ID * @return */ - virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override { return &dataset; } + LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override { return &dataset; } - virtual LocalPoolObjectBase* getPoolObjectHandle(lp_id_t localPoolId) override; + LocalPoolObjectBase* getPoolObjectHandle(lp_id_t localPoolId) override; - MessageQueueMockBase* getMockQueueHandle() const { - return dynamic_cast(messageQueue); + [[nodiscard]] MessageQueueMockBase& getMockQueueHandle() const { + return dynamic_cast(queue); } ReturnValue_t subscribePeriodicHk(bool enableReporting) { - return poolManager.subscribeForPeriodicPacket(lpool::testSid, enableReporting, 0.2, false); + return poolManager.subscribeForRegularPeriodicPacket( + subdp::RegularHkPeriodicParams(lpool::testSid, enableReporting, 0.2)); } - ReturnValue_t subscribeWrapperSetUpdate() { + ReturnValue_t subscribeWrapperSetUpdate(MessageQueueId_t receiverId) { return poolManager.subscribeForSetUpdateMessage(lpool::testSetId, objects::NO_OBJECT, - objects::HK_RECEIVER_MOCK, false); + receiverId, false); } - ReturnValue_t subscribeWrapperSetUpdateSnapshot() { + ReturnValue_t subscribeWrapperSetUpdateSnapshot(MessageQueueId_t receiverId) { return poolManager.subscribeForSetUpdateMessage(lpool::testSetId, objects::NO_OBJECT, - objects::HK_RECEIVER_MOCK, true); + receiverId, true); } - ReturnValue_t subscribeWrapperSetUpdateHk(bool diagnostics = false) { - return poolManager.subscribeForUpdatePacket(lpool::testSid, diagnostics, false, - objects::HK_RECEIVER_MOCK); + ReturnValue_t subscribeWrapperSetUpdateHk(bool diagnostics = false, + AcceptsHkPacketsIF* receiver = nullptr) { + if (diagnostics) { + auto params = subdp::DiagnosticsHkUpdateParams(lpool::testSid, true); + if (receiver != nullptr) { + params.receiver = receiver->getHkQueue(); + } + return poolManager.subscribeForDiagUpdatePacket(params); + } else { + auto params = subdp::RegularHkUpdateParams(lpool::testSid, true); + if (receiver != nullptr) { + params.receiver = receiver->getHkQueue(); + } + return poolManager.subscribeForRegularUpdatePacket(params); + } } - ReturnValue_t subscribeWrapperVariableUpdate(lp_id_t localPoolId) { + ReturnValue_t subscribeWrapperVariableUpdate(MessageQueueId_t receiverId, lp_id_t localPoolId) { return poolManager.subscribeForVariableUpdateMessage(localPoolId, MessageQueueIF::NO_QUEUE, - objects::HK_RECEIVER_MOCK, false); + receiverId, false); } - ReturnValue_t subscribeWrapperVariableSnapshot(lp_id_t localPoolId) { + ReturnValue_t subscribeWrapperVariableSnapshot(MessageQueueId_t receiverId, lp_id_t localPoolId) { return poolManager.subscribeForVariableUpdateMessage(localPoolId, MessageQueueIF::NO_QUEUE, - objects::HK_RECEIVER_MOCK, true); + receiverId, true); } ReturnValue_t reset(); @@ -155,7 +171,7 @@ class LocalPoolOwnerBase : public SystemObject, public HasLocalDataPoolIF { lp_vec_t testUint16Vec = lp_vec_t(this, lpool::uint16Vec3Id); lp_vec_t testInt64Vec = lp_vec_t(this, lpool::int64Vec2Id); - MessageQueueIF* messageQueue = nullptr; + MessageQueueIF& queue; bool initialized = false; bool initializedAfterTaskCreation = false; diff --git a/unittests/mocks/MessageQueueMockBase.cpp b/unittests/mocks/MessageQueueMockBase.cpp index 63caee26e..16388e256 100644 --- a/unittests/mocks/MessageQueueMockBase.cpp +++ b/unittests/mocks/MessageQueueMockBase.cpp @@ -1,5 +1,7 @@ #include "MessageQueueMockBase.h" +#include +#include MessageQueueMockBase::MessageQueueMockBase() : MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, nullptr) {} @@ -7,32 +9,47 @@ MessageQueueMockBase::MessageQueueMockBase() MessageQueueMockBase::MessageQueueMockBase(MessageQueueId_t queueId) : MessageQueueBase(queueId, MessageQueueIF::NO_QUEUE, nullptr) {} -bool MessageQueueMockBase::wasMessageSent(uint8_t* messageSentCounter_, bool resetCounter) { - bool tempMessageSent = messageSent; - messageSent = false; - if (messageSentCounter_ != nullptr) { - *messageSentCounter_ = this->messageSentCounter; - } - if (resetCounter) { - this->messageSentCounter = 0; - } - return tempMessageSent; +bool MessageQueueMockBase::wasMessageSent() const { + return std::any_of( + sendMap.begin(), sendMap.end(), + [](const std::pair& pair) { return pair.second.callCount > 0; }); } -ReturnValue_t MessageQueueMockBase::popMessage() { - CommandMessage message; - message.clear(); - return receiveMessage(&message); +size_t MessageQueueMockBase::numberOfSentMessage() const { + size_t callCount = 0; + for (auto& destInfo : sendMap) { + callCount += destInfo.second.callCount; + } + return callCount; +} + +size_t MessageQueueMockBase::numberOfSentMessage(MessageQueueId_t id) const { + auto iter = sendMap.find(id); + if (iter == sendMap.end()) { + return 0; + } + return iter->second.callCount; +} + +ReturnValue_t MessageQueueMockBase::clearLastReceivedMessage(bool clearCmdMsg) { + if (receivedMsgs.empty()) { + return MessageQueueIF::EMPTY; + } + if (clearCmdMsg) { + CommandMessage message; + std::memcpy(message.getBuffer(), receivedMsgs.front().getBuffer(), message.getMessageSize()); + message.clearCommandMessage(); + } + receivedMsgs.pop_front(); + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t MessageQueueMockBase::receiveMessage(MessageQueueMessageIF* message) { - if (messagesSentQueue.empty()) { + if (receivedMsgs.empty()) { return MessageQueueIF::EMPTY; } - this->last = message->getSender(); - std::memcpy(message->getBuffer(), messagesSentQueue.front().getBuffer(), - message->getMessageSize()); - messagesSentQueue.pop(); + std::memcpy(message->getBuffer(), receivedMsgs.front().getBuffer(), message->getMessageSize()); + receivedMsgs.pop_front(); return HasReturnvaluesIF::RETURN_OK; } @@ -43,12 +60,18 @@ ReturnValue_t MessageQueueMockBase::flush(uint32_t* count) { ReturnValue_t MessageQueueMockBase::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, MessageQueueId_t sentFrom, bool ignoreFault) { + if (message == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } auto iter = sendMap.find(sendTo); + MessageQueueMessage messageCopy; if (iter == sendMap.end()) { - sendMap.emplace(sendTo, SendInfo(message, 1)); + createMsgCopy(messageCopy, *message); + sendMap.emplace(sendTo, SendInfo(messageCopy, 1)); } else { iter->second.callCount += 1; - iter->second.msgs.push(message); + createMsgCopy(messageCopy, *message); + iter->second.msgs.push_back(messageCopy); } return HasReturnvaluesIF::RETURN_OK; } @@ -58,19 +81,87 @@ ReturnValue_t MessageQueueMockBase::reply(MessageQueueMessageIF* message) { } void MessageQueueMockBase::clearMessages(bool clearCommandMessages) { - for (const auto& destInfo: sendMap) { - if (clearCommandMessages) { - CommandMessage message; - std::memcpy(message.getBuffer(), destInfo.second.msgs.front()->getBuffer(), - message.getMessageSize()); + if (not clearCommandMessages) { + sendMap.clear(); + return; } - while (not messagesSentQueue.empty()) { - if (clearCommandMessages) { + for (auto& destInfo : sendMap) { + for (auto& msg : destInfo.second.msgs) { CommandMessage message; - std::memcpy(message.getBuffer(), messagesSentQueue.front().getBuffer(), + std::memcpy(message.getBuffer(), destInfo.second.msgs.front().getBuffer(), message.getMessageSize()); message.clear(); + destInfo.second.msgs.pop_front(); + destInfo.second.callCount--; + } + } + sendMap.clear(); +} + +void MessageQueueMockBase::addReceivedMessage(MessageQueueMessageIF& msg) { + MessageQueueMessage messageCopy; + createMsgCopy(messageCopy, msg); + receivedMsgs.push_back(messageCopy); +} + +void MessageQueueMockBase::createMsgCopy(MessageQueueMessageIF& into, MessageQueueMessageIF& from) { + if (from.getMessageSize() > into.getMaximumDataSize()) { + throw std::invalid_argument("Passed message does not fit into message copy"); + } + std::memcpy(into.getBuffer(), from.getBuffer(), from.getMaximumDataSize()); +} + +ReturnValue_t MessageQueueMockBase::getNextSentMessage(MessageQueueId_t id, + MessageQueueMessageIF& message) { + auto iter = sendMap.find(id); + if (iter == sendMap.end() or iter->second.callCount == 0) { + return MessageQueueIF::EMPTY; + } + createMsgCopy(message, iter->second.msgs.front()); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t MessageQueueMockBase::getNextSentMessage(MessageQueueMessageIF& message) { + return getNextSentMessage(MessageQueueBase::getDefaultDestination(), message); +} + +ReturnValue_t MessageQueueMockBase::clearLastSentMessage(MessageQueueId_t destId, + bool clearCmdMsg) { + auto iter = sendMap.find(destId); + if (iter == sendMap.end()) { + return MessageQueueIF::EMPTY; + } + return clearLastSentMessage(iter, clearCmdMsg); +} + +ReturnValue_t MessageQueueMockBase::clearLastSentMessage(bool clearCmdMsg) { + auto iter = sendMap.find(getDefaultDestination()); + if (iter == sendMap.end()) { + return MessageQueueIF::EMPTY; + } + ReturnValue_t result = clearLastSentMessage(iter, clearCmdMsg); + clearEmptyEntries(); + return result; +} + +ReturnValue_t MessageQueueMockBase::clearLastSentMessage( + std::map::iterator& iter, bool clearCmdMsg) { + if (clearCmdMsg) { + CommandMessage message; + std::memcpy(message.getBuffer(), iter->second.msgs.front().getBuffer(), + message.getMessageSize()); + message.clear(); + } + iter->second.msgs.pop_front(); + iter->second.callCount--; + return HasReturnvaluesIF::RETURN_OK; +} +void MessageQueueMockBase::clearEmptyEntries() { + for (auto it = sendMap.cbegin(); it != sendMap.cend();) { + if (it->second.callCount == 0) { + sendMap.erase(it++); + } else { + ++it; } - messagesSentQueue.pop(); } } diff --git a/unittests/mocks/MessageQueueMockBase.h b/unittests/mocks/MessageQueueMockBase.h index e42a0a671..fa63b1719 100644 --- a/unittests/mocks/MessageQueueMockBase.h +++ b/unittests/mocks/MessageQueueMockBase.h @@ -2,8 +2,8 @@ #define FSFW_UNITTEST_TESTS_MOCKS_MESSAGEQUEUEMOCKBASE_H_ #include -#include #include +#include #include "CatchDefinitions.h" #include "fsfw/ipc/CommandMessage.h" @@ -12,39 +12,52 @@ #include "fsfw/ipc/MessageQueueMessage.h" struct SendInfo { - explicit SendInfo(MessageQueueMessageIF* initMsg, unsigned int initCallCnt = 1): callCount(initCallCnt) { - msgs.push(initMsg); + explicit SendInfo(MessageQueueMessage& initMsg, unsigned int initCallCnt = 1) + : callCount(initCallCnt) { + msgs.push_back(initMsg); } unsigned int callCount = 0; - std::queue msgs; + std::deque msgs; }; class MessageQueueMockBase : public MessageQueueBase { public: MessageQueueMockBase(); + void addReceivedMessage(MessageQueueMessageIF& msg); explicit MessageQueueMockBase(MessageQueueId_t queueId); - std::map sendMap; - - bool wasMessageSent(uint8_t* messageSentCounter_ = nullptr, bool resetCounter = true); - + //! Get next message which was sent to the default destination + ReturnValue_t getNextSentMessage(MessageQueueMessageIF& message); + //! Get message which was sent to a specific ID + ReturnValue_t getNextSentMessage(MessageQueueId_t id, MessageQueueMessageIF& message); + [[nodiscard]] bool wasMessageSent() const; + [[nodiscard]] size_t numberOfSentMessage() const; + [[nodiscard]] size_t numberOfSentMessage(MessageQueueId_t id) const; /** * Pop a message, clearing it in the process. * @return */ - ReturnValue_t popMessage(); - - ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override; + ReturnValue_t clearLastReceivedMessage(bool clearCmdMsg = true); ReturnValue_t flush(uint32_t* count) override; ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, - MessageQueueId_t sentFrom, - bool ignoreFault = false) override; + MessageQueueId_t sentFrom, bool ignoreFault = false) override; ReturnValue_t reply(MessageQueueMessageIF* message) override; - void clearMessages(bool clearCommandMessages = true); + ReturnValue_t clearLastSentMessage(MessageQueueId_t destId, bool clearCmdMsg = true); + ReturnValue_t clearLastSentMessage(bool clearCmdMsg = true); + void clearMessages(bool clearCmdMsg = true); + private: + using SendMap = std::map; + SendMap sendMap; + std::deque receivedMsgs; + + void clearEmptyEntries(); + ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override; + static ReturnValue_t clearLastSentMessage(SendMap::iterator& iter, bool clearCmdMsg = true); + static void createMsgCopy(MessageQueueMessageIF& into, MessageQueueMessageIF& from); }; #endif /* FSFW_UNITTEST_TESTS_MOCKS_MESSAGEQUEUEMOCKBASE_H_ */ diff --git a/unittests/serialize/testSerializeIF.cpp b/unittests/serialize/testSerializeIF.cpp index b619025a7..ecd613578 100644 --- a/unittests/serialize/testSerializeIF.cpp +++ b/unittests/serialize/testSerializeIF.cpp @@ -65,7 +65,8 @@ TEST_CASE("Serialize IF Serialize", "[serialize-if-ser]") { HasReturnvaluesIF::RETURN_OK); } SECTION("Network 1") { - REQUIRE(simpleSer.SerializeIF::serializeBe(buf.data(), buf.size()) == HasReturnvaluesIF::RETURN_OK); + REQUIRE(simpleSer.SerializeIF::serializeBe(buf.data(), buf.size()) == + HasReturnvaluesIF::RETURN_OK); } CHECK(buf[0] == 1); CHECK(buf[1] == 2); @@ -154,7 +155,8 @@ TEST_CASE("SerializeIF Deserialize", "[serialize-if-de]") { HasReturnvaluesIF::RETURN_OK); } SECTION("Network 1") { - REQUIRE(simpleSer.SerializeIF::deSerializeBe(buf.data(), buf.size()) == HasReturnvaluesIF::RETURN_OK); + REQUIRE(simpleSer.SerializeIF::deSerializeBe(buf.data(), buf.size()) == + HasReturnvaluesIF::RETURN_OK); } CHECK(simpleSer.getU8() == 5); CHECK(simpleSer.getU16() == 1); diff --git a/unittests/testcfg/objects/systemObjectList.h b/unittests/testcfg/objects/systemObjectList.h index 7d12e5c6e..1e86d5f7f 100644 --- a/unittests/testcfg/objects/systemObjectList.h +++ b/unittests/testcfg/objects/systemObjectList.h @@ -31,4 +31,4 @@ enum sourceObjects : uint32_t { }; } -#endif /* BSP_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ */ +#endif /* HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ */ diff --git a/unittests/tmtcservices/testSendHelper.cpp b/unittests/tmtcservices/testSendHelper.cpp index 6e6fb0695..9877d2eff 100644 --- a/unittests/tmtcservices/testSendHelper.cpp +++ b/unittests/tmtcservices/testSendHelper.cpp @@ -9,7 +9,5 @@ TEST_CASE("TM Send Helper", "[tm-send-helper]") { auto msgQueue = MessageQueueMockBase(); TmSendHelper sendHelper(&msgQueue, &errReporter); - SECTION("State") { - - } + SECTION("State") {} } \ No newline at end of file