From 0aff71bfdef5fbbf30572932bdbb858267c562d6 Mon Sep 17 00:00:00 2001
From: kpetridis <petridkon@gmail.com>
Date: Sun, 27 Mar 2022 02:05:20 +0200
Subject: [PATCH] Unit tests addition

---
 inc/ErrorHandler.hpp                          |   8 +-
 inc/Helpers/ForwardControlConfiguration.hpp   |   1 +
 .../RealTimeForwardingControlService.hpp      |   6 +
 .../RealTimeForwardingControlService.cpp      |  33 ++-
 test/Services/RealTimeForwardingControl.cpp   | 255 +++++++++++++++++-
 5 files changed, 280 insertions(+), 23 deletions(-)

diff --git a/inc/ErrorHandler.hpp b/inc/ErrorHandler.hpp
index ea4e8266..feab4ebe 100644
--- a/inc/ErrorHandler.hpp
+++ b/inc/ErrorHandler.hpp
@@ -204,17 +204,17 @@ public:
 		 * Attempt to add a new report type, when the addition of all report types is already enabled in the
 		 * Application Process configuration (ST[14])
 		 */
-		AdditionOfAllReportTypesAlreadyEnabled = 22,
+		AllReportTypesAlreadyAllowed = 22,
 		/**
 		 * Attempt to add a new service type, when the addition of all service types is already enabled in the
 		 * Application Process configuration (ST[14])
 		 */
-		AdditionOfAllServiceTypesAlreadyEnabled = 23,
+		AllServiceTypesAlreadyAllowed = 23,
 		/**
 		 * Attempt to add a new report type, when the max number of reports types allowed per service type
 		 * definition in the Application Process configuration is already reached (ST[14])
 		 */
-		MaxReportTypeDefinitionsReached = 24,
+		MaxReportTypesReached = 24,
 		/**
 		 * Attempt to add a new service type, when the max number of service types allowed per application process
 		 * definition in the Application Process configuration is already reached (ST[14])
@@ -224,7 +224,7 @@ public:
 		 * Attempt to add a report/event definition/housekeeping report type, when the specified application process
 		 * ID is not controlled by the Service (ST[14])
 		 */
-		ApplicationNotControlled = 26,
+		NotControlledApplication = 26,
 	};
 
 	/**
diff --git a/inc/Helpers/ForwardControlConfiguration.hpp b/inc/Helpers/ForwardControlConfiguration.hpp
index c965601d..353a481b 100644
--- a/inc/Helpers/ForwardControlConfiguration.hpp
+++ b/inc/Helpers/ForwardControlConfiguration.hpp
@@ -31,6 +31,7 @@ public:
 	 * Indicates the meaning of a service type being empty of report types. It specifies whether the 'empty' means that
 	 * it has not been filled yet (so we proceed to add new report types) or it is empty because we accept every
 	 * report type for the service.
+	 * TODO: rename to 'allServicesAllowed'
 	 */
 	etl::map<uint8_t, reportsAreNotEmpty, ECSSMaxControlledApplications> serviceNotEmpty;
 
diff --git a/inc/Services/RealTimeForwardingControlService.hpp b/inc/Services/RealTimeForwardingControlService.hpp
index 9be63b97..fa88121b 100644
--- a/inc/Services/RealTimeForwardingControlService.hpp
+++ b/inc/Services/RealTimeForwardingControlService.hpp
@@ -106,6 +106,12 @@ private:
 	 */
 	bool maxReportTypesReached(Message& request, uint8_t applicationID, uint8_t serviceType);
 
+	/**
+	 * Checks if the maximum number of message types that can be contained inside a service type definition, is
+	 * already reached.
+	 */
+	bool checkMessage1(Message& request, 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 62e24a32..38f528ac 100644
--- a/src/Services/RealTimeForwardingControlService.cpp
+++ b/src/Services/RealTimeForwardingControlService.cpp
@@ -4,7 +4,7 @@
 bool RealTimeForwardingControlService::appIsControlled(Message& request, uint8_t applicationId) {
 	if (std::find(controlledApplications.begin(), controlledApplications.end(), applicationId) ==
 	    controlledApplications.end()) {
-		ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::ApplicationNotControlled);
+		ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::NotControlledApplication);
 		return false;
 	}
 	return true;
@@ -12,8 +12,7 @@ bool RealTimeForwardingControlService::appIsControlled(Message& request, uint8_t
 
 bool RealTimeForwardingControlService::checkApplication1(Message& request, uint8_t applicationID,
                                                          uint8_t numOfServices) {
-	if (not appIsControlled(request, applicationID) or allServiceTypesAllowed(request, applicationID) or
-	    maxServiceTypesReached(request, applicationID)) {
+	if (not appIsControlled(request, applicationID) or allServiceTypesAllowed(request, applicationID)) {
 		for (uint8_t l = 0; l < numOfServices; l++) {
 			request.skipBytes(1);
 			uint8_t numOfMessages = request.readUint8();
@@ -27,8 +26,7 @@ bool RealTimeForwardingControlService::checkApplication1(Message& request, uint8
 bool RealTimeForwardingControlService::allServiceTypesAllowed(Message& request, uint8_t applicationID) {
 	if (applicationProcessConfiguration.definitions[applicationID].empty() and
 	    not applicationProcessConfiguration.serviceNotEmpty[applicationID].empty()) {
-		ErrorHandler::reportError(request,
-		                          ErrorHandler::ExecutionStartErrorType::AdditionOfAllServiceTypesAlreadyEnabled);
+		ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::AllServiceTypesAlreadyAllowed);
 		return true;
 	}
 	return false;
@@ -44,8 +42,7 @@ bool RealTimeForwardingControlService::maxServiceTypesReached(Message& request,
 
 bool RealTimeForwardingControlService::checkService1(Message& request, uint8_t applicationID, uint8_t serviceType,
                                                      uint8_t numOfMessages) {
-	if (allReportTypesAllowed(request, applicationID, serviceType) or
-	    maxReportTypesReached(request, applicationID, serviceType)) {
+	if (maxServiceTypesReached(request, applicationID) or allReportTypesAllowed(request, applicationID, serviceType)) {
 		request.skipBytes(numOfMessages);
 		return false;
 	}
@@ -56,8 +53,7 @@ bool RealTimeForwardingControlService::allReportTypesAllowed(Message& request, u
                                                              uint8_t serviceType) {
 	if (applicationProcessConfiguration.definitions[applicationID][serviceType].empty() and
 	    applicationProcessConfiguration.serviceNotEmpty[applicationID][serviceType]) {
-		ErrorHandler::reportError(request,
-		                          ErrorHandler::ExecutionStartErrorType::AdditionOfAllReportTypesAlreadyEnabled);
+		ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::AllReportTypesAlreadyAllowed);
 		return true;
 	}
 	return false;
@@ -67,12 +63,22 @@ bool RealTimeForwardingControlService::maxReportTypesReached(Message& request, u
                                                              uint8_t serviceType) {
 	if (applicationProcessConfiguration.definitions[applicationID][serviceType].size() >=
 	    ECSSMaxReportTypeDefinitions) {
-		ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::MaxReportTypeDefinitionsReached);
+		ErrorHandler::reportError(request, ErrorHandler::ExecutionStartErrorType::MaxReportTypesReached);
 		return true;
 	}
 	return false;
 }
 
+bool RealTimeForwardingControlService::checkMessage1(Message& request, uint8_t applicationID, uint8_t serviceType,
+                                                     uint8_t messageType) {
+	if (maxReportTypesReached(request, applicationID, serviceType) or
+	    reportExistsInAppProcessConfiguration(messageType, applicationID, serviceType)) {
+		//		request.skipBytes(1);
+		return false;
+	}
+	return true;
+}
+
 bool RealTimeForwardingControlService::reportExistsInAppProcessConfiguration(uint8_t target, uint8_t applicationID,
                                                                              uint8_t serviceType) {
 	return std::find(applicationProcessConfiguration.definitions[applicationID][serviceType].begin(),
@@ -105,7 +111,6 @@ void RealTimeForwardingControlService::addReportTypesToAppProcessConfiguration(M
 			if (not checkService1(request, applicationID, serviceType, numOfMessages)) {
 				continue;
 			}
-
 			//			if (numOfMessages == 0) {
 			//				// todo: add all report types of the service type to the configuration.
 			//				continue;
@@ -113,10 +118,12 @@ 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)) {
+
+				if (not checkMessage1(request, applicationID, serviceType, messageType)) {
 					continue;
 				}
+
+				// todo: check if message type is valid.
 				applicationProcessConfiguration.definitions[applicationID][serviceType].push_back(messageType);
 				applicationProcessConfiguration.serviceNotEmpty[applicationID][serviceType] = true;
 			}
diff --git a/test/Services/RealTimeForwardingControl.cpp b/test/Services/RealTimeForwardingControl.cpp
index 75dd95e6..39a4dfa4 100644
--- a/test/Services/RealTimeForwardingControl.cpp
+++ b/test/Services/RealTimeForwardingControl.cpp
@@ -5,17 +5,19 @@
 #include "ECSS_Definitions.hpp"
 #include "Services/RealTimeForwardingControlService.hpp"
 
+RealTimeForwardingControlService& realTimeForwarding = Services.realTimeForwarding;
+
 uint8_t applications[] = {1};
 uint8_t services[] = {3, 5};
+uint8_t allServices[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+uint8_t redundantServices[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
 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) {
+void initializeValid(Message& request) {
 	uint8_t numOfApplications = 1;
 	uint8_t numOfServicesPerApp = 2;
 	uint8_t numOfMessagesPerService = 2;
@@ -52,20 +54,59 @@ void initialize(Message& request) {
 	request.resetRead();
 }
 
+void initializeCombined(Message& request) {
+	uint8_t numOfApplications = 3;
+	uint8_t numOfMessagesPerService = 2;
+
+	uint8_t applications2[] = {1, 2, 3};
+	request.appendUint8(numOfApplications);
+
+	for (uint8_t i = 0; i < numOfApplications; i++) {
+		request.appendUint8(applications2[i]);
+		uint8_t numOfServicesPerApp = (i == 0) ? 17 : 2;
+		uint8_t* servicesToPick = (i == 0) ? redundantServices : services;
+		request.appendUint8(numOfServicesPerApp);
+
+		for (uint8_t j = 0; j < numOfServicesPerApp; j++) {
+			uint8_t serviceType = servicesToPick[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() == 3);
+	//	REQUIRE(request.readUint8() == 1);
+	//	REQUIRE(request.readUint8() == 17);
+	//	REQUIRE(request.readUint8() == 1);
+	//	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") {
+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);
+		initializeValid(request);
 
 		MessageParser::execute(request);
 
@@ -90,6 +131,208 @@ TEST_CASE("Add report types to the application process configuration") {
 				}
 			}
 		}
+
+		auto& servicesAllowed = realTimeForwarding.applicationProcessConfiguration.serviceNotEmpty;
+		REQUIRE(servicesAllowed[applicationID].size() == 2);
+		REQUIRE(servicesAllowed[applicationID][services[0]] == true);
+		REQUIRE(servicesAllowed[applicationID][services[1]] == true);
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Requested Application Process is not controlled by the service") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+
+		uint8_t applicationID = 1;
+		initializeValid(request);
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::NotControlledApplication) == 1);
+		REQUIRE(realTimeForwarding.applicationProcessConfiguration.definitions.empty());
+		REQUIRE(realTimeForwarding.applicationProcessConfiguration.serviceNotEmpty[applicationID].empty());
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("All service types already allowed") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+
+		uint8_t applicationID = 1;
+		realTimeForwarding.controlledApplications.push_back(applicationID);
+		initializeValid(request);
+
+		realTimeForwarding.applicationProcessConfiguration.definitions[applicationID].clear();
+		CHECK(realTimeForwarding.applicationProcessConfiguration.definitions[applicationID].empty());
+		realTimeForwarding.applicationProcessConfiguration.serviceNotEmpty[applicationID][services[0]] = true;
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::AllServiceTypesAlreadyAllowed) ==
+		      1);
+		REQUIRE(realTimeForwarding.applicationProcessConfiguration.definitions[applicationID].empty());
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Max service types already reached") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+
+		uint8_t applicationID = 1;
+		realTimeForwarding.controlledApplications.push_back(applicationID);
+		initializeValid(request);
+
+		auto& applicationProcessConfig = realTimeForwarding.applicationProcessConfiguration;
+
+		for (auto service : allServices) {
+			applicationProcessConfig.definitions[applicationID][service].clear();
+			applicationProcessConfig.serviceNotEmpty[applicationID][service] = true;
+		}
+		REQUIRE(applicationProcessConfig.definitions[applicationID].size() == 15);
+		REQUIRE(applicationProcessConfig.serviceNotEmpty[applicationID].size() == 15);
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 2);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::MaxServiceTypesReached) == 2);
+		REQUIRE(applicationProcessConfig.definitions[applicationID].size() == 15);
+		REQUIRE(applicationProcessConfig.serviceNotEmpty[applicationID].size() == 15);
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("All report types already allowed") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+
+		uint8_t applicationID = 1;
+		uint8_t serviceType = services[0];
+		realTimeForwarding.controlledApplications.push_back(applicationID);
+		initializeValid(request);
+
+		realTimeForwarding.applicationProcessConfiguration.definitions[applicationID][serviceType].clear();
+		CHECK(realTimeForwarding.applicationProcessConfiguration.definitions[applicationID][serviceType].empty());
+		realTimeForwarding.applicationProcessConfiguration.serviceNotEmpty[applicationID][serviceType] = true;
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::AllReportTypesAlreadyAllowed) ==
+		      1);
+		REQUIRE(realTimeForwarding.applicationProcessConfiguration.definitions[applicationID].size() == 2);
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Max report types already reached") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+
+		uint8_t applicationID = 1;
+		uint8_t serviceType = services[0];
+		realTimeForwarding.controlledApplications.push_back(applicationID);
+		initializeValid(request);
+
+		auto& applicationProcessConfig = realTimeForwarding.applicationProcessConfiguration;
+
+		applicationProcessConfig.serviceNotEmpty[applicationID][serviceType] = true;
+		for (uint8_t i = 0; i < ECSSMaxReportTypeDefinitions; i++) {
+			applicationProcessConfig.definitions[applicationID][serviceType].push_back(i);
+		}
+
+		REQUIRE(applicationProcessConfig.definitions[applicationID].size() == 1);
+		REQUIRE(applicationProcessConfig.serviceNotEmpty[applicationID].size() == 1);
+		REQUIRE(applicationProcessConfig.definitions[applicationID][serviceType].size() ==
+		        ECSSMaxReportTypeDefinitions);
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 2);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::MaxReportTypesReached) == 2);
+		REQUIRE(applicationProcessConfig.definitions[applicationID].size() == 2);
+		REQUIRE(applicationProcessConfig.serviceNotEmpty[applicationID].size() == 2);
+		REQUIRE(applicationProcessConfig.definitions[applicationID][services[1]].size() == 2);
+		REQUIRE(applicationProcessConfig.definitions[applicationID][serviceType].size() ==
+		        ECSSMaxReportTypeDefinitions);
+
+		resetAppProcessConfiguration();
+		ServiceTests::reset();
+		Services.reset();
+	}
+
+	SECTION("Valid and invalid application-related requests combined") {
+		Message request(RealTimeForwardingControlService::ServiceType,
+		                RealTimeForwardingControlService::MessageType::AddReportTypesToAppProcessConfiguration,
+		                Message::TC, 1);
+
+		uint8_t applicationID1 = 1;
+		uint8_t applicationID2 = 2;
+		uint8_t applicationID3 = 3;
+		realTimeForwarding.controlledApplications.push_back(applicationID1);
+		realTimeForwarding.controlledApplications.push_back(applicationID3);
+		initializeCombined(request);
+
+		realTimeForwarding.applicationProcessConfiguration.definitions[applicationID3].clear();
+		CHECK(realTimeForwarding.applicationProcessConfiguration.definitions[applicationID3].empty());
+		realTimeForwarding.applicationProcessConfiguration.serviceNotEmpty[applicationID3][services[0]] = true;
+
+		MessageParser::execute(request);
+
+		CHECK(ServiceTests::count() == 4);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::NotControlledApplication) == 1);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::MaxServiceTypesReached) == 2);
+		CHECK(ServiceTests::countThrownErrors(ErrorHandler::ExecutionStartErrorType::AllServiceTypesAlreadyAllowed) ==
+		      1);
+
+		auto& applicationProcesses = realTimeForwarding.applicationProcessConfiguration.definitions;
+		auto& servicesAllowed = realTimeForwarding.applicationProcessConfiguration.serviceNotEmpty;
+
+		REQUIRE(applicationProcesses.size() == 2);
+		REQUIRE(applicationProcesses.find(applicationID2) == applicationProcesses.end());
+		REQUIRE(applicationProcesses.find(applicationID1) != applicationProcesses.end());
+		REQUIRE(applicationProcesses.find(applicationID3) != applicationProcesses.end());
+
+		REQUIRE(applicationProcesses[applicationID1].size() == 15);
+		REQUIRE(servicesAllowed[applicationID1].size() == 15);
+		for (auto serviceType : allServices) {
+			REQUIRE(servicesAllowed[applicationID1][serviceType]);
+		}
+		REQUIRE(applicationProcesses[applicationID3].empty());
+
+		for (auto& serviceType : applicationProcesses[applicationID1]) {
+			REQUIRE(std::find(std::begin(allServices), std::end(allServices), serviceType.first) !=
+			        std::end(allServices));
+			REQUIRE(serviceType.second.size() == 2);
+			auto& messagesToCheck = (serviceType.first == 1) ? messages1 : messages2;
+			for (auto message : serviceType.second) {
+				REQUIRE(std::find(std::begin(messagesToCheck), std::end(messagesToCheck), message) !=
+				        std::end(messagesToCheck));
+			}
+		}
+
+		REQUIRE(servicesAllowed[applicationID3].size() == 1);
+		REQUIRE(servicesAllowed[applicationID3][services[0]] == true);
+
 		resetAppProcessConfiguration();
 		ServiceTests::reset();
 		Services.reset();
-- 
GitLab