From ad540c919f59463ff4335711486ecff541461c1d Mon Sep 17 00:00:00 2001
From: Xhulio Luli <lulixhulio@gmail.com>
Date: Sat, 2 Jul 2022 22:42:42 +0000
Subject: [PATCH] St11 fix activities list

---
 .idea/.gitignore                             |  8 ++++
 inc/Services/TimeBasedSchedulingService.hpp  | 26 +++++++-----
 inc/Time/Time.hpp                            |  4 ++
 src/Services/TimeBasedSchedulingService.cpp  | 17 +++++++-
 test/Services/TimeBasedSchedulingService.cpp | 43 +++++++++++++++++++-
 5 files changed, 85 insertions(+), 13 deletions(-)
 create mode 100644 .idea/.gitignore

diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..13566b81
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/inc/Services/TimeBasedSchedulingService.hpp b/inc/Services/TimeBasedSchedulingService.hpp
index a027190b..efdc72bf 100644
--- a/inc/Services/TimeBasedSchedulingService.hpp
+++ b/inc/Services/TimeBasedSchedulingService.hpp
@@ -1,11 +1,11 @@
 #ifndef ECSS_SERVICES_TIMEBASEDSCHEDULINGSERVICE_HPP
 #define ECSS_SERVICES_TIMEBASEDSCHEDULINGSERVICE_HPP
 
-#include "etl/list.h"
-#include "Service.hpp"
 #include "ErrorHandler.hpp"
-#include "MessageParser.hpp"
 #include "Helpers/CRCHelper.hpp"
+#include "MessageParser.hpp"
+#include "Service.hpp"
+#include "etl/list.h"
 
 // Include platform specific files
 #include "Helpers/TimeGetter.hpp"
@@ -28,9 +28,8 @@
  *
  * @details Define a namespace for the access of the private members to avoid conflicts
  */
-namespace unit_test
-{
-struct Tester;
+namespace unit_test {
+	struct Tester;
 } // namespace unit_test
 
 /**
@@ -62,7 +61,7 @@ private:
 	struct RequestID {
 		uint16_t applicationID = 0; ///< Application process ID
 		uint16_t sequenceCount = 0; ///< Packet sequence count
-		uint8_t sourceID = 0; ///< Packet source ID
+		uint8_t sourceID = 0;       ///< Packet source ID
 
 		bool operator!=(const RequestID& rightSide) const {
 			return (sequenceCount != rightSide.sequenceCount) or (applicationID != rightSide.applicationID) or
@@ -80,8 +79,8 @@ private:
 	 * @todo If groups are used, then the group ID has to be defined here
 	 */
 	struct ScheduledActivity {
-		Message request; ///< Hold the received command request
-		RequestID requestID; ///< Request ID, characteristic of the definition
+		Message request;                         ///< Hold the received command request
+		RequestID requestID;                     ///< Request ID, characteristic of the definition
 		Time::CustomCUC_t requestReleaseTime{0}; ///< Keep the command release time
 	};
 
@@ -117,7 +116,6 @@ private:
 	friend struct ::unit_test::Tester;
 
 public:
-
 	/*
 * ST[11] TimeBased Scheduling Service and Sub-Service Macros, for readability purpose
 */
@@ -145,6 +143,12 @@ public:
 	 */
 	TimeBasedSchedulingService();
 
+	/**
+	 * This function executes the next activity and removes it from the list.
+	 * @return the requestReleaseTime of next activity to be executed after this time
+	 */
+	Time::CustomCUC_t executeScheduledActivity(Time::CustomCUC_t currentTime);
+
 	/**
 	 * @brief TC[11,1] enable the time-based schedule execution function
 	 *
@@ -260,7 +264,7 @@ public:
 	 * Also if an activity with a specified request identifier is not found, generate a failed
 	 * start of execution for that specific instruction.
 	 */
-	void timeShiftActivitiesByID(Message &request);
+	void timeShiftActivitiesByID(Message& request);
 
 	/**
 	 * It is responsible to call the suitable function that executes a telecommand packet. The source of that packet
diff --git a/inc/Time/Time.hpp b/inc/Time/Time.hpp
index 298f35f8..b7c80333 100644
--- a/inc/Time/Time.hpp
+++ b/inc/Time/Time.hpp
@@ -311,6 +311,10 @@ namespace Time {
 		return time1.elapsed100msTicks == time2.elapsed100msTicks;
 	}
 
+	inline bool operator>=(Time::CustomCUC_t time1, Time::CustomCUC_t time2) {
+		return time1.elapsed100msTicks >= time2.elapsed100msTicks;
+	}
+
 } // namespace Time
 
 #endif
diff --git a/src/Services/TimeBasedSchedulingService.cpp b/src/Services/TimeBasedSchedulingService.cpp
index 864a9a70..967adcdd 100644
--- a/src/Services/TimeBasedSchedulingService.cpp
+++ b/src/Services/TimeBasedSchedulingService.cpp
@@ -7,6 +7,21 @@ TimeBasedSchedulingService::TimeBasedSchedulingService() {
 	serviceType = TimeBasedSchedulingService::ServiceType;
 }
 
+Time::CustomCUC_t TimeBasedSchedulingService::executeScheduledActivity(Time::CustomCUC_t currentTime) {
+	if (currentTime >= scheduledActivities.front().requestReleaseTime && !scheduledActivities.empty()) {
+		MessageParser::execute(scheduledActivities.front().request);
+		scheduledActivities.pop_front();
+	}
+
+	if (!scheduledActivities.empty()) {
+		return scheduledActivities.front().requestReleaseTime;
+	} else {
+		Time::CustomCUC_t infinity;
+		infinity.elapsed100msTicks = std::numeric_limits<decltype(infinity.elapsed100msTicks)>::max();
+		return infinity;
+	}
+}
+
 void TimeBasedSchedulingService::enableScheduleExecution(Message& request) {
 	request.assertTC(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::EnableTimeBasedScheduleExecutionFunction);
 	executionFunctionStatus = true;
@@ -100,7 +115,7 @@ void TimeBasedSchedulingService::timeShiftActivitiesByID(Message& request) {
 			    (current_time + ECSSTimeMarginForActivation)) {
 				ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
 			} else {
-				requestIDMatch->requestReleaseTime +=  relativeOffset;
+				requestIDMatch->requestReleaseTime += relativeOffset;
 			}
 		} else {
 			ErrorHandler::reportError(request, ErrorHandler::InstructionExecutionStartError);
diff --git a/test/Services/TimeBasedSchedulingService.cpp b/test/Services/TimeBasedSchedulingService.cpp
index bedd6836..47e70433 100644
--- a/test/Services/TimeBasedSchedulingService.cpp
+++ b/test/Services/TimeBasedSchedulingService.cpp
@@ -58,7 +58,7 @@ auto activityInsertion(TimeBasedSchedulingService& timeService) {
 		testMessage3.appendUint16(456); // Append dummy data
 
 		testMessage4.serviceType = 12;
-		testMessage4.messageType = 23;
+		testMessage4.messageType = 3;
 		testMessage4.packetType = Message::TC;
 		testMessage4.appendUint16(934); // Append dummy data
 
@@ -93,6 +93,47 @@ auto activityInsertion(TimeBasedSchedulingService& timeService) {
 
 TimeBasedSchedulingService& timeBasedService = Services.timeBasedScheduling;
 
+TEST_CASE("Execute the first activity, removes it from the list and return the release time of next activity to be executed") {
+	Services.reset();
+	auto scheduledActivities = activityInsertion(timeBasedService);
+
+	auto nextActivityExecutionCUCTime = timeBasedService.executeScheduledActivity(currentTime + 1556435);
+	REQUIRE(nextActivityExecutionCUCTime == currentTime + 1726435);
+
+	Message receivedMessage(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::DetailReportAllScheduledActivities, Message::TC, 1);
+	timeBasedService.detailReportAllActivities(receivedMessage);
+	Message response = ServiceTests::get(0);
+	uint16_t iterationCount = response.readUint16();
+	REQUIRE(iterationCount == 3);
+
+	nextActivityExecutionCUCTime = timeBasedService.executeScheduledActivity(currentTime + 100);
+	REQUIRE(nextActivityExecutionCUCTime == currentTime + 1726435);
+
+	nextActivityExecutionCUCTime = timeBasedService.executeScheduledActivity(currentTime + 1726435);
+	REQUIRE(nextActivityExecutionCUCTime == currentTime + 1957232);
+
+	timeBasedService.detailReportAllActivities(receivedMessage);
+	response = ServiceTests::get(1);
+	iterationCount = response.readUint16();
+	REQUIRE(iterationCount == 2);
+
+	nextActivityExecutionCUCTime = timeBasedService.executeScheduledActivity(currentTime + 1957232);
+	REQUIRE(nextActivityExecutionCUCTime == currentTime + 17248435);
+
+	timeBasedService.detailReportAllActivities(receivedMessage);
+	response = ServiceTests::get(2);
+	iterationCount = response.readUint16();
+	REQUIRE(iterationCount == 1);
+
+	nextActivityExecutionCUCTime = timeBasedService.executeScheduledActivity(currentTime + 17248435);
+	REQUIRE(nextActivityExecutionCUCTime.elapsed100msTicks == std::numeric_limits<decltype(nextActivityExecutionCUCTime.elapsed100msTicks)>::max());
+
+	timeBasedService.detailReportAllActivities(receivedMessage);
+	response = ServiceTests::get(3);
+	iterationCount = response.readUint16();
+	REQUIRE(iterationCount == 0);
+}
+
 TEST_CASE("TC[11,1] Enable Schedule Execution", "[service][st11]") {
 	Services.reset();
 	Message receivedMessage(TimeBasedSchedulingService::ServiceType, TimeBasedSchedulingService::MessageType::EnableTimeBasedScheduleExecutionFunction, Message::TC, 1);
-- 
GitLab