From e9da8e79f32fc2dfc34b779aa069c0c1faae339a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 3 Jan 2021 22:00:40 +0100 Subject: [PATCH 01/38] updated testcfg --- unittest/user/testcfg/FSFWConfig.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/unittest/user/testcfg/FSFWConfig.h b/unittest/user/testcfg/FSFWConfig.h index 6b0def90..261e3d6d 100644 --- a/unittest/user/testcfg/FSFWConfig.h +++ b/unittest/user/testcfg/FSFWConfig.h @@ -4,17 +4,26 @@ #include #include -//! Used to determine whether C++ ostreams are used -//! Those can lead to code bloat. +//! Used to determine whether C++ ostreams are used which can increase +//! the binary size significantly. If this is disabled, +//! the C stdio functions can be used alternatively #define FSFW_CPP_OSTREAM_ENABLED 1 -//! Reduced printout to further decrease code size +//! More FSFW related printouts. //! Be careful, this also turns off most diagnostic prinouts! #define FSFW_ENHANCED_PRINTOUT 0 +//! Can be used to completely disable printouts, even the C stdio ones. +#if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_ENHANCED_PRINTOUT == 0 + #define FSFW_DISABLE_PRINTOUT 0 +#endif + //! Can be used to enable additional debugging printouts for developing the FSFW #define FSFW_PRINT_VERBOSITY_LEVEL 0 +//! Can be used to disable the ANSI color sequences for C stdio. +#define FSFW_COLORED_OUTPUT 1 + //! If FSFW_OBJ_EVENT_TRANSLATION is set to one, //! additional output which requires the translation files translateObjects //! and translateEvents (and their compiled source files) @@ -49,7 +58,9 @@ static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120; //! also determines how many commands a CSB service can handle in one cycle //! simulataneously. This will increase the required RAM for //! each CSB service ! -static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 3; +static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 6; + +static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 124; } #endif /* CONFIG_FSFWCONFIG_H_ */ From e9a8313df7e5f4ae8f5afb732ef461bd348fcbb5 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 3 Jan 2021 23:18:10 +0100 Subject: [PATCH 02/38] repaired unit tests --- container/FixedOrderedMultimap.h | 1 + .../tests/container/TestPlacementFactory.cpp | 93 ++--- .../tests/storagemanager/TestNewAccessor.cpp | 321 +++++++++--------- unittest/tests/storagemanager/TestPool.cpp | 2 - 4 files changed, 209 insertions(+), 208 deletions(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 96bc0073..acf2368a 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -3,6 +3,7 @@ #include "ArrayList.h" #include +#include /** * @brief An associative container which allows multiple entries of the same key. diff --git a/unittest/tests/container/TestPlacementFactory.cpp b/unittest/tests/container/TestPlacementFactory.cpp index 5edbb9d2..14cf8eb4 100644 --- a/unittest/tests/container/TestPlacementFactory.cpp +++ b/unittest/tests/container/TestPlacementFactory.cpp @@ -1,45 +1,48 @@ -//#include -//#include -//#include -//#include -// -//#include -//#include "../../core/CatchDefinitions.h" -// -//TEST_CASE( "PlacementFactory Tests", "[TestPlacementFactory]") { -// INFO("PlacementFactory Tests"); -// -// const uint16_t element_sizes[3] = {sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t)}; -// const uint16_t n_elements[3] = {1, 1, 1}; -// LocalPool<3> storagePool(0x1, element_sizes, n_elements, false, true); -// PlacementFactory factory(&storagePool); -// -// SECTION("Pool overload"){ -// store_address_t address; -// uint8_t* ptr = nullptr; -// REQUIRE(storagePool.getFreeElement(&address, sizeof(ArrayList), &ptr) -// == static_cast(StorageManagerIF::DATA_TOO_LARGE)); -// ArrayList* list2 = factory.generate >(80); -// REQUIRE(list2 == nullptr); -// } -// -// SECTION("Test generate and destroy"){ -// uint64_t* number = factory.generate(32000); -// REQUIRE(number != nullptr); -// REQUIRE(*number == 32000); -// store_address_t address; -// uint8_t* ptr = nullptr; -// REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr) -// == static_cast(StorageManagerIF::DATA_TOO_LARGE)); -// uint64_t* number2 = factory.generate(12345); -// REQUIRE(number2 == nullptr); -// REQUIRE(factory.destroy(number) == static_cast(HasReturnvaluesIF::RETURN_OK)); -// REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr) -// == static_cast(HasReturnvaluesIF::RETURN_OK)); -// REQUIRE(storagePool.deleteData(address) == static_cast(HasReturnvaluesIF::RETURN_OK)); -// -// //Check that PlacementFactory checks for nullptr -// ptr = nullptr; -// REQUIRE(factory.destroy(ptr) == static_cast(HasReturnvaluesIF::RETURN_FAILED)); -// } -//} +#include +#include +#include +#include + +#include +#include + +TEST_CASE( "PlacementFactory Tests", "[TestPlacementFactory]") { + INFO("PlacementFactory Tests"); + + LocalPool::LocalPoolConfig poolCfg= {{1, sizeof(uint16_t)}, + {1, sizeof(uint32_t)}, {1, sizeof(uint64_t)} + }; + //const uint16_t element_sizes[3] = {sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t)}; + //const uint16_t n_elements[3] = {1, 1, 1}; + LocalPool storagePool(0x1, poolCfg, false, true); + PlacementFactory factory(&storagePool); + + SECTION("Pool overload"){ + store_address_t address; + uint8_t* ptr = nullptr; + REQUIRE(storagePool.getFreeElement(&address, sizeof(ArrayList), &ptr) + == static_cast(StorageManagerIF::DATA_TOO_LARGE)); + ArrayList* list2 = factory.generate >(80); + REQUIRE(list2 == nullptr); + } + + SECTION("Test generate and destroy"){ + uint64_t* number = factory.generate(32000); + REQUIRE(number != nullptr); + REQUIRE(*number == 32000); + store_address_t address; + uint8_t* ptr = nullptr; + REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr) + == static_cast(StorageManagerIF::DATA_TOO_LARGE)); + uint64_t* number2 = factory.generate(12345); + REQUIRE(number2 == nullptr); + REQUIRE(factory.destroy(number) == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(storagePool.getFreeElement(&address, sizeof(uint64_t), &ptr) + == static_cast(HasReturnvaluesIF::RETURN_OK)); + REQUIRE(storagePool.deleteData(address) == static_cast(HasReturnvaluesIF::RETURN_OK)); + + //Check that PlacementFactory checks for nullptr + ptr = nullptr; + REQUIRE(factory.destroy(ptr) == static_cast(HasReturnvaluesIF::RETURN_FAILED)); + } +} diff --git a/unittest/tests/storagemanager/TestNewAccessor.cpp b/unittest/tests/storagemanager/TestNewAccessor.cpp index 7bd0dee2..87ea00ca 100644 --- a/unittest/tests/storagemanager/TestNewAccessor.cpp +++ b/unittest/tests/storagemanager/TestNewAccessor.cpp @@ -1,161 +1,160 @@ -//#include -//#include -//#include "../../core/CatchDefinitions.h" -//#include -// -//TEST_CASE( "New Accessor" , "[NewAccessor]") { -// uint16_t numberOfElements[1] = {1}; -// uint16_t sizeofElements[1] = {10}; -// LocalPool<1> SimplePool = LocalPool<1>(0, sizeofElements, numberOfElements); -// std::array testDataArray; -// std::array receptionArray; -// store_address_t testStoreId; -// ReturnValue_t result = retval::CATCH_FAILED; -// -// for(size_t i = 0; i < testDataArray.size(); i++) { -// testDataArray[i] = i; -// } -// size_t size = 10; -// -// SECTION ("Simple tests getter functions") { -// result = SimplePool.addData(&testStoreId, testDataArray.data(), size); -// REQUIRE(result == retval::CATCH_OK); -// auto resultPair = SimplePool.getData(testStoreId); -// REQUIRE(resultPair.first == retval::CATCH_OK); -// resultPair.second.getDataCopy(receptionArray.data(), 20); -// CHECK(resultPair.second.getId() == testStoreId); -// CHECK(resultPair.second.size() == 10); -// for(size_t i = 0; i < size; i++) { -// CHECK(receptionArray[i] == i ); -// } -// -// std::copy(resultPair.second.data(), resultPair.second.data() + -// resultPair.second.size(), receptionArray.data()); -// for(size_t i = 0; i < size; i++) { -// CHECK(receptionArray[i] == i ); -// } -// -// { -// auto resultPairLoc = SimplePool.getData(testStoreId); -// REQUIRE(resultPairLoc.first == retval::CATCH_OK); -// // data should be deleted when accessor goes out of scope. -// } -// resultPair = SimplePool.getData(testStoreId); -// REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST); -// -// result = SimplePool.addData(&testStoreId, testDataArray.data(), size); -// REQUIRE(result == retval::CATCH_OK); -// { -// ConstStorageAccessor constAccessor(testStoreId); -// result = SimplePool.getData(testStoreId, constAccessor); -// REQUIRE(result == retval::CATCH_OK); -// constAccessor.getDataCopy(receptionArray.data(), 20); -// for(size_t i = 0; i < size; i++) { -// CHECK(receptionArray[i] == i ); -// } -// // likewise, data should be deleted when accessor gets out of scope. -// } -// resultPair = SimplePool.getData(testStoreId); -// REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST); -// -// result = SimplePool.addData(&testStoreId, testDataArray.data(), size); -// { -// resultPair = SimplePool.getData(testStoreId); -// REQUIRE(resultPair.first == retval::CATCH_OK); -// resultPair.second.release(); -// // now data should not be deleted anymore -// } -// resultPair = SimplePool.getData(testStoreId); -// REQUIRE(resultPair.first == retval::CATCH_OK); -// resultPair.second.getDataCopy(receptionArray.data(), 20); -// for(size_t i = 0; i < size; i++) { -// CHECK(receptionArray[i] == i ); -// } -// } -// -// -// SECTION("Simple tests modify functions") { -// result = SimplePool.addData(&testStoreId, testDataArray.data(), size); -// REQUIRE(result == retval::CATCH_OK); -// { -// StorageAccessor accessor(testStoreId); -// result = SimplePool.modifyData(testStoreId, accessor); -// REQUIRE(result == retval::CATCH_OK); -// CHECK(accessor.getId() == testStoreId); -// CHECK(accessor.size() == 10); -// accessor.getDataCopy(receptionArray.data(), 20); -// for(size_t i = 0; i < size; i++) { -// CHECK(receptionArray[i] == i ); -// } -// std::copy(accessor.data(), accessor.data() + -// accessor.size(), receptionArray.data()); -// for(size_t i = 0; i < size; i++) { -// CHECK(receptionArray[i] == i ); -// } -// // data should be deleted when accessor goes out of scope -// } -// auto resultPair = SimplePool.getData(testStoreId); -// REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST); -// -// result = SimplePool.addData(&testStoreId, testDataArray.data(), size); -// REQUIRE(result == retval::CATCH_OK); -// { -// auto resultPairLoc = SimplePool.modifyData(testStoreId); -// REQUIRE(resultPairLoc.first == retval::CATCH_OK); -// CHECK(resultPairLoc.second.getId() == testStoreId); -// CHECK(resultPairLoc.second.size() == 10); -// resultPairLoc.second.getDataCopy(receptionArray.data(), 20); -// for(size_t i = 0; i < size; i++) { -// CHECK(receptionArray[i] == i ); -// } -// std::copy(resultPairLoc.second.data(), resultPairLoc.second.data() + -// resultPairLoc.second.size(), receptionArray.data()); -// for(size_t i = 0; i < size; i++) { -// CHECK(receptionArray[i] == i ); -// } -// resultPairLoc.second.release(); -// // data should not be deleted when accessor goes out of scope -// } -// resultPair = SimplePool.getData(testStoreId); -// REQUIRE(resultPair.first == retval::CATCH_OK); -// } -// -// -// SECTION("Write tests") { -// result = SimplePool.addData(&testStoreId, testDataArray.data(), size); -// REQUIRE(result == retval::CATCH_OK); -// { -// auto resultPair = SimplePool.modifyData(testStoreId); -// REQUIRE(resultPair.first == retval::CATCH_OK); -// testDataArray[9] = 42; -// resultPair.second.write(testDataArray.data(), 10, 0); -// // now data should not be deleted -// resultPair.second.release(); -// } -// auto resultConstPair = SimplePool.getData(testStoreId); -// REQUIRE(resultConstPair.first == retval::CATCH_OK); -// -// resultConstPair.second.getDataCopy(receptionArray.data(), 10); -// for(size_t i = 0; i < size-1; i++) { -// CHECK(receptionArray[i] == i ); -// } -// CHECK(receptionArray[9] == 42 ); -// -// auto resultPair = SimplePool.modifyData(testStoreId); -// REQUIRE(resultPair.first == retval::CATCH_OK); -// result = resultPair.second.write(testDataArray.data(), 20, 0); -// REQUIRE(result == retval::CATCH_FAILED); -// result = resultPair.second.write(testDataArray.data(), 10, 5); -// REQUIRE(result == retval::CATCH_FAILED); -// -// memset(testDataArray.data(), 42, 5); -// result = resultPair.second.write(testDataArray.data(), 5, 5); -// REQUIRE(result == retval::CATCH_OK); -// resultConstPair = SimplePool.getData(testStoreId); -// resultPair.second.getDataCopy(receptionArray.data(), 20); -// for(size_t i = 5; i < 10; i++) { -// CHECK(receptionArray[i] == 42 ); -// } -// -// } -//} +#include +#include +#include +#include + +TEST_CASE( "New Accessor" , "[NewAccessor]") { + LocalPool::LocalPoolConfig poolCfg = {{1, 10}}; + LocalPool SimplePool = LocalPool(0, poolCfg); + std::array testDataArray; + std::array receptionArray; + store_address_t testStoreId; + ReturnValue_t result = retval::CATCH_FAILED; + + for(size_t i = 0; i < testDataArray.size(); i++) { + testDataArray[i] = i; + } + size_t size = 10; + + SECTION ("Simple tests getter functions") { + result = SimplePool.addData(&testStoreId, testDataArray.data(), size); + REQUIRE(result == retval::CATCH_OK); + auto resultPair = SimplePool.getData(testStoreId); + REQUIRE(resultPair.first == retval::CATCH_OK); + resultPair.second.getDataCopy(receptionArray.data(), 20); + CHECK(resultPair.second.getId() == testStoreId); + CHECK(resultPair.second.size() == 10); + for(size_t i = 0; i < size; i++) { + CHECK(receptionArray[i] == i ); + } + + std::copy(resultPair.second.data(), resultPair.second.data() + + resultPair.second.size(), receptionArray.data()); + for(size_t i = 0; i < size; i++) { + CHECK(receptionArray[i] == i ); + } + + { + auto resultPairLoc = SimplePool.getData(testStoreId); + REQUIRE(resultPairLoc.first == retval::CATCH_OK); + // data should be deleted when accessor goes out of scope. + } + resultPair = SimplePool.getData(testStoreId); + REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST); + + result = SimplePool.addData(&testStoreId, testDataArray.data(), size); + REQUIRE(result == retval::CATCH_OK); + { + ConstStorageAccessor constAccessor(testStoreId); + result = SimplePool.getData(testStoreId, constAccessor); + REQUIRE(result == retval::CATCH_OK); + constAccessor.getDataCopy(receptionArray.data(), 20); + for(size_t i = 0; i < size; i++) { + CHECK(receptionArray[i] == i ); + } + // likewise, data should be deleted when accessor gets out of scope. + } + resultPair = SimplePool.getData(testStoreId); + REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST); + + result = SimplePool.addData(&testStoreId, testDataArray.data(), size); + { + resultPair = SimplePool.getData(testStoreId); + REQUIRE(resultPair.first == retval::CATCH_OK); + resultPair.second.release(); + // now data should not be deleted anymore + } + resultPair = SimplePool.getData(testStoreId); + REQUIRE(resultPair.first == retval::CATCH_OK); + resultPair.second.getDataCopy(receptionArray.data(), 20); + for(size_t i = 0; i < size; i++) { + CHECK(receptionArray[i] == i ); + } + } + + + SECTION("Simple tests modify functions") { + result = SimplePool.addData(&testStoreId, testDataArray.data(), size); + REQUIRE(result == retval::CATCH_OK); + { + StorageAccessor accessor(testStoreId); + result = SimplePool.modifyData(testStoreId, accessor); + REQUIRE(result == retval::CATCH_OK); + CHECK(accessor.getId() == testStoreId); + CHECK(accessor.size() == 10); + accessor.getDataCopy(receptionArray.data(), 20); + for(size_t i = 0; i < size; i++) { + CHECK(receptionArray[i] == i ); + } + std::copy(accessor.data(), accessor.data() + + accessor.size(), receptionArray.data()); + for(size_t i = 0; i < size; i++) { + CHECK(receptionArray[i] == i ); + } + // data should be deleted when accessor goes out of scope + } + auto resultPair = SimplePool.getData(testStoreId); + REQUIRE(resultPair.first == (int) StorageManagerIF::DATA_DOES_NOT_EXIST); + + result = SimplePool.addData(&testStoreId, testDataArray.data(), size); + REQUIRE(result == retval::CATCH_OK); + { + auto resultPairLoc = SimplePool.modifyData(testStoreId); + REQUIRE(resultPairLoc.first == retval::CATCH_OK); + CHECK(resultPairLoc.second.getId() == testStoreId); + CHECK(resultPairLoc.second.size() == 10); + resultPairLoc.second.getDataCopy(receptionArray.data(), 20); + for(size_t i = 0; i < size; i++) { + CHECK(receptionArray[i] == i ); + } + std::copy(resultPairLoc.second.data(), resultPairLoc.second.data() + + resultPairLoc.second.size(), receptionArray.data()); + for(size_t i = 0; i < size; i++) { + CHECK(receptionArray[i] == i ); + } + resultPairLoc.second.release(); + // data should not be deleted when accessor goes out of scope + } + resultPair = SimplePool.getData(testStoreId); + REQUIRE(resultPair.first == retval::CATCH_OK); + } + + + SECTION("Write tests") { + result = SimplePool.addData(&testStoreId, testDataArray.data(), size); + REQUIRE(result == retval::CATCH_OK); + { + auto resultPair = SimplePool.modifyData(testStoreId); + REQUIRE(resultPair.first == retval::CATCH_OK); + testDataArray[9] = 42; + resultPair.second.write(testDataArray.data(), 10, 0); + // now data should not be deleted + resultPair.second.release(); + } + auto resultConstPair = SimplePool.getData(testStoreId); + REQUIRE(resultConstPair.first == retval::CATCH_OK); + + resultConstPair.second.getDataCopy(receptionArray.data(), 10); + for(size_t i = 0; i < size-1; i++) { + CHECK(receptionArray[i] == i ); + } + CHECK(receptionArray[9] == 42 ); + + auto resultPair = SimplePool.modifyData(testStoreId); + REQUIRE(resultPair.first == retval::CATCH_OK); + result = resultPair.second.write(testDataArray.data(), 20, 0); + REQUIRE(result == retval::CATCH_FAILED); + result = resultPair.second.write(testDataArray.data(), 10, 5); + REQUIRE(result == retval::CATCH_FAILED); + + memset(testDataArray.data(), 42, 5); + result = resultPair.second.write(testDataArray.data(), 5, 5); + REQUIRE(result == retval::CATCH_OK); + resultConstPair = SimplePool.getData(testStoreId); + resultPair.second.getDataCopy(receptionArray.data(), 20); + for(size_t i = 5; i < 10; i++) { + CHECK(receptionArray[i] == 42 ); + } + + } +} diff --git a/unittest/tests/storagemanager/TestPool.cpp b/unittest/tests/storagemanager/TestPool.cpp index dcfb6c03..50bde01a 100644 --- a/unittest/tests/storagemanager/TestPool.cpp +++ b/unittest/tests/storagemanager/TestPool.cpp @@ -8,8 +8,6 @@ TEST_CASE( "Local Pool Simple Tests [1 Pool]" , "[TestPool]") { -// uint16_t numberOfElements[1] = {1}; -// uint16_t sizeofElements[1] = {10}; LocalPool::LocalPoolConfig config = {{1, 10}}; LocalPool simplePool(0, config); std::array testDataArray; From 49c6cd947300bef7db1622a547af7ce5fdf7980b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 3 Jan 2021 23:27:49 +0100 Subject: [PATCH 03/38] added local pool owner base --- unittest/tests/datapoollocal/LocalPoolOwnerBase.h | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 unittest/tests/datapoollocal/LocalPoolOwnerBase.h diff --git a/unittest/tests/datapoollocal/LocalPoolOwnerBase.h b/unittest/tests/datapoollocal/LocalPoolOwnerBase.h new file mode 100644 index 00000000..5e62234b --- /dev/null +++ b/unittest/tests/datapoollocal/LocalPoolOwnerBase.h @@ -0,0 +1,8 @@ +#ifndef FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_ +#define FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_ + + + + + +#endif /* FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_ */ From 8e3aef5df05669d686d1ec0a6a899e3c6a369d7a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 4 Jan 2021 00:21:44 +0100 Subject: [PATCH 04/38] adding new tests for local pool variable --- unittest/tests/CMakeLists.txt | 1 + unittest/tests/datapoollocal/CMakeLists.txt | 3 + .../tests/datapoollocal/LocalPoolOwnerBase.h | 75 +++++++++++++++++++ .../datapoollocal/LocalPoolVariableTest.cpp | 37 +++++++++ .../user/testcfg/objects/systemObjectList.h | 14 +++- 5 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 unittest/tests/datapoollocal/CMakeLists.txt create mode 100644 unittest/tests/datapoollocal/LocalPoolVariableTest.cpp diff --git a/unittest/tests/CMakeLists.txt b/unittest/tests/CMakeLists.txt index 97074417..180e1a51 100644 --- a/unittest/tests/CMakeLists.txt +++ b/unittest/tests/CMakeLists.txt @@ -2,5 +2,6 @@ add_subdirectory(action) add_subdirectory(container) add_subdirectory(osal) add_subdirectory(serialize) +add_subdirectory(datapoollocal) add_subdirectory(storagemanager) diff --git a/unittest/tests/datapoollocal/CMakeLists.txt b/unittest/tests/datapoollocal/CMakeLists.txt new file mode 100644 index 00000000..569a8d5f --- /dev/null +++ b/unittest/tests/datapoollocal/CMakeLists.txt @@ -0,0 +1,3 @@ +target_sources(${TARGET_NAME} PRIVATE + LocalPoolVariableTest.cpp +) diff --git a/unittest/tests/datapoollocal/LocalPoolOwnerBase.h b/unittest/tests/datapoollocal/LocalPoolOwnerBase.h index 5e62234b..b73c5299 100644 --- a/unittest/tests/datapoollocal/LocalPoolOwnerBase.h +++ b/unittest/tests/datapoollocal/LocalPoolOwnerBase.h @@ -1,8 +1,83 @@ #ifndef FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_ #define FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_ +#include +#include +#include +#include +#include + +namespace lpool { +static constexpr lp_id_t uint8VarId = 0; +static constexpr lp_id_t floatVarId = 1; +} +class LocalPoolOwnerBase: public SystemObject, public HasLocalDataPoolIF { +public: + LocalPoolOwnerBase( + object_id_t objectId = objects::TEST_LOCAL_POOL_OWNER_BASE): + SystemObject(objectId), hkManager(this, messageQueue) { + messageQueue = QueueFactory::instance()->createMessageQueue(10); + } + ~LocalPoolOwnerBase() { + QueueFactory::instance()->deleteMessageQueue(messageQueue); + } + + object_id_t getObjectId() const override { + return SystemObject::getObjectId(); + } + + ReturnValue_t initializeHkManager() { + return hkManager.initialize(messageQueue); + + } + + ReturnValue_t initializeHkManagerAfterTaskCreation() { + return hkManager.initializeAfterTaskCreation(); + } + + /** Command queue for housekeeping messages. */ + MessageQueueId_t getCommandQueue() const override { + return messageQueue->getId(); + } + + virtual ReturnValue_t initializeLocalDataPool( + LocalDataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) { + // Default initialization empty for now. + localDataPoolMap.emplace(lpool::uint8VarId, new PoolEntry({0})); + localDataPoolMap.emplace(lpool::floatVarId, new PoolEntry({0})); + return HasReturnvaluesIF::RETURN_OK; + } + + LocalDataPoolManager* getHkManagerHandle() override { + return &hkManager; + } + + uint32_t getPeriodicOperationFrequency() const override { + return 0; + } + + /** + * This function is used by the pool manager to get a valid dataset + * from a SID + * @param sid Corresponding structure ID + * @return + */ + virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override { + // empty for now + return nullptr; + } +private: + + lp_var_t testUint8 = lp_var_t(this, lpool::uint8VarId); + lp_var_t testFloat = lp_var_t(this, lpool::floatVarId); + + MessageQueueIF* messageQueue = nullptr; + LocalDataPoolManager hkManager; + +}; #endif /* FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_ */ diff --git a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp new file mode 100644 index 00000000..0c233193 --- /dev/null +++ b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp @@ -0,0 +1,37 @@ +#include "LocalPoolOwnerBase.h" + +#include +#include +#include + + +TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { + LocalPoolOwnerBase poolOwner(objects::TEST_LOCAL_POOL_OWNER_BASE); + REQUIRE(poolOwner.initializeHkManager() == retval::CATCH_OK); + REQUIRE(poolOwner.initializeHkManagerAfterTaskCreation() + == retval::CATCH_OK); + + // very basic test. + lp_var_t testVariable = lp_var_t( + objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId); + REQUIRE(testVariable.read() == retval::CATCH_OK); + CHECK(testVariable.value == 0); + testVariable.value = 5; + REQUIRE(testVariable.commit() == retval::CATCH_OK); + REQUIRE(testVariable.read() == retval::CATCH_OK); + REQUIRE(testVariable.value == 5); + + // not try to use a local pool variable which does not exist + lp_var_t invalidVariable = lp_var_t( + objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff); + REQUIRE(invalidVariable.read() == + static_cast(HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND)); + + // now try to access with wrong type + lp_var_t invalidVariable2 = lp_var_t( + objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId); + REQUIRE(invalidVariable2.read() == + static_cast(HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT)); +} + + diff --git a/unittest/user/testcfg/objects/systemObjectList.h b/unittest/user/testcfg/objects/systemObjectList.h index 0e034aff..da95617c 100644 --- a/unittest/user/testcfg/objects/systemObjectList.h +++ b/unittest/user/testcfg/objects/systemObjectList.h @@ -9,7 +9,19 @@ namespace objects { enum sourceObjects: uint32_t { /* All addresses between start and end are reserved for the FSFW */ FSFW_CONFIG_RESERVED_START = PUS_SERVICE_1_VERIFICATION, - FSFW_CONFIG_RESERVED_END = TM_STORE + FSFW_CONFIG_RESERVED_END = TM_STORE, + + CCSDS_DISTRIBUTOR = 10, + PUS_DISTRIBUTOR = 11, + TM_FUNNEL = 12, + + UDP_BRIDGE = 15, + UDP_POLLING_TASK = 16, + + TEST_ECHO_COM_IF = 20, + TEST_DEVICE = 21, + + TEST_LOCAL_POOL_OWNER_BASE = 25 }; } From cca5689a18425627559308e87dfde34f22cc28d0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 4 Jan 2021 15:17:11 +0100 Subject: [PATCH 05/38] clock improvements for rtems --- osal/rtems/Clock.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/osal/rtems/Clock.cpp b/osal/rtems/Clock.cpp index dda15464..8bd7ac37 100644 --- a/osal/rtems/Clock.cpp +++ b/osal/rtems/Clock.cpp @@ -37,15 +37,24 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { } ReturnValue_t Clock::setClock(const timeval* time) { - //TODO This routine uses _TOD_Set which is not timespec newTime; newTime.tv_sec = time->tv_sec; + if(time->tv_usec < 0) { + // better returnvalue. + return HasReturnvaluesIF::RETURN_FAILED; + } newTime.tv_nsec = time->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND; - //SHOULDDO: Not sure if we need to protect this call somehow (by thread lock or something). - //Uli: rtems docu says you can call this from an ISR, not sure if this means no protetion needed - //TODO Second parameter is ISR_lock_Context - _TOD_Set(&newTime,nullptr); - return HasReturnvaluesIF::RETURN_OK; + + ISR_lock_Context context; + _TOD_Lock(); + _TOD_Acquire(&context); + Status_Control status = _TOD_Set(&newTime, &context); + _TOD_Unlock(); + if(status == STATUS_SUCCESSFUL) { + return HasReturnvaluesIF::RETURN_OK; + } + // better returnvalue + return HasReturnvaluesIF::RETURN_FAILED; } ReturnValue_t Clock::getClock_timeval(timeval* time) { @@ -95,6 +104,7 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) { } ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { + // TIsn't this a bug? Are RTEMS ticks always microseconds? rtems_time_of_day* timeRtems = reinterpret_cast(time); rtems_status_code status = rtems_clock_get_tod(timeRtems); switch (status) { From 3c041388d6705bccda5790ceeb5545ed9e48613d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 4 Jan 2021 15:31:06 +0100 Subject: [PATCH 06/38] bugfix --- serviceinterface/ServiceInterfaceBuffer.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 20ea61dd..5846d233 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -28,18 +28,21 @@ ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, } #if FSFW_COLORED_OUTPUT == 1 - if(setMessage.find("DEBUG")) { + if(setMessage.find("DEBUG") != std::string::npos) { colorPrefix = fsfw::ANSI_COLOR_MAGENTA; } - else if(setMessage.find("INFO")) { + else if(setMessage.find("INFO") != std::string::npos) { colorPrefix = fsfw::ANSI_COLOR_GREEN; } - else if(setMessage.find("WARNING")) { + else if(setMessage.find("WARNING") != std::string::npos) { colorPrefix = fsfw::ANSI_COLOR_YELLOW; } - else if(setMessage.find("ERROR")) { + else if(setMessage.find("ERROR") != std::string::npos) { colorPrefix = fsfw::ANSI_COLOR_RED; } + else { + colorPrefix = fsfw::ANSI_COLOR_RESET; + } #ifdef WIN32 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); From 85764ba94c3f4edf1cbabc260cb94dd916b2d72f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 5 Jan 2021 17:30:15 +0100 Subject: [PATCH 07/38] added include --- unittest/tests/storagemanager/TestNewAccessor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unittest/tests/storagemanager/TestNewAccessor.cpp b/unittest/tests/storagemanager/TestNewAccessor.cpp index 87ea00ca..10d05c6b 100644 --- a/unittest/tests/storagemanager/TestNewAccessor.cpp +++ b/unittest/tests/storagemanager/TestNewAccessor.cpp @@ -2,6 +2,7 @@ #include #include #include +#include TEST_CASE( "New Accessor" , "[NewAccessor]") { LocalPool::LocalPoolConfig poolCfg = {{1, 10}}; @@ -147,7 +148,7 @@ TEST_CASE( "New Accessor" , "[NewAccessor]") { result = resultPair.second.write(testDataArray.data(), 10, 5); REQUIRE(result == retval::CATCH_FAILED); - memset(testDataArray.data(), 42, 5); + std::memset(testDataArray.data(), 42, 5); result = resultPair.second.write(testDataArray.data(), 5, 5); REQUIRE(result == retval::CATCH_OK); resultConstPair = SimplePool.getData(testStoreId); From a05cf8d4ab54066f6cc9f6450f80f98577fad1af Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 5 Jan 2021 22:46:17 +0100 Subject: [PATCH 08/38] updated tests --- .../datapoollocal/LocalPoolVariableTest.cpp | 50 ++++++++++++------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp index 0c233193..f52ff925 100644 --- a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp +++ b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp @@ -11,27 +11,39 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { REQUIRE(poolOwner.initializeHkManagerAfterTaskCreation() == retval::CATCH_OK); - // very basic test. - lp_var_t testVariable = lp_var_t( - objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId); - REQUIRE(testVariable.read() == retval::CATCH_OK); - CHECK(testVariable.value == 0); - testVariable.value = 5; - REQUIRE(testVariable.commit() == retval::CATCH_OK); - REQUIRE(testVariable.read() == retval::CATCH_OK); - REQUIRE(testVariable.value == 5); + SECTION("Basic Tests") { + // very basic test. + lp_var_t testVariable = lp_var_t( + objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId); + REQUIRE(testVariable.read() == retval::CATCH_OK); + CHECK(testVariable.value == 0); + testVariable.value = 5; + REQUIRE(testVariable.commit() == retval::CATCH_OK); + REQUIRE(testVariable.read() == retval::CATCH_OK); + REQUIRE(testVariable.value == 5); - // not try to use a local pool variable which does not exist - lp_var_t invalidVariable = lp_var_t( - objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff); - REQUIRE(invalidVariable.read() == - static_cast(HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND)); + CHECK(not testVariable.isValid()); + + // not try to use a local pool variable which does not exist + lp_var_t invalidVariable = lp_var_t( + objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff); + REQUIRE(invalidVariable.read() == + static_cast(HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND)); + + // now try to access with wrong type + lp_var_t invalidVariable2 = lp_var_t( + objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId); + REQUIRE(invalidVariable2.read() == + static_cast(HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT)); + + // now try to access with wrong type + lp_var_t readOnlyVar = lp_var_t( + objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId, + nullptr, pool_rwm_t::VAR_READ); + REQUIRE(readOnlyVar.commit() == + static_cast(PoolVariableIF::INVALID_READ_WRITE_MODE)); + } - // now try to access with wrong type - lp_var_t invalidVariable2 = lp_var_t( - objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId); - REQUIRE(invalidVariable2.read() == - static_cast(HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT)); } From b241ef6aad5861dc570548fd17bdf856e3332984 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 5 Jan 2021 22:51:49 +0100 Subject: [PATCH 09/38] continued tests --- unittest/tests/datapoollocal/LocalPoolOwnerBase.h | 2 ++ .../tests/datapoollocal/LocalPoolVariableTest.cpp | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/unittest/tests/datapoollocal/LocalPoolOwnerBase.h b/unittest/tests/datapoollocal/LocalPoolOwnerBase.h index b73c5299..40f657be 100644 --- a/unittest/tests/datapoollocal/LocalPoolOwnerBase.h +++ b/unittest/tests/datapoollocal/LocalPoolOwnerBase.h @@ -10,6 +10,7 @@ namespace lpool { static constexpr lp_id_t uint8VarId = 0; static constexpr lp_id_t floatVarId = 1; +static constexpr lp_id_t uint32VarId = 2; } @@ -74,6 +75,7 @@ private: lp_var_t testUint8 = lp_var_t(this, lpool::uint8VarId); lp_var_t testFloat = lp_var_t(this, lpool::floatVarId); + lp_var_t testUint32 = lp_var_t(this, lpool::uint32VarId); MessageQueueIF* messageQueue = nullptr; LocalDataPoolManager hkManager; diff --git a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp index f52ff925..faca03e3 100644 --- a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp +++ b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp @@ -23,6 +23,8 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { REQUIRE(testVariable.value == 5); CHECK(not testVariable.isValid()); + testVariable.setValid(true); + CHECK(testVariable.isValid()); // not try to use a local pool variable which does not exist lp_var_t invalidVariable = lp_var_t( @@ -36,12 +38,20 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { REQUIRE(invalidVariable2.read() == static_cast(HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT)); - // now try to access with wrong type - lp_var_t readOnlyVar = lp_var_t( + lp_var_t readOnlyVar = lp_var_t( objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId, nullptr, pool_rwm_t::VAR_READ); REQUIRE(readOnlyVar.commit() == static_cast(PoolVariableIF::INVALID_READ_WRITE_MODE)); + lp_var_t writeOnlyVar = lp_var_t( + objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId, + nullptr, pool_rwm_t::VAR_WRITE); + REQUIRE(writeOnlyVar.read() == static_cast( + PoolVariableIF::INVALID_READ_WRITE_MODE)); + + lp_var_t uint32tVar = lp_var_t( + objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint32VarId); + sif::info << "LocalPoolVariable printout: " < Date: Wed, 6 Jan 2021 16:26:08 +0100 Subject: [PATCH 10/38] local pool variabel tweaks and fixes --- datapoollocal/LocalPoolVariable.tpp | 34 +++++++++++++++++------------ 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/datapoollocal/LocalPoolVariable.tpp b/datapoollocal/LocalPoolVariable.tpp index cd5117c8..dd6219b1 100644 --- a/datapoollocal/LocalPoolVariable.tpp +++ b/datapoollocal/LocalPoolVariable.tpp @@ -34,7 +34,7 @@ template inline ReturnValue_t LocalPoolVariable::readWithoutLock() { if(readWriteMode == pool_rwm_t::VAR_WRITE) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "LocalPoolVar: Invalid read write " + sif::warning << "LocalPoolVariable: Invalid read write " "mode for read() call." << std::endl; #endif return PoolVariableIF::INVALID_READ_WRITE_MODE; @@ -44,7 +44,7 @@ inline ReturnValue_t LocalPoolVariable::readWithoutLock() { ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); if(result != RETURN_OK or poolEntry == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PoolVector: Read of local pool variable of object " + sif::error << "PoolPoolVariable: Read of local pool variable of object " << std::hex << std::setw(8) << std::setfill('0') << hkManager->getOwner() << " and lp ID " << localPoolId << std::dec << " failed." << std::setfill(' ') << std::endl; @@ -67,7 +67,7 @@ template inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { if(readWriteMode == pool_rwm_t::VAR_READ) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "LocalPoolVariable: Invalid read write " + sif::warning << "LocalPoolVariable: Invalid read write " "mode for commit() call." << std::endl; #endif return PoolVariableIF::INVALID_READ_WRITE_MODE; @@ -76,10 +76,10 @@ inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); if(result != RETURN_OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PoolVector: Read of local pool variable of object " - "0x" << std::hex << std::setw(8) << std::setfill('0') << - hkManager->getOwner() << " and lp ID 0x" << localPoolId << - std::dec << " failed.\n" << std::flush; + sif::error << "PoolPoolVariable: Read of local pool variable of " + << "object " << std::hex << std::setw(8) << std::setfill('0') + << hkManager->getOwner() << " and lp ID " << localPoolId + << std::dec << " failed." << std::endl; #endif return result; } @@ -89,8 +89,9 @@ inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { } template -inline ReturnValue_t LocalPoolVariable::serialize(uint8_t** buffer, size_t* size, - const size_t max_size, SerializeIF::Endianness streamEndianness) const { +inline ReturnValue_t LocalPoolVariable::serialize(uint8_t** buffer, + size_t* size, const size_t max_size, + SerializeIF::Endianness streamEndianness) const { return SerializeAdapter::serialize(&value, buffer, size ,max_size, streamEndianness); } @@ -121,7 +122,8 @@ inline LocalPoolVariable::operator T() const { } template -inline LocalPoolVariable & LocalPoolVariable::operator=(const T& newValue) { +inline LocalPoolVariable & LocalPoolVariable::operator=( + const T& newValue) { value = newValue; return *this; } @@ -134,7 +136,8 @@ inline LocalPoolVariable& LocalPoolVariable::operator =( } template -inline bool LocalPoolVariable::operator ==(const LocalPoolVariable &other) const { +inline bool LocalPoolVariable::operator ==( + const LocalPoolVariable &other) const { return this->value == other.value; } @@ -145,7 +148,8 @@ inline bool LocalPoolVariable::operator ==(const T &other) const { template -inline bool LocalPoolVariable::operator !=(const LocalPoolVariable &other) const { +inline bool LocalPoolVariable::operator !=( + const LocalPoolVariable &other) const { return not (*this == other); } @@ -156,7 +160,8 @@ inline bool LocalPoolVariable::operator !=(const T &other) const { template -inline bool LocalPoolVariable::operator <(const LocalPoolVariable &other) const { +inline bool LocalPoolVariable::operator <( + const LocalPoolVariable &other) const { return this->value < other.value; } @@ -167,7 +172,8 @@ inline bool LocalPoolVariable::operator <(const T &other) const { template -inline bool LocalPoolVariable::operator >(const LocalPoolVariable &other) const { +inline bool LocalPoolVariable::operator >( + const LocalPoolVariable &other) const { return not (*this < other); } From 16458f6a1e42fa75c4ca0155f22117bd0acf2b0b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 6 Jan 2021 18:20:38 +0100 Subject: [PATCH 11/38] continued tests --- datapoollocal/LocalPoolVariable.tpp | 4 ++-- datapoollocal/LocalPoolVector.tpp | 20 +++++++++---------- .../datapoollocal/LocalPoolVariableTest.cpp | 11 ++++++++++ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/datapoollocal/LocalPoolVariable.tpp b/datapoollocal/LocalPoolVariable.tpp index dd6219b1..153a13d0 100644 --- a/datapoollocal/LocalPoolVariable.tpp +++ b/datapoollocal/LocalPoolVariable.tpp @@ -46,7 +46,7 @@ inline ReturnValue_t LocalPoolVariable::readWithoutLock() { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "PoolPoolVariable: Read of local pool variable of object " << std::hex << std::setw(8) << std::setfill('0') - << hkManager->getOwner() << " and lp ID " << localPoolId + << hkManager->getOwner() << " and lp ID 0x" << localPoolId << std::dec << " failed." << std::setfill(' ') << std::endl; #endif return result; @@ -78,7 +78,7 @@ inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "PoolPoolVariable: Read of local pool variable of " << "object " << std::hex << std::setw(8) << std::setfill('0') - << hkManager->getOwner() << " and lp ID " << localPoolId + << hkManager->getOwner() << " and lp ID 0x" << localPoolId << std::dec << " failed." << std::endl; #endif return result; diff --git a/datapoollocal/LocalPoolVector.tpp b/datapoollocal/LocalPoolVector.tpp index 5c3b0ce0..a010a8bb 100644 --- a/datapoollocal/LocalPoolVector.tpp +++ b/datapoollocal/LocalPoolVector.tpp @@ -33,7 +33,7 @@ template inline ReturnValue_t LocalPoolVector::readWithoutLock() { if(readWriteMode == pool_rwm_t::VAR_WRITE) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "LocalPoolVar: Invalid read write " + sif::warning << "LocalPoolVector: Invalid read write " "mode for read() call." << std::endl; #endif return PoolVariableIF::INVALID_READ_WRITE_MODE; @@ -45,10 +45,10 @@ inline ReturnValue_t LocalPoolVector::readWithoutLock() { if(result != RETURN_OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PoolVector: Read of local pool variable of object " - "0x" << std::hex << std::setw(8) << std::setfill('0') << - hkManager->getOwner() << "and lp ID 0x" << localPoolId << - std::dec << " failed." << std::endl; + sif::error << "LocalPoolVector: Read of local pool variable of object " + << std::hex << std::setw(8) << std::setfill('0') + << hkManager->getOwner() << "and lp ID 0x" << localPoolId + << std::dec << " failed." << std::endl; #endif return result; } @@ -69,7 +69,7 @@ template inline ReturnValue_t LocalPoolVector::commitWithoutLock() { if(readWriteMode == pool_rwm_t::VAR_READ) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "LocalPoolVar: Invalid read write " + sif::warning << "LocalPoolVector: Invalid read write " "mode for commit() call." << std::endl; #endif return PoolVariableIF::INVALID_READ_WRITE_MODE; @@ -78,10 +78,10 @@ inline ReturnValue_t LocalPoolVector::commitWithoutLock() { ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); if(result != RETURN_OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PoolVector: Read of local pool variable of object " - "0x" << std::hex << std::setw(8) << std::setfill('0') << - hkManager->getOwner() << " and lp ID 0x" << localPoolId << - std::dec << " failed.\n" << std::flush; + sif::error << "LocalPoolVector: Read of local pool variable of object " + << std::hex << std::setw(8) << std::setfill('0') + << hkManager->getOwner() << " and lp ID " << localPoolId + << std::dec << " failed." << std::endl; #endif return result; } diff --git a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp index faca03e3..2a7f9863 100644 --- a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp +++ b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp @@ -26,12 +26,23 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { testVariable.setValid(true); CHECK(testVariable.isValid()); + gp_id_t globPoolId(objects::TEST_LOCAL_POOL_OWNER_BASE, + lpool::uint8VarId); + lp_var_t testVariable2 = lp_var_t(globPoolId); + REQUIRE(testVariable.read() == retval::CATCH_OK); + REQUIRE(testVariable == 5); + } + + SECTION("ErrorHandling") { + // not try to use a local pool variable which does not exist lp_var_t invalidVariable = lp_var_t( objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff); REQUIRE(invalidVariable.read() == static_cast(HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND)); + REQUIRE(invalidVariable.commit() == + static_cast(HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND)); // now try to access with wrong type lp_var_t invalidVariable2 = lp_var_t( objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId); From dc8dd770e7e9500da1ce5813a954ea5c8111ca8f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 6 Jan 2021 19:07:35 +0100 Subject: [PATCH 12/38] added more tests --- .../datapoollocal/LocalPoolVariableTest.cpp | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp index 2a7f9863..e60d5a6b 100644 --- a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp +++ b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp @@ -29,8 +29,25 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { gp_id_t globPoolId(objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId); lp_var_t testVariable2 = lp_var_t(globPoolId); - REQUIRE(testVariable.read() == retval::CATCH_OK); - REQUIRE(testVariable == 5); + REQUIRE(testVariable2.read() == retval::CATCH_OK); + CHECK(testVariable2 == 5); + CHECK(testVariable == testVariable2); + testVariable = 10; + CHECK(testVariable != 5); + //CHECK(not testVariable != testVariable2); + uint8_t variableRaw = 0; + uint8_t* varPtr = &variableRaw; + size_t maxSize = testVariable.getSerializedSize(); + CHECK(maxSize == 1); + size_t serSize = 0; + CHECK(testVariable.serialize(&varPtr, &serSize, maxSize, + SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); + CHECK(variableRaw == 10); + const uint8_t* varConstPtr = &variableRaw; + testVariable = 5; + CHECK(testVariable.deSerialize(&varConstPtr, &serSize, + SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); + CHECK(testVariable == 10); } SECTION("ErrorHandling") { From 8807772d134c04dc495627ebeef7d4f45cb31057 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 6 Jan 2021 19:16:41 +0100 Subject: [PATCH 13/38] 100 % line coverage reached --- .../tests/datapoollocal/LocalPoolVariableTest.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp index e60d5a6b..b173089c 100644 --- a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp +++ b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp @@ -48,6 +48,17 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { CHECK(testVariable.deSerialize(&varConstPtr, &serSize, SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); CHECK(testVariable == 10); + CHECK(testVariable != testVariable2); + CHECK(testVariable2 < testVariable); + CHECK(testVariable2 < 10); + CHECK(testVariable > 5); + CHECK(testVariable > testVariable2); + variableRaw = static_cast(testVariable2); + CHECK(variableRaw == 5); + + CHECK(testVariable == 10); + testVariable = testVariable2; + CHECK(testVariable == 5); } SECTION("ErrorHandling") { From db7d28f8526c7a6998f712b5ed4f904f757f011a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 6 Jan 2021 19:32:33 +0100 Subject: [PATCH 14/38] test update --- datapoollocal/LocalPoolVariable.h | 1 + datapoollocal/LocalPoolVariable.tpp | 21 +++- unittest/internal/UnittDefinitions.h | 1 + unittest/tests/action/TestActionHelper.cpp | 2 + .../datapoollocal/LocalPoolVariableTest.cpp | 2 + unittest/user/CMakeLists.txt | 108 ++++++++++++++++-- unittest/user/unittest/core/CMakeLists.txt | 6 + .../user/unittest/core/CatchDefinitions.cpp | 3 + unittest/user/unittest/core/CatchFactory.cpp | 22 +++- unittest/user/unittest/core/CatchRunner.cpp | 13 +-- unittest/user/unittest/core/CatchSetup.cpp | 14 +-- unittest/user/unittest/core/printChar.cpp | 2 +- 12 files changed, 164 insertions(+), 31 deletions(-) diff --git a/datapoollocal/LocalPoolVariable.h b/datapoollocal/LocalPoolVariable.h index 84be54b1..21ee2764 100644 --- a/datapoollocal/LocalPoolVariable.h +++ b/datapoollocal/LocalPoolVariable.h @@ -7,6 +7,7 @@ #include "../datapool/PoolVariableIF.h" #include "../datapool/DataSetIF.h" +#include "../serviceinterface/ServiceInterface.h" #include "../objectmanager/ObjectManagerIF.h" #include "../serialize/SerializeAdapter.h" diff --git a/datapoollocal/LocalPoolVariable.tpp b/datapoollocal/LocalPoolVariable.tpp index 153a13d0..f35c8be2 100644 --- a/datapoollocal/LocalPoolVariable.tpp +++ b/datapoollocal/LocalPoolVariable.tpp @@ -35,8 +35,11 @@ inline ReturnValue_t LocalPoolVariable::readWithoutLock() { if(readWriteMode == pool_rwm_t::VAR_WRITE) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "LocalPoolVariable: Invalid read write " - "mode for read() call." << std::endl; -#endif + "mode for read call." << std::endl; +#else + fsfw::printWarning("LocalPoolVariable: Invalid read write " + "mode for read call."); +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ return PoolVariableIF::INVALID_READ_WRITE_MODE; } @@ -48,7 +51,11 @@ inline ReturnValue_t LocalPoolVariable::readWithoutLock() { << std::hex << std::setw(8) << std::setfill('0') << hkManager->getOwner() << " and lp ID 0x" << localPoolId << std::dec << " failed." << std::setfill(' ') << std::endl; -#endif +#else + fsfw::printError("LocalPoolVariable: Read of local pool variable of " + "object 0x%08x and lp ID 0x08x failed.", hkManager->getOwner(), + localPoolId); +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ return result; } this->value = *(poolEntry->address); @@ -69,7 +76,7 @@ inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "LocalPoolVariable: Invalid read write " "mode for commit() call." << std::endl; -#endif +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ return PoolVariableIF::INVALID_READ_WRITE_MODE; } PoolEntry* poolEntry = nullptr; @@ -80,7 +87,11 @@ inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { << "object " << std::hex << std::setw(8) << std::setfill('0') << hkManager->getOwner() << " and lp ID 0x" << localPoolId << std::dec << " failed." << std::endl; -#endif +#else + fsfw::printError("LocalPoolVariable: Read of local pool variable of " + "object 0x%08x and lp ID 0x08x failed.", hkManager->getOwner(), + localPoolId); +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ return result; } *(poolEntry->address) = this->value; diff --git a/unittest/internal/UnittDefinitions.h b/unittest/internal/UnittDefinitions.h index ea36fea4..d319f4bc 100644 --- a/unittest/internal/UnittDefinitions.h +++ b/unittest/internal/UnittDefinitions.h @@ -5,6 +5,7 @@ #include "../../serviceinterface/ServiceInterfaceStream.h" #include #include +#include namespace tv { // POD test values diff --git a/unittest/tests/action/TestActionHelper.cpp b/unittest/tests/action/TestActionHelper.cpp index 3109eba1..3957bba2 100644 --- a/unittest/tests/action/TestActionHelper.cpp +++ b/unittest/tests/action/TestActionHelper.cpp @@ -7,6 +7,8 @@ #include +#include + TEST_CASE( "Action Helper" , "[ActionHelper]") { ActionHelperOwnerMockBase testDhMock; diff --git a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp index b173089c..cf4f4b6b 100644 --- a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp +++ b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp @@ -90,7 +90,9 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { lp_var_t uint32tVar = lp_var_t( objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint32VarId); +#if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "LocalPoolVariable printout: " < #include StorageManagerIF* tglob::getIpcStoreHandle() { @@ -7,6 +8,8 @@ StorageManagerIF* tglob::getIpcStoreHandle() { } else { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "Global object manager uninitialized" << std::endl; +#else + fsfw::printError("Global object manager uninitialized"); #endif return nullptr; } diff --git a/unittest/user/unittest/core/CatchFactory.cpp b/unittest/user/unittest/core/CatchFactory.cpp index 3177212f..0597f08c 100644 --- a/unittest/user/unittest/core/CatchFactory.cpp +++ b/unittest/user/unittest/core/CatchFactory.cpp @@ -1,11 +1,15 @@ +#include +#include #include "CatchFactory.h" #include #include - #include #include #include +#include +#include +#include /** * @brief Produces system objects. @@ -50,7 +54,23 @@ void Factory::produce(void) { } void Factory::setStaticFrameworkObjectIds() { + PusServiceBase::packetSource = objects::NO_OBJECT; + PusServiceBase::packetDestination = objects::NO_OBJECT; + CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT; + CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT; + + VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION; + + DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT; + DeviceHandlerBase::rawDataReceiverId = objects::PUS_SERVICE_2_DEVICE_ACCESS; + + LocalDataPoolManager::defaultHkDestination = objects::NO_OBJECT; + + DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT; + + TmPacketStored::timeStamperId = objects::NO_OBJECT; } + diff --git a/unittest/user/unittest/core/CatchRunner.cpp b/unittest/user/unittest/core/CatchRunner.cpp index 35c53cd4..886d641f 100644 --- a/unittest/user/unittest/core/CatchRunner.cpp +++ b/unittest/user/unittest/core/CatchRunner.cpp @@ -1,17 +1,16 @@ /** - * @file CatchSource.cpp + * @file CatchRunner.cpp * @brief Source file to compile catch framework. * @details All tests should be written in other files. * For eclipse console output, install ANSI Escape in Console * from the eclipse market place to get colored characters. */ -#ifndef NO_UNIT_TEST_FRAMEWORK +#include -#define CATCH_CONFIG_RUNNER -#include +#define CATCH_CONFIG_COLOUR_WINDOWS -#if CUSTOM_UNITTEST_RUNNER == 0 +#include extern int customSetup(); @@ -25,7 +24,3 @@ int main( int argc, char* argv[] ) { return result; } -#endif - - -#endif diff --git a/unittest/user/unittest/core/CatchSetup.cpp b/unittest/user/unittest/core/CatchSetup.cpp index c93cf032..bda31400 100644 --- a/unittest/user/unittest/core/CatchSetup.cpp +++ b/unittest/user/unittest/core/CatchSetup.cpp @@ -1,21 +1,20 @@ -#include +#include "CatchFactory.h" #include "CatchDefinitions.h" -#include #ifdef GCOV #include #endif -#include "../../objectmanager/ObjectManager.h" -#include "../../objectmanager/ObjectManagerIF.h" -#include "../../storagemanager/StorageManagerIF.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" +#include +#include +#include +#include /* Global instantiations normally done in main.cpp */ /* Initialize Data Pool */ - +#if FSFW_CPP_OSTREAM_ENABLED == 1 namespace sif { /* Set up output streams */ ServiceInterfaceStream debug("DEBUG"); @@ -23,6 +22,7 @@ ServiceInterfaceStream info("INFO"); ServiceInterfaceStream error("ERROR"); ServiceInterfaceStream warning("WARNING"); } +#endif /* Global object manager */ ObjectManagerIF *objectManager; diff --git a/unittest/user/unittest/core/printChar.cpp b/unittest/user/unittest/core/printChar.cpp index 755a13b2..5d4f1b17 100644 --- a/unittest/user/unittest/core/printChar.cpp +++ b/unittest/user/unittest/core/printChar.cpp @@ -1,4 +1,4 @@ -#include +#include "printChar.h" #include void printChar(const char* character, bool errStream) { From 91cf5f176400a12c18e66ef53bf7efe1fab9265f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 6 Jan 2021 19:49:58 +0100 Subject: [PATCH 15/38] added way to completely disable printouts --- datapoollocal/LocalPoolVariable.tpp | 15 +++++---- serviceinterface/ServiceInterfacePrinter.cpp | 32 ++++++++++++++------ serviceinterface/ServiceInterfacePrinter.h | 2 ++ unittest/internal/UnittDefinitions.cpp | 6 ++-- unittest/internal/UnittDefinitions.h | 2 +- 5 files changed, 38 insertions(+), 19 deletions(-) diff --git a/datapoollocal/LocalPoolVariable.tpp b/datapoollocal/LocalPoolVariable.tpp index f35c8be2..f70e4e91 100644 --- a/datapoollocal/LocalPoolVariable.tpp +++ b/datapoollocal/LocalPoolVariable.tpp @@ -38,7 +38,7 @@ inline ReturnValue_t LocalPoolVariable::readWithoutLock() { "mode for read call." << std::endl; #else fsfw::printWarning("LocalPoolVariable: Invalid read write " - "mode for read call."); + "mode for read call.\n\r"); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ return PoolVariableIF::INVALID_READ_WRITE_MODE; } @@ -53,8 +53,8 @@ inline ReturnValue_t LocalPoolVariable::readWithoutLock() { << std::dec << " failed." << std::setfill(' ') << std::endl; #else fsfw::printError("LocalPoolVariable: Read of local pool variable of " - "object 0x%08x and lp ID 0x08x failed.", hkManager->getOwner(), - localPoolId); + "object 0x%08x and lp ID 0x%08x failed.\n\r", + hkManager->getOwner(), localPoolId); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ return result; } @@ -75,7 +75,10 @@ inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { if(readWriteMode == pool_rwm_t::VAR_READ) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "LocalPoolVariable: Invalid read write " - "mode for commit() call." << std::endl; + "mode for commit call." << std::endl; +#else + fsfw::printWarning("LocalPoolVariable: Invalid read write " + "mode for commit call.\n\r"); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ return PoolVariableIF::INVALID_READ_WRITE_MODE; } @@ -89,8 +92,8 @@ inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { << std::dec << " failed." << std::endl; #else fsfw::printError("LocalPoolVariable: Read of local pool variable of " - "object 0x%08x and lp ID 0x08x failed.", hkManager->getOwner(), - localPoolId); + "object 0x%08x and lp ID 0x%08x failed.\n\r", + hkManager->getOwner(), localPoolId); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ return result; } diff --git a/serviceinterface/ServiceInterfacePrinter.cpp b/serviceinterface/ServiceInterfacePrinter.cpp index e8eb498f..15e738a8 100644 --- a/serviceinterface/ServiceInterfacePrinter.cpp +++ b/serviceinterface/ServiceInterfacePrinter.cpp @@ -6,12 +6,14 @@ #include #include - fsfw::PrintLevel printLevel = fsfw::PrintLevel::DEBUG; -uint8_t printBuffer[fsfwconfig::FSFW_PRINT_BUFFER_SIZE]; #if defined(WIN32) && FSFW_COLORED_OUTPUT == 1 bool consoleInitialized = false; -#endif +#endif /* defined(WIN32) && FSFW_COLORED_OUTPUT == 1 */ + + +#if FSFW_DISABLE_PRINTOUT == 0 +uint8_t printBuffer[fsfwconfig::FSFW_PRINT_BUFFER_SIZE]; void fsfwPrint(fsfw::PrintLevel printType, const char* fmt, va_list arg) { @@ -81,13 +83,6 @@ void fsfwPrint(fsfw::PrintLevel printType, const char* fmt, va_list arg) { printf("%s", printBuffer); } -void fsfw::setPrintLevel(PrintLevel printLevel_) { - printLevel = printLevel_; -} - -fsfw::PrintLevel fsfw::getPrintLevel() { - return printLevel; -} void fsfw::printInfo(const char *fmt, ...) { va_list args; @@ -116,3 +111,20 @@ void fsfw::printError(const char *fmt, ...) { fsfwPrint(fsfw::PrintLevel::ERROR_TYPE, fmt, args); va_end(args); } + +#else + +void fsfw::printInfo(const char *fmt, ...) {} +void fsfw::printWarning(const char *fmt, ...) {} +void fsfw::printDebug(const char *fmt, ...) {} +void fsfw::printError(const char *fmt, ...) {} + +#endif /* FSFW_DISABLE_PRINTOUT == 0 */ + +void fsfw::setPrintLevel(PrintLevel printLevel_) { + printLevel = printLevel_; +} + +fsfw::PrintLevel fsfw::getPrintLevel() { + return printLevel; +} diff --git a/serviceinterface/ServiceInterfacePrinter.h b/serviceinterface/ServiceInterfacePrinter.h index 8b81ee7a..a60b6332 100644 --- a/serviceinterface/ServiceInterfacePrinter.h +++ b/serviceinterface/ServiceInterfacePrinter.h @@ -1,4 +1,6 @@ +#if FSFW_DISABLE_PRINTOUT == 0 #include +#endif namespace fsfw { diff --git a/unittest/internal/UnittDefinitions.cpp b/unittest/internal/UnittDefinitions.cpp index 7138e6c6..d20771a4 100644 --- a/unittest/internal/UnittDefinitions.cpp +++ b/unittest/internal/UnittDefinitions.cpp @@ -3,7 +3,9 @@ ReturnValue_t unitt::put_error(std::string errorId) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "Unit Tester error: Failed at test ID " - << errorId << "\n" << std::flush; -#endif + << errorId << std::endl; +#else + fsfw::printError("Unit Tester error: Failed at test ID 0x%08x", errorId); +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ return HasReturnvaluesIF::RETURN_FAILED; } diff --git a/unittest/internal/UnittDefinitions.h b/unittest/internal/UnittDefinitions.h index d319f4bc..3e14fec5 100644 --- a/unittest/internal/UnittDefinitions.h +++ b/unittest/internal/UnittDefinitions.h @@ -2,7 +2,7 @@ #define UNITTEST_INTERNAL_UNITTDEFINITIONS_H_ #include "../../returnvalues/HasReturnvaluesIF.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../serviceinterface/ServiceInterface.h" #include #include #include From dacdfc62d3841a89be5aa4988e35784737027dd1 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 6 Jan 2021 21:14:23 +0100 Subject: [PATCH 16/38] a lot of bugfixes and important api change --- datapool/PoolDataSetBase.cpp | 34 ++++++---- datapool/PoolDataSetBase.h | 23 ++++--- datapool/PoolDataSetIF.h | 5 +- datapool/PoolEntry.cpp | 2 + datapool/ReadCommitIF.h | 11 ++-- datapoollocal/LocalPoolDataSetBase.cpp | 65 +++++++++++++++---- datapoollocal/LocalPoolDataSetBase.h | 21 +++++- datapoollocal/LocalPoolVariable.h | 19 +++++- datapoollocal/LocalPoolVariable.tpp | 19 ++++-- datapoollocal/LocalPoolVector.h | 14 ++-- datapoollocal/LocalPoolVector.tpp | 13 ++-- devicehandlers/DeviceHandlerBase.cpp | 3 +- events/EventManager.cpp | 8 ++- events/EventManager.h | 4 ++ internalError/InternalErrorReporter.cpp | 29 +++++---- internalError/InternalErrorReporter.h | 8 ++- ipc/MutexIF.h | 2 +- osal/host/Clock.cpp | 4 +- osal/host/Mutex.cpp | 6 +- power/Fuse.cpp | 7 +- power/PowerSensor.cpp | 3 +- unittest/internal/osal/IntTestMutex.cpp | 2 +- unittest/tests/datapoollocal/DataSetTest.cpp | 21 ++++++ .../tests/datapoollocal/LocalPoolOwnerBase.h | 39 +++++++++-- .../datapoollocal/LocalPoolVariableTest.cpp | 29 ++++++++- .../datapoollocal/LocalPoolVectorTest.cpp | 16 +++++ 26 files changed, 314 insertions(+), 93 deletions(-) create mode 100644 unittest/tests/datapoollocal/DataSetTest.cpp create mode 100644 unittest/tests/datapoollocal/LocalPoolVectorTest.cpp diff --git a/datapool/PoolDataSetBase.cpp b/datapool/PoolDataSetBase.cpp index 5fb1c3c7..05797012 100644 --- a/datapool/PoolDataSetBase.cpp +++ b/datapool/PoolDataSetBase.cpp @@ -38,11 +38,12 @@ ReturnValue_t PoolDataSetBase::registerVariable( return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t PoolDataSetBase::read(uint32_t lockTimeout) { +ReturnValue_t PoolDataSetBase::read(MutexIF::TimeoutType timeoutType, + uint32_t lockTimeout) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t error = result; if (state == States::STATE_SET_UNINITIALISED) { - lockDataPool(lockTimeout); + lockDataPool(timeoutType, lockTimeout); for (uint16_t count = 0; count < fillCount; count++) { result = readVariable(count); if(result != RETURN_OK) { @@ -86,7 +87,8 @@ ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) { != PoolVariableIF::NO_PARAMETER) { if(protectEveryReadCommitCall) { - result = registeredVariables[count]->read(mutexTimeout); + result = registeredVariables[count]->read( + MutexIF::TimeoutType::WAITING, mutexTimeout); } else { result = registeredVariables[count]->readWithoutLock(); @@ -99,25 +101,28 @@ ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) { return result; } -ReturnValue_t PoolDataSetBase::commit(uint32_t lockTimeout) { +ReturnValue_t PoolDataSetBase::commit(MutexIF::TimeoutType timeoutType, + uint32_t lockTimeout) { if (state == States::STATE_SET_WAS_READ) { - handleAlreadyReadDatasetCommit(lockTimeout); + handleAlreadyReadDatasetCommit(timeoutType, lockTimeout); return HasReturnvaluesIF::RETURN_OK; } else { - return handleUnreadDatasetCommit(lockTimeout); + return handleUnreadDatasetCommit(timeoutType, lockTimeout); } } -void PoolDataSetBase::handleAlreadyReadDatasetCommit(uint32_t lockTimeout) { - lockDataPool(lockTimeout); +void PoolDataSetBase::handleAlreadyReadDatasetCommit( + MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) { + lockDataPool(timeoutType, lockTimeout); for (uint16_t count = 0; count < fillCount; count++) { if (registeredVariables[count]->getReadWriteMode() != PoolVariableIF::VAR_READ && registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) { if(protectEveryReadCommitCall) { - registeredVariables[count]->commit(mutexTimeout); + registeredVariables[count]->commit( + MutexIF::TimeoutType::WAITING, mutexTimeout); } else { registeredVariables[count]->commitWithoutLock(); @@ -128,16 +133,18 @@ void PoolDataSetBase::handleAlreadyReadDatasetCommit(uint32_t lockTimeout) { unlockDataPool(); } -ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(uint32_t lockTimeout) { +ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit( + MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - lockDataPool(lockTimeout); + lockDataPool(timeoutType, lockTimeout); for (uint16_t count = 0; count < fillCount; count++) { if (registeredVariables[count]->getReadWriteMode() == PoolVariableIF::VAR_WRITE && registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) { if(protectEveryReadCommitCall) { - result = registeredVariables[count]->commit(mutexTimeout); + result = registeredVariables[count]->commit( + MutexIF::TimeoutType::WAITING, mutexTimeout); } else { result = registeredVariables[count]->commitWithoutLock(); @@ -160,7 +167,8 @@ ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(uint32_t lockTimeout) { } -ReturnValue_t PoolDataSetBase::lockDataPool(uint32_t timeoutMs) { +ReturnValue_t PoolDataSetBase::lockDataPool(MutexIF::TimeoutType timeoutType, + uint32_t lockTimeout) { return HasReturnvaluesIF::RETURN_OK; } diff --git a/datapool/PoolDataSetBase.h b/datapool/PoolDataSetBase.h index 7c1d84a4..0528f40f 100644 --- a/datapool/PoolDataSetBase.h +++ b/datapool/PoolDataSetBase.h @@ -62,8 +62,9 @@ public: * - @c SET_WAS_ALREADY_READ if read() is called twice without calling * commit() in between */ - virtual ReturnValue_t read(uint32_t lockTimeout = - MutexIF::BLOCKING) override; + virtual ReturnValue_t read( + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t lockTimeout = 20) override; /** * @brief The commit call initializes writing back the registered variables. * @details @@ -82,8 +83,9 @@ public: * - @c COMMITING_WITHOUT_READING if set was not read yet and * contains non write-only variables */ - virtual ReturnValue_t commit(uint32_t lockTimeout = - MutexIF::BLOCKING) override; + virtual ReturnValue_t commit( + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t lockTimeout = 20) override; /** * Register the passed pool variable instance into the data set. @@ -97,8 +99,9 @@ public: * thread-safety. Default implementation is empty * @return Always returns -@c RETURN_OK */ - virtual ReturnValue_t lockDataPool(uint32_t timeoutMs = - MutexIF::BLOCKING) override; + virtual ReturnValue_t lockDataPool( + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20) override; /** * Provides the means to unlock the underlying data structure to ensure * thread-safety. Default implementation is empty @@ -160,8 +163,12 @@ private: uint32_t mutexTimeout = 20; ReturnValue_t readVariable(uint16_t count); - void handleAlreadyReadDatasetCommit(uint32_t lockTimeout); - ReturnValue_t handleUnreadDatasetCommit(uint32_t lockTimeout); + void handleAlreadyReadDatasetCommit( + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20); + ReturnValue_t handleUnreadDatasetCommit( + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20); }; #endif /* FSFW_DATAPOOL_POOLDATASETBASE_H_ */ diff --git a/datapool/PoolDataSetIF.h b/datapool/PoolDataSetIF.h index 99c06cfd..1f52871d 100644 --- a/datapool/PoolDataSetIF.h +++ b/datapool/PoolDataSetIF.h @@ -18,7 +18,10 @@ public: * thread-safety * @return Lock operation result */ - virtual ReturnValue_t lockDataPool(dur_millis_t timeoutMs) = 0; + virtual ReturnValue_t lockDataPool( + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20) = 0; + /** * @brief Unlock call corresponding to the lock call. * @return Unlock operation result diff --git a/datapool/PoolEntry.cpp b/datapool/PoolEntry.cpp index 58375162..5f5f56f2 100644 --- a/datapool/PoolEntry.cpp +++ b/datapool/PoolEntry.cpp @@ -88,8 +88,10 @@ Type PoolEntry::getType() { template class PoolEntry; template class PoolEntry; template class PoolEntry; +template class PoolEntry; template class PoolEntry; template class PoolEntry; template class PoolEntry; +template class PoolEntry; template class PoolEntry; template class PoolEntry; diff --git a/datapool/ReadCommitIF.h b/datapool/ReadCommitIF.h index 0cdce371..efe51594 100644 --- a/datapool/ReadCommitIF.h +++ b/datapool/ReadCommitIF.h @@ -2,6 +2,7 @@ #define FSFW_DATAPOOL_READCOMMITIF_H_ #include +#include /** * @brief Common interface for all software objects which employ read-commit @@ -10,8 +11,10 @@ class ReadCommitIF { public: virtual ~ReadCommitIF() {} - virtual ReturnValue_t read(uint32_t mutexTimeout) = 0; - virtual ReturnValue_t commit(uint32_t mutexTimeout) = 0; + virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) = 0; + virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) = 0; protected: @@ -19,11 +22,11 @@ protected: //! members with commit and read semantics where the lock is only necessary //! once. virtual ReturnValue_t readWithoutLock() { - return read(20); + return read(MutexIF::TimeoutType::WAITING, 20); } virtual ReturnValue_t commitWithoutLock() { - return commit(20); + return commit(MutexIF::TimeoutType::WAITING, 20); } }; diff --git a/datapoollocal/LocalPoolDataSetBase.cpp b/datapoollocal/LocalPoolDataSetBase.cpp index dbe34dfd..af492146 100644 --- a/datapoollocal/LocalPoolDataSetBase.cpp +++ b/datapoollocal/LocalPoolDataSetBase.cpp @@ -1,4 +1,6 @@ #include "LocalPoolDataSetBase.h" + +#include "../serviceinterface/ServiceInterface.h" #include "../datapoollocal/LocalDataPoolManager.h" #include "../housekeeping/PeriodicHousekeepingHelper.h" #include "../serialize/SerializeAdapter.h" @@ -15,7 +17,10 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner " << "invalid!" << std::endl; -#endif +#else + fsfw::printError("LocalPoolDataSetBase::LocalPoolDataSetBase: Owner " + "invalid!\n\r"); +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ return; } hkManager = hkOwner->getHkManagerHandle(); @@ -44,13 +49,26 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid, mutex = MutexFactory::instance()->createMutex(); } +LocalPoolDataSetBase::LocalPoolDataSetBase( + PoolVariableIF **registeredVariablesArray, + const size_t maxNumberOfVariables, bool protectFunctions): + PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) { + if(protectFunctions) { + mutex = MutexFactory::instance()->createMutex(); + } + +} + + LocalPoolDataSetBase::~LocalPoolDataSetBase() { } -ReturnValue_t LocalPoolDataSetBase::lockDataPool(uint32_t timeoutMs) { +ReturnValue_t LocalPoolDataSetBase::lockDataPool( + MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { if(hkManager != nullptr) { - MutexIF* mutex = hkManager->getMutexHandle(); - return mutex->lockMutex(MutexIF::TimeoutType::WAITING, timeoutMs); + MutexIF* poolMutex = hkManager->getMutexHandle(); + return poolMutex->lockMutex(timeoutType, timeoutMs); } return HasReturnvaluesIF::RETURN_OK; } @@ -150,9 +168,12 @@ ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer, size, maxSize, streamEndianness); if(result != HasReturnvaluesIF::RETURN_OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "LocalDataSet::serializeLocalPoolIds: Serialization" - " error!" << std::endl; -#endif + sif::warning << "LocalPoolDataSetBase::serializeLocalPoolIds: " + << "Serialization error!" << std::endl; +#else + fsfw::printWarning("LocalPoolDataSetBase::serializeLocalPoolIds: " + "Serialization error!\n\r"); +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ return result; } } @@ -211,8 +232,11 @@ ReturnValue_t LocalPoolDataSetBase::serialize(uint8_t **buffer, size_t *size, void LocalPoolDataSetBase::bitSetter(uint8_t* byte, uint8_t position) const { if(position > 7) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "Pool Raw Access: Bit setting invalid position" + sif::warning << "LocalPoolDataSetBase::bitSetter: Invalid position!" << std::endl; +#else + fsfw::printWarning("LocalPoolDataSetBase::bitSetter: " + "Invalid position!\n\r"); #endif return; } @@ -244,14 +268,19 @@ void LocalPoolDataSetBase::initializePeriodicHelper( } void LocalPoolDataSetBase::setChanged(bool changed) { - // TODO: Make this configurable? - MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20); + if(mutex == nullptr) { + this->changed = changed; + return; + } + MutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeout); this->changed = changed; } bool LocalPoolDataSetBase::hasChanged() const { - // TODO: Make this configurable? - MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20); + if(mutex == nullptr) { + return changed; + } + MutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeout); return changed; } @@ -273,18 +302,22 @@ bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte, } bool LocalPoolDataSetBase::isValid() const { + if(mutex == nullptr) { + return this->valid; + } MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 5); return this->valid; } void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) { - MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 5); + mutex->lockMutex(timeoutType, mutexTimeout); if(setEntriesRecursively) { for(size_t idx = 0; idx < this->getFillCount(); idx++) { registeredVariables[idx] -> setValid(valid); } } this->valid = valid; + mutex->unlockMutex(); } void LocalPoolDataSetBase::setReadCommitProtectionBehaviour( @@ -292,3 +325,9 @@ void LocalPoolDataSetBase::setReadCommitProtectionBehaviour( PoolDataSetBase::setReadCommitProtectionBehaviour(protectEveryReadCommit, mutexTimeout); } + +void LocalPoolDataSetBase::setDataSetMutexTimeout( + MutexIF::TimeoutType timeoutType, uint32_t mutexTimeout) { + this->timeoutType = timeoutType; + this->mutexTimeout = mutexTimeout; +} diff --git a/datapoollocal/LocalPoolDataSetBase.h b/datapoollocal/LocalPoolDataSetBase.h index d9b6a221..b44f607f 100644 --- a/datapoollocal/LocalPoolDataSetBase.h +++ b/datapoollocal/LocalPoolDataSetBase.h @@ -67,6 +67,15 @@ public: LocalPoolDataSetBase(sid_t sid, PoolVariableIF** registeredVariablesArray, const size_t maxNumberOfVariables); + /** + * Simple constructor, if the dataset is not owner permanently by + * a class with a HK manager. + * @param registeredVariablesArray + * @param maxNumberOfVariables + */ + LocalPoolDataSetBase(PoolVariableIF** registeredVariablesArray, + const size_t maxNumberOfVariables, bool protectFunctions = true); + /** * @brief The destructor automatically manages writing the valid * information of variables. @@ -87,6 +96,9 @@ public: void setReadCommitProtectionBehaviour(bool protectEveryReadCommit, uint32_t mutexTimeout = 20); + void setDataSetMutexTimeout(MutexIF::TimeoutType timeoutType, + uint32_t mutexTimeout); + void setValidityBufferGeneration(bool withValidityBuffer); sid_t getSid() const; @@ -138,7 +150,12 @@ public: protected: sid_t sid; + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; uint32_t mutexTimeout = 20; + /** + * This mutex is required because the dataset can potentially be accessed + * by multiple threads for information like change status or validity. + */ MutexIF* mutex = nullptr; bool diagnostic = false; @@ -183,7 +200,9 @@ protected: * @details * It makes use of the lockDataPool method offered by the DataPool class. */ - ReturnValue_t lockDataPool(uint32_t timeoutMs) override; + ReturnValue_t lockDataPool(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) override; + /** * @brief This is a small helper function to facilitate * unlocking the global data pool diff --git a/datapoollocal/LocalPoolVariable.h b/datapoollocal/LocalPoolVariable.h index 21ee2764..c81967a1 100644 --- a/datapoollocal/LocalPoolVariable.h +++ b/datapoollocal/LocalPoolVariable.h @@ -106,7 +106,9 @@ public: * at once to avoid the overhead of unnecessary lock und unlock operations. * */ - ReturnValue_t read(dur_millis_t lockTimeout = MutexIF::BLOCKING) override; + ReturnValue_t read(MutexIF::TimeoutType timeoutType = + MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20) override; /** * @brief The commit call copies the array values back to the data pool. * @details @@ -116,8 +118,21 @@ public: * It is recommended to use DataSets to read and commit multiple variables * at once to avoid the overhead of unnecessary lock und unlock operations. */ - ReturnValue_t commit(dur_millis_t lockTimeout = MutexIF::BLOCKING) override; + ReturnValue_t commit(MutexIF::TimeoutType timeoutType = + MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20) override; + /** + * @brief This commit function can be used to set the pool variable valid + * as well. + * @param setValid + * @param timeoutType + * @param timeoutMs + * @return + */ + ReturnValue_t commit(bool setValid, MutexIF::TimeoutType timeoutType = + MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20); LocalPoolVariable &operator=(const T& newValue); LocalPoolVariable &operator=(const LocalPoolVariable& newPoolVariable); diff --git a/datapoollocal/LocalPoolVariable.tpp b/datapoollocal/LocalPoolVariable.tpp index f70e4e91..9387acc5 100644 --- a/datapoollocal/LocalPoolVariable.tpp +++ b/datapoollocal/LocalPoolVariable.tpp @@ -24,9 +24,9 @@ inline LocalPoolVariable::LocalPoolVariable(gp_id_t globalPoolId, template -inline ReturnValue_t LocalPoolVariable::read(dur_millis_t lockTimeout) { - MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, - lockTimeout); +inline ReturnValue_t LocalPoolVariable::read( + MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { + MutexHelper(hkManager->getMutexHandle(), timeoutType, timeoutMs); return readWithoutLock(); } @@ -64,9 +64,16 @@ inline ReturnValue_t LocalPoolVariable::readWithoutLock() { } template -inline ReturnValue_t LocalPoolVariable::commit(dur_millis_t lockTimeout) { - MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, - lockTimeout); +inline ReturnValue_t LocalPoolVariable::commit(bool setValid, + MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { + this->setValid(setValid); + return commit(timeoutType, timeoutMs); +} + +template +inline ReturnValue_t LocalPoolVariable::commit( + MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { + MutexHelper(hkManager->getMutexHandle(), timeoutType, timeoutMs); return commitWithoutLock(); } diff --git a/datapoollocal/LocalPoolVector.h b/datapoollocal/LocalPoolVector.h index 58face3c..773a52cc 100644 --- a/datapoollocal/LocalPoolVector.h +++ b/datapoollocal/LocalPoolVector.h @@ -7,7 +7,7 @@ #include "../datapool/PoolVariableIF.h" #include "../datapoollocal/LocalDataPoolManager.h" #include "../serialize/SerializeAdapter.h" -#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../serviceinterface/ServiceInterface.h" /** @@ -123,7 +123,9 @@ public: * It is recommended to use DataSets to read and commit multiple variables * at once to avoid the overhead of unnecessary lock und unlock operations. */ - ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; + ReturnValue_t read(MutexIF::TimeoutType timeoutType = + MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20) override; /** * @brief The commit call copies the array values back to the data pool. * @details @@ -133,7 +135,9 @@ public: * It is recommended to use DataSets to read and commit multiple variables * at once to avoid the overhead of unnecessary lock und unlock operations. */ - ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + ReturnValue_t commit(MutexIF::TimeoutType timeoutType = + MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20) override; protected: /** @@ -157,12 +161,12 @@ protected: private: - +#if FSFW_CPP_OSTREAM_ENABLED == 1 // std::ostream is the type for object std::cout template friend std::ostream& operator<< (std::ostream &out, const LocalPoolVector &var); - +#endif }; diff --git a/datapoollocal/LocalPoolVector.tpp b/datapoollocal/LocalPoolVector.tpp index a010a8bb..6af80de6 100644 --- a/datapoollocal/LocalPoolVector.tpp +++ b/datapoollocal/LocalPoolVector.tpp @@ -24,9 +24,9 @@ inline LocalPoolVector::LocalPoolVector(gp_id_t globalPoolId, dataSet, setReadWriteMode) {} template -inline ReturnValue_t LocalPoolVector::read(uint32_t lockTimeout) { - MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, - lockTimeout); +inline ReturnValue_t LocalPoolVector::read( + MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { + MutexHelper(hkManager->getMutexHandle(), timeoutType, timeoutMs); return readWithoutLock(); } template @@ -59,9 +59,8 @@ inline ReturnValue_t LocalPoolVector::readWithoutLock() { template inline ReturnValue_t LocalPoolVector::commit( - uint32_t lockTimeout) { - MutexHelper(hkManager->getMutexHandle(), MutexIF::TimeoutType::WAITING, - lockTimeout); + MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { + MutexHelper(hkManager->getMutexHandle(), timeoutType, timeoutMs); return commitWithoutLock(); } @@ -153,6 +152,7 @@ inline ReturnValue_t LocalPoolVector::deSerialize( return result; } +#if FSFW_CPP_OSTREAM_ENABLED == 1 template inline std::ostream& operator<< (std::ostream &out, const LocalPoolVector &var) { @@ -166,5 +166,6 @@ inline std::ostream& operator<< (std::ostream &out, out << "]"; return out; } +#endif #endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_TPP_ */ diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 1af6932a..580f8c0d 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -229,7 +229,8 @@ ReturnValue_t DeviceHandlerBase::initialize() { if(result == HasReturnvaluesIF::RETURN_OK) { thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL; - thermalSet->commit(PoolVariableIF::VALID); + thermalSet->heaterRequest.setValid(true); + thermalSet->commit(); } } diff --git a/events/EventManager.cpp b/events/EventManager.cpp index 65e19d10..e25e574f 100644 --- a/events/EventManager.cpp +++ b/events/EventManager.cpp @@ -162,9 +162,15 @@ void EventManager::printEvent(EventMessage* message) { #endif void EventManager::lockMutex() { - mutex->lockMutex(MutexIF::BLOCKING); + mutex->lockMutex(timeoutType, timeoutMs); } void EventManager::unlockMutex() { mutex->unlockMutex(); } + +void EventManager::setMutexTimeout(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + this->timeoutType = timeoutType; + this->timeoutMs = timeoutMs; +} diff --git a/events/EventManager.h b/events/EventManager.h index c6bd07be..abce9b8b 100644 --- a/events/EventManager.h +++ b/events/EventManager.h @@ -29,6 +29,8 @@ public: EventManager(object_id_t setObjectId); virtual ~EventManager(); + void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs); + MessageQueueId_t getEventReportQueue(); ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false); @@ -51,6 +53,8 @@ protected: std::map listenerList; MutexIF* mutex = nullptr; + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; + uint32_t timeoutMs = 20; static const uint8_t N_POOLS = 3; LocalPool factoryBackend; diff --git a/internalError/InternalErrorReporter.cpp b/internalError/InternalErrorReporter.cpp index 48b6f851..6842da8e 100644 --- a/internalError/InternalErrorReporter.cpp +++ b/internalError/InternalErrorReporter.cpp @@ -23,7 +23,7 @@ void InternalErrorReporter::setDiagnosticPrintout(bool enable) { } ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { - internalErrorDataset.read(INTERNAL_ERROR_MUTEX_TIMEOUT); + internalErrorDataset.read(timeoutType, timeoutMs); uint32_t newQueueHits = getAndResetQueueHits(); uint32_t newTmHits = getAndResetTmHits(); @@ -46,8 +46,8 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { internalErrorDataset.queueHits.value += newQueueHits; internalErrorDataset.storeHits.value += newStoreHits; internalErrorDataset.tmHits.value += newTmHits; - - internalErrorDataset.commit(INTERNAL_ERROR_MUTEX_TIMEOUT); + internalErrorDataset.setValidity(true, true); + internalErrorDataset.commit(timeoutType, timeoutMs); poolManager.performHkOperation(); @@ -69,7 +69,7 @@ void InternalErrorReporter::lostTm() { uint32_t InternalErrorReporter::getAndResetQueueHits() { uint32_t value; - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); value = queueHits; queueHits = 0; mutex->unlockMutex(); @@ -78,21 +78,21 @@ uint32_t InternalErrorReporter::getAndResetQueueHits() { uint32_t InternalErrorReporter::getQueueHits() { uint32_t value; - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); value = queueHits; mutex->unlockMutex(); return value; } void InternalErrorReporter::incrementQueueHits() { - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); queueHits++; mutex->unlockMutex(); } uint32_t InternalErrorReporter::getAndResetTmHits() { uint32_t value; - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); value = tmHits; tmHits = 0; mutex->unlockMutex(); @@ -101,14 +101,14 @@ uint32_t InternalErrorReporter::getAndResetTmHits() { uint32_t InternalErrorReporter::getTmHits() { uint32_t value; - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); value = tmHits; mutex->unlockMutex(); return value; } void InternalErrorReporter::incrementTmHits() { - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); tmHits++; mutex->unlockMutex(); } @@ -119,7 +119,7 @@ void InternalErrorReporter::storeFull() { uint32_t InternalErrorReporter::getAndResetStoreHits() { uint32_t value; - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); value = storeHits; storeHits = 0; mutex->unlockMutex(); @@ -128,14 +128,14 @@ uint32_t InternalErrorReporter::getAndResetStoreHits() { uint32_t InternalErrorReporter::getStoreHits() { uint32_t value; - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); value = storeHits; mutex->unlockMutex(); return value; } void InternalErrorReporter::incrementStoreHits() { - mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT); + mutex->lockMutex(timeoutType, timeoutMs); storeHits++; mutex->unlockMutex(); } @@ -190,3 +190,8 @@ ReturnValue_t InternalErrorReporter::initializeAfterTaskCreation() { return poolManager.initializeAfterTaskCreation(); } +void InternalErrorReporter::setMutexTimeout(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs) { + this->timeoutType = timeoutType; + this->timeoutMs = timeoutMs; +} diff --git a/internalError/InternalErrorReporter.h b/internalError/InternalErrorReporter.h index 8d33c06e..c85057d6 100644 --- a/internalError/InternalErrorReporter.h +++ b/internalError/InternalErrorReporter.h @@ -22,7 +22,6 @@ class InternalErrorReporter: public SystemObject, public InternalErrorReporterIF, public HasLocalDataPoolIF { public: - static constexpr uint8_t INTERNAL_ERROR_MUTEX_TIMEOUT = 20; InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth = 5); @@ -34,6 +33,9 @@ public: */ void setDiagnosticPrintout(bool enable); + void setMutexTimeout(MutexIF::TimeoutType timeoutType, + uint32_t timeoutMs); + virtual ~InternalErrorReporter(); virtual object_id_t getObjectId() const override; @@ -61,7 +63,11 @@ protected: LocalDataPoolManager poolManager; PeriodicTaskIF* executingTask = nullptr; + MutexIF* mutex = nullptr; + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; + uint32_t timeoutMs = 20; + sid_t internalErrorSid; InternalErrorDataset internalErrorDataset; diff --git a/ipc/MutexIF.h b/ipc/MutexIF.h index 5673e4d7..084b702b 100644 --- a/ipc/MutexIF.h +++ b/ipc/MutexIF.h @@ -14,7 +14,7 @@ public: /** * Different types of timeout for the mutex lock. */ - enum TimeoutType { + enum class TimeoutType { POLLING, //!< If mutex is not available, return immediately WAITING, //!< Wait a specified time for the mutex to become available BLOCKING //!< Block indefinitely until the mutex becomes available. diff --git a/osal/host/Clock.cpp b/osal/host/Clock.cpp index 2bc78785..88bf51d2 100644 --- a/osal/host/Clock.cpp +++ b/osal/host/Clock.cpp @@ -202,7 +202,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){ return HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); + ReturnValue_t result = timeMutex->lockMutex(); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -217,7 +217,7 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { if(timeMutex == nullptr){ return HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); + ReturnValue_t result = timeMutex->lockMutex(); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } diff --git a/osal/host/Mutex.cpp b/osal/host/Mutex.cpp index ad8873df..892028b2 100644 --- a/osal/host/Mutex.cpp +++ b/osal/host/Mutex.cpp @@ -4,16 +4,16 @@ Mutex::Mutex() {} ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType, uint32_t timeoutMs) { - if(timeoutType == MutexIF::BLOCKING) { + if(timeoutType == TimeoutType::BLOCKING) { mutex.lock(); return HasReturnvaluesIF::RETURN_OK; } - else if(timeoutType == MutexIF::POLLING) { + else if(timeoutType == TimeoutType::POLLING) { if(mutex.try_lock()) { return HasReturnvaluesIF::RETURN_OK; } } - else if(timeoutMs > MutexIF::POLLING){ + else if(timeoutType == TimeoutType::WAITING){ auto chronoMs = std::chrono::milliseconds(timeoutMs); if(mutex.try_lock_for(chronoMs)) { return HasReturnvaluesIF::RETURN_OK; diff --git a/power/Fuse.cpp b/power/Fuse.cpp index 1c30d83f..b6e0a7f1 100644 --- a/power/Fuse.cpp +++ b/power/Fuse.cpp @@ -65,8 +65,8 @@ ReturnValue_t Fuse::check() { set.read(); if (!healthHelper.healthTable->isHealthy(getObjectId())) { setAllMonitorsToUnchecked(); - set.commit(PoolVariableIF::INVALID); - return RETURN_OK; + set.setValidity(false, true); + return set.commit(); } ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; checkFuseState(); @@ -206,7 +206,8 @@ float Fuse::getPower() { void Fuse::setDataPoolEntriesInvalid() { set.read(); - set.commit(PoolVariableIF::INVALID); + set.setValidity(false, true); + set.commit(); } ReturnValue_t Fuse::getParameter(uint8_t domainId, uint16_t parameterId, diff --git a/power/PowerSensor.cpp b/power/PowerSensor.cpp index 1ef041e3..fb181d9f 100644 --- a/power/PowerSensor.cpp +++ b/power/PowerSensor.cpp @@ -97,7 +97,8 @@ void PowerSensor::checkCommandQueue() { void PowerSensor::setDataPoolEntriesInvalid() { powerSensorSet.read(); - powerSensorSet.commit(PoolVariableIF::INVALID); + powerSensorSet.setValidity(false, true); + powerSensorSet.commit(); } float PowerSensor::getPower() { diff --git a/unittest/internal/osal/IntTestMutex.cpp b/unittest/internal/osal/IntTestMutex.cpp index 3316de74..2a1584b8 100644 --- a/unittest/internal/osal/IntTestMutex.cpp +++ b/unittest/internal/osal/IntTestMutex.cpp @@ -13,7 +13,7 @@ void testmutex::testMutex() { std::string id = "[testMutex]"; MutexIF* mutex = MutexFactory::instance()->createMutex(); - auto result = mutex->lockMutex(MutexIF::POLLING); + auto result = mutex->lockMutex(MutexIF::TimeoutType::POLLING); if(result != HasReturnvaluesIF::RETURN_OK) { unitt::put_error(id); } diff --git a/unittest/tests/datapoollocal/DataSetTest.cpp b/unittest/tests/datapoollocal/DataSetTest.cpp new file mode 100644 index 00000000..ccb7603d --- /dev/null +++ b/unittest/tests/datapoollocal/DataSetTest.cpp @@ -0,0 +1,21 @@ +#include "LocalPoolOwnerBase.h" + +#include +#include +#include + +TEST_CASE("LocalDataSet" , "[LocDataSetTest]") { + LocalPoolOwnerBase* poolOwner = objectManager-> + get(objects::TEST_LOCAL_POOL_OWNER_BASE); + REQUIRE(poolOwner != nullptr); + REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); + REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() + == retval::CATCH_OK); + + SECTION("BasicTest") { + //StaticLocalDataSet<3> localSet = StaticLocalDataSet<3>() + } +} + + + diff --git a/unittest/tests/datapoollocal/LocalPoolOwnerBase.h b/unittest/tests/datapoollocal/LocalPoolOwnerBase.h index 40f657be..c665cb7f 100644 --- a/unittest/tests/datapoollocal/LocalPoolOwnerBase.h +++ b/unittest/tests/datapoollocal/LocalPoolOwnerBase.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -11,9 +12,12 @@ namespace lpool { static constexpr lp_id_t uint8VarId = 0; static constexpr lp_id_t floatVarId = 1; static constexpr lp_id_t uint32VarId = 2; +static constexpr lp_id_t uint16Vec3Id = 3; +static constexpr lp_id_t int64Vec2Id = 4; } + class LocalPoolOwnerBase: public SystemObject, public HasLocalDataPoolIF { public: LocalPoolOwnerBase( @@ -31,12 +35,19 @@ public: } ReturnValue_t initializeHkManager() { - return hkManager.initialize(messageQueue); - + if(not initialized) { + initialized = true; + return hkManager.initialize(messageQueue); + } + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t initializeHkManagerAfterTaskCreation() { - return hkManager.initializeAfterTaskCreation(); + if(not initializedAfterTaskCreation) { + initializedAfterTaskCreation = true; + return hkManager.initializeAfterTaskCreation(); + } + return HasReturnvaluesIF::RETURN_OK; } /** Command queue for housekeeping messages. */ @@ -44,12 +55,22 @@ public: return messageQueue->getId(); } + // This is called by initializeAfterTaskCreation of the HK manager. virtual ReturnValue_t initializeLocalDataPool( LocalDataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { // Default initialization empty for now. - localDataPoolMap.emplace(lpool::uint8VarId, new PoolEntry({0})); - localDataPoolMap.emplace(lpool::floatVarId, new PoolEntry({0})); + localDataPoolMap.emplace(lpool::uint8VarId, + new PoolEntry({0})); + localDataPoolMap.emplace(lpool::floatVarId, + new PoolEntry({0})); + localDataPoolMap.emplace(lpool::uint32VarId, + new PoolEntry({0})); + + localDataPoolMap.emplace(lpool::uint16Vec3Id, + new PoolEntry({0, 0, 0})); + localDataPoolMap.emplace(lpool::int64Vec2Id, + new PoolEntry({0, 0})); return HasReturnvaluesIF::RETURN_OK; } @@ -77,9 +98,17 @@ private: lp_var_t testFloat = lp_var_t(this, lpool::floatVarId); lp_var_t testUint32 = lp_var_t(this, lpool::uint32VarId); + lp_vec_t testUint16Vec = lp_vec_t(this, + lpool::uint16Vec3Id); + lp_vec_t testInt64Vec = lp_vec_t(this, + lpool::int64Vec2Id); + MessageQueueIF* messageQueue = nullptr; LocalDataPoolManager hkManager; + bool initialized = false; + bool initializedAfterTaskCreation = false; + }; #endif /* FSFW_UNITTEST_TESTS_DATAPOOLLOCAL_LOCALPOOLOWNERBASE_H_ */ diff --git a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp index cf4f4b6b..eb5abf35 100644 --- a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp +++ b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp @@ -6,9 +6,11 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { - LocalPoolOwnerBase poolOwner(objects::TEST_LOCAL_POOL_OWNER_BASE); - REQUIRE(poolOwner.initializeHkManager() == retval::CATCH_OK); - REQUIRE(poolOwner.initializeHkManagerAfterTaskCreation() + LocalPoolOwnerBase* poolOwner = objectManager-> + get(objects::TEST_LOCAL_POOL_OWNER_BASE); + REQUIRE(poolOwner != nullptr); + REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); + REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() == retval::CATCH_OK); SECTION("Basic Tests") { @@ -26,6 +28,18 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { testVariable.setValid(true); CHECK(testVariable.isValid()); + testVariable.setReadWriteMode(pool_rwm_t::VAR_READ); + CHECK(testVariable.getReadWriteMode() == pool_rwm_t::VAR_READ); + testVariable.setReadWriteMode(pool_rwm_t::VAR_READ_WRITE); + + testVariable.setDataPoolId(22); + CHECK(testVariable.getDataPoolId() == 22); + testVariable.setDataPoolId(lpool::uint8VarId); + + testVariable.setChanged(true); + CHECK(testVariable.hasChanged()); + testVariable.setChanged(false); + gp_id_t globPoolId(objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint8VarId); lp_var_t testVariable2 = lp_var_t(globPoolId); @@ -93,6 +107,15 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "LocalPoolVariable printout: " < OK + lp_var_t invalidObjectVar = lp_var_t( + 0xffffffff, lpool::uint8VarId); + gp_id_t globPoolId(0xffffffff, + lpool::uint8VarId); + lp_var_t invalidObjectVar2 = lp_var_t(globPoolId); + lp_var_t invalidObjectVar3 = lp_var_t(nullptr, + lpool::uint8VarId); } } diff --git a/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp b/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp new file mode 100644 index 00000000..c86a2681 --- /dev/null +++ b/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp @@ -0,0 +1,16 @@ +#include "LocalPoolOwnerBase.h" + +#include +#include +#include + +TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") { + LocalPoolOwnerBase* poolOwner = objectManager-> + get(objects::TEST_LOCAL_POOL_OWNER_BASE); + REQUIRE(poolOwner != nullptr); + REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); + REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() + == retval::CATCH_OK); +} + + From 2b287dfc3ac227af78f68a003948b92656cd4005 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 6 Jan 2021 21:33:54 +0100 Subject: [PATCH 17/38] freertos and pool read helper fix --- datapoollocal/PoolReadHelper.h | 9 ++++++--- osal/FreeRTOS/Clock.cpp | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/datapoollocal/PoolReadHelper.h b/datapoollocal/PoolReadHelper.h index a059685b..c89fff98 100644 --- a/datapoollocal/PoolReadHelper.h +++ b/datapoollocal/PoolReadHelper.h @@ -9,10 +9,12 @@ */ class PoolReadHelper { public: - PoolReadHelper(ReadCommitIF* readObject, uint32_t mutexTimeout = 20): + PoolReadHelper(ReadCommitIF* readObject, + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, + uint32_t mutexTimeout = 20): readObject(readObject), mutexTimeout(mutexTimeout) { if(readObject != nullptr) { - readResult = readObject->read(mutexTimeout); + readResult = readObject->read(timeoutType, mutexTimeout); #if FSFW_PRINT_VERBOSITY_LEVEL == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "PoolReadHelper: Read failed!" << std::endl; @@ -27,7 +29,7 @@ public: ~PoolReadHelper() { if(readObject != nullptr) { - readObject->commit(mutexTimeout); + readObject->commit(timeoutType, mutexTimeout); } } @@ -35,6 +37,7 @@ public: private: ReadCommitIF* readObject = nullptr; ReturnValue_t readResult = HasReturnvaluesIF::RETURN_OK; + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; uint32_t mutexTimeout = 20; }; diff --git a/osal/FreeRTOS/Clock.cpp b/osal/FreeRTOS/Clock.cpp index d3f4e68e..9c0a0267 100644 --- a/osal/FreeRTOS/Clock.cpp +++ b/osal/FreeRTOS/Clock.cpp @@ -163,7 +163,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { if (checkOrCreateClockMutex() != HasReturnvaluesIF::RETURN_OK) { return HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); + ReturnValue_t result = timeMutex->lockMutex(MutexIF::TimeoutType::BLOCKING); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -178,7 +178,7 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { if (timeMutex == NULL) { return HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); + ReturnValue_t result = timeMutex->lockMutex(MutexIF::TimeoutType::BLOCKING); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } From fcb33201a4c40ae868d82fcff1060fc6fdf2c342 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 6 Jan 2021 21:45:35 +0100 Subject: [PATCH 18/38] fixed linux osal --- osal/linux/Clock.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osal/linux/Clock.cpp b/osal/linux/Clock.cpp index 54dad839..35cbfae0 100644 --- a/osal/linux/Clock.cpp +++ b/osal/linux/Clock.cpp @@ -182,7 +182,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){ return HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); + ReturnValue_t result = timeMutex->lockMutex(MutexIF::TimeoutType::BLOCKING); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -197,7 +197,7 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { if(timeMutex==NULL){ return HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::BLOCKING); + ReturnValue_t result = timeMutex->lockMutex(MutexIF::TimeoutType::BLOCKING); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -209,13 +209,13 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { } ReturnValue_t Clock::checkOrCreateClockMutex(){ - if(timeMutex==NULL){ + if(timeMutex == nullptr){ MutexFactory* mutexFactory = MutexFactory::instance(); - if (mutexFactory == NULL) { + if (mutexFactory == nullptr) { return HasReturnvaluesIF::RETURN_FAILED; } timeMutex = mutexFactory->createMutex(); - if (timeMutex == NULL) { + if (timeMutex == nullptr) { return HasReturnvaluesIF::RETURN_FAILED; } } From 8aaf45049faa4677208d3486ce4e6c2946416ee2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 6 Jan 2021 21:49:40 +0100 Subject: [PATCH 19/38] major bugfix in rtems osal --- osal/rtems/Mutex.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osal/rtems/Mutex.cpp b/osal/rtems/Mutex.cpp index 71c5782f..7dd512fa 100644 --- a/osal/rtems/Mutex.cpp +++ b/osal/rtems/Mutex.cpp @@ -30,11 +30,11 @@ Mutex::~Mutex() { ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType = TimeoutType::BLOCKING, uint32_t timeoutMs) { rtems_status_code status = RTEMS_INVALID_ID; - if(timeoutMs == MutexIF::TimeoutType::BLOCKING) { + if(timeoutType == MutexIF::TimeoutType::BLOCKING) { status = rtems_semaphore_obtain(mutexId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); } - else if(timeoutMs == MutexIF::TimeoutType::POLLING) { + else if(timeoutType == MutexIF::TimeoutType::POLLING) { timeoutMs = RTEMS_NO_TIMEOUT; status = rtems_semaphore_obtain(mutexId, RTEMS_NO_WAIT, 0); From 007526c0502d7db92d37dcdc080bf4c08c5f9030 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 7 Jan 2021 19:10:07 +0100 Subject: [PATCH 20/38] new f unctions for read error reporting, bugfix --- datapool/PoolVariableIF.h | 1 + datapoollocal/LocalDataPoolManager.h | 11 +++++- datapoollocal/LocalPoolVariable.h | 1 + datapoollocal/LocalPoolVariable.tpp | 58 ++++++++++++++++++---------- 4 files changed, 48 insertions(+), 23 deletions(-) diff --git a/datapool/PoolVariableIF.h b/datapool/PoolVariableIF.h index 9740fc12..444e19d0 100644 --- a/datapool/PoolVariableIF.h +++ b/datapool/PoolVariableIF.h @@ -25,6 +25,7 @@ class PoolVariableIF : public SerializeIF, public: static constexpr uint8_t INTERFACE_ID = CLASS_ID::POOL_VARIABLE_IF; static constexpr ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0); + static constexpr ReturnValue_t INVALID_POOL_ENTRY = MAKE_RETURN_CODE(0xA1); static constexpr bool VALID = 1; static constexpr bool INVALID = 0; diff --git a/datapoollocal/LocalDataPoolManager.h b/datapoollocal/LocalDataPoolManager.h index 0e98b90c..bcb8f0af 100644 --- a/datapoollocal/LocalDataPoolManager.h +++ b/datapoollocal/LocalDataPoolManager.h @@ -3,6 +3,7 @@ #include "HasLocalDataPoolIF.h" +#include "../serviceinterface/ServiceInterface.h" #include "../housekeeping/HousekeepingPacketDownlink.h" #include "../housekeeping/HousekeepingMessage.h" #include "../housekeeping/PeriodicHousekeepingHelper.h" @@ -378,6 +379,9 @@ ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId, #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "HousekeepingManager::fechPoolEntry: Pool entry " "not found." << std::endl; +#else + fsfw::printWarning("HousekeepingManager::fechPoolEntry: Pool entry " + "not found."); #endif return HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND; } @@ -385,8 +389,11 @@ ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId, *poolEntry = dynamic_cast< PoolEntry* >(poolIter->second); if(*poolEntry == nullptr) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "HousekeepingManager::fetchPoolEntry:" - " Pool entry not found." << std::endl; + sif::warning << "HousekeepingManager::fetchPoolEntry:" + " Pool entry type conflict." << std::endl; +#else + fsfw::printWarning("HousekeepingManager::fetchPoolEntry:" + " Pool entry type conflict."); #endif return HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT; } diff --git a/datapoollocal/LocalPoolVariable.h b/datapoollocal/LocalPoolVariable.h index c81967a1..ca0aede9 100644 --- a/datapoollocal/LocalPoolVariable.h +++ b/datapoollocal/LocalPoolVariable.h @@ -181,6 +181,7 @@ protected: #endif private: + void reportReadCommitError(bool read, object_id_t objectId, lp_id_t lpId); }; #include "LocalPoolVariable.tpp" diff --git a/datapoollocal/LocalPoolVariable.tpp b/datapoollocal/LocalPoolVariable.tpp index 9387acc5..c20e9230 100644 --- a/datapoollocal/LocalPoolVariable.tpp +++ b/datapoollocal/LocalPoolVariable.tpp @@ -46,18 +46,17 @@ inline ReturnValue_t LocalPoolVariable::readWithoutLock() { PoolEntry* poolEntry = nullptr; ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); if(result != RETURN_OK or poolEntry == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PoolPoolVariable: Read of local pool variable of object " - << std::hex << std::setw(8) << std::setfill('0') - << hkManager->getOwner() << " and lp ID 0x" << localPoolId - << std::dec << " failed." << std::setfill(' ') << std::endl; -#else - fsfw::printError("LocalPoolVariable: Read of local pool variable of " - "object 0x%08x and lp ID 0x%08x failed.\n\r", - hkManager->getOwner(), localPoolId); -#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ + object_id_t ownerObjectId = hkManager->getOwner()->getObjectId(); + reportReadCommitError(true, ownerObjectId, localPoolId); return result; } + + if(poolEntry->address == nullptr) { + object_id_t ownerObjectId = hkManager->getOwner()->getObjectId(); + reportReadCommitError(true, ownerObjectId, localPoolId); + return PoolVariableIF::INVALID_POOL_ENTRY; + } + this->value = *(poolEntry->address); this->valid = poolEntry->valid; return RETURN_OK; @@ -91,19 +90,12 @@ inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { } PoolEntry* poolEntry = nullptr; ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); - if(result != RETURN_OK) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "PoolPoolVariable: Read of local pool variable of " - << "object " << std::hex << std::setw(8) << std::setfill('0') - << hkManager->getOwner() << " and lp ID 0x" << localPoolId - << std::dec << " failed." << std::endl; -#else - fsfw::printError("LocalPoolVariable: Read of local pool variable of " - "object 0x%08x and lp ID 0x%08x failed.\n\r", - hkManager->getOwner(), localPoolId); -#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ + if(result != RETURN_OK or poolEntry == nullptr) { + object_id_t ownerObjectId = hkManager->getOwner()->getObjectId(); + reportReadCommitError(false, ownerObjectId, localPoolId); return result; } + *(poolEntry->address) = this->value; poolEntry->valid = this->valid; return RETURN_OK; @@ -203,4 +195,28 @@ inline bool LocalPoolVariable::operator >(const T &other) const { return not (*this < other); } +template +inline void LocalPoolVariable::reportReadCommitError(bool read, + object_id_t objectId, lp_id_t lpId) { + const char* type = nullptr; + if(read) { + type = "read"; + } + else { + type = "commit"; + } + +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "PoolPoolVariable: " << type << " of local pool " + <<"variable of object " << std::hex << std::setw(8) + << std::setfill('0') << objectId << " and lp ID 0x" << lpId + << std::dec << " failed." << std::endl; +#else + fsfw::printWarning("LocalPoolVariable: %s of local pool variable of " + "object 0x%08x and lp ID 0x%08x failed.\n\r", + type, objectId, lpId); +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ +} + + #endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ */ From 3be51762cccb8964ab3d19e379f1d427a99710b7 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 7 Jan 2021 20:23:23 +0100 Subject: [PATCH 21/38] improved error handling significantly --- datapoollocal/LocalPoolObjectBase.cpp | 41 +++++++++++++++++++++++++++ datapoollocal/LocalPoolObjectBase.h | 2 ++ datapoollocal/LocalPoolVariable.h | 3 -- datapoollocal/LocalPoolVariable.tpp | 41 +++++++-------------------- datapoollocal/LocalPoolVector.tpp | 23 +++++++-------- 5 files changed, 64 insertions(+), 46 deletions(-) diff --git a/datapoollocal/LocalPoolObjectBase.cpp b/datapoollocal/LocalPoolObjectBase.cpp index 4b57dede..b84569b8 100644 --- a/datapoollocal/LocalPoolObjectBase.cpp +++ b/datapoollocal/LocalPoolObjectBase.cpp @@ -79,3 +79,44 @@ bool LocalPoolObjectBase::hasChanged() const { void LocalPoolObjectBase::setReadWriteMode(pool_rwm_t newReadWriteMode) { this->readWriteMode = newReadWriteMode; } + +void LocalPoolObjectBase::reportReadCommitError(const char* variableType, + ReturnValue_t error, bool read, object_id_t objectId, lp_id_t lpId) { +#if FSFW_DISABLE_PRINTOUT == 0 + const char* type = nullptr; + if(read) { + type = "read"; + } + else { + type = "commit"; + } + + const char* errMsg = nullptr; + if(error == HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND) { + errMsg = "Pool entry not found"; + } + else if(error == HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT) { + errMsg = "Pool entry type conflict"; + } + else if(error == PoolVariableIF::INVALID_READ_WRITE_MODE) { + errMsg = "Pool variable wrong read-write mode"; + } + else if(error == PoolVariableIF::INVALID_POOL_ENTRY) { + errMsg = "Pool entry invalid"; + } + else { + errMsg = "Unknown error code"; + } + +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << variableType << ": " << type << " call | " << errMsg + << " | Owner: " << std::hex << std::setw(8) + << std::setfill('0') << objectId << " LPID: 0x" << lpId + << std::dec << std::endl; +#else + fsfw::printWarning("LocalPoolVariable: %s of local pool variable of " + "object 0x%08x and lp ID 0x%08x failed.\n\r", + type, objectId, lpId); +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ +#endif /* FSFW_DISABLE_PRINTOUT == 0 */ +} diff --git a/datapoollocal/LocalPoolObjectBase.h b/datapoollocal/LocalPoolObjectBase.h index 7165fc24..25ca594d 100644 --- a/datapoollocal/LocalPoolObjectBase.h +++ b/datapoollocal/LocalPoolObjectBase.h @@ -56,6 +56,8 @@ protected: //! @brief Pointer to the class which manages the HK pool. LocalDataPoolManager* hkManager; + void reportReadCommitError(const char* variableType, + ReturnValue_t error, bool read, object_id_t objectId, lp_id_t lpId); }; diff --git a/datapoollocal/LocalPoolVariable.h b/datapoollocal/LocalPoolVariable.h index ca0aede9..22019c2f 100644 --- a/datapoollocal/LocalPoolVariable.h +++ b/datapoollocal/LocalPoolVariable.h @@ -179,9 +179,6 @@ protected: friend std::ostream& operator<< (std::ostream &out, const LocalPoolVariable &var); #endif - -private: - void reportReadCommitError(bool read, object_id_t objectId, lp_id_t lpId); }; #include "LocalPoolVariable.tpp" diff --git a/datapoollocal/LocalPoolVariable.tpp b/datapoollocal/LocalPoolVariable.tpp index c20e9230..4d472c31 100644 --- a/datapoollocal/LocalPoolVariable.tpp +++ b/datapoollocal/LocalPoolVariable.tpp @@ -45,16 +45,20 @@ inline ReturnValue_t LocalPoolVariable::readWithoutLock() { PoolEntry* poolEntry = nullptr; ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); - if(result != RETURN_OK or poolEntry == nullptr) { + if(result != RETURN_OK) { object_id_t ownerObjectId = hkManager->getOwner()->getObjectId(); - reportReadCommitError(true, ownerObjectId, localPoolId); + reportReadCommitError("LocalPoolVariable", result, + false, ownerObjectId, localPoolId); return result; } + // Actually this should never happen.. if(poolEntry->address == nullptr) { + result = PoolVariableIF::INVALID_POOL_ENTRY; object_id_t ownerObjectId = hkManager->getOwner()->getObjectId(); - reportReadCommitError(true, ownerObjectId, localPoolId); - return PoolVariableIF::INVALID_POOL_ENTRY; + reportReadCommitError("LocalPoolVariable", result, + false, ownerObjectId, localPoolId); + return result; } this->value = *(poolEntry->address); @@ -90,9 +94,10 @@ inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { } PoolEntry* poolEntry = nullptr; ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); - if(result != RETURN_OK or poolEntry == nullptr) { + if(result != RETURN_OK) { object_id_t ownerObjectId = hkManager->getOwner()->getObjectId(); - reportReadCommitError(false, ownerObjectId, localPoolId); + reportReadCommitError("LocalPoolVariable", result, + false, ownerObjectId, localPoolId); return result; } @@ -195,28 +200,4 @@ inline bool LocalPoolVariable::operator >(const T &other) const { return not (*this < other); } -template -inline void LocalPoolVariable::reportReadCommitError(bool read, - object_id_t objectId, lp_id_t lpId) { - const char* type = nullptr; - if(read) { - type = "read"; - } - else { - type = "commit"; - } - -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "PoolPoolVariable: " << type << " of local pool " - <<"variable of object " << std::hex << std::setw(8) - << std::setfill('0') << objectId << " and lp ID 0x" << lpId - << std::dec << " failed." << std::endl; -#else - fsfw::printWarning("LocalPoolVariable: %s of local pool variable of " - "object 0x%08x and lp ID 0x%08x failed.\n\r", - type, objectId, lpId); -#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ -} - - #endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ */ diff --git a/datapoollocal/LocalPoolVector.tpp b/datapoollocal/LocalPoolVector.tpp index 6af80de6..99e37a87 100644 --- a/datapoollocal/LocalPoolVector.tpp +++ b/datapoollocal/LocalPoolVector.tpp @@ -44,12 +44,9 @@ inline ReturnValue_t LocalPoolVector::readWithoutLock() { memset(this->value, 0, vectorSize * sizeof(T)); if(result != RETURN_OK) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "LocalPoolVector: Read of local pool variable of object " - << std::hex << std::setw(8) << std::setfill('0') - << hkManager->getOwner() << "and lp ID 0x" << localPoolId - << std::dec << " failed." << std::endl; -#endif + object_id_t targetObjectId = hkManager->getOwner()->getObjectId(); + reportReadCommitError("LocalPoolVector", result, true, targetObjectId, + localPoolId); return result; } std::memcpy(this->value, poolEntry->address, poolEntry->getByteSize()); @@ -69,19 +66,19 @@ inline ReturnValue_t LocalPoolVector::commitWithoutLock() { if(readWriteMode == pool_rwm_t::VAR_READ) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "LocalPoolVector: Invalid read write " - "mode for commit() call." << std::endl; + "mode for commit call." << std::endl; +#else + sif::warning << "LocalPoolVector: Invalid read write " + "mode for commit call." << std::endl; #endif return PoolVariableIF::INVALID_READ_WRITE_MODE; } PoolEntry* poolEntry = nullptr; ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); if(result != RETURN_OK) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "LocalPoolVector: Read of local pool variable of object " - << std::hex << std::setw(8) << std::setfill('0') - << hkManager->getOwner() << " and lp ID " << localPoolId - << std::dec << " failed." << std::endl; -#endif + object_id_t targetObjectId = hkManager->getOwner()->getObjectId(); + reportReadCommitError("LocalPoolVector", result, true, targetObjectId, + localPoolId); return result; } std::memcpy(poolEntry->address, this->value, poolEntry->getByteSize()); From 44a5430555766db0d6bae8a1dca7221c122c80a9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 7 Jan 2021 20:28:03 +0100 Subject: [PATCH 22/38] pool vector improvements --- datapoollocal/LocalPoolVector.tpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/datapoollocal/LocalPoolVector.tpp b/datapoollocal/LocalPoolVector.tpp index 99e37a87..88ba084a 100644 --- a/datapoollocal/LocalPoolVector.tpp +++ b/datapoollocal/LocalPoolVector.tpp @@ -32,10 +32,10 @@ inline ReturnValue_t LocalPoolVector::read( template inline ReturnValue_t LocalPoolVector::readWithoutLock() { if(readWriteMode == pool_rwm_t::VAR_WRITE) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "LocalPoolVector: Invalid read write " - "mode for read() call." << std::endl; -#endif + object_id_t targetObjectId = hkManager->getOwner()->getObjectId(); + reportReadCommitError("LocalPoolVector", + PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId, + localPoolId); return PoolVariableIF::INVALID_READ_WRITE_MODE; } @@ -64,20 +64,17 @@ inline ReturnValue_t LocalPoolVector::commit( template inline ReturnValue_t LocalPoolVector::commitWithoutLock() { if(readWriteMode == pool_rwm_t::VAR_READ) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "LocalPoolVector: Invalid read write " - "mode for commit call." << std::endl; -#else - sif::warning << "LocalPoolVector: Invalid read write " - "mode for commit call." << std::endl; -#endif + object_id_t targetObjectId = hkManager->getOwner()->getObjectId(); + reportReadCommitError("LocalPoolVector", + PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId, + localPoolId); return PoolVariableIF::INVALID_READ_WRITE_MODE; } PoolEntry* poolEntry = nullptr; ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); if(result != RETURN_OK) { object_id_t targetObjectId = hkManager->getOwner()->getObjectId(); - reportReadCommitError("LocalPoolVector", result, true, targetObjectId, + reportReadCommitError("LocalPoolVector", result, false, targetObjectId, localPoolId); return result; } From d3fbe4a3b96184b1f1620041fd7f433cf902b56e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 7 Jan 2021 20:29:38 +0100 Subject: [PATCH 23/38] local pool variable error handling improved --- datapoollocal/LocalPoolVariable.tpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/datapoollocal/LocalPoolVariable.tpp b/datapoollocal/LocalPoolVariable.tpp index 4d472c31..3cf0fc84 100644 --- a/datapoollocal/LocalPoolVariable.tpp +++ b/datapoollocal/LocalPoolVariable.tpp @@ -33,13 +33,10 @@ inline ReturnValue_t LocalPoolVariable::read( template inline ReturnValue_t LocalPoolVariable::readWithoutLock() { if(readWriteMode == pool_rwm_t::VAR_WRITE) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "LocalPoolVariable: Invalid read write " - "mode for read call." << std::endl; -#else - fsfw::printWarning("LocalPoolVariable: Invalid read write " - "mode for read call.\n\r"); -#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ + object_id_t targetObjectId = hkManager->getOwner()->getObjectId(); + reportReadCommitError("LocalPoolVector", + PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId, + localPoolId); return PoolVariableIF::INVALID_READ_WRITE_MODE; } @@ -83,13 +80,10 @@ inline ReturnValue_t LocalPoolVariable::commit( template inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { if(readWriteMode == pool_rwm_t::VAR_READ) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "LocalPoolVariable: Invalid read write " - "mode for commit call." << std::endl; -#else - fsfw::printWarning("LocalPoolVariable: Invalid read write " - "mode for commit call.\n\r"); -#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ + object_id_t targetObjectId = hkManager->getOwner()->getObjectId(); + reportReadCommitError("LocalPoolVector", + PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId, + localPoolId); return PoolVariableIF::INVALID_READ_WRITE_MODE; } PoolEntry* poolEntry = nullptr; From d3405ee34063eca17a529dcf521ff860d91e5b50 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 7 Jan 2021 20:30:52 +0100 Subject: [PATCH 24/38] whitespace --- datapoollocal/LocalPoolVariable.tpp | 1 + 1 file changed, 1 insertion(+) diff --git a/datapoollocal/LocalPoolVariable.tpp b/datapoollocal/LocalPoolVariable.tpp index 3cf0fc84..d9d45d38 100644 --- a/datapoollocal/LocalPoolVariable.tpp +++ b/datapoollocal/LocalPoolVariable.tpp @@ -86,6 +86,7 @@ inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { localPoolId); return PoolVariableIF::INVALID_READ_WRITE_MODE; } + PoolEntry* poolEntry = nullptr; ReturnValue_t result = hkManager->fetchPoolEntry(localPoolId, &poolEntry); if(result != RETURN_OK) { From c1c331e29ef4501d923830cc38a3179d7d7b6332 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Jan 2021 00:10:10 +0100 Subject: [PATCH 25/38] fixed vector test --- datapool/PoolEntry.cpp | 14 +++--------- datapool/PoolEntry.h | 8 +++---- datapoollocal/LocalPoolVector.h | 8 +++++++ datapoollocal/LocalPoolVector.tpp | 7 ++++++ osal/host/Mutex.h | 1 - unittest/tests/datapoollocal/CMakeLists.txt | 1 + .../datapoollocal/LocalPoolVectorTest.cpp | 22 +++++++++++++++++++ 7 files changed, 45 insertions(+), 16 deletions(-) diff --git a/datapool/PoolEntry.cpp b/datapool/PoolEntry.cpp index 5f5f56f2..d21cf2ec 100644 --- a/datapool/PoolEntry.cpp +++ b/datapool/PoolEntry.cpp @@ -6,27 +6,19 @@ #include template -PoolEntry::PoolEntry(std::initializer_list initValue, uint8_t setLength, - bool setValid ) : length(setLength), valid(setValid) { +PoolEntry::PoolEntry(std::initializer_list initValue, bool setValid ): + length(initValue.size()), valid(setValid) { this->address = new T[this->length]; if(initValue.size() == 0) { std::memset(this->address, 0, this->getByteSize()); } - else if (initValue.size() != setLength){ -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "PoolEntry: setLength is not equal to initializer list" - "length! Performing zero initialization with given setLength" - << std::endl; -#endif - std::memset(this->address, 0, this->getByteSize()); - } else { std::copy(initValue.begin(), initValue.end(), this->address); } } template -PoolEntry::PoolEntry( T* initValue, uint8_t setLength, bool setValid ) : +PoolEntry::PoolEntry(T* initValue, uint8_t setLength, bool setValid): length(setLength), valid(setValid) { this->address = new T[this->length]; if (initValue != nullptr) { diff --git a/datapool/PoolEntry.h b/datapool/PoolEntry.h index 033db40d..83f7fc50 100644 --- a/datapool/PoolEntry.h +++ b/datapool/PoolEntry.h @@ -43,16 +43,16 @@ public: * corresponding length should be passed too, otherwise a zero * initialization will be performed with the given setLength. * @param initValue - * Initializer list with values to initialize with, for example {0,0} to - * initialize the two entries to zero. + * Initializer list with values to initialize with, for example {0, 0} to + * initialize the a pool entry of a vector with two entries to 0. * @param setLength * Defines the array length of this entry. Should be equal to the * intializer list length. * @param setValid * Sets the initialization flag. It is invalid by default. */ - PoolEntry(std::initializer_list initValue = {}, uint8_t setLength = 1, - bool setValid = false); + PoolEntry(std::initializer_list initValue = {0}, bool setValid = false); + /** * @brief In the classe's constructor, space is allocated on the heap and * potential init values are copied to that space. diff --git a/datapoollocal/LocalPoolVector.h b/datapoollocal/LocalPoolVector.h index 773a52cc..ce3b1a14 100644 --- a/datapoollocal/LocalPoolVector.h +++ b/datapoollocal/LocalPoolVector.h @@ -139,6 +139,14 @@ public: MutexIF::TimeoutType::WAITING, uint32_t timeoutMs = 20) override; + /** + * @brief This commit call also sets the validity of the pool entry. + * @details + */ + ReturnValue_t commit(bool valid, MutexIF::TimeoutType timeoutType = + MutexIF::TimeoutType::WAITING, + uint32_t timeoutMs = 20); + protected: /** * @brief Like #read, but without a lock protection of the global pool. diff --git a/datapoollocal/LocalPoolVector.tpp b/datapoollocal/LocalPoolVector.tpp index 88ba084a..ce68982b 100644 --- a/datapoollocal/LocalPoolVector.tpp +++ b/datapoollocal/LocalPoolVector.tpp @@ -54,6 +54,13 @@ inline ReturnValue_t LocalPoolVector::readWithoutLock() { return RETURN_OK; } +template +inline ReturnValue_t LocalPoolVector::commit(bool valid, + MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { + this->setValid(valid); + return commit(timeoutType, timeoutMs); +} + template inline ReturnValue_t LocalPoolVector::commit( MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { diff --git a/osal/host/Mutex.h b/osal/host/Mutex.h index c0fa19b7..0bd93c8a 100644 --- a/osal/host/Mutex.h +++ b/osal/host/Mutex.h @@ -22,7 +22,6 @@ public: std::timed_mutex* getMutexHandle(); private: - //bool locked = false; std::timed_mutex mutex; }; diff --git a/unittest/tests/datapoollocal/CMakeLists.txt b/unittest/tests/datapoollocal/CMakeLists.txt index 569a8d5f..9d828de5 100644 --- a/unittest/tests/datapoollocal/CMakeLists.txt +++ b/unittest/tests/datapoollocal/CMakeLists.txt @@ -1,3 +1,4 @@ target_sources(${TARGET_NAME} PRIVATE LocalPoolVariableTest.cpp + LocalPoolVectorTest.cpp ) diff --git a/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp b/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp index c86a2681..188011df 100644 --- a/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp +++ b/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp @@ -11,6 +11,28 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") { REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() == retval::CATCH_OK); + + SECTION("BasicTest") { + // very basic test. + lp_vec_t testVector = lp_vec_t( + objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id); + CHECK(testVector.read() == retval::CATCH_OK); + testVector.value[0] = 5; + testVector.value[1] = 232; + testVector.value[2] = 32023; + + REQUIRE(testVector.commit(true) == retval::CATCH_OK); + CHECK(testVector.isValid()); + + testVector.value[0] = 0; + testVector.value[1] = 0; + testVector.value[2] = 0; + + CHECK(testVector.read() == retval::CATCH_OK); + CHECK(testVector.value[0] == 5); + CHECK(testVector.value[1] == 232); + CHECK(testVector.value[2] == 32023); + } } From 8e3f4c81a5d0db9709052012e71824ca019938b9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Jan 2021 00:20:39 +0100 Subject: [PATCH 26/38] pool entry doc correction --- datapool/PoolEntry.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/datapool/PoolEntry.h b/datapool/PoolEntry.h index 83f7fc50..d3d4cd6d 100644 --- a/datapool/PoolEntry.h +++ b/datapool/PoolEntry.h @@ -35,19 +35,17 @@ public: "uint8_t"); /** * @brief In the classe's constructor, space is allocated on the heap and - * potential init values are copied to that space. + * potential initialization values are copied to that space. * @details * Not passing any arguments will initialize an non-array pool entry - * (setLength = 1) with an initial invalid state. - * Please note that if an initializer list is passed, the correct - * corresponding length should be passed too, otherwise a zero - * initialization will be performed with the given setLength. + * with an initial invalid state and the value 0. + * Please note that if an initializer list is passed, the length of the + * initializer list needs to be correct for vector entries because + * required allocated space will be deduced from the initializer list length + * and the pool entry type. * @param initValue * Initializer list with values to initialize with, for example {0, 0} to * initialize the a pool entry of a vector with two entries to 0. - * @param setLength - * Defines the array length of this entry. Should be equal to the - * intializer list length. * @param setValid * Sets the initialization flag. It is invalid by default. */ From 41d8cbda5597c61aac6c965cc14f4fe571fe3263 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Jan 2021 00:22:04 +0100 Subject: [PATCH 27/38] small form changes --- datapool/PoolEntry.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datapool/PoolEntry.h b/datapool/PoolEntry.h index d3d4cd6d..aecfce94 100644 --- a/datapool/PoolEntry.h +++ b/datapool/PoolEntry.h @@ -64,9 +64,9 @@ public: */ PoolEntry(T* initValue, uint8_t setLength = 1, bool setValid = false); - //! Explicitely deleted copy ctor, copying is not allowed! + //! Explicitely deleted copy ctor, copying is not allowed. PoolEntry(const PoolEntry&) = delete; - //! Explicitely deleted copy assignment, copying is not allowed! + //! Explicitely deleted copy assignment, copying is not allowed. PoolEntry& operator=(const PoolEntry&) = delete; /** From 4255176b5c499d3be11947f8b77d9bbcc21bb12c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Jan 2021 01:49:00 +0100 Subject: [PATCH 28/38] more tests, minor bugfix --- datapoollocal/LocalPoolVector.h | 5 +-- datapoollocal/LocalPoolVector.tpp | 18 ++++++---- .../datapoollocal/LocalPoolVectorTest.cpp | 34 ++++++++++++++++++- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/datapoollocal/LocalPoolVector.h b/datapoollocal/LocalPoolVector.h index ce3b1a14..a28fe327 100644 --- a/datapoollocal/LocalPoolVector.h +++ b/datapoollocal/LocalPoolVector.h @@ -100,8 +100,8 @@ public: return vectorSize; } - T& operator [](int i); - const T &operator [](int i) const; + T& operator [](size_t i); + const T &operator [](size_t i) const; virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize, @@ -126,6 +126,7 @@ public: ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, uint32_t timeoutMs = 20) override; + /** * @brief The commit call copies the array values back to the data pool. * @details diff --git a/datapoollocal/LocalPoolVector.tpp b/datapoollocal/LocalPoolVector.tpp index ce68982b..6612a491 100644 --- a/datapoollocal/LocalPoolVector.tpp +++ b/datapoollocal/LocalPoolVector.tpp @@ -91,8 +91,8 @@ inline ReturnValue_t LocalPoolVector::commitWithoutLock() { } template -inline T& LocalPoolVector::operator [](int i) { - if(i <= vectorSize) { +inline T& LocalPoolVector::operator [](size_t i) { + if(i < vectorSize) { return value[i]; } // If this happens, I have to set some value. I consider this @@ -100,13 +100,16 @@ inline T& LocalPoolVector::operator [](int i) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "LocalPoolVector: Invalid index. Setting or returning" " last value!" << std::endl; +#else + fsfw::printError("LocalPoolVector: Invalid index. Setting or returning" + " last value!\n\r"); #endif - return value[i]; + return value[vectorSize]; } template -inline const T& LocalPoolVector::operator [](int i) const { - if(i <= vectorSize) { +inline const T& LocalPoolVector::operator [](size_t i) const { + if(i < vectorSize) { return value[i]; } // If this happens, I have to set some value. I consider this @@ -114,8 +117,11 @@ inline const T& LocalPoolVector::operator [](int i) const { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "LocalPoolVector: Invalid index. Setting or returning" " last value!" << std::endl; +#else + fsfw::printError("LocalPoolVector: Invalid index. Setting or returning" + " last value!\n\r"); #endif - return value[i]; + return value[vectorSize]; } template diff --git a/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp b/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp index 188011df..7e40e898 100644 --- a/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp +++ b/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp @@ -16,7 +16,7 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") { // very basic test. lp_vec_t testVector = lp_vec_t( objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id); - CHECK(testVector.read() == retval::CATCH_OK); + REQUIRE(testVector.read() == retval::CATCH_OK); testVector.value[0] = 5; testVector.value[1] = 232; testVector.value[2] = 32023; @@ -32,6 +32,38 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") { CHECK(testVector.value[0] == 5); CHECK(testVector.value[1] == 232); CHECK(testVector.value[2] == 32023); + + CHECK(testVector[0] == 5); + + // This is invalid access, so the last value will be set instead. + // (we can't throw exceptions) + testVector[4] = 12; + CHECK(testVector[3] == 12); + CHECK(testVector.commit() == retval::CATCH_OK); + + // Use read-only reference. + const lp_vec_t& roTestVec = testVector; + uint16_t valueOne = roTestVec[0]; + CHECK(valueOne == 5); + + uint16_t lastVal = roTestVec[25]; + CHECK(lastVal == 12); + } + + SECTION("ErrorHandling") { + // not try to use a local pool variable which does not exist + lp_vec_t invalidVector = lp_vec_t( + objects::TEST_LOCAL_POOL_OWNER_BASE, 0xffffffff); + REQUIRE(invalidVector.read() == + static_cast(HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND)); + REQUIRE(invalidVector.commit() == + static_cast(HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND)); + + // now try to access with wrong type + lp_vec_t invalidVector2 = lp_vec_t( + objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id); + REQUIRE(invalidVector2.read() == + static_cast(HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT)); } } From 2ef3e0aa7b502b5ac1d40057a4fdc9b324af9fcb Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Jan 2021 02:06:27 +0100 Subject: [PATCH 29/38] added option to add CR for printf support --- datapoollocal/LocalDataPoolManager.h | 8 ++++---- datapoollocal/LocalPoolObjectBase.cpp | 11 +++++------ datapoollocal/LocalPoolVector.tpp | 12 ++++++------ serviceinterface/ServiceInterfacePrinter.cpp | 10 +++++++++- serviceinterface/ServiceInterfacePrinter.h | 2 ++ 5 files changed, 26 insertions(+), 17 deletions(-) diff --git a/datapoollocal/LocalDataPoolManager.h b/datapoollocal/LocalDataPoolManager.h index bcb8f0af..7fa480cb 100644 --- a/datapoollocal/LocalDataPoolManager.h +++ b/datapoollocal/LocalDataPoolManager.h @@ -377,11 +377,11 @@ ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId, auto poolIter = localPoolMap.find(localPoolId); if (poolIter == localPoolMap.end()) { #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "HousekeepingManager::fechPoolEntry: Pool entry " + sif::warning << "HousekeepingManager::fetchPoolEntry: Pool entry " "not found." << std::endl; #else - fsfw::printWarning("HousekeepingManager::fechPoolEntry: Pool entry " - "not found."); + fsfw::printWarning("HousekeepingManager::fetchPoolEntry: Pool entry " + "not found.\n"); #endif return HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND; } @@ -393,7 +393,7 @@ ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId, " Pool entry type conflict." << std::endl; #else fsfw::printWarning("HousekeepingManager::fetchPoolEntry:" - " Pool entry type conflict."); + " Pool entry type conflict.\n"); #endif return HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT; } diff --git a/datapoollocal/LocalPoolObjectBase.cpp b/datapoollocal/LocalPoolObjectBase.cpp index b84569b8..bb7822da 100644 --- a/datapoollocal/LocalPoolObjectBase.cpp +++ b/datapoollocal/LocalPoolObjectBase.cpp @@ -110,13 +110,12 @@ void LocalPoolObjectBase::reportReadCommitError(const char* variableType, #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << variableType << ": " << type << " call | " << errMsg - << " | Owner: " << std::hex << std::setw(8) - << std::setfill('0') << objectId << " LPID: 0x" << lpId - << std::dec << std::endl; + << " | Owner: 0x" << std::hex << std::setw(8) + << std::setfill('0') << objectId << std::dec << " LPID: " << lpId + << std::endl; #else - fsfw::printWarning("LocalPoolVariable: %s of local pool variable of " - "object 0x%08x and lp ID 0x%08x failed.\n\r", - type, objectId, lpId); + fsfw::printWarning("%s: %s call | %s | Owner: 0x%08x LPID: %lu\n", + variableType, type, errMsg, objectId, lpId); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_DISABLE_PRINTOUT == 0 */ } diff --git a/datapoollocal/LocalPoolVector.tpp b/datapoollocal/LocalPoolVector.tpp index 6612a491..94f3916e 100644 --- a/datapoollocal/LocalPoolVector.tpp +++ b/datapoollocal/LocalPoolVector.tpp @@ -98,11 +98,11 @@ inline T& LocalPoolVector::operator [](size_t i) { // If this happens, I have to set some value. I consider this // a configuration error, but I wont exit here. #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "LocalPoolVector: Invalid index. Setting or returning" + sif::warning << "LocalPoolVector: Invalid index. Setting or returning" " last value!" << std::endl; #else - fsfw::printError("LocalPoolVector: Invalid index. Setting or returning" - " last value!\n\r"); + fsfw::printWarning("LocalPoolVector: Invalid index. Setting or returning" + " last value!\n"); #endif return value[vectorSize]; } @@ -115,11 +115,11 @@ inline const T& LocalPoolVector::operator [](size_t i) const { // If this happens, I have to set some value. I consider this // a configuration error, but I wont exit here. #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "LocalPoolVector: Invalid index. Setting or returning" + sif::warning << "LocalPoolVector: Invalid index. Setting or returning" " last value!" << std::endl; #else - fsfw::printError("LocalPoolVector: Invalid index. Setting or returning" - " last value!\n\r"); + fsfw::printWarning("LocalPoolVector: Invalid index. Setting or returning" + " last value!\n"); #endif return value[vectorSize]; } diff --git a/serviceinterface/ServiceInterfacePrinter.cpp b/serviceinterface/ServiceInterfacePrinter.cpp index 15e738a8..cb3a958d 100644 --- a/serviceinterface/ServiceInterfacePrinter.cpp +++ b/serviceinterface/ServiceInterfacePrinter.cpp @@ -10,7 +10,7 @@ fsfw::PrintLevel printLevel = fsfw::PrintLevel::DEBUG; #if defined(WIN32) && FSFW_COLORED_OUTPUT == 1 bool consoleInitialized = false; #endif /* defined(WIN32) && FSFW_COLORED_OUTPUT == 1 */ - +bool addCrAtEnd = false; #if FSFW_DISABLE_PRINTOUT == 0 uint8_t printBuffer[fsfwconfig::FSFW_PRINT_BUFFER_SIZE]; @@ -80,6 +80,10 @@ void fsfwPrint(fsfw::PrintLevel printType, const char* fmt, va_list arg) { len += vsnprintf(bufferPosition + len, sizeof(printBuffer) - len, fmt, arg); + if(addCrAtEnd) { + len += sprintf(bufferPosition + len, "\r"); + } + printf("%s", printBuffer); } @@ -105,6 +109,10 @@ void fsfw::printDebug(const char *fmt, ...) { va_end(args); } +void fsfw::setToAddCrAtEnd(bool addCrAtEnd_) { + addCrAtEnd = addCrAtEnd_; +} + void fsfw::printError(const char *fmt, ...) { va_list args; va_start(args, fmt); diff --git a/serviceinterface/ServiceInterfacePrinter.h b/serviceinterface/ServiceInterfacePrinter.h index a60b6332..1f82ba98 100644 --- a/serviceinterface/ServiceInterfacePrinter.h +++ b/serviceinterface/ServiceInterfacePrinter.h @@ -16,6 +16,8 @@ enum class PrintLevel { void setPrintLevel(PrintLevel printLevel); PrintLevel getPrintLevel(); +void setToAddCrAtEnd(bool addCrAtEnd_); + /** * These functions can be used like the C stdio printf and forward the * supplied formatted string arguments to a printf function. From 3b39c6b6e26fd523b732b14bf00c4c5933cf0ea3 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Jan 2021 02:07:37 +0100 Subject: [PATCH 30/38] defaultcfg update --- defaultcfg/fsfwconfig/FSFWConfig.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/defaultcfg/fsfwconfig/FSFWConfig.h b/defaultcfg/fsfwconfig/FSFWConfig.h index 261e3d6d..e251729c 100644 --- a/defaultcfg/fsfwconfig/FSFWConfig.h +++ b/defaultcfg/fsfwconfig/FSFWConfig.h @@ -9,8 +9,7 @@ //! the C stdio functions can be used alternatively #define FSFW_CPP_OSTREAM_ENABLED 1 -//! More FSFW related printouts. -//! Be careful, this also turns off most diagnostic prinouts! +//! More FSFW related printouts. Useful for development. #define FSFW_ENHANCED_PRINTOUT 0 //! Can be used to completely disable printouts, even the C stdio ones. From 5a8647d36701b9eda4d6b6a29f2d83dd9b5eeeab Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Jan 2021 13:40:13 +0100 Subject: [PATCH 31/38] better returnvalues etc. --- datapool/PoolEntry.cpp | 26 +++++++++++++------ datapool/PoolEntry.h | 35 ++++++++++++++++---------- datapoollocal/LocalDataPoolManager.cpp | 6 ++--- datapoollocal/LocalDataPoolManager.h | 10 +++++--- datapoollocal/LocalPoolVariable.tpp | 22 ++++++++-------- datapoollocal/LocalPoolVector.tpp | 8 +++--- globalfunctions/arrayprinter.cpp | 10 +++++++- 7 files changed, 74 insertions(+), 43 deletions(-) diff --git a/datapool/PoolEntry.cpp b/datapool/PoolEntry.cpp index d21cf2ec..1e99a28c 100644 --- a/datapool/PoolEntry.cpp +++ b/datapool/PoolEntry.cpp @@ -1,6 +1,6 @@ #include "PoolEntry.h" -#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../serviceinterface/ServiceInterface.h" #include "../globalfunctions/arrayprinter.h" #include #include @@ -62,14 +62,26 @@ bool PoolEntry::getValid() { template void PoolEntry::print() { + const char* validString = nullptr; + if(valid) { + validString = "Valid"; + } + else { + validString = "Invalid"; + } #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "Pool Entry Validity: " << - (this->valid? " (valid) " : " (invalid) ") << std::endl; -#endif - arrayprinter::print(reinterpret_cast(address), length); -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << std::dec << std::endl; + sif::info << "PoolEntry information." << std::endl; + sif::info << "PoolEntry validity: " << validString << std::endl; +#else + fsfw::printInfo("PoolEntry information.\n"); + fsfw::printInfo("PoolEntry validity: %s\n", validString); #endif + arrayprinter::print(reinterpret_cast(address), getByteSize()); +} + +template +inline T* PoolEntry::getDataPtr() { + return this->address; } template diff --git a/datapool/PoolEntry.h b/datapool/PoolEntry.h index aecfce94..30940320 100644 --- a/datapool/PoolEntry.h +++ b/datapool/PoolEntry.h @@ -80,21 +80,16 @@ public: ~PoolEntry(); /** - * @brief This is the address pointing to the allocated memory. + * Return typed pointer to start of data. + * @return */ - T* address; - /** - * @brief This attribute stores the length information. - */ - uint8_t length; - /** - * @brief Here, the validity information for a variable is stored. - * Every entry (single variable or vector) has one valid flag. - */ - uint8_t valid; + T* getDataPtr(); + /** * @brief getSize returns the array size of the entry. - * @details A single parameter has size 1. + * @details + * For non-array pool entries return type size, for vector entries + * return type size times the number of entries. */ uint8_t getSize(); /** @@ -121,8 +116,22 @@ public: * information to the screen. It prints all array entries in a row. */ void print(); - Type getType(); + +private: + /** + * @brief This attribute stores the length information. + */ + uint8_t length; + /** + * @brief Here, the validity information for a variable is stored. + * Every entry (single variable or vector) has one valid flag. + */ + uint8_t valid; + /** + * @brief This is the address pointing to the allocated memory. + */ + T* address; }; #endif /* FSFW_DATAPOOL_POOLENTRY_H_ */ diff --git a/datapoollocal/LocalDataPoolManager.cpp b/datapoollocal/LocalDataPoolManager.cpp index 24516aad..db5cd5dd 100644 --- a/datapoollocal/LocalDataPoolManager.cpp +++ b/datapoollocal/LocalDataPoolManager.cpp @@ -213,7 +213,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot( LocalPoolObjectBase* poolObj = owner->getPoolObjectHandle( receiver.dataId.localPoolId); if(poolObj == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return POOLOBJECT_NOT_FOUND; } if (not poolObj->hasChanged()) { @@ -249,7 +249,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot( LocalPoolDataSetBase* dataSet = owner->getDataSetHandle( receiver.dataId.sid); if(dataSet == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + return DATASET_NOT_FOUND; } if(not dataSet->hasChanged()) { @@ -618,7 +618,7 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid, sif::warning << "HousekeepingManager::generateHousekeepingPacket:" << " Set ID not found or dataset not assigned!" << std::endl; #endif - return HasReturnvaluesIF::RETURN_FAILED; + return DATASET_NOT_FOUND; } store_address_t storeId; diff --git a/datapoollocal/LocalDataPoolManager.h b/datapoollocal/LocalDataPoolManager.h index 7fa480cb..098158da 100644 --- a/datapoollocal/LocalDataPoolManager.h +++ b/datapoollocal/LocalDataPoolManager.h @@ -56,11 +56,13 @@ class LocalDataPoolManager { public: static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER; - static constexpr ReturnValue_t QUEUE_OR_DESTINATION_NOT_SET = MAKE_RETURN_CODE(0x0); + static constexpr ReturnValue_t QUEUE_OR_DESTINATION_NOT_SET = MAKE_RETURN_CODE(0); - static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(0x01); - static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(0x02); - static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(0x03); + static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(1); + static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(2); + static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(3); + static constexpr ReturnValue_t POOLOBJECT_NOT_FOUND = MAKE_RETURN_CODE(4); + static constexpr ReturnValue_t DATASET_NOT_FOUND = MAKE_RETURN_CODE(5); /** * This constructor is used by a class which wants to implement diff --git a/datapoollocal/LocalPoolVariable.tpp b/datapoollocal/LocalPoolVariable.tpp index d9d45d38..ef94b620 100644 --- a/datapoollocal/LocalPoolVariable.tpp +++ b/datapoollocal/LocalPoolVariable.tpp @@ -50,16 +50,16 @@ inline ReturnValue_t LocalPoolVariable::readWithoutLock() { } // Actually this should never happen.. - if(poolEntry->address == nullptr) { - result = PoolVariableIF::INVALID_POOL_ENTRY; - object_id_t ownerObjectId = hkManager->getOwner()->getObjectId(); - reportReadCommitError("LocalPoolVariable", result, - false, ownerObjectId, localPoolId); - return result; - } +// if(poolEntry->address == nullptr) { +// result = PoolVariableIF::INVALID_POOL_ENTRY; +// object_id_t ownerObjectId = hkManager->getOwner()->getObjectId(); +// reportReadCommitError("LocalPoolVariable", result, +// false, ownerObjectId, localPoolId); +// return result; +// } - this->value = *(poolEntry->address); - this->valid = poolEntry->valid; + this->value = *(poolEntry->getDataPtr()); + this->valid = poolEntry->getValid(); return RETURN_OK; } @@ -96,8 +96,8 @@ inline ReturnValue_t LocalPoolVariable::commitWithoutLock() { return result; } - *(poolEntry->address) = this->value; - poolEntry->valid = this->valid; + *(poolEntry->getDataPtr()) = this->value; + poolEntry->setValid(this->valid); return RETURN_OK; } diff --git a/datapoollocal/LocalPoolVector.tpp b/datapoollocal/LocalPoolVector.tpp index 94f3916e..a0e32f62 100644 --- a/datapoollocal/LocalPoolVector.tpp +++ b/datapoollocal/LocalPoolVector.tpp @@ -49,8 +49,8 @@ inline ReturnValue_t LocalPoolVector::readWithoutLock() { localPoolId); return result; } - std::memcpy(this->value, poolEntry->address, poolEntry->getByteSize()); - this->valid = poolEntry->valid; + std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize()); + this->valid = poolEntry->getValid(); return RETURN_OK; } @@ -85,8 +85,8 @@ inline ReturnValue_t LocalPoolVector::commitWithoutLock() { localPoolId); return result; } - std::memcpy(poolEntry->address, this->value, poolEntry->getByteSize()); - poolEntry->valid = this->valid; + std::memcpy(poolEntry->getDataPtr(), this->value, poolEntry->getByteSize()); + poolEntry->setValid(this->valid); return RETURN_OK; } diff --git a/globalfunctions/arrayprinter.cpp b/globalfunctions/arrayprinter.cpp index c273b250..ebf21bb8 100644 --- a/globalfunctions/arrayprinter.cpp +++ b/globalfunctions/arrayprinter.cpp @@ -1,5 +1,5 @@ #include "arrayprinter.h" -#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../serviceinterface/ServiceInterface.h" #include void arrayprinter::print(const uint8_t *data, size_t size, OutputType type, @@ -9,6 +9,8 @@ void arrayprinter::print(const uint8_t *data, size_t size, OutputType type, sif::info << "Printing data with size " << size << ": "; } sif::info << "["; +#else + fsfw::printInfo("Printing data with size %zu: [", size); #endif if(type == OutputType::HEX) { arrayprinter::printHex(data, size, maxCharPerLine); @@ -37,6 +39,8 @@ void arrayprinter::printHex(const uint8_t *data, size_t size, } sif::info << std::dec; sif::info << "]" << std::endl; +#else + // how much memory to reserve for printout? #endif } @@ -54,6 +58,8 @@ void arrayprinter::printDec(const uint8_t *data, size_t size, } } sif::info << "]" << std::endl; +#else + // how much memory to reserve for printout? #endif } @@ -65,5 +71,7 @@ void arrayprinter::printBin(const uint8_t *data, size_t size) { std::bitset<8>(data[i]) << ",\n" << std::flush; } sif::info << "]" << std::endl; +#else + // how much memory to reserve for printout? #endif } From f2ecd6d740763e55e682c5892b8ad3b0df74e627 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Jan 2021 15:10:33 +0100 Subject: [PATCH 32/38] revamed and imroved error handling --- datapoollocal/LocalDataPoolManager.cpp | 187 ++++++++++++++++--------- datapoollocal/LocalDataPoolManager.h | 11 +- 2 files changed, 131 insertions(+), 67 deletions(-) diff --git a/datapoollocal/LocalDataPoolManager.cpp b/datapoollocal/LocalDataPoolManager.cpp index db5cd5dd..e5ee499c 100644 --- a/datapoollocal/LocalDataPoolManager.cpp +++ b/datapoollocal/LocalDataPoolManager.cpp @@ -3,6 +3,7 @@ #include "LocalPoolDataSetBase.h" #include "../housekeeping/HousekeepingPacketUpdate.h" +#include "../serviceinterface/ServiceInterface.h" #include "../housekeeping/HousekeepingSetPacket.h" #include "../housekeeping/AcceptsHkPacketsIF.h" @@ -21,19 +22,17 @@ LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse, bool appendValidityBuffer): appendValidityBuffer(appendValidityBuffer) { if(owner == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "LocalDataPoolManager::LocalDataPoolManager: " - << "Invalid supplied owner!" << std::endl; -#endif + printWarningOrError(ErrorTypes::WARNING_TYPE, + "LocalDataPoolManager", HasReturnvaluesIF::RETURN_FAILED, + "Invalid supplied owner"); return; } this->owner = owner; mutex = MutexFactory::instance()->createMutex(); if(mutex == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "LocalDataPoolManager::LocalDataPoolManager: " - << "Could not create mutex." << std::endl; -#endif + printWarningOrError(ErrorTypes::ERROR_TYPE, + "LocalDataPoolManager", HasReturnvaluesIF::RETURN_FAILED, + "Could not create mutex"); } hkQueue = queueToUse; @@ -43,21 +42,18 @@ LocalDataPoolManager::~LocalDataPoolManager() {} ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) { if(queueToUse == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "LocalDataPoolManager::initialize: " - << std::hex << "0x" << owner->getObjectId() << ". Supplied " - << "queue invalid!" << std::dec << std::endl; -#endif + // error, all destinations invalid + printWarningOrError(ErrorTypes::ERROR_TYPE, + "initialize", QUEUE_OR_DESTINATION_INVALID); } hkQueue = queueToUse; ipcStore = objectManager->get(objects::IPC_STORE); if(ipcStore == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "LocalDataPoolManager::initialize: " - << std::hex << "0x" << owner->getObjectId() << ": Could not " - << "set IPC store." <getHkQueue(); } else { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "LocalDataPoolManager::LocalDataPoolManager: " - << "Default HK destination object is invalid!" << std::endl; -#endif - return HasReturnvaluesIF::RETURN_FAILED; + printWarningOrError(ErrorTypes::ERROR_TYPE, + "initialize", QUEUE_OR_DESTINATION_INVALID); + return QUEUE_OR_DESTINATION_INVALID; } } @@ -95,10 +89,10 @@ ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() { } return result; } -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "HousekeepingManager: The map should only be initialized " - << "once!" << std::endl; -#endif + + printWarningOrError(ErrorTypes::WARNING_TYPE, + "initialize", HasReturnvaluesIF::RETURN_FAILED, + "The map should only be initialized once"); return HasReturnvaluesIF::RETURN_OK; } @@ -163,7 +157,9 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate( LocalPoolObjectBase* poolObj = owner->getPoolObjectHandle( receiver.dataId.localPoolId); if(poolObj == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + printWarningOrError(ErrorTypes::WARNING_TYPE, + "handleNotificationUpdate", POOLOBJECT_NOT_FOUND); + return POOLOBJECT_NOT_FOUND; } if(poolObj->hasChanged()) { // prepare and send update notification. @@ -183,7 +179,9 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate( LocalPoolDataSetBase* dataSet = owner->getDataSetHandle( receiver.dataId.sid); if(dataSet == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; + printWarningOrError(ErrorTypes::WARNING_TYPE, + "handleNotificationUpdate", DATASET_NOT_FOUND); + return DATASET_NOT_FOUND; } if(dataSet->hasChanged()) { // prepare and send update notification @@ -213,6 +211,8 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot( LocalPoolObjectBase* poolObj = owner->getPoolObjectHandle( receiver.dataId.localPoolId); if(poolObj == nullptr) { + printWarningOrError(ErrorTypes::WARNING_TYPE, + "handleNotificationSnapshot", POOLOBJECT_NOT_FOUND); return POOLOBJECT_NOT_FOUND; } @@ -249,6 +249,8 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot( LocalPoolDataSetBase* dataSet = owner->getDataSetHandle( receiver.dataId.sid); if(dataSet == nullptr) { + printWarningOrError(ErrorTypes::WARNING_TYPE, + "handleNotificationSnapshot", DATASET_NOT_FOUND); return DATASET_NOT_FOUND; } @@ -351,11 +353,9 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, AcceptsHkPacketsIF* hkReceiverObject = objectManager->get(packetDestination); if(hkReceiverObject == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "LocalDataPoolManager::subscribeForPeriodicPacket:" - << " Invalid receiver!"<< std::endl; -#endif - return HasReturnvaluesIF::RETURN_OK; + printWarningOrError(ErrorTypes::WARNING_TYPE, + "subscribeForPeriodicPacket", QUEUE_OR_DESTINATION_INVALID); + return QUEUE_OR_DESTINATION_INVALID; } struct HkReceiver hkReceiver; @@ -383,11 +383,9 @@ ReturnValue_t LocalDataPoolManager::subscribeForUpdatePackets(sid_t sid, AcceptsHkPacketsIF* hkReceiverObject = objectManager->get(packetDestination); if(hkReceiverObject == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "LocalDataPoolManager::subscribeForPeriodicPacket:" - << " Invalid receiver!"<< std::endl; -#endif - return HasReturnvaluesIF::RETURN_OK; + printWarningOrError(ErrorTypes::WARNING_TYPE, + "subscribeForPeriodicPacket", QUEUE_OR_DESTINATION_INVALID); + return QUEUE_OR_DESTINATION_INVALID; } struct HkReceiver hkReceiver; @@ -591,10 +589,8 @@ ReturnValue_t LocalDataPoolManager::printPoolEntry( lp_id_t localPoolId) { auto poolIter = localPoolMap.find(localPoolId); if (poolIter == localPoolMap.end()) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "HousekeepingManager::fechPoolEntry:" - << " Pool entry not found." << std::endl; -#endif + printWarningOrError(ErrorTypes::WARNING_TYPE, "printPoolEntry", + HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND); return HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND; } poolIter->second->print(); @@ -614,10 +610,9 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid, MessageQueueId_t destination) { if(dataSet == nullptr) { // Configuration error. -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "HousekeepingManager::generateHousekeepingPacket:" - << " Set ID not found or dataset not assigned!" << std::endl; -#endif + printWarningOrError(ErrorTypes::WARNING_TYPE, + "generateHousekeepingPacket", + DATASET_NOT_FOUND); return DATASET_NOT_FOUND; } @@ -640,12 +635,18 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid, } if(hkQueue == nullptr) { - return QUEUE_OR_DESTINATION_NOT_SET; + // error, all destinations invalid + printWarningOrError(ErrorTypes::WARNING_TYPE, + "generateHousekeepingPacket", + QUEUE_OR_DESTINATION_INVALID); + return QUEUE_OR_DESTINATION_INVALID; } if(destination == MessageQueueIF::NO_QUEUE) { if(hkDestinationId == MessageQueueIF::NO_QUEUE) { // error, all destinations invalid - return HasReturnvaluesIF::RETURN_FAILED; + printWarningOrError(ErrorTypes::WARNING_TYPE, + "generateHousekeepingPacket", + QUEUE_OR_DESTINATION_INVALID); } destination = hkDestinationId; } @@ -681,6 +682,13 @@ void LocalDataPoolManager::setNonDiagnosticIntervalFactor( void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) { sid_t sid = receiver.dataId.sid; LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); + if(dataSet == nullptr) { + printWarningOrError(ErrorTypes::WARNING_TYPE, + "performPeriodicHkGeneration", + DATASET_NOT_FOUND); + return; + } + if(not dataSet->getReportingEnabled()) { return; } @@ -699,10 +707,11 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) { if(result != HasReturnvaluesIF::RETURN_OK) { // configuration error #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << "LocalDataPoolManager::performHkOperation:" - << "0x" << std::hex << std::setfill('0') << std::setw(8) - << owner->getObjectId() << " Error generating " - << "HK packet" << std::setfill(' ') << std::dec << std::endl; + sif::warning << "LocalDataPoolManager::performHkOperation: " + << "HK generation failed." << std::endl; +#else + fsfw::printWarning("LocalDataPoolManager::performHkOperation: " + "HK generation failed.\n"); #endif } } @@ -748,11 +757,10 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, // Get and check dataset first. LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); if(dataSet == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "HousekeepingManager::generateHousekeepingPacket:" - << " Set ID not found" << std::endl; -#endif - return HasReturnvaluesIF::RETURN_FAILED; + printWarningOrError(ErrorTypes::WARNING_TYPE, + "performPeriodicHkGeneration", + DATASET_NOT_FOUND); + return DATASET_NOT_FOUND; } @@ -776,10 +784,9 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, ReturnValue_t result = ipcStore->getFreeElement(&storeId, expectedSize,&storePtr); if(result != HasReturnvaluesIF::RETURN_OK) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "HousekeepingManager::generateHousekeepingPacket: " - << "Could not get free element from IPC store." << std::endl; -#endif + printWarningOrError(ErrorTypes::ERROR_TYPE, + "generateSetStructurePacket", HasReturnvaluesIF::RETURN_FAILED, + "Could not get free element from IPC store."); return result; } @@ -788,10 +795,9 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, result = setPacket.serialize(&storePtr, &size, expectedSize, SerializeIF::Endianness::BIG); if(expectedSize != size) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "HousekeepingManager::generateSetStructurePacket: " - << "Expected size is not equal to serialized size" << std::endl; -#endif + printWarningOrError(ErrorTypes::WARNING_TYPE, + "generateSetStructurePacket", HasReturnvaluesIF::RETURN_FAILED, + "Expected size is not equal to serialized size"); } // Send structure reporting reply. @@ -808,3 +814,52 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, hkQueue->reply(&reply); return result; } + +void LocalDataPoolManager::printWarningOrError(ErrorTypes errorType, + const char* functionName, ReturnValue_t error, const char* errorPrint) { + if(errorPrint == nullptr) { + if(error == DATASET_NOT_FOUND) { + errorPrint = "Dataset not found"; + } + else if(error == POOLOBJECT_NOT_FOUND) { + errorPrint = "Pool Object not found"; + } + else if(error == HasReturnvaluesIF::RETURN_FAILED) { + if(errorType == ErrorTypes::WARNING_TYPE) { + errorPrint = "Generic Warning"; + } + else { + errorPrint = "Generic error"; + } + } + else if(error == QUEUE_OR_DESTINATION_INVALID) { + errorPrint = "Queue or destination not set"; + } + else { + errorPrint = "Unknown error"; + } + } + + if(errorType == ErrorTypes::WARNING_TYPE) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "LocalDataPoolManager::" << functionName + << ": Object ID " << std::setw(8) << std::setfill('0') + << std::hex << owner->getObjectId() << " | " << errorPrint + << std::dec << std::setfill(' ') << std::endl; +#else + fsfw::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n", + owner->getObjectId(), errorPrint); +#endif + } + else if(errorType == ErrorTypes::ERROR_TYPE) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "LocalDataPoolManager::" << functionName + << ": Object ID " << std::setw(8) << std::setfill('0') + << std::hex << owner->getObjectId() << " | " << errorPrint + << std::dec << std::setfill(' ') << std::endl; +#else + fsfw::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n", + owner->getObjectId(), errorPrint); +#endif + } +} diff --git a/datapoollocal/LocalDataPoolManager.h b/datapoollocal/LocalDataPoolManager.h index 098158da..6502294e 100644 --- a/datapoollocal/LocalDataPoolManager.h +++ b/datapoollocal/LocalDataPoolManager.h @@ -56,7 +56,7 @@ class LocalDataPoolManager { public: static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER; - static constexpr ReturnValue_t QUEUE_OR_DESTINATION_NOT_SET = MAKE_RETURN_CODE(0); + static constexpr ReturnValue_t QUEUE_OR_DESTINATION_INVALID = MAKE_RETURN_CODE(0); static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(1); static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(2); @@ -370,6 +370,15 @@ private: ReturnValue_t& status); ReturnValue_t addUpdateToStore(HousekeepingPacketUpdate& updatePacket, store_address_t& storeId); + + enum class ErrorTypes { + WARNING_TYPE, + ERROR_TYPE + }; + + void printWarningOrError(ErrorTypes errorType, const char* functionName, + ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED, + const char* errorPrint = nullptr); }; From 541478e4d5f4ad029dd4fd968e10ccc6cc72068d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Jan 2021 15:15:02 +0100 Subject: [PATCH 33/38] another small improvement --- datapoollocal/LocalDataPoolManager.cpp | 8 ++++++-- datapoollocal/LocalDataPoolManager.h | 18 ++++-------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/datapoollocal/LocalDataPoolManager.cpp b/datapoollocal/LocalDataPoolManager.cpp index e5ee499c..d1ab553d 100644 --- a/datapoollocal/LocalDataPoolManager.cpp +++ b/datapoollocal/LocalDataPoolManager.cpp @@ -3,10 +3,8 @@ #include "LocalPoolDataSetBase.h" #include "../housekeeping/HousekeepingPacketUpdate.h" -#include "../serviceinterface/ServiceInterface.h" #include "../housekeeping/HousekeepingSetPacket.h" #include "../housekeeping/AcceptsHkPacketsIF.h" - #include "../timemanager/CCSDSTime.h" #include "../ipc/MutexFactory.h" #include "../ipc/MutexHelper.h" @@ -835,6 +833,12 @@ void LocalDataPoolManager::printWarningOrError(ErrorTypes errorType, else if(error == QUEUE_OR_DESTINATION_INVALID) { errorPrint = "Queue or destination not set"; } + else if(error == HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT) { + errorPrint = "Pool entry type conflict"; + } + else if(error == HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND) { + errorPrint = "Pool entry not found"; + } else { errorPrint = "Unknown error"; } diff --git a/datapoollocal/LocalDataPoolManager.h b/datapoollocal/LocalDataPoolManager.h index 6502294e..730e03e4 100644 --- a/datapoollocal/LocalDataPoolManager.h +++ b/datapoollocal/LocalDataPoolManager.h @@ -387,25 +387,15 @@ ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId, PoolEntry **poolEntry) { auto poolIter = localPoolMap.find(localPoolId); if (poolIter == localPoolMap.end()) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "HousekeepingManager::fetchPoolEntry: Pool entry " - "not found." << std::endl; -#else - fsfw::printWarning("HousekeepingManager::fetchPoolEntry: Pool entry " - "not found.\n"); -#endif + printWarningOrError(ErrorTypes::ERROR_TYPE, "fetchPoolEntry", + HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND); return HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND; } *poolEntry = dynamic_cast< PoolEntry* >(poolIter->second); if(*poolEntry == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "HousekeepingManager::fetchPoolEntry:" - " Pool entry type conflict." << std::endl; -#else - fsfw::printWarning("HousekeepingManager::fetchPoolEntry:" - " Pool entry type conflict.\n"); -#endif + printWarningOrError(ErrorTypes::ERROR_TYPE, "fetchPoolEntry", + HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT); return HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT; } return HasReturnvaluesIF::RETURN_OK; From c0fd981360dbb7d16018e9803a2a9a0f97de32f9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Jan 2021 16:14:11 +0100 Subject: [PATCH 34/38] improved DHB error handling --- datapoollocal/LocalDataPoolManager.cpp | 48 +++--- datapoollocal/LocalDataPoolManager.h | 12 +- devicehandlers/DeviceHandlerBase.cpp | 143 ++++++++++++------ devicehandlers/DeviceHandlerBase.h | 20 ++- serviceinterface/ServiceInterface.h | 1 + serviceinterface/ServiceInterfacePrinter.h | 8 +- serviceinterface/serviceInterfaceDefintions.h | 7 + 7 files changed, 152 insertions(+), 87 deletions(-) diff --git a/datapoollocal/LocalDataPoolManager.cpp b/datapoollocal/LocalDataPoolManager.cpp index d1ab553d..0ab6f150 100644 --- a/datapoollocal/LocalDataPoolManager.cpp +++ b/datapoollocal/LocalDataPoolManager.cpp @@ -20,7 +20,7 @@ LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse, bool appendValidityBuffer): appendValidityBuffer(appendValidityBuffer) { if(owner == nullptr) { - printWarningOrError(ErrorTypes::WARNING_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "LocalDataPoolManager", HasReturnvaluesIF::RETURN_FAILED, "Invalid supplied owner"); return; @@ -28,7 +28,7 @@ LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, this->owner = owner; mutex = MutexFactory::instance()->createMutex(); if(mutex == nullptr) { - printWarningOrError(ErrorTypes::ERROR_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "LocalDataPoolManager", HasReturnvaluesIF::RETURN_FAILED, "Could not create mutex"); } @@ -41,7 +41,7 @@ LocalDataPoolManager::~LocalDataPoolManager() {} ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) { if(queueToUse == nullptr) { // error, all destinations invalid - printWarningOrError(ErrorTypes::ERROR_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "initialize", QUEUE_OR_DESTINATION_INVALID); } hkQueue = queueToUse; @@ -49,7 +49,7 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) { ipcStore = objectManager->get(objects::IPC_STORE); if(ipcStore == nullptr) { // error, all destinations invalid - printWarningOrError(ErrorTypes::ERROR_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "initialize", HasReturnvaluesIF::RETURN_FAILED, "Could not set IPC store."); return HasReturnvaluesIF::RETURN_FAILED; @@ -63,7 +63,7 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) { hkDestinationId = hkPacketReceiver->getHkQueue(); } else { - printWarningOrError(ErrorTypes::ERROR_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "initialize", QUEUE_OR_DESTINATION_INVALID); return QUEUE_OR_DESTINATION_INVALID; } @@ -88,7 +88,7 @@ ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() { return result; } - printWarningOrError(ErrorTypes::WARNING_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "initialize", HasReturnvaluesIF::RETURN_FAILED, "The map should only be initialized once"); return HasReturnvaluesIF::RETURN_OK; @@ -155,7 +155,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate( LocalPoolObjectBase* poolObj = owner->getPoolObjectHandle( receiver.dataId.localPoolId); if(poolObj == nullptr) { - printWarningOrError(ErrorTypes::WARNING_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "handleNotificationUpdate", POOLOBJECT_NOT_FOUND); return POOLOBJECT_NOT_FOUND; } @@ -177,7 +177,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate( LocalPoolDataSetBase* dataSet = owner->getDataSetHandle( receiver.dataId.sid); if(dataSet == nullptr) { - printWarningOrError(ErrorTypes::WARNING_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "handleNotificationUpdate", DATASET_NOT_FOUND); return DATASET_NOT_FOUND; } @@ -209,7 +209,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot( LocalPoolObjectBase* poolObj = owner->getPoolObjectHandle( receiver.dataId.localPoolId); if(poolObj == nullptr) { - printWarningOrError(ErrorTypes::WARNING_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "handleNotificationSnapshot", POOLOBJECT_NOT_FOUND); return POOLOBJECT_NOT_FOUND; } @@ -247,7 +247,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot( LocalPoolDataSetBase* dataSet = owner->getDataSetHandle( receiver.dataId.sid); if(dataSet == nullptr) { - printWarningOrError(ErrorTypes::WARNING_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "handleNotificationSnapshot", DATASET_NOT_FOUND); return DATASET_NOT_FOUND; } @@ -351,7 +351,7 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, AcceptsHkPacketsIF* hkReceiverObject = objectManager->get(packetDestination); if(hkReceiverObject == nullptr) { - printWarningOrError(ErrorTypes::WARNING_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "subscribeForPeriodicPacket", QUEUE_OR_DESTINATION_INVALID); return QUEUE_OR_DESTINATION_INVALID; } @@ -381,7 +381,7 @@ ReturnValue_t LocalDataPoolManager::subscribeForUpdatePackets(sid_t sid, AcceptsHkPacketsIF* hkReceiverObject = objectManager->get(packetDestination); if(hkReceiverObject == nullptr) { - printWarningOrError(ErrorTypes::WARNING_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "subscribeForPeriodicPacket", QUEUE_OR_DESTINATION_INVALID); return QUEUE_OR_DESTINATION_INVALID; } @@ -587,7 +587,7 @@ ReturnValue_t LocalDataPoolManager::printPoolEntry( lp_id_t localPoolId) { auto poolIter = localPoolMap.find(localPoolId); if (poolIter == localPoolMap.end()) { - printWarningOrError(ErrorTypes::WARNING_TYPE, "printPoolEntry", + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "printPoolEntry", HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND); return HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND; } @@ -608,7 +608,7 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid, MessageQueueId_t destination) { if(dataSet == nullptr) { // Configuration error. - printWarningOrError(ErrorTypes::WARNING_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "generateHousekeepingPacket", DATASET_NOT_FOUND); return DATASET_NOT_FOUND; @@ -634,7 +634,7 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid, if(hkQueue == nullptr) { // error, all destinations invalid - printWarningOrError(ErrorTypes::WARNING_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "generateHousekeepingPacket", QUEUE_OR_DESTINATION_INVALID); return QUEUE_OR_DESTINATION_INVALID; @@ -642,7 +642,7 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid, if(destination == MessageQueueIF::NO_QUEUE) { if(hkDestinationId == MessageQueueIF::NO_QUEUE) { // error, all destinations invalid - printWarningOrError(ErrorTypes::WARNING_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "generateHousekeepingPacket", QUEUE_OR_DESTINATION_INVALID); } @@ -681,7 +681,7 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) { sid_t sid = receiver.dataId.sid; LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); if(dataSet == nullptr) { - printWarningOrError(ErrorTypes::WARNING_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "performPeriodicHkGeneration", DATASET_NOT_FOUND); return; @@ -755,7 +755,7 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, // Get and check dataset first. LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid); if(dataSet == nullptr) { - printWarningOrError(ErrorTypes::WARNING_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "performPeriodicHkGeneration", DATASET_NOT_FOUND); return DATASET_NOT_FOUND; @@ -782,7 +782,7 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, ReturnValue_t result = ipcStore->getFreeElement(&storeId, expectedSize,&storePtr); if(result != HasReturnvaluesIF::RETURN_OK) { - printWarningOrError(ErrorTypes::ERROR_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "generateSetStructurePacket", HasReturnvaluesIF::RETURN_FAILED, "Could not get free element from IPC store."); return result; @@ -793,7 +793,7 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, result = setPacket.serialize(&storePtr, &size, expectedSize, SerializeIF::Endianness::BIG); if(expectedSize != size) { - printWarningOrError(ErrorTypes::WARNING_TYPE, + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "generateSetStructurePacket", HasReturnvaluesIF::RETURN_FAILED, "Expected size is not equal to serialized size"); } @@ -813,7 +813,7 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, return result; } -void LocalDataPoolManager::printWarningOrError(ErrorTypes errorType, +void LocalDataPoolManager::printWarningOrError(fsfw::OutputTypes outputType, const char* functionName, ReturnValue_t error, const char* errorPrint) { if(errorPrint == nullptr) { if(error == DATASET_NOT_FOUND) { @@ -823,7 +823,7 @@ void LocalDataPoolManager::printWarningOrError(ErrorTypes errorType, errorPrint = "Pool Object not found"; } else if(error == HasReturnvaluesIF::RETURN_FAILED) { - if(errorType == ErrorTypes::WARNING_TYPE) { + if(outputType == fsfw::OutputTypes::OUT_WARNING) { errorPrint = "Generic Warning"; } else { @@ -844,7 +844,7 @@ void LocalDataPoolManager::printWarningOrError(ErrorTypes errorType, } } - if(errorType == ErrorTypes::WARNING_TYPE) { + if(outputType == fsfw::OutputTypes::OUT_WARNING) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "LocalDataPoolManager::" << functionName << ": Object ID " << std::setw(8) << std::setfill('0') @@ -855,7 +855,7 @@ void LocalDataPoolManager::printWarningOrError(ErrorTypes errorType, owner->getObjectId(), errorPrint); #endif } - else if(errorType == ErrorTypes::ERROR_TYPE) { + else if(outputType == fsfw::OutputTypes::OUT_ERROR) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "LocalDataPoolManager::" << functionName << ": Object ID " << std::setw(8) << std::setfill('0') diff --git a/datapoollocal/LocalDataPoolManager.h b/datapoollocal/LocalDataPoolManager.h index 730e03e4..eee4c593 100644 --- a/datapoollocal/LocalDataPoolManager.h +++ b/datapoollocal/LocalDataPoolManager.h @@ -371,12 +371,8 @@ private: ReturnValue_t addUpdateToStore(HousekeepingPacketUpdate& updatePacket, store_address_t& storeId); - enum class ErrorTypes { - WARNING_TYPE, - ERROR_TYPE - }; - - void printWarningOrError(ErrorTypes errorType, const char* functionName, + void printWarningOrError(fsfw::OutputTypes outputType, + const char* functionName, ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED, const char* errorPrint = nullptr); }; @@ -387,14 +383,14 @@ ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId, PoolEntry **poolEntry) { auto poolIter = localPoolMap.find(localPoolId); if (poolIter == localPoolMap.end()) { - printWarningOrError(ErrorTypes::ERROR_TYPE, "fetchPoolEntry", + printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "fetchPoolEntry", HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND); return HasLocalDataPoolIF::POOL_ENTRY_NOT_FOUND; } *poolEntry = dynamic_cast< PoolEntry* >(poolIter->second); if(*poolEntry == nullptr) { - printWarningOrError(ErrorTypes::ERROR_TYPE, "fetchPoolEntry", + printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "fetchPoolEntry", HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT); return HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT; } diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 580f8c0d..7ca9922a 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -39,13 +39,8 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, cookieInfo.state = COOKIE_UNUSED; cookieInfo.pendingCommand = deviceCommandMap.end(); if (comCookie == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "DeviceHandlerBase: ObjectID 0x" << std::hex - << std::setw(8) << std::setfill('0') << this->getObjectId() - << std::dec << ": Do not pass nullptr as a cookie, consider " - << std::setfill(' ') << "passing a dummy cookie instead!" - << std::endl; -#endif + printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "DeviceHandlerBase", + HasReturnvaluesIF::RETURN_FAILED, "Invalid cookie"); } if (this->fdirInstance == nullptr) { this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, @@ -132,30 +127,24 @@ ReturnValue_t DeviceHandlerBase::initialize() { communicationInterface = objectManager->get( deviceCommunicationId); if (communicationInterface == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "DeviceHandlerBase::initialize: Communication interface " - "invalid." << std::endl; - sif::error << "Make sure it is set up properly and implements" - " DeviceCommunicationIF" << std::endl; -#endif + printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "initialize", + ObjectManagerIF::CHILD_INIT_FAILED, + "Passed communication IF invalid"); return ObjectManagerIF::CHILD_INIT_FAILED; } result = communicationInterface->initializeInterface(comCookie); if (result != RETURN_OK) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "DeviceHandlerBase::initialize: Initializing " - "communication interface failed!" << std::endl; -#endif + printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "initialize", + ObjectManagerIF::CHILD_INIT_FAILED, + "ComIF initialization failed"); return result; } IPCStore = objectManager->get(objects::IPC_STORE); if (IPCStore == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "DeviceHandlerBase::initialize: IPC store not set up in " - "factory." << std::endl; -#endif + printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "initialize", + ObjectManagerIF::CHILD_INIT_FAILED, "IPC Store not set up"); return ObjectManagerIF::CHILD_INIT_FAILED; } @@ -164,11 +153,15 @@ ReturnValue_t DeviceHandlerBase::initialize() { AcceptsDeviceResponsesIF>(rawDataReceiverId); if (rawReceiver == nullptr) { + printWarningOrError(fsfw::OutputTypes::OUT_ERROR, + "initialize", ObjectManagerIF::CHILD_INIT_FAILED, + "Raw receiver object ID set but no valid object found."); #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "DeviceHandlerBase::initialize: Raw receiver object " - "ID set but no valid object found." << std::endl; sif::error << "Make sure the raw receiver object is set up properly" " and implements AcceptsDeviceResponsesIF" << std::endl; +#else + fsfw::printError("Make sure the raw receiver object is set up " + "properly and implements AcceptsDeviceResponsesIF\n"); #endif return ObjectManagerIF::CHILD_INIT_FAILED; } @@ -178,11 +171,15 @@ ReturnValue_t DeviceHandlerBase::initialize() { if(powerSwitcherId != objects::NO_OBJECT) { powerSwitcher = objectManager->get(powerSwitcherId); if (powerSwitcher == nullptr) { + printWarningOrError(fsfw::OutputTypes::OUT_ERROR, + "initialize", ObjectManagerIF::CHILD_INIT_FAILED, + "Power switcher set but no valid object found."); #if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "DeviceHandlerBase::initialize: Power switcher " - << "object ID set but no valid object found." << std::endl; - sif::error << "Make sure the raw receiver object is set up properly" - << " and implements PowerSwitchIF" << std::endl; + sif::error << "Make sure the power switcher object is set up " + << "properly and implements PowerSwitchIF" << std::endl; +#else + fsfw::printError("Make sure the power switcher object is set up " + "properly and implements PowerSwitchIF\n"); #endif return ObjectManagerIF::CHILD_INIT_FAILED; } @@ -556,17 +553,17 @@ void DeviceHandlerBase::replyReturnvalueToCommand(ReturnValue_t status, void DeviceHandlerBase::replyToCommand(ReturnValue_t status, uint32_t parameter) { -//Check if we reply to a raw command. + // Check if we reply to a raw command. if (cookieInfo.pendingCommand->first == RAW_COMMAND_ID) { if (status == NO_REPLY_EXPECTED) { status = RETURN_OK; } replyReturnvalueToCommand(status, parameter); - //Always delete data from a raw command. + // Always delete data from a raw command. IPCStore->deleteData(storedRawData); return; } -//Check if we were externally commanded. + // Check if we were externally commanded. if (cookieInfo.pendingCommand->second.sendReplyTo != NO_COMMANDER) { MessageQueueId_t queueId = cookieInfo.pendingCommand->second.sendReplyTo; if (status == NO_REPLY_EXPECTED) { @@ -581,15 +578,17 @@ void DeviceHandlerBase::replyToCommand(ReturnValue_t status, void DeviceHandlerBase::replyToReply(DeviceReplyMap::iterator iter, ReturnValue_t status) { -//No need to check if iter exists, as this is checked by callers. If someone else uses the method, add check. + // No need to check if iter exists, as this is checked by callers. + // If someone else uses the method, add check. if (iter->second.command == deviceCommandMap.end()) { //Is most likely periodic reply. Silent return. return; } -//Check if more replies are expected. If so, do nothing. + // Check if more replies are expected. If so, do nothing. DeviceCommandInfo* info = &(iter->second.command->second); if (--info->expectedReplies == 0) { - //Check if it was transition or internal command. Don't send any replies in that case. + // Check if it was transition or internal command. + // Don't send any replies in that case. if (info->sendReplyTo != NO_COMMANDER) { actionHelper.finish(info->sendReplyTo, iter->first, status); } @@ -606,7 +605,7 @@ void DeviceHandlerBase::doSendWrite() { if (result == RETURN_OK) { cookieInfo.state = COOKIE_WRITE_SENT; } else { - //always generate a failure event, so that FDIR knows what's up + // always generate a failure event, so that FDIR knows what's up triggerEvent(DEVICE_SENDING_COMMAND_FAILED, result, cookieInfo.pendingCommand->first); replyToCommand(result); @@ -735,6 +734,9 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData, foundId); } if(foundLen == 0) { + printWarningOrError(fsfw::OutputTypes::OUT_ERROR, + "parseReply", ObjectManagerIF::CHILD_INIT_FAILED, + "Power switcher set but no valid object found."); #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "DeviceHandlerBase::parseReply: foundLen is 0!" " Packet parsing will be stuck." << std::endl; @@ -968,7 +970,8 @@ ReturnValue_t DeviceHandlerBase::getStateOfSwitches(void) { } Mode_t DeviceHandlerBase::getBaseMode(Mode_t transitionMode) { -//only child action special modes are handled, as a child should never see any base action modes + // only child action special modes are handled, as a child should + // never see any base action modes if (transitionMode == _MODE_START_UP) { return _MODE_TO_ON; } @@ -1291,12 +1294,11 @@ void DeviceHandlerBase::buildInternalCommand(void) { if (mode == MODE_NORMAL) { result = buildNormalDeviceCommand(&deviceCommandId); if (result == BUSY) { - //so we can track misconfigurations -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << std::hex << getObjectId() - << ": DHB::buildInternalCommand: Busy" << std::dec - << std::endl; -#endif + // so we can track misconfigurations + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, + "buildInternalCommand", + HasReturnvaluesIF::RETURN_FAILED, + "Busy."); result = NOTHING_TO_SEND; //no need to report this } } @@ -1320,13 +1322,13 @@ void DeviceHandlerBase::buildInternalCommand(void) { if (iter == deviceCommandMap.end()) { result = COMMAND_NOT_SUPPORTED; } else if (iter->second.isExecuting) { - //so we can track misconfigurations -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::debug << std::hex << getObjectId() - << ": DHB::buildInternalCommand: Command " - << deviceCommandId << " isExecuting" << std::dec - << std::endl; -#endif + char* output = nullptr; + sprintf(output, "Command %lu is executing", deviceCommandId); + // so we can track misconfigurations + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, + "buildInternalCommand", + HasReturnvaluesIF::RETURN_FAILED, + output); // this is an internal command, no need to report a failure here, // missed reply will track if a reply is too late, otherwise, it's ok return; @@ -1485,3 +1487,48 @@ void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() { } } } + +void DeviceHandlerBase::printWarningOrError(fsfw::OutputTypes errorType, + const char *functionName, ReturnValue_t errorCode, + const char *errorPrint) { + if(errorPrint == nullptr) { + if(errorCode == ObjectManagerIF::CHILD_INIT_FAILED) { + errorPrint = "Initialization error"; + } + if(errorCode == HasReturnvaluesIF::RETURN_FAILED) { + if(errorType == fsfw::OutputTypes::OUT_WARNING) { + errorPrint = "Generic Warning"; + } + else { + errorPrint = "Generic Error"; + } + } + else { + errorPrint = "Unknown error"; + } + } + + if(errorType == fsfw::OutputTypes::OUT_WARNING) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "DeviceHandlerBase::" << functionName << ": Object ID " + << std::hex << std::setw(8) << std::setfill('0') + << this->getObjectId() << " | " << errorPrint << std::dec + << std::setfill(' ') << std::endl; +#else + fsfw::printWarning("DeviceHandlerBase::%s: Object ID 0x%08x | %s\n", + this->getObjectId(), errorPrint); +#endif + } + else if(errorType == fsfw::OutputTypes::OUT_ERROR) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "DeviceHandlerBase::" << functionName << ": Object ID " + << std::hex << std::setw(8) << std::setfill('0') + << this->getObjectId() << " | " << errorPrint << std::dec + << std::setfill(' ') << std::endl; +#else + fsfw::printError("DeviceHandlerBase::%s: Object ID 0x%08x | %s\n", + this->getObjectId(), errorPrint); +#endif + } + +} diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 24ba0372..4c745b4f 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -6,6 +6,8 @@ #include "DeviceHandlerFailureIsolation.h" #include "DeviceHandlerThermalSet.h" +#include "../serviceinterface/ServiceInterface.h" +#include "../serviceinterface/serviceInterfaceDefintions.h" #include "../objectmanager/SystemObject.h" #include "../tasks/ExecutableObjectIF.h" #include "../returnvalues/HasReturnvaluesIF.h" @@ -1111,7 +1113,7 @@ private: /** * @brief The mode the current transition originated from * - * This is private so the child can not change it and fuck up the timeouts + * This is private so the child can not change it and mess up the timeouts * * IMPORTANT: This is not valid during _MODE_SHUT_DOWN and _MODE_START_UP!! * (it is _MODE_POWER_DOWN during this modes) @@ -1190,7 +1192,8 @@ private: * Check if the RMAP sendWrite action was successful. * * Depending on the result, the following is done - * - if the device command was external commanded, a reply is sent indicating the result + * - if the device command was external commanded, a reply is sent + * indicating the result * - if the action was successful, the reply timout counter is initialized */ void doGetWrite(void); @@ -1206,9 +1209,9 @@ private: /** * Check the getRead reply and the contained data. * - * If data was received scanForReply() and, if successful, handleReply() are called. - * If the current mode is @c MODE_RAW, the received packet is sent to the commanding object - * via commandQueue. + * If data was received scanForReply() and, if successful, handleReply() + * are called. If the current mode is @c MODE_RAW, the received packet + * is sent to the commanding object via commandQueue. */ void doGetRead(void); @@ -1227,7 +1230,7 @@ private: uint32_t *len); /** - * @param modeTo either @c MODE_ON, MODE_NORMAL or MODE_RAW NOTHING ELSE!!! + * @param modeTo either @c MODE_ON, MODE_NORMAL or MODE_RAW, nothing else! */ void setTransition(Mode_t modeTo, Submode_t submodeTo); @@ -1247,6 +1250,11 @@ private: void handleTransitionToOnMode(Mode_t commandedMode, Submode_t commandedSubmode); + + void printWarningOrError(fsfw::OutputTypes errorType, + const char* functionName, + ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED, + const char* errorPrint = nullptr); }; #endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */ diff --git a/serviceinterface/ServiceInterface.h b/serviceinterface/ServiceInterface.h index 0c7c4383..1f7e5e84 100644 --- a/serviceinterface/ServiceInterface.h +++ b/serviceinterface/ServiceInterface.h @@ -2,6 +2,7 @@ #define FSFW_SERVICEINTERFACE_SERVICEINTERFACE_H_ #include +#include "serviceInterfaceDefintions.h" #if FSFW_CPP_OSTREAM_ENABLED == 1 #include diff --git a/serviceinterface/ServiceInterfacePrinter.h b/serviceinterface/ServiceInterfacePrinter.h index 1f82ba98..9a84f629 100644 --- a/serviceinterface/ServiceInterfacePrinter.h +++ b/serviceinterface/ServiceInterfacePrinter.h @@ -4,7 +4,7 @@ namespace fsfw { -enum class PrintLevel { +enum PrintLevel { NONE = 0, //! Strange error when using just ERROR.. ERROR_TYPE = 1, @@ -13,6 +13,12 @@ enum class PrintLevel { DEBUG = 4 }; +/** + * Set the print level. All print types with a smaller level will be printed + * as well. For example, set to PrintLevel::WARNING to only enable error + * and warning output. + * @param printLevel + */ void setPrintLevel(PrintLevel printLevel); PrintLevel getPrintLevel(); diff --git a/serviceinterface/serviceInterfaceDefintions.h b/serviceinterface/serviceInterfaceDefintions.h index 684c7366..de445907 100644 --- a/serviceinterface/serviceInterfaceDefintions.h +++ b/serviceinterface/serviceInterfaceDefintions.h @@ -3,6 +3,13 @@ namespace fsfw { +enum class OutputTypes { + OUT_INFO, + OUT_DEBUG, + OUT_WARNING, + OUT_ERROR +}; + static const char* const ANSI_COLOR_RED = "\x1b[31m"; static const char* const ANSI_COLOR_GREEN = "\x1b[32m"; static const char* const ANSI_COLOR_YELLOW = "\x1b[33m"; From a9dba82661f6a88eeaa3fd1aab0948bf1919158c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Jan 2021 16:16:17 +0100 Subject: [PATCH 35/38] bugfix --- devicehandlers/DeviceHandlerBase.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 7ca9922a..1a106844 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -1322,8 +1322,8 @@ void DeviceHandlerBase::buildInternalCommand(void) { if (iter == deviceCommandMap.end()) { result = COMMAND_NOT_SUPPORTED; } else if (iter->second.isExecuting) { - char* output = nullptr; - sprintf(output, "Command %lu is executing", deviceCommandId); + char output[36]; + sprintf(output, "Command 0x%08x is executing", deviceCommandId); // so we can track misconfigurations printWarningOrError(fsfw::OutputTypes::OUT_WARNING, "buildInternalCommand", From a1c394143a1b6ba4c80abcb54302ca1020053f69 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Jan 2021 16:18:08 +0100 Subject: [PATCH 36/38] small formatting stuff --- devicehandlers/DeviceHandlerBase.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 1a106844..835a02b8 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -749,7 +749,8 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData, case IGNORE_FULL_PACKET: return; default: - //We need to wait for timeout.. don't know what command failed and who sent it. + // We need to wait for timeout.. don't know what command failed + // and who sent it. replyRawReplyIfnotWiretapped(receivedData, foundLen); triggerEvent(DEVICE_READING_REPLY_FAILED, result, foundLen); break; From 9f15cd697d154d0d464560ce2c26cedee9c87388 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Jan 2021 16:23:57 +0100 Subject: [PATCH 37/38] improved includes --- devicehandlers/DeviceHandlerBase.cpp | 14 ++++++-------- serviceinterface/ServiceInterfacePrinter.h | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 835a02b8..0efdeba0 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -2,7 +2,7 @@ #include "AcceptsDeviceResponsesIF.h" #include "DeviceTmReportingWrapper.h" -#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../serviceinterface/ServiceInterface.h" #include "../objectmanager/ObjectManager.h" #include "../storagemanager/StorageManagerIF.h" #include "../thermal/ThermalComponentIF.h" @@ -13,9 +13,6 @@ #include "../subsystem/SubsystemBase.h" #include "../datapoollocal/LocalPoolVariable.h" -#include - - object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT; object_id_t DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT; object_id_t DeviceHandlerBase::defaultFdirParentId = objects::NO_OBJECT; @@ -720,10 +717,9 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData, case RETURN_OK: handleReply(receivedData, foundId, foundLen); if(foundLen == 0) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "DeviceHandlerBase::parseReply: foundLen is 0!" - " Packet parsing will be stuck." << std::endl; -#endif + printWarningOrError(fsfw::OutputTypes::OUT_WARNING, + "parseReply", ObjectManagerIF::CHILD_INIT_FAILED, + "Found length is one, parsing might be stuck"); } break; case APERIODIC_REPLY: { @@ -1323,6 +1319,7 @@ void DeviceHandlerBase::buildInternalCommand(void) { if (iter == deviceCommandMap.end()) { result = COMMAND_NOT_SUPPORTED; } else if (iter->second.isExecuting) { +#if FSFW_DISABLE_PRINTOUT == 0 char output[36]; sprintf(output, "Command 0x%08x is executing", deviceCommandId); // so we can track misconfigurations @@ -1330,6 +1327,7 @@ void DeviceHandlerBase::buildInternalCommand(void) { "buildInternalCommand", HasReturnvaluesIF::RETURN_FAILED, output); +#endif // this is an internal command, no need to report a failure here, // missed reply will track if a reply is too late, otherwise, it's ok return; diff --git a/serviceinterface/ServiceInterfacePrinter.h b/serviceinterface/ServiceInterfacePrinter.h index 9a84f629..fdff797a 100644 --- a/serviceinterface/ServiceInterfacePrinter.h +++ b/serviceinterface/ServiceInterfacePrinter.h @@ -1,5 +1,5 @@ #if FSFW_DISABLE_PRINTOUT == 0 -#include +#include #endif namespace fsfw { From 7c47b1ce345182c6a69ff2fcaf6e89d81ef8c867 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Jan 2021 20:44:05 +0100 Subject: [PATCH 38/38] 100 percent test coverage for pool vector --- datapoollocal/LocalPoolVector.tpp | 4 +- unittest/tests/datapoollocal/CMakeLists.txt | 1 + unittest/tests/datapoollocal/DataSetTest.cpp | 6 ++- .../datapoollocal/LocalPoolVariableTest.cpp | 2 +- .../datapoollocal/LocalPoolVectorTest.cpp | 52 ++++++++++++++++++- 5 files changed, 59 insertions(+), 6 deletions(-) diff --git a/datapoollocal/LocalPoolVector.tpp b/datapoollocal/LocalPoolVector.tpp index a0e32f62..f311c23d 100644 --- a/datapoollocal/LocalPoolVector.tpp +++ b/datapoollocal/LocalPoolVector.tpp @@ -104,7 +104,7 @@ inline T& LocalPoolVector::operator [](size_t i) { fsfw::printWarning("LocalPoolVector: Invalid index. Setting or returning" " last value!\n"); #endif - return value[vectorSize]; + return value[vectorSize - 1]; } template @@ -121,7 +121,7 @@ inline const T& LocalPoolVector::operator [](size_t i) const { fsfw::printWarning("LocalPoolVector: Invalid index. Setting or returning" " last value!\n"); #endif - return value[vectorSize]; + return value[vectorSize - 1]; } template diff --git a/unittest/tests/datapoollocal/CMakeLists.txt b/unittest/tests/datapoollocal/CMakeLists.txt index 9d828de5..fd7f61b8 100644 --- a/unittest/tests/datapoollocal/CMakeLists.txt +++ b/unittest/tests/datapoollocal/CMakeLists.txt @@ -1,4 +1,5 @@ target_sources(${TARGET_NAME} PRIVATE LocalPoolVariableTest.cpp LocalPoolVectorTest.cpp + DataSetTest.cpp ) diff --git a/unittest/tests/datapoollocal/DataSetTest.cpp b/unittest/tests/datapoollocal/DataSetTest.cpp index ccb7603d..968a0b3d 100644 --- a/unittest/tests/datapoollocal/DataSetTest.cpp +++ b/unittest/tests/datapoollocal/DataSetTest.cpp @@ -2,6 +2,7 @@ #include #include +#include #include TEST_CASE("LocalDataSet" , "[LocDataSetTest]") { @@ -11,9 +12,10 @@ TEST_CASE("LocalDataSet" , "[LocDataSetTest]") { REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK); REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() == retval::CATCH_OK); - + const uint32_t setId = 0; SECTION("BasicTest") { - //StaticLocalDataSet<3> localSet = StaticLocalDataSet<3>() + StaticLocalDataSet<3> localSet = StaticLocalDataSet<3>( + sid_t(objects::TEST_LOCAL_POOL_OWNER_BASE, setId)); } } diff --git a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp index eb5abf35..5f7118ff 100644 --- a/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp +++ b/unittest/tests/datapoollocal/LocalPoolVariableTest.cpp @@ -23,10 +23,10 @@ TEST_CASE("LocalPoolVariable" , "[LocPoolVarTest]") { REQUIRE(testVariable.commit() == retval::CATCH_OK); REQUIRE(testVariable.read() == retval::CATCH_OK); REQUIRE(testVariable.value == 5); - CHECK(not testVariable.isValid()); testVariable.setValid(true); CHECK(testVariable.isValid()); + CHECK(testVariable.commit(true) == retval::CATCH_OK); testVariable.setReadWriteMode(pool_rwm_t::VAR_READ); CHECK(testVariable.getReadWriteMode() == pool_rwm_t::VAR_READ); diff --git a/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp b/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp index 7e40e898..cfc2ec2e 100644 --- a/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp +++ b/unittest/tests/datapoollocal/LocalPoolVectorTest.cpp @@ -38,7 +38,7 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") { // This is invalid access, so the last value will be set instead. // (we can't throw exceptions) testVector[4] = 12; - CHECK(testVector[3] == 12); + CHECK(testVector[2] == 12); CHECK(testVector.commit() == retval::CATCH_OK); // Use read-only reference. @@ -48,6 +48,42 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") { uint16_t lastVal = roTestVec[25]; CHECK(lastVal == 12); + + size_t maxSize = testVector.getSerializedSize(); + CHECK(maxSize == 6); + + uint16_t serializedVector[3]; + uint8_t* vecPtr = reinterpret_cast(serializedVector); + size_t serSize = 0; + REQUIRE(testVector.serialize(&vecPtr, &serSize, + maxSize, SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); + + CHECK(serSize == 6); + CHECK(serializedVector[0] == 5); + CHECK(serializedVector[1] == 232); + CHECK(serializedVector[2] == 12); + + maxSize = 1; + REQUIRE(testVector.serialize(&vecPtr, &serSize, + maxSize, SerializeIF::Endianness::MACHINE) == + static_cast(SerializeIF::BUFFER_TOO_SHORT)); + + serializedVector[0] = 16; + serializedVector[1] = 7832; + serializedVector[2] = 39232; + + const uint8_t* constVecPtr = reinterpret_cast( + serializedVector); + REQUIRE(testVector.deSerialize(&constVecPtr, &serSize, + SerializeIF::Endianness::MACHINE) == retval::CATCH_OK); + CHECK(testVector[0] == 16); + CHECK(testVector[1] == 7832); + CHECK(testVector[2] == 39232); + + serSize = 1; + REQUIRE(testVector.deSerialize(&constVecPtr, &serSize, + SerializeIF::Endianness::MACHINE) == + static_cast(SerializeIF::STREAM_TOO_SHORT)); } SECTION("ErrorHandling") { @@ -64,6 +100,20 @@ TEST_CASE("LocalPoolVector" , "[LocPoolVecTest]") { objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id); REQUIRE(invalidVector2.read() == static_cast(HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT)); + REQUIRE(invalidVector2.commit() == + static_cast(HasLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT)); + + lp_vec_t writeOnlyVec = lp_vec_t( + objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id, + nullptr, pool_rwm_t::VAR_WRITE); + REQUIRE(writeOnlyVec.read() == + static_cast(PoolVariableIF::INVALID_READ_WRITE_MODE)); + + lp_vec_t readOnlyVec = lp_vec_t( + objects::TEST_LOCAL_POOL_OWNER_BASE, lpool::uint16Vec3Id, + nullptr, pool_rwm_t::VAR_READ); + REQUIRE(readOnlyVec.commit() == + static_cast(PoolVariableIF::INVALID_READ_WRITE_MODE)); } }