diff --git a/inc/Services/RealTimeForwardingControlService.hpp b/inc/Services/RealTimeForwardingControlService.hpp index 2e231b7f92dd6316fb4f2e6aabe2cff831bf10bd..077a37833781c9c796018fe4506d73922e51ed99 100644 --- a/inc/Services/RealTimeForwardingControlService.hpp +++ b/inc/Services/RealTimeForwardingControlService.hpp @@ -112,6 +112,34 @@ private: */ bool checkMessage(Message& request, uint8_t applicationID, uint8_t serviceType, uint8_t messageType); + /** + * Checks whether the requested application is present in the application process configuration. + */ + bool applicationExists(Message& request, uint8_t applicationID, uint8_t numOfServices); + + /** + * Checks whether the requested service type is present in the application process configuration. + */ + bool serviceTypeExists(Message& request, uint8_t applicationID, uint8_t serviceType, uint8_t numOfMessages); + + /** + * Checks whether the requested report type is present in the application process configuration. + */ + bool reportTypeExists(Message& request, uint8_t applicationID, uint8_t serviceType, uint8_t messageType); + + /** + * Deletes the requested service type from the application process configuration. If the deletion results in an + * empty application process, it deletes the corresponding application process definition as well. + */ + void deleteServiceRecursive(uint8_t applicationID, uint8_t serviceType); + + /** + * Deletes the requested report type from the application process configuration. If the deletion results in an + * empty service, it deletes the corresponding service. If the deletion of the service, results in an empty + * application process, it deletes the corresponding application process definition as well. + */ + void deleteReportRecursive(uint8_t applicationID, uint8_t serviceType, uint8_t messageType); + public: /** * TC[14,1] 'Add report types to the application process forward control configuration'. diff --git a/src/Services/RealTimeForwardingControlService.cpp b/src/Services/RealTimeForwardingControlService.cpp index b96bd18b97ce69e045c0a5fba0c624fe33262b98..892fcc4f5aa3b942540279d0e1d846b0dc8dda76 100644 --- a/src/Services/RealTimeForwardingControlService.cpp +++ b/src/Services/RealTimeForwardingControlService.cpp @@ -84,6 +84,61 @@ bool RealTimeForwardingControlService::reportExistsInAppProcessConfiguration(uin return std::find(serviceTypes.begin(), serviceTypes.end(), target) != serviceTypes.end(); } +bool RealTimeForwardingControlService::applicationExists(Message& request, uint8_t applicationID, + uint8_t numOfServices) { + if (applicationProcessConfiguration.definitions.find(applicationID) == + applicationProcessConfiguration.definitions.end()) { + ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::NonExistingApplication); + for (uint8_t z = 0; z < numOfServices; z++) { + request.skipBytes(1); + uint8_t numOfMessages = request.readUint8(); + request.skipBytes(numOfMessages); + } + return false; + } + return true; +} + +bool RealTimeForwardingControlService::serviceTypeExists(Message& request, uint8_t applicationID, uint8_t serviceType, + uint8_t numOfMessages) { + if (applicationProcessConfiguration.definitions[applicationID].find(serviceType) == + applicationProcessConfiguration.definitions[applicationID].end()) { + ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::NonExistingServiceTypeDefinition); + request.skipBytes(numOfMessages); + return false; + } + return true; +} + +bool RealTimeForwardingControlService::reportTypeExists(Message& request, uint8_t applicationID, uint8_t serviceType, + uint8_t messageType) { + if (not reportExistsInAppProcessConfiguration(messageType, applicationID, serviceType)) { + ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::NonExistingReportTypeDefinition); + return false; + } + return true; +} + +void RealTimeForwardingControlService::deleteServiceRecursive(uint8_t applicationID, uint8_t serviceType) { + applicationProcessConfiguration.definitions[applicationID].erase(serviceType); + applicationProcessConfiguration.notEmpty[applicationID].erase(serviceType); + + if (applicationProcessConfiguration.definitions[applicationID].empty()) { + applicationProcessConfiguration.definitions.erase(applicationID); + applicationProcessConfiguration.notEmpty.erase(applicationID); + } +} + +void RealTimeForwardingControlService::deleteReportRecursive(uint8_t applicationID, uint8_t serviceType, + uint8_t messageType) { + auto& reportTypes = applicationProcessConfiguration.definitions[applicationID][serviceType]; + reportTypes.erase(std::remove(reportTypes.begin(), reportTypes.end(), messageType)); + + if (applicationProcessConfiguration.definitions[applicationID][serviceType].empty()) { + deleteServiceRecursive(applicationID, serviceType); + } +} + void RealTimeForwardingControlService::addReportTypesToAppProcessConfiguration(Message& request) { request.assertTC(ServiceType, MessageType::AddReportTypesToAppProcessConfiguration); uint8_t numOfApplications = request.readUint8(); @@ -144,19 +199,9 @@ void RealTimeForwardingControlService::deleteReportTypesFromAppProcessConfigurat uint8_t applicationID = request.readUint8(); uint8_t numOfServices = request.readUint8(); - // application not present in the application process configuration - if (applicationProcessConfiguration.definitions.find(applicationID) == - applicationProcessConfiguration.definitions.end()) { - ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::NonExistingApplication); - for (uint8_t z = 0; z < numOfServices; z++) { - request.skipBytes(1); - uint8_t numOfMessages = request.readUint8(); - request.skipBytes(numOfMessages); - } + if (not applicationExists(request, applicationID, numOfServices)) { continue; } - - // delete the application process if (numOfServices == 0) { applicationProcessConfiguration.definitions.erase(applicationID); applicationProcessConfiguration.notEmpty.erase(applicationID); @@ -167,51 +212,21 @@ void RealTimeForwardingControlService::deleteReportTypesFromAppProcessConfigurat uint8_t serviceType = request.readUint8(); uint8_t numOfMessages = request.readUint8(); - // Service type not present in the specified application process definition - if (applicationProcessConfiguration.definitions[applicationID].find(serviceType) == - applicationProcessConfiguration.definitions[applicationID].end()) { - ErrorHandler::reportError(request, - ErrorHandler::ExecutionStartErrorType::NonExistingServiceTypeDefinition); - request.skipBytes(numOfMessages); + if (not serviceTypeExists(request, applicationID, serviceType, numOfMessages)) { continue; } - - // delete service type if (numOfMessages == 0) { - applicationProcessConfiguration.definitions[applicationID].erase(serviceType); - applicationProcessConfiguration.notEmpty[applicationID].erase(serviceType); - // if empty application - if (applicationProcessConfiguration.definitions[applicationID].empty()) { - applicationProcessConfiguration.definitions.erase(applicationID); - applicationProcessConfiguration.notEmpty.erase(applicationID); - } + deleteServiceRecursive(applicationID, serviceType); continue; } - // if not check service - for (uint8_t k = 0; k < numOfMessages; k++) { uint8_t messageType = request.readUint8(); - if (not reportExistsInAppProcessConfiguration(messageType, applicationID, serviceType)) { - ErrorHandler::reportError(request, - ErrorHandler::ExecutionStartErrorType::NonExistingReportTypeDefinition); + if (not reportTypeExists(request, applicationID, serviceType, messageType)) { continue; } - // delete - auto& reportTypes = applicationProcessConfiguration.definitions[applicationID][serviceType]; - reportTypes.erase(std::remove(reportTypes.begin(), reportTypes.end(), messageType)); - // if service is empty, delete service type. - if (applicationProcessConfiguration.definitions[applicationID][serviceType].empty()) { - applicationProcessConfiguration.definitions[applicationID].erase(serviceType); - applicationProcessConfiguration.notEmpty[applicationID].erase(serviceType); - - // if application is empty, delete application - if (applicationProcessConfiguration.definitions[applicationID].empty()) { - applicationProcessConfiguration.definitions.erase(applicationID); - applicationProcessConfiguration.notEmpty.erase(applicationID); - } - } + deleteReportRecursive(applicationID, serviceType, messageType); } } } diff --git a/test/Services/HousekeepingService.cpp b/test/Services/HousekeepingService.cpp index 37848827d3ff4f71b3eb5994f5fc72692a30bd7c..19b4f54e7231bf938a2666283d02082368c4a135 100644 --- a/test/Services/HousekeepingService.cpp +++ b/test/Services/HousekeepingService.cpp @@ -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}); @@ -68,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); } } @@ -85,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); } @@ -137,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); @@ -167,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); } @@ -179,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)); } @@ -205,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); } @@ -251,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); @@ -279,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; @@ -308,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); @@ -422,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); @@ -511,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)); @@ -531,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) != @@ -561,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++]); } @@ -586,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; @@ -600,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 e1cfb9c973b59265cc83846d1ccadaa706cb1185..379aefcfcd57d8e8ac83211087d1bc578ed4d079 100644 --- a/test/Services/RealTimeForwardingControl.cpp +++ b/test/Services/RealTimeForwardingControl.cpp @@ -221,6 +221,68 @@ void initializeAppProcessConfig() { checkAppProcessConfig(); } +void checkAppProcessConfig2() { + auto& applicationProcesses = realTimeForwarding.applicationProcessConfiguration.definitions; + auto& isNotEmpty = realTimeForwarding.applicationProcessConfiguration.notEmpty; + uint8_t applications2[] = {1, 2, 3}; + + uint8_t numOfApplications = 3; + uint8_t numOfMessagesPerService = 2; + + // Check if configuration is initialized properly + for (uint8_t i = 0; i < numOfApplications; i++) { + uint8_t appID = applications2[i]; + REQUIRE(applicationProcesses.find(appID) != applicationProcesses.end()); + REQUIRE(isNotEmpty.find(appID) != isNotEmpty.end()); + + uint8_t numOfServices = (i == 2) ? 15 : 2; + uint8_t* serviceTypes = (i == 2) ? allServices : services; + REQUIRE(applicationProcesses[appID].size() == numOfServices); + + for (uint8_t j = 0; j < numOfServices; j++) { + uint8_t serviceType = serviceTypes[j]; + uint8_t* messages = (i == 2) ? messages2 : messages1; + + REQUIRE(applicationProcesses[appID].find(serviceType) != applicationProcesses[appID].end()); + REQUIRE(applicationProcesses[appID][serviceType].size() == 2); + REQUIRE(isNotEmpty[appID].find(serviceType) != isNotEmpty[appID].end()); + + for (uint8_t k = 0; k < numOfMessagesPerService; k++) { + uint8_t messageType = messages[k]; + REQUIRE(std::find(applicationProcesses[appID][serviceType].begin(), + applicationProcesses[appID][serviceType].end(), + messageType) != applicationProcesses[appID][serviceType].end()); + } + } + } +} + +void initializeAppProcessConfig2() { + uint8_t numOfApplications = 3; + uint8_t numOfMessagesPerService = 2; + + uint8_t applications2[] = {1, 2, 3}; + + for (uint8_t i = 0; i < numOfApplications; i++) { + uint8_t appID = applications2[i]; + uint8_t numOfServices = (i == 2) ? 15 : 2; + uint8_t* serviceTypes = (i == 2) ? allServices : services; + + for (uint8_t j = 0; j < numOfServices; j++) { + uint8_t serviceType = serviceTypes[j]; + uint8_t* messages = (i == 2) ? messages2 : messages1; + + for (uint8_t k = 0; k < numOfMessagesPerService; k++) { + uint8_t messageType = messages[k]; + realTimeForwarding.applicationProcessConfiguration.definitions[appID][serviceType].push_back( + messageType); + realTimeForwarding.applicationProcessConfiguration.notEmpty[appID][serviceType] = true; + } + } + } + checkAppProcessConfig2(); +} + void serviceNotInApplication(Message& request) { uint8_t numOfApplications = 1; uint8_t numOfServicesPerApp = 2; @@ -384,6 +446,37 @@ void deleteServiceEmptyApplication(Message& request) { } } +void deleteValidInvalidReportTypes(Message& request) { + uint8_t numOfApplications = 4; + uint8_t numOfServices = 2; + uint8_t numOfMessages = 2; + uint8_t validInvalidApplications[] = {1, 99, 3, 2}; // one invalid and three valid + uint8_t validInvalidServices[][2] = {{3, 9}, {3, 5}, {1, 8}, {3, 5}}; + uint8_t validInvalidMessages[] = {EventReportService::MessageType::DisabledListEventReport, + HousekeepingService::MessageType::HousekeepingParametersReport}; + + request.appendUint8(numOfApplications); + for (uint8_t i = 0; i < numOfApplications; i++) { + uint8_t appID = validInvalidApplications[i]; + + request.appendUint8(appID); + request.appendUint8(numOfServices); + + for (uint8_t j = 0; j < numOfServices; j++) { + uint8_t serviceType = validInvalidServices[i][j]; + uint8_t* messages = (i == 2) ? validInvalidMessages : messages1; + + request.appendUint8(serviceType); + request.appendUint8(numOfMessages); + + for (uint8_t k = 0; k < numOfMessages; k++) { + uint8_t messageType = messages[k]; + request.appendUint8(messageType); + } + } + } +} + void resetAppProcessConfiguration() { realTimeForwarding.applicationProcessConfiguration.definitions.clear(); REQUIRE(realTimeForwarding.applicationProcessConfiguration.definitions.empty()); @@ -991,4 +1084,73 @@ TEST_CASE("Delete report types from the Application Process Configuration") { ServiceTests::reset(); Services.reset(); } + + SECTION("Valid and invalid requests to delete report types, combined") { + Message request(RealTimeForwardingControlService::ServiceType, + RealTimeForwardingControlService::MessageType::DeleteReportTypesFromAppProcessConfiguration, + Message::TC, 1); + uint8_t remainingApps[] = {1, 3}; + uint8_t remainingMessage[] = {EventReportService::MessageType::InformativeEventReport}; + + deleteValidInvalidReportTypes(request); + initializeAppProcessConfig2(); + + MessageParser::execute(request); + + CHECK(ServiceTests::count() == 4); + CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::NonExistingApplication) == 1); + CHECK(ServiceTests::countThrownErrors( + ErrorHandler::ExecutionStartErrorType::NonExistingServiceTypeDefinition) == 1); + CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::NonExistingReportTypeDefinition) == + 2); + + auto& applicationProcesses = realTimeForwarding.applicationProcessConfiguration.definitions; + auto& isNotEmpty = realTimeForwarding.applicationProcessConfiguration.notEmpty; + + REQUIRE(applicationProcesses.size() == 2); + for (auto appID : remainingApps) { + REQUIRE(applicationProcesses.find(appID) != applicationProcesses.end()); + } + + // Check for appID = 1 + uint8_t appID1 = remainingApps[0]; + REQUIRE(applicationProcesses[appID1].size() == 1); + REQUIRE(isNotEmpty[appID1].size() == 1); + REQUIRE(applicationProcesses[appID1].find(services[0]) == applicationProcesses[appID1].end()); + REQUIRE(applicationProcesses[appID1][services[1]].size() == 2); + REQUIRE(isNotEmpty[appID1][services[1]] == true); + + for (auto& message : messages1) { + REQUIRE(std::find(applicationProcesses[appID1][services[1]].begin(), + applicationProcesses[appID1][services[1]].end(), + message) != applicationProcesses[appID1][services[1]].end()); + } + + // Check for appID = 2 + uint8_t appID2 = 2; + REQUIRE(applicationProcesses.find(appID2) == applicationProcesses.end()); + REQUIRE(isNotEmpty.find(appID2) == isNotEmpty.end()); + + // Check for appID = 3 + uint8_t appID3 = remainingApps[1]; + REQUIRE(applicationProcesses[appID3].size() == 15); + REQUIRE(isNotEmpty[appID3].size() == 15); + + for (uint8_t i = 0; i < 15; i++) { + uint8_t numOfMessages = (i == 0 or i == 7) ? 1 : 2; // we only deleted one report from services 1 and 8 + uint8_t* messages = (i == 0 or i == 7) ? remainingMessage : messages2; + + REQUIRE(applicationProcesses[appID3][allServices[i]].size() == numOfMessages); + REQUIRE(isNotEmpty[appID3][allServices[i]] == true); + + for (uint8_t j = 0; j < numOfMessages; j++) { + REQUIRE(std::find(applicationProcesses[appID3][allServices[i]].begin(), + applicationProcesses[appID3][allServices[i]].end(), + messages[j]) != applicationProcesses[appID3][allServices[i]].end()); + } + } + resetAppProcessConfiguration(); + ServiceTests::reset(); + Services.reset(); + } }