diff --git a/inc/Helpers/ForwardControlConfiguration.hpp b/inc/Helpers/ForwardControlConfiguration.hpp index aad43f1899734447bfd13f73fdbfbb5ad0426066..9e3072a8df4928359e4e10647445c0e69ce81c5d 100644 --- a/inc/Helpers/ForwardControlConfiguration.hpp +++ b/inc/Helpers/ForwardControlConfiguration.hpp @@ -26,13 +26,15 @@ public: * Empty report type vector, can both mean that we haven't added report types yet, and added all report types. To * be able to distinguish what the current 'empty' state means, we need this indicator. */ - bool notEmptyReports = false; + typedef etl::map<uint8_t, bool, ECSSMaxServiceTypeDefinitions> reportsAreNotEmpty; /** * Empty service type vector, can both mean that we haven't added service types yet, and added all service types. To * be able to distinguish what the current 'empty' state means, we need this indicator. */ - bool notEmptyServices = false; + etl::map<uint8_t, reportsAreNotEmpty, ECSSMaxControlledApplications> serviceNotEmpty; + +// etl::map<uint8_t, bool, ECSSMaxControlledApplications> serviceOfAppNotEmpty; /** * Vector containing the Report Type definitions. Each definition has its unique name of type uint8. For @@ -52,7 +54,6 @@ public: * key to provide access to the list of Service Type definitions, included by the application. */ etl::map<uint8_t, serviceTypeDefinitions, ECSSMaxControlledApplications> definitions; - ApplicationProcess() = default; }; diff --git a/inc/Services/RealTimeForwardingControlService.hpp b/inc/Services/RealTimeForwardingControlService.hpp index 04a3305cbc77047ebd3317a154d538ab631c16ae..9be63b972804b7b6ce3d5050d14d874d440e1cdd 100644 --- a/inc/Services/RealTimeForwardingControlService.hpp +++ b/inc/Services/RealTimeForwardingControlService.hpp @@ -38,7 +38,6 @@ public: RealTimeForwardingControlService() = default; -private: /** * Contains the Application IDs, controlled by the Service. */ @@ -61,6 +60,13 @@ private: */ ForwardControlConfiguration::EventReportBlocking eventReportBlockingConfiguration; +private: + /** + * Checks whether the specified message type already exists in the specified application process and service + * type definition. + */ + inline bool reportExistsInAppProcessConfiguration(uint8_t target, uint8_t applicationID, uint8_t serviceType); + /** * Performs the necessary error checking/logging for a specific application process ID. Also, skips the necessary * bytes from the request message, in case of an invalid request. diff --git a/src/Services/RealTimeForwardingControlService.cpp b/src/Services/RealTimeForwardingControlService.cpp index ed38a6c8f99d5cf3574c8178fc78605b735d0dfd..62e24a32c0b645b30f1772b8da98ee52036d3acf 100644 --- a/src/Services/RealTimeForwardingControlService.cpp +++ b/src/Services/RealTimeForwardingControlService.cpp @@ -1,3 +1,4 @@ +#include <iostream> #include "Services/RealTimeForwardingControlService.hpp" bool RealTimeForwardingControlService::appIsControlled(Message& request, uint8_t applicationId) { @@ -25,7 +26,7 @@ bool RealTimeForwardingControlService::checkApplication1(Message& request, uint8 bool RealTimeForwardingControlService::allServiceTypesAllowed(Message& request, uint8_t applicationID) { if (applicationProcessConfiguration.definitions[applicationID].empty() and - applicationProcessConfiguration.notEmptyServices) { + not applicationProcessConfiguration.serviceNotEmpty[applicationID].empty()) { ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::AdditionOfAllServiceTypesAlreadyEnabled); return true; @@ -54,7 +55,7 @@ bool RealTimeForwardingControlService::checkService1(Message& request, uint8_t a bool RealTimeForwardingControlService::allReportTypesAllowed(Message& request, uint8_t applicationID, uint8_t serviceType) { if (applicationProcessConfiguration.definitions[applicationID][serviceType].empty() and - applicationProcessConfiguration.notEmptyReports) { + applicationProcessConfiguration.serviceNotEmpty[applicationID][serviceType]) { ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::AdditionOfAllReportTypesAlreadyEnabled); return true; @@ -72,9 +73,16 @@ bool RealTimeForwardingControlService::maxReportTypesReached(Message& request, u return false; } +bool RealTimeForwardingControlService::reportExistsInAppProcessConfiguration(uint8_t target, uint8_t applicationID, + uint8_t serviceType) { + return std::find(applicationProcessConfiguration.definitions[applicationID][serviceType].begin(), + applicationProcessConfiguration.definitions[applicationID][serviceType].end(), + target) != applicationProcessConfiguration.definitions[applicationID][serviceType].end(); +} + void RealTimeForwardingControlService::addReportTypesToAppProcessConfiguration(Message& request) { request.assertTC(ServiceType, MessageType::AddReportTypesToAppProcessConfiguration); - uint8_t numOfApplications = request.readUint16(); + uint8_t numOfApplications = request.readUint8(); for (uint8_t i = 0; i < numOfApplications; i++) { uint8_t applicationID = request.readUint8(); @@ -106,6 +114,11 @@ void RealTimeForwardingControlService::addReportTypesToAppProcessConfiguration(M for (uint8_t k = 0; k < numOfMessages; k++) { uint8_t messageType = request.readUint8(); // todo: check if message type is valid. + if (reportExistsInAppProcessConfiguration(messageType, applicationID, serviceType)) { + continue; + } + applicationProcessConfiguration.definitions[applicationID][serviceType].push_back(messageType); + applicationProcessConfiguration.serviceNotEmpty[applicationID][serviceType] = true; } } } @@ -116,29 +129,29 @@ void RealTimeForwardingControlService::execute(Message& message) { case AddReportTypesToAppProcessConfiguration: addReportTypesToAppProcessConfiguration(message); break; -// case DeleteReportTypesFromAppProcessConfiguration: -// deleteReportTypesFromAppProcessConfiguration(message); -// break; -// case ReportAppProcessConfigurationContent: -// reportAppProcessConfigurationContent(message); -// break; -// case AddStructuresToHousekeepingConfiguration: -// addStructuresToHousekeepingConfiguration(message); -// break; -// case DeleteStructuresFromHousekeepingConfiguration: -// deleteStructuresFromHousekeepingConfiguration(message); -// break; -// case ReportHousekeepingConfigurationContent: -// reportHousekeepingConfigurationContent(message); -// break; -// case AddEventDefinitionsToEventReportConfiguration: -// addEventDefinitionsToEventReportConfiguration(message); -// break; -// case DeleteEventDefinitionsFromEventReportConfiguration: -// deleteEventDefinitionsFromEventReportConfiguration(message); -// break; -// case ReportEventReportConfigurationContent: -// reportEventReportConfigurationContent(message); -// break; + // case DeleteReportTypesFromAppProcessConfiguration: + // deleteReportTypesFromAppProcessConfiguration(message); + // break; + // case ReportAppProcessConfigurationContent: + // reportAppProcessConfigurationContent(message); + // break; + // case AddStructuresToHousekeepingConfiguration: + // addStructuresToHousekeepingConfiguration(message); + // break; + // case DeleteStructuresFromHousekeepingConfiguration: + // deleteStructuresFromHousekeepingConfiguration(message); + // break; + // case ReportHousekeepingConfigurationContent: + // reportHousekeepingConfigurationContent(message); + // break; + // case AddEventDefinitionsToEventReportConfiguration: + // addEventDefinitionsToEventReportConfiguration(message); + // break; + // case DeleteEventDefinitionsFromEventReportConfiguration: + // deleteEventDefinitionsFromEventReportConfiguration(message); + // break; + // case ReportEventReportConfigurationContent: + // reportEventReportConfigurationContent(message); + // break; } } diff --git a/test/Services/HousekeepingService.cpp b/test/Services/HousekeepingService.cpp index c26ce5119b41c816591a90c389b4a8608d2e8134..37848827d3ff4f71b3eb5994f5fc72692a30bd7c 100644 --- a/test/Services/HousekeepingService.cpp +++ b/test/Services/HousekeepingService.cpp @@ -1,8 +1,8 @@ +#include "Services/HousekeepingService.hpp" #include <iostream> -#include "catch2/catch.hpp" #include "Message.hpp" #include "ServiceTests.hpp" -#include "Services/HousekeepingService.hpp" +#include "catch2/catch.hpp" #include "etl/algorithm.h" HousekeepingService& housekeepingService = Services.housekeeping; @@ -18,7 +18,7 @@ void buildRequest(Message& request, uint8_t idToCreate) { request.appendUint8(idToCreate); request.appendUint32(interval); request.appendUint16(numOfSimplyCommutatedParams); - for (auto& id : simplyCommutatedIds) { + for (auto& id: simplyCommutatedIds) { request.appendUint16(id); } } @@ -33,11 +33,11 @@ void initializeHousekeepingStructures() { HousekeepingStructure structures[3]; int i = 0; - for (auto& newStructure : structures) { + for (auto& newStructure: structures) { newStructure.structureId = ids[i]; newStructure.collectionInterval = interval; newStructure.periodicGenerationActionStatus = false; - for (uint16_t parameterId : simplyCommutatedIds) { + for (uint16_t parameterId: simplyCommutatedIds) { newStructure.simplyCommutatedParameterIds.push_back(parameterId); } housekeepingService.housekeepingStructures.insert({ids[i], newStructure}); @@ -54,9 +54,6 @@ void initializeHousekeepingStructures() { * Helper function that stores samples into simply commutated parameters of different data type each. */ void storeSamplesToParameters(uint16_t id1, uint16_t id2, uint16_t id3) { - Message samples(HousekeepingService::ServiceType, - HousekeepingService::MessageType::ReportHousekeepingPeriodicProperties, Message::TM, 1); - static_cast<Parameter<uint16_t>&>(Services.parameterManagement.getParameter(id1)->get()).setValue(33); static_cast<Parameter<uint8_t>&>(Services.parameterManagement.getParameter(id2)->get()).setValue(77); static_cast<Parameter<uint32_t>&>(Services.parameterManagement.getParameter(id3)->get()).setValue(99); @@ -71,7 +68,7 @@ void appendNewParameters(Message& request, uint8_t idToAppend) { request.appendUint8(idToAppend); request.appendUint16(numOfSimplyCommutatedParams); - for (auto& id : simplyCommutatedIds) { + for (auto& id: simplyCommutatedIds) { request.appendUint16(id); } } @@ -88,7 +85,7 @@ TEST_CASE("Create housekeeping structure") { request.appendUint8(idToCreate); request.appendUint32(interval); request.appendUint16(numOfSimplyCommutatedParams); - for (auto& id : simplyCommutatedIds) { + for (auto& id: simplyCommutatedIds) { request.appendUint16(id); } @@ -140,11 +137,11 @@ TEST_CASE("Create housekeeping structure") { REQUIRE(housekeepingService.housekeepingStructures.size() == 0); - for (auto& structId : idsToCreate) { + for (auto& structId: idsToCreate) { request.appendUint8(structId); request.appendUint32(interval); request.appendUint16(numOfSimplyCommutatedParams); - for (auto& parameterId : simplyCommutatedIds) { + for (auto& parameterId: simplyCommutatedIds) { request.appendUint16(parameterId); } MessageParser::execute(request); @@ -170,7 +167,7 @@ TEST_CASE("Create housekeeping structure") { request.appendUint8(idToCreate); request.appendUint32(interval); request.appendUint16(numOfSimplyCommutatedParams); - for (auto& id : simplyCommutatedIds) { + for (auto& id: simplyCommutatedIds) { request.appendUint16(id); } @@ -182,7 +179,7 @@ TEST_CASE("Create housekeeping structure") { REQUIRE(newStruct.simplyCommutatedParameterIds.size() == 4); uint16_t existingParameterIds[4] = {8, 4, 5, 11}; - for (auto parameterId : newStruct.simplyCommutatedParameterIds) { + for (auto parameterId: newStruct.simplyCommutatedParameterIds) { CHECK(std::find(std::begin(existingParameterIds), std::end(existingParameterIds), parameterId) != std::end(existingParameterIds)); } @@ -208,7 +205,7 @@ TEST_CASE("Delete housekeeping structure") { uint8_t numOfStructs = 5; uint8_t ids[5] = {2, 3, 4, 7, 8}; request.appendUint8(numOfStructs); - for (auto& id : ids) { + for (auto& id: ids) { request.appendUint8(id); } @@ -254,7 +251,7 @@ TEST_CASE("Enable the periodic generation of housekeeping structures") { uint8_t numOfStructs = 5; uint8_t idsToEnable[5] = {1, 3, 4, 6, 7}; request2.appendUint8(numOfStructs); - for (auto& id : idsToEnable) { + for (auto& id: idsToEnable) { request2.appendUint8(id); } REQUIRE(not housekeepingService.housekeepingStructures[0].periodicGenerationActionStatus); @@ -282,7 +279,7 @@ TEST_CASE("Disable the periodic generation of housekeeping structures") { uint8_t numOfStructs = 4; uint8_t idsToDisable[4] = {0, 1, 4, 6}; request2.appendUint8(numOfStructs); - for (auto& id : idsToDisable) { + for (auto& id: idsToDisable) { request2.appendUint8(id); } housekeepingService.housekeepingStructures[0].periodicGenerationActionStatus = true; @@ -311,7 +308,7 @@ TEST_CASE("Reporting of housekeeping structures") { uint8_t numOfStructs = 3; uint8_t idsToReport[3] = {9, 4, 2}; request2.appendUint8(numOfStructs); - for (auto& id : idsToReport) { + for (auto& id: idsToReport) { request2.appendUint8(id); } MessageParser::execute(request2); @@ -425,7 +422,7 @@ TEST_CASE("One-shot housekeeping parameter report generation") { uint8_t numOfStructs = 5; uint8_t structIds[5] = {0, 4, 7, 8, 11}; request2.appendUint8(numOfStructs); - for (auto& id : structIds) { + for (auto& id: structIds) { request2.appendUint8(id); } MessageParser::execute(request2); @@ -514,7 +511,7 @@ TEST_CASE("Append parameters in housekeeping report structure") { uint16_t currentlyExistingParameters[] = {8, 4, 5, 9, 10, 11}; HousekeepingStructure structToCheck = housekeepingService.housekeepingStructures[structId]; REQUIRE(structToCheck.simplyCommutatedParameterIds.size() == 6); - for (auto& existingParameter : currentlyExistingParameters) { + for (auto& existingParameter: currentlyExistingParameters) { CHECK(std::find(std::begin(structToCheck.simplyCommutatedParameterIds), std::end(structToCheck.simplyCommutatedParameterIds), existingParameter) != std::end(structToCheck.simplyCommutatedParameterIds)); @@ -534,7 +531,7 @@ TEST_CASE("Append parameters in housekeeping report structure") { request.appendUint8(structId); request.appendUint16(numOfSimplyCommutatedParams); - for (auto& id : simplyCommutatedIds) { + for (auto& id: simplyCommutatedIds) { request.appendUint16(id); } REQUIRE(housekeepingService.housekeepingStructures.find(structId) != @@ -564,7 +561,7 @@ TEST_CASE("Modification of housekeeping structures' interval") { uint32_t intervals[4] = {12, 21, 32, 17}; request.appendUint8(numOfStructs); int i = 0; - for (auto& id : structIds) { + for (auto& id: structIds) { request.appendUint8(id); request.appendUint32(intervals[i++]); } @@ -589,7 +586,7 @@ TEST_CASE("Reporting of housekeeping structure periodic properties") { uint8_t numOfStructs = 6; uint8_t structIds[6] = {0, 4, 1, 6, 9, 10}; request.appendUint8(numOfStructs); - for (auto& id : structIds) { + for (auto& id: structIds) { request.appendUint8(id); } housekeepingService.housekeepingStructures[0].periodicGenerationActionStatus = true; @@ -603,16 +600,16 @@ TEST_CASE("Reporting of housekeeping structure periodic properties") { 3); Message report = ServiceTests::get(3); - CHECK(report.readUint8() == 3); // Number of valid ids - CHECK(report.readUint8() == 0); // Id - CHECK(report.readBoolean() == true); // Periodic status - CHECK(report.readUint32() == 7); // Interval - CHECK(report.readUint8() == 4); // Id + CHECK(report.readUint8() == 3); // Number of valid ids + CHECK(report.readUint8() == 0); // Id + CHECK(report.readBoolean() == true); // Periodic status + CHECK(report.readUint32() == 7); // Interval + CHECK(report.readUint8() == 4); // Id CHECK(report.readBoolean() == false); // Periodic status - CHECK(report.readUint32() == 24); // Interval - CHECK(report.readUint8() == 6); // Id + CHECK(report.readUint32() == 24); // Interval + CHECK(report.readUint8() == 6); // Id CHECK(report.readBoolean() == false); // Periodic status - CHECK(report.readUint32() == 13); // Interval + CHECK(report.readUint32() == 13); // Interval ServiceTests::reset(); Services.reset(); diff --git a/test/Services/RealTimeForwardingControl.cpp b/test/Services/RealTimeForwardingControl.cpp index 14039ab4c18d95e6f0885ea7c758fd8eba934feb..75dd95e645bda50274e5ed4dc0dcc27763684d44 100644 --- a/test/Services/RealTimeForwardingControl.cpp +++ b/test/Services/RealTimeForwardingControl.cpp @@ -4,3 +4,94 @@ #include "ServiceTests.hpp" #include "ECSS_Definitions.hpp" #include "Services/RealTimeForwardingControlService.hpp" + +uint8_t applications[] = {1}; +uint8_t services[] = {3, 5}; +uint8_t messages1[] = {HousekeepingService::MessageType::HousekeepingPeriodicPropertiesReport, + HousekeepingService::MessageType::DisablePeriodicHousekeepingParametersReport}; + +uint8_t messages2[] = {EventReportService::MessageType::InformativeEventReport, + EventReportService::MessageType::DisabledListEventReport}; + +RealTimeForwardingControlService& realTimeForwarding = Services.realTimeForwarding; + +void initialize(Message& request) { + uint8_t numOfApplications = 1; + uint8_t numOfServicesPerApp = 2; + uint8_t numOfMessagesPerService = 2; + + request.appendUint8(numOfApplications); + + for (auto appID : applications) { + request.appendUint8(appID); + request.appendUint8(numOfServicesPerApp); + + for (uint8_t j = 0; j < numOfServicesPerApp; j++) { + uint8_t serviceType = services[j]; + request.appendUint8(serviceType); + request.appendUint8(numOfMessagesPerService); + uint8_t* messages = (j == 0) ? messages1 : messages2; + + for (uint8_t k = 0; k < numOfMessagesPerService; k++) { + request.appendUint8(messages[k]); + } + } + } + + REQUIRE(request.readUint8() == 1); + REQUIRE(request.readUint8() == 1); + REQUIRE(request.readUint8() == 2); + REQUIRE(request.readUint8() == 3); + REQUIRE(request.readUint8() == 2); + REQUIRE(request.readUint8() == HousekeepingService::MessageType::HousekeepingPeriodicPropertiesReport); + REQUIRE(request.readUint8() == HousekeepingService::MessageType::DisablePeriodicHousekeepingParametersReport); + REQUIRE(request.readUint8() == 5); + REQUIRE(request.readUint8() == 2); + REQUIRE(request.readUint8() == EventReportService::MessageType::InformativeEventReport); + REQUIRE(request.readUint8() == EventReportService::MessageType::DisabledListEventReport); + request.resetRead(); +} + +void resetAppProcessConfiguration() { + realTimeForwarding.applicationProcessConfiguration.definitions.clear(); + REQUIRE(realTimeForwarding.applicationProcessConfiguration.definitions.empty()); +} + +TEST_CASE("Add report types to the application process configuration") { + SECTION("Successful addition of report types to the application process configuration") { + Message request(RealTimeForwardingControlService::ServiceType, + RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration, + Message::TC, 1); + + uint8_t applicationID = 1; + realTimeForwarding.controlledApplications.push_back(applicationID); + initialize(request); + + MessageParser::execute(request); + + CHECK(ServiceTests::count() == 0); + auto& applicationProcesses = realTimeForwarding.applicationProcessConfiguration.definitions; + REQUIRE(applicationProcesses.size() == 1); + + for (auto appID : applications) { + REQUIRE(applicationProcesses.find(appID) != applicationProcesses.end()); + REQUIRE(applicationProcesses[appID].size() == 2); + + for (uint8_t j = 0; j < 2; j++) { + uint8_t serviceType = services[j]; + REQUIRE(applicationProcesses[appID].find(serviceType) != applicationProcesses[appID].end()); + REQUIRE(applicationProcesses[appID][serviceType].size() == 2); + uint8_t* messages = (j == 0) ? messages1 : messages2; + + for (uint8_t k = 0; k < 2; k++) { + REQUIRE(std::find(applicationProcesses[appID][serviceType].begin(), + applicationProcesses[appID][serviceType].end(), + messages[k]) != applicationProcesses[appID][serviceType].end()); + } + } + } + resetAppProcessConfiguration(); + ServiceTests::reset(); + Services.reset(); + } +}