From b7f3eff74230fa89fc02cc28a368460b32cfb80d Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Fri, 18 Feb 2022 19:08:06 +0100 Subject: [PATCH] WIP unit tests --- scripts/helper.py | 4 -- .../internalerror/InternalErrorReporter.cpp | 3 + .../internalerror/InternalErrorReporter.h | 6 +- tests/src/fsfw_tests/unit/CMakeLists.txt | 1 + .../unit/internalerror/CMakeLists.txt | 3 + .../TestInternalErrorReporter.cpp | 71 +++++++++++++++++++ .../unit/mocks/PeriodicTaskIFMock.h | 45 ++++++++++++ .../fsfw_tests/unit/osal/TestMessageQueue.cpp | 21 ++++++ 8 files changed, 147 insertions(+), 7 deletions(-) create mode 100644 tests/src/fsfw_tests/unit/internalerror/CMakeLists.txt create mode 100644 tests/src/fsfw_tests/unit/internalerror/TestInternalErrorReporter.cpp create mode 100644 tests/src/fsfw_tests/unit/mocks/PeriodicTaskIFMock.h diff --git a/scripts/helper.py b/scripts/helper.py index 68693c40..079a5548 100755 --- a/scripts/helper.py +++ b/scripts/helper.py @@ -143,10 +143,6 @@ def handle_tests_type(args, build_dir_list: list): if which("valgrind") is None: print("Please install valgrind first") sys.exit(1) - if os.path.split(os.getcwd())[1] != UNITTEST_FOLDER_NAME: - # If we are in a different directory we try to switch into it but - # this might fail - os.chdir(UNITTEST_FOLDER_NAME) os.system("valgrind --leak-check=full ./fsfw-tests") os.chdir("..") diff --git a/src/fsfw/internalerror/InternalErrorReporter.cpp b/src/fsfw/internalerror/InternalErrorReporter.cpp index e7088e2c..98ed2af3 100644 --- a/src/fsfw/internalerror/InternalErrorReporter.cpp +++ b/src/fsfw/internalerror/InternalErrorReporter.cpp @@ -57,6 +57,9 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { internalErrorDataset.storeHits.value += newStoreHits; internalErrorDataset.tmHits.value += newTmHits; internalErrorDataset.setValidity(true, true); + if((newQueueHits != 0) or (newStoreHits !=0) or (newTmHits != 0)){ + internalErrorDataset.setChanged(true); + } } } diff --git a/src/fsfw/internalerror/InternalErrorReporter.h b/src/fsfw/internalerror/InternalErrorReporter.h index 98711139..a946b81c 100644 --- a/src/fsfw/internalerror/InternalErrorReporter.h +++ b/src/fsfw/internalerror/InternalErrorReporter.h @@ -46,11 +46,11 @@ class InternalErrorReporter : public SystemObject, virtual ReturnValue_t initializeAfterTaskCreation() override; virtual ReturnValue_t performOperation(uint8_t opCode) override; - virtual void queueMessageNotSent(); + virtual void queueMessageNotSent() override; - virtual void lostTm(); + virtual void lostTm() override; - virtual void storeFull(); + virtual void storeFull() override; virtual void setTaskIF(PeriodicTaskIF* task) override; diff --git a/tests/src/fsfw_tests/unit/CMakeLists.txt b/tests/src/fsfw_tests/unit/CMakeLists.txt index fc73f7b5..a83e2f7f 100644 --- a/tests/src/fsfw_tests/unit/CMakeLists.txt +++ b/tests/src/fsfw_tests/unit/CMakeLists.txt @@ -23,3 +23,4 @@ add_subdirectory(timemanager) add_subdirectory(tmtcpacket) add_subdirectory(cfdp) add_subdirectory(hal) +add_subdirectory(internalerror) diff --git a/tests/src/fsfw_tests/unit/internalerror/CMakeLists.txt b/tests/src/fsfw_tests/unit/internalerror/CMakeLists.txt new file mode 100644 index 00000000..d49ce006 --- /dev/null +++ b/tests/src/fsfw_tests/unit/internalerror/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(${FSFW_TEST_TGT} PRIVATE + TestInternalErrorReporter.cpp +) diff --git a/tests/src/fsfw_tests/unit/internalerror/TestInternalErrorReporter.cpp b/tests/src/fsfw_tests/unit/internalerror/TestInternalErrorReporter.cpp new file mode 100644 index 00000000..d394166e --- /dev/null +++ b/tests/src/fsfw_tests/unit/internalerror/TestInternalErrorReporter.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include "fsfw/action/ActionMessage.h" +#include "fsfw/ipc/CommandMessage.h" +#include "fsfw/ipc/MessageQueueMessage.h" +#include "fsfw/objectmanager/frameworkObjects.h" +#include "fsfw_tests/unit/CatchDefinitions.h" +#include "fsfw_tests/unit/mocks/PeriodicTaskIFMock.h" + +TEST_CASE("Internal Error Reporter", "[TestInternalError]") { + PeriodicTaskMock task(10); + ObjectManagerIF* manager = ObjectManager::instance(); + if(manager == nullptr){ + FAIL(); + } + InternalErrorReporter* internalErrorReporter = + dynamic_cast(ObjectManager::instance()->get(objects::INTERNAL_ERROR_REPORTER)); + task.addComponent(objects::INTERNAL_ERROR_REPORTER); + MessageQueueIF* testQueue = QueueFactory::instance()->createMessageQueue(1); + MessageQueueIF* hkQueue = QueueFactory::instance()->createMessageQueue(1); + internalErrorReporter->getSubscriptionInterface()-> + subscribeForSetUpdateMessage(InternalErrorDataset::ERROR_SET_ID, objects::NO_OBJECT, hkQueue->getId(), true); + StorageManagerIF* ipcStore = ObjectManager::instance()->get(objects::IPC_STORE); + SECTION("MessageQueueFull"){ + CommandMessage message; + ActionMessage::setCompletionReply(&message, 10, true); + auto result = hkQueue->sendMessage(testQueue->getId(), &message); + REQUIRE(result == retval::CATCH_OK); + internalErrorReporter->performOperation(0); + { + CommandMessage hkMessage; + result = hkQueue->receiveMessage(&hkMessage); + REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(hkMessage.getCommand() == HousekeepingMessage::UPDATE_SNAPSHOT_SET); + store_address_t storeAddress; + gp_id_t gpid = HousekeepingMessage::getUpdateSnapshotVariableCommand(&hkMessage, &storeAddress); + REQUIRE(gpid.objectId == objects::INTERNAL_ERROR_REPORTER); + InternalErrorDataset dataset(objects::NO_OBJECT); + CCSDSTime::CDS_short time; + ConstAccessorPair data = ipcStore->getData(storeAddress); + HousekeepingSnapshot hkSnapshot(&time, &dataset); + const uint8_t* buffer = data.second.data(); + size_t size = data.second.size(); + hkSnapshot.deSerialize(&buffer, &size, SerializeIF::Endianness::MACHINE); + } + result = hkQueue->sendMessage(testQueue->getId(), &message); + REQUIRE(result == MessageQueueIF::FULL); + { + internalErrorReporter->performOperation(0); + CommandMessage hkMessage; + result = hkQueue->receiveMessage(&hkMessage); + REQUIRE(result == HasReturnvaluesIF::RETURN_OK); + REQUIRE(hkMessage.getCommand() == HousekeepingMessage::UPDATE_SNAPSHOT_SET); + store_address_t storeAddress; + gp_id_t gpid = HousekeepingMessage::getUpdateSnapshotVariableCommand(&hkMessage, &storeAddress); + REQUIRE(gpid.objectId == objects::INTERNAL_ERROR_REPORTER); + + ConstAccessorPair data = ipcStore->getData(storeAddress); + REQUIRE(data.first == HasReturnvaluesIF::RETURN_OK); + } + } + delete testQueue; + delete hkQueue; +} \ No newline at end of file diff --git a/tests/src/fsfw_tests/unit/mocks/PeriodicTaskIFMock.h b/tests/src/fsfw_tests/unit/mocks/PeriodicTaskIFMock.h new file mode 100644 index 00000000..dd5bca12 --- /dev/null +++ b/tests/src/fsfw_tests/unit/mocks/PeriodicTaskIFMock.h @@ -0,0 +1,45 @@ +#ifndef FSFW_UNITTEST_TESTS_MOCKS_PERIODICTASKMOCK_H_ +#define FSFW_UNITTEST_TESTS_MOCKS_PERIODICTASKMOCK_H_ + +#include +#include + +class PeriodicTaskMock: public PeriodicTaskIF{ +public: + PeriodicTaskMock(uint32_t period = 5):period(period){ + + } + /** + * @brief A virtual destructor as it is mandatory for interfaces. + */ + virtual ~PeriodicTaskMock() {} + /** + * @brief With the startTask method, a created task can be started + * for the first time. + */ + virtual ReturnValue_t startTask() override{ + return HasReturnvaluesIF::RETURN_OK; + }; + + virtual ReturnValue_t addComponent(object_id_t object) override{ + ExecutableObjectIF* executableObject = ObjectManager::instance()->get(objects::INTERNAL_ERROR_REPORTER); + if(executableObject == nullptr){ + return HasReturnvaluesIF::RETURN_FAILED; + } + executableObject->setTaskIF(this); + executableObject->initializeAfterTaskCreation(); + return HasReturnvaluesIF::RETURN_OK; + }; + + virtual ReturnValue_t sleepFor(uint32_t ms) override{ + return HasReturnvaluesIF::RETURN_OK; + }; + + virtual uint32_t getPeriodMs() const override{ + return period; + }; + uint32_t period; +}; + + +#endif // FSFW_UNITTEST_TESTS_MOCKS_PERIODICTASKMOCK_H_ \ No newline at end of file diff --git a/tests/src/fsfw_tests/unit/osal/TestMessageQueue.cpp b/tests/src/fsfw_tests/unit/osal/TestMessageQueue.cpp index 232ffb94..365df379 100644 --- a/tests/src/fsfw_tests/unit/osal/TestMessageQueue.cpp +++ b/tests/src/fsfw_tests/unit/osal/TestMessageQueue.cpp @@ -35,4 +35,25 @@ TEST_CASE("MessageQueue Basic Test", "[TestMq]") { senderId = testReceiverMq->getLastPartner(); CHECK(senderId == testSenderMqId); } + SECTION("Test Full") { + auto result = testSenderMq->sendMessage(testReceiverMqId, &testMessage); + REQUIRE(result == retval::CATCH_OK); + result = testSenderMq->sendMessage(testReceiverMqId, &testMessage); + REQUIRE(result == MessageQueueIF::FULL); + // We try another message + result = testSenderMq->sendMessage(testReceiverMqId, &testMessage); + REQUIRE(result == MessageQueueIF::FULL); + MessageQueueMessage recvMessage; + result = testReceiverMq->receiveMessage(&recvMessage); + REQUIRE(result == retval::CATCH_OK); + CHECK(recvMessage.getData()[0] == 42); + result = testSenderMq->sendMessage(testReceiverMqId, &testMessage); + REQUIRE(result == retval::CATCH_OK); + result = testReceiverMq->receiveMessage(&recvMessage); + REQUIRE(result == retval::CATCH_OK); + CHECK(recvMessage.getData()[0] == 42); + } + // We have to clear MQs ourself ATM + delete testSenderMq; + delete testReceiverMq; }