diff --git a/inc/Services/HousekeepingService.hpp b/inc/Services/HousekeepingService.hpp index 08f475240428b172ea6509edaa94145733e66295..8614b5529f153f757c68ab4c8029ff6b915f2743 100644 --- a/inc/Services/HousekeepingService.hpp +++ b/inc/Services/HousekeepingService.hpp @@ -1,6 +1,7 @@ #ifndef ECSS_SERVICES_HOUSEKEEPINGSERVICE_HPP #define ECSS_SERVICES_HOUSEKEEPINGSERVICE_HPP +#include <optional> #include "ECSS_Definitions.hpp" #include "ErrorHandler.hpp" #include "Helpers/HousekeepingStructure.hpp" @@ -65,6 +66,148 @@ public: initializeHousekeepingStructures(); }; + /** + * Returns the periodic generation action status of a Housekeeping structure. + * @param id Housekeeping structure ID + * @return boolean True if periodic generation of housekeeping reports is enabled, false otherwise + */ + inline bool getPeriodicGenerationActionStatus(uint8_t id) { + HousekeepingStructure newStructure{}; + if (hasNonExistingStructInternalError(id)) { + return newStructure.periodicGenerationActionStatus; + } + return housekeepingStructures.at(id).periodicGenerationActionStatus; + } + + /** + * Returns a reference to the structure at position of "id" in the map. + * @param id Housekeeping structure ID + * @return optional<std::reference_wrapper<HousekeepingStructure>> Reference to Housekeeping Structure + */ + inline std::optional<std::reference_wrapper<HousekeepingStructure>> getStruct(uint8_t id) { + if (hasNonExistingStructInternalError(id)) { + return {}; + } + return housekeepingStructures.at(id); + } + + /** + * Returns the collection interval (how often data is collected) of a Housekeeping structure. + * @param id Housekeeping structure ID + * @return uint32_t Integer multiples of the minimum sampling interval + */ + inline uint32_t getCollectionInterval(uint8_t id) { + HousekeepingStructure newStructure{}; + if (hasNonExistingStructInternalError(id)) { + return newStructure.collectionInterval; + } + return housekeepingStructures.at(id).collectionInterval; + } + + /** + * Sets the periodic generation action status of a Housekeeping structure. + * @param id Housekeeping structure ID + * @param status Periodic generation status of housekeeping reports + */ + inline void setPeriodicGenerationActionStatus(uint8_t id, bool status) { + if (hasNonExistingStructInternalError(id)) { + return; + } + housekeepingStructures.at(id).periodicGenerationActionStatus = status; + } + + /** + * Sets the collection interval of a Housekeeping structure. + * @param id Housekeeping structure ID + * @param interval Integer multiples of the minimum sampling interval + */ + inline void setCollectionInterval(uint8_t id, uint32_t interval) { + if (hasNonExistingStructInternalError(id)) { + return; + } + housekeepingStructures.at(id).collectionInterval = interval; + } + + /** + * Checks if the structure exists in the map. + * @param id Housekeeping structure ID + * @return boolean True if the structure exists, false otherwise + */ + inline bool structExists(uint8_t id) { + return (housekeepingStructures.find(id) != housekeepingStructures.end()); + } + + /** + * Checks if the structure doesn't exist in the map and then accordingly reports execution start error. + * @param id Housekeeping structure ID + * @param request Telemetry (TM) or telecommand (TC) message + * @return boolean True if the structure doesn't exist, false otherwise + */ + bool hasNonExistingStructExecutionError(uint8_t id, Message& request); + + /** + * Checks if the structure doesn't exist in the map and then accordingly reports error. + * @param id Housekeeping structure ID + * @param request Telemetry (TM) or telecommand (TC) message + * @return boolean True if the structure doesn't exist, false otherwise + */ + bool hasNonExistingStructError(uint8_t id, Message& request); + + /** + * Checks if the structure doesn't exist in the map and then accordingly reports internal error. + * @param id Housekeeping structure ID + * @return boolean True if the structure doesn't exist, false otherwise + */ + bool hasNonExistingStructInternalError(uint8_t id); + + /** + * Checks if the parameter exists in the vector and if it does it reports an error. + * @param id Parameter ID + * @param housekeepingStruct Housekkeping Structure + * @param request Telemetry (TM) or telecommand (TC) message + * @return boolean True if the parameter exists, false otherwise + */ + static bool hasAlreadyExistingParameterError(HousekeepingStructure& housekeepingStruct, uint8_t id, Message& request); + + /** + * Checks if the struct requested exists and if it exists reports execution error. + * @param id Housekeeping structure ID + * @param request Telemetry (TM) or telecommand (TC) message + * @return boolean True if the structure exists, false otherwise + */ + bool hasAlreadyExistingStructError(uint8_t id, Message& request); + + /** + * Reports execution error if the max number of housekeeping structures is exceeded. + * @param request Telemetry (TM) or telecommand (TC) message + * @return boolean True if max number of housekeeping structures is exceeded, false otherwise + */ + bool hasExceededMaxNumOfHousekeepingStructsError(Message& request); + + /** + * Reports execution error if it's attempted to append a new parameter id to a housekeeping structure, but the periodic generation status is enabled. + * @param housekeepingStruct Housekkeping Structure + * @param request Telemetry (TM) or telecommand (TC) message + * @return boolean True if periodic generation status is enabled, false otherwise + */ + static bool hasRequestedAppendToEnabledHousekeepingError(HousekeepingStructure& housekeepingStruct, Message& request); + + /** + * Reports execution error if it's attempted to delete structure which has the periodic reporting status enabled. + * @param id Housekeeping structure ID + * @param request Telemetry (TM) or telecommand (TC) message + * @return boolean True if periodic reporting status is enabled, false otherwise + */ + bool hasRequestedDeletionOfEnabledHousekeepingError(uint8_t id, Message& request); + + /** + * Reports execution error if the max number of simply commutated parameters is exceeded. + * @param housekeepingStruct Housekkeping Structure + * @param request Telemetry (TM) or telecommand (TC) message + * @return boolean True if max number of simply commutated parameters is exceeded, false otherwise + */ + static bool hasExceededMaxNumOfSimplyCommutatedParamsError(HousekeepingStructure& housekeepingStruct, Message& request); + /** * Implementation of TC[3,1]. Request to create a housekeeping parameters report structure. */ diff --git a/src/Services/HousekeepingService.cpp b/src/Services/HousekeepingService.cpp index 0f4bca42fe35ba956a83b47378836489a5015b0b..d7c8f9dfa2a2d5b98cb19db8f8bca91c7dc00866 100644 --- a/src/Services/HousekeepingService.cpp +++ b/src/Services/HousekeepingService.cpp @@ -5,13 +5,10 @@ void HousekeepingService::createHousekeepingReportStructure(Message& request) { request.assertTC(ServiceType, MessageType::CreateHousekeepingReportStructure); uint8_t idToCreate = request.readUint8(); - if (housekeepingStructures.find(idToCreate) != housekeepingStructures.end()) { - ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedAlreadyExistingStructure); + if (hasAlreadyExistingStructError(idToCreate, request)) { return; } - if (housekeepingStructures.size() >= ECSSMaxHousekeepingStructures) { - ErrorHandler::reportError(request, - ErrorHandler::ExecutionStartErrorType::ExceededMaxNumberOfHousekeepingStructures); + if (hasExceededMaxNumOfHousekeepingStructsError(request)) { return; } HousekeepingStructure newStructure; @@ -23,8 +20,7 @@ void HousekeepingService::createHousekeepingReportStructure(Message& request) { for (uint16_t i = 0; i < numOfSimplyCommutatedParams; i++) { uint16_t newParamId = request.readUint16(); - if (existsInVector(newStructure.simplyCommutatedParameterIds, newParamId)) { - ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::AlreadyExistingParameter); + if (hasAlreadyExistingParameterError(newStructure, newParamId, request)) { continue; } newStructure.simplyCommutatedParameterIds.push_back(newParamId); @@ -37,13 +33,11 @@ void HousekeepingService::deleteHousekeepingReportStructure(Message& request) { uint8_t numOfStructuresToDelete = request.readUint8(); for (uint8_t i = 0; i < numOfStructuresToDelete; i++) { uint8_t structureId = request.readUint8(); - if (housekeepingStructures.find(structureId) == housekeepingStructures.end()) { - ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure); + if (hasNonExistingStructExecutionError(structureId, request)) { continue; } - if (housekeepingStructures.at(structureId).periodicGenerationActionStatus) { - ErrorHandler::reportError(request, - ErrorHandler::ExecutionStartErrorType::RequestedDeletionOfEnabledHousekeeping); + + if (hasRequestedDeletionOfEnabledHousekeepingError(structureId, request)) { continue; } housekeepingStructures.erase(structureId); @@ -56,11 +50,10 @@ void HousekeepingService::enablePeriodicHousekeepingParametersReport(Message& re uint8_t numOfStructIds = request.readUint8(); for (uint8_t i = 0; i < numOfStructIds; i++) { uint8_t structIdToEnable = request.readUint8(); - if (housekeepingStructures.find(structIdToEnable) == housekeepingStructures.end()) { - ErrorHandler::reportError(request, ErrorHandler::RequestedNonExistingStructure); + if (hasNonExistingStructError(structIdToEnable, request)) { continue; } - housekeepingStructures.at(structIdToEnable).periodicGenerationActionStatus = true; + setPeriodicGenerationActionStatus(structIdToEnable, true); } } @@ -70,11 +63,10 @@ void HousekeepingService::disablePeriodicHousekeepingParametersReport(Message& r uint8_t numOfStructIds = request.readUint8(); for (uint8_t i = 0; i < numOfStructIds; i++) { uint8_t structIdToDisable = request.readUint8(); - if (housekeepingStructures.find(structIdToDisable) == housekeepingStructures.end()) { - ErrorHandler::reportError(request, ErrorHandler::RequestedNonExistingStructure); + if (hasNonExistingStructError(structIdToDisable, request)) { continue; } - housekeepingStructures.at(structIdToDisable).periodicGenerationActionStatus = false; + setPeriodicGenerationActionStatus(structIdToDisable, false); } } @@ -84,18 +76,17 @@ void HousekeepingService::reportHousekeepingStructures(Message& request) { uint8_t numOfStructsToReport = request.readUint8(); for (uint8_t i = 0; i < numOfStructsToReport; i++) { uint8_t structureId = request.readUint8(); - if (housekeepingStructures.find(structureId) == housekeepingStructures.end()) { - ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure); + if (hasNonExistingStructExecutionError(structureId, request)) { continue; } + housekeepingStructureReport(structureId); } } void HousekeepingService::housekeepingStructureReport(uint8_t structIdToReport) { auto housekeepingStructure = housekeepingStructures.find(structIdToReport); - if (housekeepingStructure == housekeepingStructures.end()) { - ErrorHandler::reportInternalError(ErrorHandler::InternalErrorType::NonExistentHousekeeping); + if (hasNonExistingStructInternalError(structIdToReport)) { return; } Message structReport = createTM(MessageType::HousekeepingStructuresReport); @@ -112,12 +103,11 @@ void HousekeepingService::housekeepingStructureReport(uint8_t structIdToReport) } void HousekeepingService::housekeepingParametersReport(uint8_t structureId) { - if (housekeepingStructures.find(structureId) == housekeepingStructures.end()) { - ErrorHandler::reportInternalError(ErrorHandler::InternalErrorType::NonExistentHousekeeping); + if (hasNonExistingStructInternalError(structureId)) { return; } - HousekeepingStructure& housekeepingStructure = housekeepingStructures.at(structureId); + auto& housekeepingStructure = getStruct(structureId)->get(); Message housekeepingReport = createTM(MessageType::HousekeepingParametersReport); @@ -136,10 +126,10 @@ void HousekeepingService::generateOneShotHousekeepingReport(Message& request) { uint8_t numOfStructsToReport = request.readUint8(); for (uint8_t i = 0; i < numOfStructsToReport; i++) { uint8_t structureId = request.readUint8(); - if (housekeepingStructures.find(structureId) == housekeepingStructures.end()) { - ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure); + if (hasNonExistingStructExecutionError(structureId, request)) { continue; } + housekeepingParametersReport(structureId); } } @@ -148,21 +138,17 @@ void HousekeepingService::appendParametersToHousekeepingStructure(Message& reque request.assertTC(ServiceType, MessageType::AppendParametersToHousekeepingStructure); uint8_t targetStructId = request.readUint8(); - if (housekeepingStructures.find(targetStructId) == housekeepingStructures.end()) { - ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure); + if (hasNonExistingStructExecutionError(targetStructId, request)) { return; } - auto& housekeepingStructure = housekeepingStructures.at(targetStructId); - if (housekeepingStructure.periodicGenerationActionStatus) { - ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedAppendToEnabledHousekeeping); + auto& housekeepingStructure = getStruct(targetStructId)->get(); + if (hasRequestedAppendToEnabledHousekeepingError(housekeepingStructure, request)) { return; } uint16_t numOfSimplyCommutatedParameters = request.readUint16(); for (uint16_t i = 0; i < numOfSimplyCommutatedParameters; i++) { - if (housekeepingStructure.simplyCommutatedParameterIds.size() >= ECSSMaxSimplyCommutatedParameters) { - ErrorHandler::reportError( - request, ErrorHandler::ExecutionStartErrorType::ExceededMaxNumberOfSimplyCommutatedParameters); + if (hasExceededMaxNumOfSimplyCommutatedParamsError(housekeepingStructure, request)) { return; } uint16_t newParamId = request.readUint16(); @@ -170,8 +156,7 @@ void HousekeepingService::appendParametersToHousekeepingStructure(Message& reque ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::GetNonExistingParameter); continue; } - if (existsInVector(housekeepingStructure.simplyCommutatedParameterIds, newParamId)) { - ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::AlreadyExistingParameter); + if (hasAlreadyExistingParameterError(housekeepingStructure, newParamId, request)) { continue; } housekeepingStructure.simplyCommutatedParameterIds.push_back(newParamId); @@ -185,11 +170,10 @@ void HousekeepingService::modifyCollectionIntervalOfStructures(Message& request) for (uint8_t i = 0; i < numOfTargetStructs; i++) { uint8_t targetStructId = request.readUint8(); uint32_t newCollectionInterval = request.readUint32(); - if (housekeepingStructures.find(targetStructId) == housekeepingStructures.end()) { - ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure); + if (hasNonExistingStructExecutionError(targetStructId, request)) { continue; } - housekeepingStructures.at(targetStructId).collectionInterval = newCollectionInterval; + setCollectionInterval(targetStructId, newCollectionInterval); } } @@ -200,7 +184,7 @@ void HousekeepingService::reportHousekeepingPeriodicProperties(Message& request) uint8_t numOfStructIds = request.readUint8(); for (uint8_t i = 0; i < numOfStructIds; i++) { uint8_t structIdToReport = request.readUint8(); - if (housekeepingStructures.find(structIdToReport) != housekeepingStructures.end()) { + if (structExists(structIdToReport)) { numOfValidIds++; } } @@ -211,8 +195,7 @@ void HousekeepingService::reportHousekeepingPeriodicProperties(Message& request) for (uint8_t i = 0; i < numOfStructIds; i++) { uint8_t structIdToReport = request.readUint8(); - if (housekeepingStructures.find(structIdToReport) == housekeepingStructures.end()) { - ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure); + if (hasNonExistingStructExecutionError(structIdToReport, request)) { continue; } appendPeriodicPropertiesToMessage(periodicPropertiesReport, structIdToReport); @@ -222,8 +205,8 @@ void HousekeepingService::reportHousekeepingPeriodicProperties(Message& request) void HousekeepingService::appendPeriodicPropertiesToMessage(Message& report, uint8_t structureId) { report.appendUint8(structureId); - report.appendBoolean(housekeepingStructures.at(structureId).periodicGenerationActionStatus); - report.appendUint32(housekeepingStructures.at(structureId).collectionInterval); + report.appendBoolean(getPeriodicGenerationActionStatus(structureId)); + report.appendUint32(getCollectionInterval(structureId)); } void HousekeepingService::execute(Message& message) { @@ -290,3 +273,74 @@ HousekeepingService::reportPendingStructures(uint32_t currentTime, uint32_t prev return nextCollection; } + +bool HousekeepingService::hasNonExistingStructExecutionError(uint8_t id, Message& req) { + if (!structExists(id)) { + ErrorHandler::reportError(req, ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure); + return true; + } + return false; +} + +bool HousekeepingService::hasNonExistingStructError(uint8_t id, Message& req) { + if (!structExists(id)) { + ErrorHandler::reportError(req, ErrorHandler::RequestedNonExistingStructure); + return true; + } + return false; +} + +bool HousekeepingService::hasNonExistingStructInternalError(uint8_t id) { + if (!structExists(id)) { + ErrorHandler::reportInternalError(ErrorHandler::InternalErrorType::NonExistentHousekeeping); + return true; + } + return false; +} +bool HousekeepingService::hasAlreadyExistingParameterError(HousekeepingStructure& housekeepingStruct, uint8_t id, Message& req) { + if (existsInVector(housekeepingStruct.simplyCommutatedParameterIds, id)) { + ErrorHandler::reportError(req, ErrorHandler::ExecutionStartErrorType::AlreadyExistingParameter); + return true; + } + return false; +} + +bool HousekeepingService::hasAlreadyExistingStructError(uint8_t id, Message& req) { + if (structExists(id)) { + ErrorHandler::reportError(req, ErrorHandler::ExecutionStartErrorType::RequestedAlreadyExistingStructure); + return true; + } + return false; +} + +bool HousekeepingService::hasExceededMaxNumOfHousekeepingStructsError(Message& req) { + if (housekeepingStructures.size() >= ECSSMaxHousekeepingStructures) { + ErrorHandler::reportError(req, ErrorHandler::ExecutionStartErrorType::ExceededMaxNumberOfHousekeepingStructures); + return true; + } + return false; +} + +bool HousekeepingService::hasRequestedAppendToEnabledHousekeepingError(HousekeepingStructure& housekeepingStruct, Message& req) { + if (housekeepingStruct.periodicGenerationActionStatus) { + ErrorHandler::reportError(req, ErrorHandler::ExecutionStartErrorType::RequestedAppendToEnabledHousekeeping); + return true; + } + return false; +} + +bool HousekeepingService::hasRequestedDeletionOfEnabledHousekeepingError(uint8_t id, Message& req) { + if (getPeriodicGenerationActionStatus(id)) { + ErrorHandler::reportError(req, ErrorHandler::ExecutionStartErrorType::RequestedDeletionOfEnabledHousekeeping); + return true; + } + return false; +} + +bool HousekeepingService::hasExceededMaxNumOfSimplyCommutatedParamsError(HousekeepingStructure& housekeepingStruct, Message& req) { + if (housekeepingStruct.simplyCommutatedParameterIds.size() >= ECSSMaxSimplyCommutatedParameters) { + ErrorHandler::reportError(req, ErrorHandler::ExecutionStartErrorType::ExceededMaxNumberOfSimplyCommutatedParameters); + return true; + } + return false; +} \ No newline at end of file diff --git a/test/Services/HousekeepingServiceTests.cpp b/test/Services/HousekeepingServiceTests.cpp index b5882c848f785580074cb9c6491a31b3c571419b..05837dfba26b52137eef7ca58e69c3b5f9262efe 100644 --- a/test/Services/HousekeepingServiceTests.cpp +++ b/test/Services/HousekeepingServiceTests.cpp @@ -252,8 +252,7 @@ TEST_CASE("Delete housekeeping structure") { TEST_CASE("Enable the periodic generation of housekeeping structures") { SECTION("Both valid and invalid structure IDs in same request") { initializeHousekeepingStructures(); - Message request2(HousekeepingService::ServiceType, - HousekeepingService::MessageType::EnablePeriodicHousekeepingParametersReport, Message::TC, 1); + Message request2(HousekeepingService::ServiceType, HousekeepingService::MessageType::EnablePeriodicHousekeepingParametersReport, Message::TC, 1); uint8_t numOfStructs = 5; uint8_t idsToEnable[5] = {1, 3, 4, 6, 7}; request2.appendUint8(numOfStructs); @@ -693,4 +692,404 @@ TEST_CASE("Periodically reporting Housekeeping Structures") { nextCollection = housekeepingService.reportPendingStructures(currentTime, previousTime, nextCollection); CHECK(nextCollection == 0); } -} \ No newline at end of file +} + +TEST_CASE("Check getPeriodicGenerationActionStatus function") { + SECTION("Returns periodic generation status") { + initializeHousekeepingStructures(); + housekeepingService.housekeepingStructures.at(4).periodicGenerationActionStatus = true; + + CHECK(housekeepingService.getPeriodicGenerationActionStatus(0) == false); + CHECK(housekeepingService.getPeriodicGenerationActionStatus(4) == true); + + ServiceTests::reset(); + Services.reset(); + } + + SECTION("Invalid structure ID in request") { + initializeHousekeepingStructures(); + + housekeepingService.getPeriodicGenerationActionStatus(1); + + CHECK(ServiceTests::countThrownErrors(ErrorHandler::InternalErrorType::NonExistentHousekeeping) == 1); + + ServiceTests::reset(); + Services.reset(); + } +} + +TEST_CASE("Check getStruct function") { + SECTION("Returns periodic generation status") { + Message request(HousekeepingService::ServiceType, + HousekeepingService::MessageType::CreateHousekeepingReportStructure, Message::TC, 1); + uint8_t idToCreate = 2; + uint32_t interval = 7; + uint16_t numOfSimplyCommutatedParams = 3; + etl::array<uint16_t, 3> simplyCommutatedIds = {4, 5, 8}; + + request.appendUint8(idToCreate); + request.appendUint32(interval); + request.appendUint16(numOfSimplyCommutatedParams); + for (auto& id: simplyCommutatedIds) { + request.appendUint16(id); + } + + MessageParser::execute(request); + HousekeepingStructure newStruct = housekeepingService.housekeepingStructures[idToCreate]; + + CHECK(std::addressof(housekeepingService.housekeepingStructures.at(2)) == std::addressof(housekeepingService.getStruct(2)->get())); + + ServiceTests::reset(); + Services.reset(); + } + + SECTION("Invalid structure ID in request") { + initializeHousekeepingStructures(); + + housekeepingService.getStruct(1); + + CHECK(ServiceTests::countThrownErrors(ErrorHandler::InternalErrorType::NonExistentHousekeeping) == 1); + + ServiceTests::reset(); + Services.reset(); + } +} + +TEST_CASE("Check getCollectionInterval function") { + SECTION("Returns Collection Interval") { + initializeHousekeepingStructures(); + + CHECK(housekeepingService.getCollectionInterval(0) == 7); + + ServiceTests::reset(); + Services.reset(); + } + + SECTION("Invalid structure ID in request") { + initializeHousekeepingStructures(); + + housekeepingService.getCollectionInterval(1); + + CHECK(ServiceTests::countThrownErrors(ErrorHandler::InternalErrorType::NonExistentHousekeeping) == 1); + + ServiceTests::reset(); + Services.reset(); + } +} + +TEST_CASE("Check setPeriodicGenerationActionStatus function") { + SECTION("Set Periodic Generation Action Status") { + initializeHousekeepingStructures(); + + housekeepingService.setPeriodicGenerationActionStatus(0, true); + + CHECK(housekeepingService.housekeepingStructures.at(0).periodicGenerationActionStatus == true); + CHECK(housekeepingService.housekeepingStructures.at(4).periodicGenerationActionStatus == false); + + ServiceTests::reset(); + Services.reset(); + } + + SECTION("Invalid structure ID in request") { + initializeHousekeepingStructures(); + + housekeepingService.setPeriodicGenerationActionStatus(1, true); + + CHECK(ServiceTests::countThrownErrors(ErrorHandler::InternalErrorType::NonExistentHousekeeping) == 1); + + ServiceTests::reset(); + Services.reset(); + } +} + +TEST_CASE("Check setCollectionInterval function") { + SECTION("Sets Collection Interval") { + initializeHousekeepingStructures(); + + housekeepingService.setCollectionInterval(0, 8); + + CHECK(housekeepingService.housekeepingStructures.at(0).collectionInterval == 8); + + ServiceTests::reset(); + Services.reset(); + } + + SECTION("Invalid structure ID in request") { + initializeHousekeepingStructures(); + + housekeepingService.setCollectionInterval(1, 8); + + CHECK(ServiceTests::countThrownErrors(ErrorHandler::InternalErrorType::NonExistentHousekeeping) == 1); + + ServiceTests::reset(); + Services.reset(); + } +} + +TEST_CASE("Check structExists function") { + SECTION("Check if it returns correct boolean") { + initializeHousekeepingStructures(); + + CHECK(housekeepingService.structExists(0) == true); + CHECK(housekeepingService.structExists(1) == false); + + ServiceTests::reset(); + Services.reset(); + } +} + +TEST_CASE("Check hasNonExistingStructExecutionError function") { + SECTION("Check if it returns correct boolean") { + Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::CreateHousekeepingReportStructure, Message::TC, 1); + initializeHousekeepingStructures(); + + CHECK(housekeepingService.hasNonExistingStructExecutionError(0, request) == false); + CHECK(housekeepingService.hasNonExistingStructExecutionError(1, request) == true); + CHECK(ServiceTests::count() == 1); + CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::RequestedNonExistingStructure) == 1); + + ServiceTests::reset(); + Services.reset(); + } +} + +TEST_CASE("Check hasNonExistingStructError function") { + SECTION("Check if it returns correct boolean") { + Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::CreateHousekeepingReportStructure, Message::TC, 1); + initializeHousekeepingStructures(); + + CHECK(housekeepingService.hasNonExistingStructError(0, request) == false); + CHECK(housekeepingService.hasNonExistingStructError(1, request) == true); + CHECK(ServiceTests::count() == 1); + CHECK(ServiceTests::countThrownErrors(ErrorHandler::RequestedNonExistingStructure) == 1); + + ServiceTests::reset(); + Services.reset(); + } +} + +TEST_CASE("Check hasNonExistingStructInternalError function") { + SECTION("Check if it returns correct boolean") { + initializeHousekeepingStructures(); + + CHECK(housekeepingService.hasNonExistingStructInternalError(0) == false); + CHECK(housekeepingService.hasNonExistingStructInternalError(1) == true); + CHECK(ServiceTests::countThrownErrors(ErrorHandler::InternalErrorType::NonExistentHousekeeping) == 1); + + ServiceTests::reset(); + Services.reset(); + } +} + +TEST_CASE("Check hasAlreadyExistingParameterError function") { + SECTION("Check if it returns correct boolean") { + Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::CreateHousekeepingReportStructure, Message::TC, 1); + uint8_t idToCreate = 2; + uint32_t interval = 7; + uint16_t numOfSimplyCommutatedParams = 3; + etl::array<uint16_t, 3> simplyCommutatedIds = {4, 5, 8}; + + request.appendUint8(idToCreate); + request.appendUint32(interval); + request.appendUint16(numOfSimplyCommutatedParams); + for (auto& id: simplyCommutatedIds) { + request.appendUint16(id); + } + + MessageParser::execute(request); + HousekeepingStructure newStruct = housekeepingService.housekeepingStructures[idToCreate]; + + auto& housekeepingStructure = housekeepingService.getStruct(idToCreate)->get(); + + CHECK(housekeepingService.hasAlreadyExistingParameterError(housekeepingStructure, 6, request) == false); + CHECK(housekeepingService.hasAlreadyExistingParameterError(housekeepingStructure, 5, request) == true); + CHECK(ServiceTests::count() == 1); + CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::AlreadyExistingParameter) == 1); + + ServiceTests::reset(); + Services.reset(); + } +} + +TEST_CASE("Check hasAlreadyExistingStructError function") { + SECTION("Check if it returns correct boolean") { + Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::CreateHousekeepingReportStructure, Message::TC, 1); + initializeHousekeepingStructures(); + + CHECK(housekeepingService.hasAlreadyExistingStructError(1, request) == false); + CHECK(housekeepingService.hasAlreadyExistingStructError(0, request) == true); + CHECK(ServiceTests::count() == 1); + CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::RequestedAlreadyExistingStructure) == 1); + + ServiceTests::reset(); + Services.reset(); + } +} + +TEST_CASE("Check hasExceededMaxNumOfHousekeepingStructsError function") { + SECTION("Check if it returns correct boolean") { + Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::CreateHousekeepingReportStructure, Message::TC, 1); + uint8_t idsToCreate[11] = {1, 3, 5, 7, 8, 9, 10, 11, 12, 13, 14}; + uint16_t numOfSimplyCommutatedParams = 3; + etl::vector<uint16_t, 3> simplyCommutatedIds = {8, 4, 5}; + uint32_t interval = 12; + + REQUIRE(housekeepingService.housekeepingStructures.size() == 0); + + for (auto& structId: idsToCreate) { + request.appendUint8(structId); + request.appendUint32(interval); + request.appendUint16(numOfSimplyCommutatedParams); + for (auto& parameterId: simplyCommutatedIds) { + request.appendUint16(parameterId); + } + MessageParser::execute(request); + + if (housekeepingService.housekeepingStructures.size() < 9) { + CHECK(housekeepingService.hasExceededMaxNumOfHousekeepingStructsError(request) == false); + } + } + + REQUIRE(housekeepingService.housekeepingStructures.size() == 10); + + CHECK(housekeepingService.hasExceededMaxNumOfHousekeepingStructsError(request) == true); + CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::ExceededMaxNumberOfHousekeepingStructures) == 2); + + ServiceTests::reset(); + Services.reset(); + } +} + +TEST_CASE("Check hasRequestedAppendToEnabledHousekeepingError function") { + SECTION("Error exists") { + Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::EnablePeriodicHousekeepingParametersReport, Message::TC, 1); + // Enable 1 periodic struct with id=0 + HousekeepingStructure newStruct; + newStruct.structureId = 0; + newStruct.periodicGenerationActionStatus = true; + housekeepingService.housekeepingStructures.insert({0, newStruct}); + + request.appendUint8(1); + request.appendUint8(0); + MessageParser::execute(request); + + REQUIRE(housekeepingService.housekeepingStructures.at(0).periodicGenerationActionStatus); + Message request2(HousekeepingService::ServiceType, HousekeepingService::MessageType::AppendParametersToHousekeepingStructure, Message::TC, 1); + uint8_t structId = 0; + request2.appendUint8(structId); + MessageParser::execute(request2); + + CHECK(housekeepingService.hasRequestedAppendToEnabledHousekeepingError(newStruct, request) == true); + CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::RequestedAppendToEnabledHousekeeping) == 2); + + ServiceTests::reset(); + Services.reset(); + } + + SECTION("Error doesn't exist") { + Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::EnablePeriodicHousekeepingParametersReport, Message::TC, 1); + // Enable 1 periodic struct with id=0 + HousekeepingStructure newStruct; + newStruct.structureId = 0; + newStruct.periodicGenerationActionStatus = false; + housekeepingService.housekeepingStructures.insert({0, newStruct}); + + request.appendUint8(1); + request.appendUint8(0); + MessageParser::execute(request); + + REQUIRE(housekeepingService.housekeepingStructures.at(0).periodicGenerationActionStatus); + Message request2(HousekeepingService::ServiceType, HousekeepingService::MessageType::AppendParametersToHousekeepingStructure, Message::TC, 1); + uint8_t structId = 0; + request2.appendUint8(structId); + MessageParser::execute(request2); + + + CHECK(housekeepingService.hasRequestedAppendToEnabledHousekeepingError(newStruct, request) == false); + + ServiceTests::reset(); + Services.reset(); + } +} + +TEST_CASE("Check hasRequestedDeletionOfEnabledHousekeepingError function") { + SECTION("Error exists") { + Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::DeleteHousekeepingReportStructure, Message::TC, 1); + HousekeepingStructure periodicStruct; + periodicStruct.structureId = 4; + periodicStruct.periodicGenerationActionStatus = true; + housekeepingService.housekeepingStructures.insert({4, periodicStruct}); + + uint8_t numOfStructs = 1; + uint8_t structureId = 4; + request.appendUint8(numOfStructs); + request.appendUint8(structureId); + + MessageParser::execute(request); + + + CHECK(housekeepingService.hasRequestedDeletionOfEnabledHousekeepingError(4, request) == true); + CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::RequestedDeletionOfEnabledHousekeeping) == 2); + + ServiceTests::reset(); + Services.reset(); + } + SECTION("Error doesn't exists") { + Message request(HousekeepingService::ServiceType, HousekeepingService::MessageType::DeleteHousekeepingReportStructure, Message::TC, 1); + HousekeepingStructure periodicStruct; + periodicStruct.structureId = 4; + periodicStruct.periodicGenerationActionStatus = false; + housekeepingService.housekeepingStructures.insert({4, periodicStruct}); + + uint8_t numOfStructs = 1; + uint8_t structureId = 4; + request.appendUint8(numOfStructs); + request.appendUint8(structureId); + + MessageParser::execute(request); + + + CHECK(housekeepingService.hasRequestedDeletionOfEnabledHousekeepingError(4, request) == false); + + ServiceTests::reset(); + Services.reset(); + } +} + +TEST_CASE("Check hasExceededMaxNumOfSimplyCommutatedParamsError function") { + SECTION("Check if it returns correct boolean") { + initializeHousekeepingStructures(); + uint8_t structId = 6; + Message request(HousekeepingService::ServiceType, + HousekeepingService::MessageType::AppendParametersToHousekeepingStructure, Message::TC, 1); + + uint16_t numOfSimplyCommutatedParams = 34; + + etl::vector<uint16_t, 34> simplyCommutatedIds; + for (uint16_t i = 0; i < 34; i++) { + simplyCommutatedIds.push_back(i); + } + + request.appendUint8(structId); + request.appendUint16(numOfSimplyCommutatedParams); + for (auto& id: simplyCommutatedIds) { + request.appendUint16(id); + + if (housekeepingService.housekeepingStructures[structId].simplyCommutatedParameterIds.size() < 30) { + CHECK(housekeepingService.hasExceededMaxNumOfSimplyCommutatedParamsError(housekeepingService.housekeepingStructures[structId], request) == false); + } + } + REQUIRE(housekeepingService.housekeepingStructures.find(structId) != housekeepingService.housekeepingStructures.end()); + REQUIRE(housekeepingService.housekeepingStructures[structId].simplyCommutatedParameterIds.size() == 3); + + MessageParser::execute(request); + + REQUIRE(housekeepingService.housekeepingStructures[structId].simplyCommutatedParameterIds.size() == 30); + + CHECK(housekeepingService.hasExceededMaxNumOfSimplyCommutatedParamsError(housekeepingService.housekeepingStructures[structId], request) == true); + CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::ExceededMaxNumberOfSimplyCommutatedParameters) == 2); + + ServiceTests::reset(); + Services.reset(); + } +}