From c4c15bc90de64ae58903b6665afffe883a91c853 Mon Sep 17 00:00:00 2001 From: Nemanja Trifunovic Date: Wed, 10 Jun 2026 14:34:31 +0000 Subject: [PATCH 1/3] Adding enum return type for SafeProcessMap --- .../details/os_handler.cpp | 33 ++-- .../details/oshandler_UT.cpp | 18 +- .../details/process_info_node.cpp | 7 +- .../details/safe_process_map.cpp | 181 ++++++++++++------ .../details/safe_process_map.hpp | 83 +++++--- .../details/safeprocessmap_UT.cpp | 178 +++++++++-------- 6 files changed, 310 insertions(+), 190 deletions(-) diff --git a/score/launch_manager/daemon/src/process_group_manager/details/os_handler.cpp b/score/launch_manager/daemon/src/process_group_manager/details/os_handler.cpp index dbde7520..0951588b 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/os_handler.cpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/os_handler.cpp @@ -13,22 +13,33 @@ #include "score/mw/launch_manager/process_group_manager/details/os_handler.hpp" -namespace score { +namespace score +{ -namespace lcm { +namespace lcm +{ -namespace internal { +namespace internal +{ -void OsHandler::run(void) { - while (is_running_) { +void OsHandler::run(void) +{ + while (is_running_) + { int32_t wait_status = 0; auto result = sys_wait_.wait(&wait_status); - if (result.has_value() && result.value() > 0) { - if (-1 == safe_process_map_.findTerminated(result.value(), wait_status)) { - LM_LOG_ERROR() << "No more resources available to track process with PID " << result.value() << "(SafeProcessMap capacity exceeded)."; + if (result.has_value() && result.value() > 0) + { + if (score::lcm::internal::SafeProcessMapReturnTypes::kInsertionError == + safe_process_map_.findTerminated(result.value(), wait_status)) + { + LM_LOG_ERROR() << "No more resources available to track process with PID " << result.value() + << "(SafeProcessMap capacity exceeded)."; } - } else { + } + else + { // This process has no children to wait for at present, // or the wait was interrupted by a signal. // Wait a while to stop this thread from hogging cpu time @@ -37,8 +48,8 @@ void OsHandler::run(void) { } } -} // namespace lcm - } // namespace internal +} // namespace lcm + } // namespace score diff --git a/score/launch_manager/daemon/src/process_group_manager/details/oshandler_UT.cpp b/score/launch_manager/daemon/src/process_group_manager/details/oshandler_UT.cpp index bfd4e76e..15b43826 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/oshandler_UT.cpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/oshandler_UT.cpp @@ -20,8 +20,8 @@ #include "score/mw/launch_manager/process_group_manager/details/os_handler.hpp" -#include "score/mw/launch_manager/process_group_manager/details/safe_process_map.hpp" #include "score/mw/launch_manager/common/constants.hpp" +#include "score/mw/launch_manager/process_group_manager/details/safe_process_map.hpp" #include "score/os/mocklib/sys_wait_mock.h" using namespace testing; @@ -32,13 +32,13 @@ namespace class MockTerminationCallback : public ITerminationCallback { - public: + public: MOCK_METHOD(void, terminated, (int32_t process_status), (override)); }; class OsHandlerTest : public ::testing::Test { - protected: + protected: void SetUp() override { RecordProperty("TestType", "interface-test"); @@ -81,8 +81,7 @@ TEST_F(OsHandlerTest, WaitReturnsProcessId_FindTerminatedIsCalled) TEST_F(OsHandlerTest, WaitReturnsError_OsHandlerSleepsAndDoesNotCallFindTerminated) { - RecordProperty("Description", - "When sys_wait returns an error, OsHandler sleeps and does not call findTerminated."); + RecordProperty("Description", "When sys_wait returns an error, OsHandler sleeps and does not call findTerminated."); // given — insert a callback that should NOT be invoked StrictMock callback; @@ -101,8 +100,7 @@ TEST_F(OsHandlerTest, WaitReturnsError_OsHandlerSleepsAndDoesNotCallFindTerminat TEST_F(OsHandlerTest, WaitReturnsZeroPid_OsHandlerSleepsAndDoesNotCallFindTerminated) { - RecordProperty("Description", - "When sys_wait returns pid 0, OsHandler sleeps and does not call findTerminated."); + RecordProperty("Description", "When sys_wait returns pid 0, OsHandler sleeps and does not call findTerminated."); // given StrictMock callback; @@ -156,7 +154,8 @@ TEST_F(OsHandlerTest, WaitReturnsProcessIdBeforeRegistration_LaterRegistrationRe // callback immediately with the saved exit status instead of creating a new live entry. StrictMock callback; EXPECT_CALL(callback, terminated(99)).Times(1); - EXPECT_EQ(process_map_.insertIfNotTerminated(4000, &callback), 1); + EXPECT_EQ(process_map_.insertIfNotTerminated(4000, &callback), + score::lcm::internal::SafeProcessMapReturnTypes::kYield); sut_.reset(); } @@ -171,7 +170,8 @@ TEST_F(OsHandlerTest, WaitReturnsUnknownPidWhenMapIsFull_OutOfResourcesPathDoesN StrictMock callbacks[kCapacity]; for (uint32_t i = 0; i < kCapacity; ++i) { - ASSERT_EQ(process_map_.insertIfNotTerminated(static_cast(i + 1U), &callbacks[i]), 0); + ASSERT_EQ(process_map_.insertIfNotTerminated(static_cast(i + 1U), &callbacks[i]), + score::lcm::internal::SafeProcessMapReturnTypes::kOk); } EXPECT_CALL(*sys_wait_mock_, wait(_)) diff --git a/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.cpp b/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.cpp index 2f2f94ac..9c73e94d 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.cpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.cpp @@ -13,9 +13,9 @@ #include "process_info_node.hpp" #include "graph.hpp" -#include "score/mw/launch_manager/process_group_manager/process_group_manager.hpp" #include "score/mw/launch_manager/common/log.hpp" #include "score/mw/launch_manager/osal/ipc_comms.hpp" +#include "score/mw/launch_manager/process_group_manager/process_group_manager.hpp" namespace score { @@ -407,10 +407,11 @@ void ProcessInfoNode::handleProcessStarted(uint32_t execution_error_code) { switch (graph_->getProcessGroupManager()->getProcessMap()->insertIfNotTerminated(pid_, this)) { - case 0: // Normal case, entry was put in the map, process still running + case score::lcm::internal::SafeProcessMapReturnTypes::kOk: // Normal case, entry was put in + // the map, process still running handleProcessStillStarting(execution_error_code); break; - case 1: // Process has already exited + case score::lcm::internal::SafeProcessMapReturnTypes::kYield: // Process has already exited handleProcessAlreadyTerminated(execution_error_code); break; default: // Error case when pn == -1 diff --git a/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.cpp b/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.cpp index 5b7b8933..2bfd0415 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.cpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.cpp @@ -17,17 +17,23 @@ #include "score/mw/launch_manager/process_group_manager/details/safe_process_map.hpp" -namespace score { +namespace score +{ -namespace lcm { +namespace lcm +{ -namespace internal { +namespace internal +{ -SafeProcessMap::SafeProcessMap(uint32_t capacity) : items_(std::make_unique(capacity)) { - if (capacity) { +SafeProcessMap::SafeProcessMap(uint32_t capacity) : items_(std::make_unique(capacity)) +{ + if (capacity) + { free_root_ = 0U; pid_root_.store(LINK_NO_VALUE); - for (std::size_t i = 0U; i < capacity; ++i) { + for (std::size_t i = 0U; i < capacity; ++i) + { items_[i].pid_ = 0; items_[i].data_.pin_ = nullptr; items_[i].pid_left_ = LINK_NO_VALUE; @@ -38,13 +44,18 @@ SafeProcessMap::SafeProcessMap(uint32_t capacity) : items_(std::make_unique(key) & mask) { + if (static_cast(key) & mask) + { rover_ = items_[last].pid_left_; - } else { + } + else + { rover_ = items_[last].pid_right_; } @@ -61,15 +72,19 @@ inline void SafeProcessMap::findNode(uint32_t& mask, uint32_t& last, osal::Proce } // RULECHECKER_comment(1, 1, check_max_parameters, "refactored with WI #9343", true); -inline int32_t SafeProcessMap::insertNode(uint32_t& mask, uint32_t& last, osal::ProcessID& key, ProcessInfoData& data) { +inline int32_t SafeProcessMap::insertNode(uint32_t& mask, uint32_t& last, osal::ProcessID& key, ProcessInfoData& data) +{ int32_t ret_value = -1; rover_ = free_root_; - if (rover_ == LINK_NO_VALUE) { + if (rover_ == LINK_NO_VALUE) + { // too bad, we are out of memory ret_value = -1; - } else { + } + else + { mask = mask >> 1U; free_root_ = items_[rover_].pid_right_; items_[rover_].pid_ = key; @@ -77,15 +92,21 @@ inline int32_t SafeProcessMap::insertNode(uint32_t& mask, uint32_t& last, osal:: items_[rover_].pid_left_ = LINK_NO_VALUE; items_[rover_].pid_right_ = LINK_NO_VALUE; - if (static_cast(key) & mask) { + if (static_cast(key) & mask) + { items_[last].pid_left_ = rover_; - } else { + } + else + { items_[last].pid_right_ = rover_; } - if (data.pin_ == nullptr) { + if (data.pin_ == nullptr) + { ret_value = 1; - } else { + } + else + { ret_value = 0; } } @@ -94,8 +115,11 @@ inline int32_t SafeProcessMap::insertNode(uint32_t& mask, uint32_t& last, osal:: } // RULECHECKER_comment(1, 1, check_max_parameters, "refactored with WI #9343", true); -inline int32_t SafeProcessMap::removeNode(ProcessInfoData& target, ProcessInfoData& data, uint32_t& last, - uint32_t& local_root) { +inline int32_t SafeProcessMap::removeNode(ProcessInfoData& target, + ProcessInfoData& data, + uint32_t& last, + uint32_t& local_root) +{ // found key. There are 4 situations: // data.pin_ == nullptr, stored pin_ != nullptr: normal findTerminated // data.pin_ != nullptr, stored pin_ == nullptr: normal insertIfNotTerminated @@ -104,17 +128,24 @@ inline int32_t SafeProcessMap::removeNode(ProcessInfoData& target, ProcessInfoDa // In other words, exactly one of data.pin_ and stored pin_ must be nullptr // or there is an anomaly and we return -2 int32_t ret_value = -2; - if ((nullptr == data.pin_) ^ (nullptr == items_[rover_].data_.pin_)) { + if ((nullptr == data.pin_) ^ (nullptr == items_[rover_].data_.pin_)) + { // found key, we will remove it! target = items_[rover_].data_; - if (target.pin_) { + if (target.pin_) + { target.status_ = data.status_; - } else { + } + else + { target.pin_ = data.pin_; } - if (data.pin_) { + if (data.pin_) + { ret_value = 1; - } else { + } + else + { ret_value = 0; } // Need to find a suitable leaf to use as the replacement @@ -126,42 +157,62 @@ inline int32_t SafeProcessMap::removeNode(ProcessInfoData& target, ProcessInfoDa return ret_value; } -inline void SafeProcessMap::findLeaf(uint32_t& leaf, uint32_t& previous) { - while (true) { - if (items_[leaf].pid_left_ != LINK_NO_VALUE) { +inline void SafeProcessMap::findLeaf(uint32_t& leaf, uint32_t& previous) +{ + while (true) + { + if (items_[leaf].pid_left_ != LINK_NO_VALUE) + { previous = leaf; leaf = items_[leaf].pid_left_; - } else if (items_[leaf].pid_right_ != LINK_NO_VALUE) { + } + else if (items_[leaf].pid_right_ != LINK_NO_VALUE) + { previous = leaf; leaf = items_[leaf].pid_right_; - } else { + } + else + { break; } } } // RULECHECKER_comment(1, 1, check_max_parameters, "refactored with WI #9343", true); -inline void SafeProcessMap::deleteNode(uint32_t& last, uint32_t& leaf, uint32_t& local_root, uint32_t& previous) { - if (leaf == local_root) { +inline void SafeProcessMap::deleteNode(uint32_t& last, uint32_t& leaf, uint32_t& local_root, uint32_t& previous) +{ + if (leaf == local_root) + { // tree is now empty! local_root = LINK_NO_VALUE; - } else { - if (leaf == rover_) { + } + else + { + if (leaf == rover_) + { // simply remove the link to rover - if (items_[last].pid_left_ == rover_) { + if (items_[last].pid_left_ == rover_) + { items_[last].pid_left_ = LINK_NO_VALUE; - } else { + } + else + { items_[last].pid_right_ = LINK_NO_VALUE; } - } else { + } + else + { // Put the leaf in place of the item we are replacing items_[rover_].pid_ = items_[leaf].pid_; items_[rover_].data_ = items_[leaf].data_; // Remove the links on the item that previously pointed to the leaf - if (items_[previous].pid_left_ == leaf) { + if (items_[previous].pid_left_ == leaf) + { items_[previous].pid_left_ = LINK_NO_VALUE; - } else { + } + else + { items_[previous].pid_right_ = LINK_NO_VALUE; } } @@ -174,23 +225,28 @@ inline void SafeProcessMap::deleteNode(uint32_t& last, uint32_t& leaf, uint32_t& free_root_ = leaf; } -int32_t SafeProcessMap::search(osal::ProcessID key, ProcessInfoData data) { +int32_t SafeProcessMap::search(osal::ProcessID key, ProcessInfoData data) +{ int32_t ret_value = -2; - if (key >= 0) { - while (-2 == ret_value) { + if (key >= 0) + { + while (-2 == ret_value) + { ProcessInfoData target; target = {data.status_, nullptr}; // Gain a lock on the root of the tree uint32_t local_root = pid_root_.exchange(LINK_LOCKED); - while (local_root == LINK_LOCKED) { + while (local_root == LINK_LOCKED) + { std::this_thread::yield(); local_root = pid_root_.exchange(LINK_LOCKED); } rover_ = local_root; - if (local_root == LINK_NO_VALUE) { + if (local_root == LINK_NO_VALUE) + { // no tree, special case. rover_ = free_root_; free_root_ = items_[rover_].pid_right_; @@ -200,22 +256,30 @@ int32_t SafeProcessMap::search(osal::ProcessID key, ProcessInfoData data) { items_[rover_].pid_right_ = LINK_NO_VALUE; local_root = rover_; - if (data.pin_ == nullptr) { + if (data.pin_ == nullptr) + { ret_value = 1; - } else { + } + else + { ret_value = 0; } - } else { + } + else + { // Look for the key uint32_t last = LINK_NO_VALUE; uint32_t mask = 1U; findNode(mask, last, key); - if (rover_ == LINK_NO_VALUE) { + if (rover_ == LINK_NO_VALUE) + { // key not found, we will add it ret_value = insertNode(mask, last, key, data); - } else { + } + else + { // found key, we will remove it! ret_value = removeNode(target, data, last, local_root); } @@ -223,10 +287,13 @@ int32_t SafeProcessMap::search(osal::ProcessID key, ProcessInfoData data) { // release the lock on the tree pid_root_.store(local_root); - if (-2 == ret_value) { + if (-2 == ret_value) + { // allow another thread to run to resolve the anomaly std::this_thread::yield(); - } else if (target.pin_) { + } + else if (target.pin_) + { target.pin_->terminated(target.status_); } } @@ -235,16 +302,18 @@ int32_t SafeProcessMap::search(osal::ProcessID key, ProcessInfoData data) { return ret_value; } -int32_t SafeProcessMap::findTerminated(osal::ProcessID key, int32_t status) { - return search(key, {status, nullptr}); +SafeProcessMapReturnTypes SafeProcessMap::findTerminated(osal::ProcessID key, int32_t status) +{ + return static_cast(search(key, {status, nullptr})); } -int32_t SafeProcessMap::insertIfNotTerminated(osal::ProcessID key, ITerminationCallback* object) { - return search(key, {0, object}); +SafeProcessMapReturnTypes SafeProcessMap::insertIfNotTerminated(osal::ProcessID key, ITerminationCallback* object) +{ + return static_cast(search(key, {0, object})); } -} // namespace lcm - } // namespace internal +} // namespace lcm + } // namespace score diff --git a/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.hpp b/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.hpp index 78c8ce5c..85dd7db1 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.hpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.hpp @@ -11,33 +11,36 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ - #ifndef SAFE_PROCESS_MAP_HPP_INCLUDED #define SAFE_PROCESS_MAP_HPP_INCLUDED +#include "score/mw/launch_manager/process_group_manager/iprocess.hpp" #include #include -#include "score/mw/launch_manager/process_group_manager/iprocess.hpp" -namespace score { +namespace score +{ -namespace lcm { +namespace lcm +{ -namespace internal { +namespace internal +{ /// @brief Callback interface for process termination notification. /// /// Decouples SafeProcessMap from concrete node types. Any object that needs to /// be notified when a tracked process terminates implements this interface. -class ITerminationCallback { - public: +class ITerminationCallback +{ + public: virtual ~ITerminationCallback() = default; /// @brief Called when the associated process has terminated. /// @param process_status The exit status reported by the operating system. virtual void terminated(int32_t process_status) = 0; - protected: + protected: ITerminationCallback() = default; ITerminationCallback(const ITerminationCallback&) = default; ITerminationCallback& operator=(const ITerminationCallback&) = default; @@ -46,22 +49,44 @@ class ITerminationCallback { }; /// @brief Struct representing data in a map item -struct ProcessInfoData { +struct ProcessInfoData +{ int32_t status_ = -1; ///< Exit status for process ITerminationCallback* pin_ = nullptr; ///< Pointer to the termination callback associated with this item. }; /// @brief Struct representing an item in the map. -struct ProcessTreeNode { +struct ProcessTreeNode +{ uint32_t pid_left_ = 0xFFFFFFFF; ///< Odd branch for binary tree of process IDs (left child). uint32_t pid_right_ = 0xFFFFFFFF; ///< Even branch for binary tree of process IDs (right child). osal::ProcessID pid_ = -1; ///< Process ID associated with this item. ProcessInfoData data_; }; -/// @brief The SafeProcessMap class provides a thread-safe mapping of unique process IDs (ProcessID) to ITerminationCallback pointers. -/// It ensures safe concurrent access and modification of the mapping, using atomic operations. -class SafeProcessMap final { - public: +enum class SafeProcessMapReturnTypes : std::int32_t +{ + /// @brief Method successfully executed. + kOk = 0, + + /// @brief Clash due to PID re-use, method yields until the situation is resolved. + kYield = 1, + + /// @brief An error occurred during insertion (e.g., out of memory). + kInsertionError = -1, + + /// @brief The provided process ID (`key`) is not valid ( < 0). + kInvalidIdError = -2, + + /// @brief The state is not defined. + kUndefined = 2, +}; + +/// @brief The SafeProcessMap class provides a thread-safe mapping of unique process IDs (ProcessID) to +/// ITerminationCallback pointers. It ensures safe concurrent access and modification of the mapping, using atomic +/// operations. +class SafeProcessMap final +{ + public: /// @brief Constructs a SafeProcessMap with a specified capacity. /// This constructor initializes the SafeProcessMap with the given capacity. /// @param capacity The maximum number of entries that the SafeProcessMap can hold. @@ -80,28 +105,32 @@ class SafeProcessMap final { /// 1 if the process ID was not found and an already-terminated entry was inserted, /// -1 if an error occurred during insertion (e.g., out of memory), /// or -2 if the provided process ID (`key`) is not valid (< 0). - int32_t findTerminated(osal::ProcessID key, int32_t status); + SafeProcessMapReturnTypes findTerminated(osal::ProcessID key, int32_t status); /// @brief Inserts a process into the map if it has not already terminated. - /// This method is called by a worker thread after starting a process. It attempts to insert the given process ID (key) - /// and its associated ITerminationCallback pointer into the map, ensuring that the process is not already marked as terminated. - /// In the case of a clash due to PID re-use, this method yields until the situation is resolved. + /// This method is called by a worker thread after starting a process. It attempts to insert the given process ID + /// (key) and its associated ITerminationCallback pointer into the map, ensuring that the process is not already + /// marked as terminated. In the case of a clash due to PID re-use, this method yields until the situation is + /// resolved. /// @param key The process ID to insert into the map. /// @param object A pointer to the ITerminationCallback associated with the process. /// @return 0 if the key (Process ID) was not found and a new entry was made, /// 1 if the key was found (indicating the process has terminated), and updated with the provided object, /// -1 if an error occurred during insertion (e.g., out of memory), /// or -2 if the provided process ID (`key`) is not valid ( < 0). - int32_t insertIfNotTerminated(osal::ProcessID key, ITerminationCallback* object); + SafeProcessMapReturnTypes insertIfNotTerminated(osal::ProcessID key, ITerminationCallback* object); - private: + private: /// @brief Searches for a process with the given process ID (key) in the map. /// If found, updates or removes the entry based on provided conditions. /// If the provided process ID (key) is valid (> 0): /// - If the process ID (key) is found in the map: - /// - If `pin_` (ITerminationCallback pointer) is not nullptr, uses it to set the return status via the callback, removes the key, and returns 0. - /// - If `pin_` is nullptr, uses the provided ITerminationCallback pointer to set the stored status, removes the key, and returns 1. - /// - Behaviour under anomalous conditions (PID re-use where either both data.pin_ and stored pin_ are nullptr or both are not nullptr): + /// - If `pin_` (ITerminationCallback pointer) is not nullptr, uses it to set the return status via the + /// callback, removes the key, and returns 0. + /// - If `pin_` is nullptr, uses the provided ITerminationCallback pointer to set the stored status, + /// removes the key, and returns 1. + /// - Behaviour under anomalous conditions (PID re-use where either both data.pin_ and stored pin_ are + /// nullptr or both are not nullptr): /// yield() and then repeat the operation. /// - If the process ID (key) is not found in the map: /// - Adds the key (`key`), `pin_`, and `status` to the map. @@ -157,8 +186,8 @@ class SafeProcessMap final { /// @brief Finds the leaf node in the SafeProcessMap starting from the given node. /// This function traverses the SafeProcessMap starting from the specified node `leaf` /// to find the first leaf node (a node without left and right children). - /// @param leaf Current leaf.Reference to an integer representing the starting node from which to find the leaf node. - /// Upon successful execution, this parameter will store the index of the found leaf node. + /// @param leaf Current leaf.Reference to an integer representing the starting node from which to find the leaf + /// node. Upon successful execution, this parameter will store the index of the found leaf node. /// @param previous Reference to an integer that will store the index of the parent node of the found leaf node. /// If the `leaf` node itself is the root or a leaf, `previous` will be set to the same as `leaf`. void findLeaf(uint32_t& leaf, uint32_t& previous); @@ -197,10 +226,10 @@ class SafeProcessMap final { uint32_t rover_{LINK_NO_VALUE}; }; -} // namespace lcm - } // namespace internal +} // namespace lcm + } // namespace score #endif /// SAFE_PROCESS_MAP_HPP_INCLUDED diff --git a/score/launch_manager/daemon/src/process_group_manager/details/safeprocessmap_UT.cpp b/score/launch_manager/daemon/src/process_group_manager/details/safeprocessmap_UT.cpp index 68abf349..a90bcbca 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/safeprocessmap_UT.cpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/safeprocessmap_UT.cpp @@ -5,10 +5,10 @@ * information regarding copyright ownership. * * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 + * terms of the Apache License Version score::lcm::internal::SafeProcessMapReturnTypes::kUndefined.0 which is available + *at https://www.apache.org/licenses/LICENSE-score::lcm::internal::SafeProcessMapReturnTypes::kUndefined.0 * - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: Apache-score::lcm::internal::SafeProcessMapReturnTypes::kUndefined.0 ********************************************************************************/ #include @@ -19,8 +19,8 @@ #include #include -#include "score/mw/launch_manager/process_group_manager/details/safe_process_map.hpp" #include "score/mw/launch_manager/common/constants.hpp" +#include "score/mw/launch_manager/process_group_manager/details/safe_process_map.hpp" using namespace testing; using namespace score::lcm::internal; @@ -32,13 +32,13 @@ constexpr uint32_t kCapacity = static_cast(ProcessLimits::kMaxProcesse class MockTerminationCallback : public ITerminationCallback { - public: + public: MOCK_METHOD(void, terminated, (int32_t process_status), (override)); }; class SafeProcessMapTest : public ::testing::Test { - protected: + protected: void SetUp() override { RecordProperty("TestType", "interface-test"); @@ -63,24 +63,27 @@ TEST_F(SafeProcessMapTest, ConstructWithZeroCapacity) TEST_F(SafeProcessMapTest, FindTerminatedWithNegativePidReturnsInvalid) { - RecordProperty("Description", "findTerminated returns -2 for a negative process ID."); + RecordProperty("Description", + "findTerminated returns -score::lcm::internal::SafeProcessMapReturnTypes::kUndefined for a negative " + "process ID."); // when - int32_t result = sut_.findTerminated(-1, 1000); + score::lcm::internal::SafeProcessMapReturnTypes result = sut_.findTerminated(-1, 1000); // then - EXPECT_EQ(result, -2); + EXPECT_EQ(result, score::lcm::internal::SafeProcessMapReturnTypes::kInvalidIdError); } TEST_F(SafeProcessMapTest, FindTerminatedInsertsEntryWhenPidNotPresent) { - RecordProperty("Description", "findTerminated inserts an entry and returns 1 when the PID is not in the map."); + RecordProperty("Description", + "findTerminated inserts an entry and returns kYield (1) when the PID is not in the map."); // when - int32_t result = sut_.findTerminated(1000, 0); + score::lcm::internal::SafeProcessMapReturnTypes result = sut_.findTerminated(1000, 0); // then - EXPECT_EQ(result, 1); + EXPECT_EQ(result, score::lcm::internal::SafeProcessMapReturnTypes::kYield); } TEST_F(SafeProcessMapTest, FindTerminatedMatchesExistingInsertAndCallsCallback) @@ -95,27 +98,28 @@ TEST_F(SafeProcessMapTest, FindTerminatedMatchesExistingInsertAndCallsCallback) EXPECT_CALL(callback_, terminated(42)); // when - int32_t result = sut_.findTerminated(1000, 42); - EXPECT_EQ(result, 0); + score::lcm::internal::SafeProcessMapReturnTypes result = sut_.findTerminated(1000, 42); + EXPECT_EQ(result, score::lcm::internal::SafeProcessMapReturnTypes::kOk); } // --- insertIfNotTerminated --- TEST_F(SafeProcessMapTest, InsertIntoEmptyTreeReturnsZero) { - RecordProperty("Description", "insertIfNotTerminated returns 0 when inserting into an empty tree."); + RecordProperty("Description", "insertIfNotTerminated returns kOk (0) when inserting into an empty tree."); // when - int32_t result = sut_.insertIfNotTerminated(2000, &callback_); + score::lcm::internal::SafeProcessMapReturnTypes result = sut_.insertIfNotTerminated(2000, &callback_); // then - EXPECT_EQ(result, 0); + EXPECT_EQ(result, score::lcm::internal::SafeProcessMapReturnTypes::kOk); } TEST_F(SafeProcessMapTest, InsertMatchesExistingFindTerminatedEntry) { - RecordProperty("Description", - "insertIfNotTerminated returns 1 when matching an entry previously added by findTerminated."); + RecordProperty( + "Description", + "insertIfNotTerminated returns kYield (1) when matching an entry previously added by findTerminated."); // given sut_.findTerminated(1000, 0); @@ -123,16 +127,16 @@ TEST_F(SafeProcessMapTest, InsertMatchesExistingFindTerminatedEntry) EXPECT_CALL(callback_, terminated(0)); // when - int32_t result = sut_.insertIfNotTerminated(1000, &callback_); + score::lcm::internal::SafeProcessMapReturnTypes result = sut_.insertIfNotTerminated(1000, &callback_); // then - EXPECT_EQ(result, 1); + EXPECT_EQ(result, score::lcm::internal::SafeProcessMapReturnTypes::kYield); } TEST_F(SafeProcessMapTest, InsertMultipleNodesThenFindTerminatedRemovesAll) { RecordProperty("Description", - "Inserting kMaxProcesses nodes and then calling findTerminated for each returns 0."); + "Inserting kMaxProcesses nodes and then calling findTerminated for each returns kOk (0)."); // given NiceMock callbacks[kCapacity]; @@ -144,27 +148,31 @@ TEST_F(SafeProcessMapTest, InsertMultipleNodesThenFindTerminatedRemovesAll) // when / then for (uint32_t j = 1; j <= kCapacity; ++j) { - EXPECT_EQ(sut_.findTerminated(static_cast(j), 0), 0); + EXPECT_EQ(sut_.findTerminated(static_cast(j), 0), + score::lcm::internal::SafeProcessMapReturnTypes::kOk); } } TEST_F(SafeProcessMapTest, InsertBeyondCapacityReturnsOutOfMemory) { - RecordProperty("Description", - "insertIfNotTerminated returns -1 when the map is full and a new entry is attempted."); + RecordProperty( + "Description", + "insertIfNotTerminated returns kInsertionError (-1) when the map is full and a new entry is attempted."); // given NiceMock callbacks[kCapacity]; for (uint32_t i = 0; i < kCapacity; ++i) { - EXPECT_EQ(sut_.insertIfNotTerminated(static_cast(i), &callbacks[i]), 0); + EXPECT_EQ(sut_.insertIfNotTerminated(static_cast(i), &callbacks[i]), + score::lcm::internal::SafeProcessMapReturnTypes::kOk); } // when - int32_t result = sut_.insertIfNotTerminated(static_cast(kCapacity + 1), &callback_); + score::lcm::internal::SafeProcessMapReturnTypes result = + sut_.insertIfNotTerminated(static_cast(kCapacity + 1), &callback_); // then - EXPECT_EQ(result, -1); + EXPECT_EQ(result, score::lcm::internal::SafeProcessMapReturnTypes::kInsertionError); } // --- Anomalous (PID reuse) cases --- @@ -176,8 +184,8 @@ TEST_F(SafeProcessMapTest, InsertSamePidTwiceYieldsUntilFindTerminatedResolves) // given std::atomic_bool first_done{false}; - int32_t ret1 = 2; - int32_t ret2 = 2; + score::lcm::internal::SafeProcessMapReturnTypes ret1 = score::lcm::internal::SafeProcessMapReturnTypes::kUndefined; + score::lcm::internal::SafeProcessMapReturnTypes ret2 = score::lcm::internal::SafeProcessMapReturnTypes::kUndefined; NiceMock cb; @@ -193,15 +201,15 @@ TEST_F(SafeProcessMapTest, InsertSamePidTwiceYieldsUntilFindTerminatedResolves) std::this_thread::sleep_for(std::chrono::milliseconds(10)); // then — first succeeded, second is still blocked - EXPECT_EQ(ret1, 0); - EXPECT_EQ(ret2, 2); + EXPECT_EQ(ret1, score::lcm::internal::SafeProcessMapReturnTypes::kOk); + EXPECT_EQ(ret2, score::lcm::internal::SafeProcessMapReturnTypes::kUndefined); // when — resolve the anomaly - EXPECT_EQ(sut_.findTerminated(42, 0), 0); + EXPECT_EQ(sut_.findTerminated(42, 0), score::lcm::internal::SafeProcessMapReturnTypes::kOk); inserter.join(); // then - EXPECT_EQ(ret2, 0); + EXPECT_EQ(ret2, score::lcm::internal::SafeProcessMapReturnTypes::kOk); } TEST_F(SafeProcessMapTest, FindTerminatedSamePidTwiceYieldsUntilInsertResolves) @@ -212,8 +220,8 @@ TEST_F(SafeProcessMapTest, FindTerminatedSamePidTwiceYieldsUntilInsertResolves) // given std::atomic_bool first_done{false}; - int32_t ret1 = 2; - int32_t ret2 = 2; + score::lcm::internal::SafeProcessMapReturnTypes ret1 = score::lcm::internal::SafeProcessMapReturnTypes::kUndefined; + score::lcm::internal::SafeProcessMapReturnTypes ret2 = score::lcm::internal::SafeProcessMapReturnTypes::kUndefined; NiceMock cb; @@ -229,15 +237,15 @@ TEST_F(SafeProcessMapTest, FindTerminatedSamePidTwiceYieldsUntilInsertResolves) std::this_thread::sleep_for(std::chrono::milliseconds(10)); // then — first succeeded, second is still blocked - EXPECT_EQ(ret1, 1); - EXPECT_EQ(ret2, 2); + EXPECT_EQ(ret1, score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(ret2, score::lcm::internal::SafeProcessMapReturnTypes::kUndefined); // when — resolve the anomaly - EXPECT_EQ(sut_.insertIfNotTerminated(42, &cb), 1); + EXPECT_EQ(sut_.insertIfNotTerminated(42, &cb), score::lcm::internal::SafeProcessMapReturnTypes::kYield); finder.join(); // then - EXPECT_EQ(ret2, 1); + EXPECT_EQ(ret2, score::lcm::internal::SafeProcessMapReturnTypes::kYield); } // --- Max depth tree --- @@ -247,51 +255,53 @@ TEST_F(SafeProcessMapTest, FindTerminatedWorksAtMaxTreeDepth) RecordProperty("Description", "The binary tree handles maximum depth correctly."); // given — build a deep tree using bit patterns that always branch one way - EXPECT_EQ(sut_.findTerminated(0x00000000, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x00000001, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x00000002, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x00000003, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x00000007, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x0000000F, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x0000001F, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x0000003F, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x0000007F, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x000000FF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x000001FF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x000003FF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x000007FF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x00000FFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x00001FFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x00003FFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x00007FFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x0000FFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x0000FFFE, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x0001FFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x0003FFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x0007FFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x000FFFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x001FFFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x003FFFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x007FFFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x00FFFFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x01FFFFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x03FFFFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x07FFFFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x0FFFFFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x1FFFFFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x3FFFFFFF, 0), 1); - EXPECT_EQ(sut_.findTerminated(0x7FFFFFFF, 0), 1); + EXPECT_EQ(sut_.findTerminated(0x00000000, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x00000001, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x00000002, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x00000003, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x00000007, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x0000000F, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x0000001F, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x0000003F, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x0000007F, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x000000FF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x000001FF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x000003FF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x000007FF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x00000FFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x00001FFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x00003FFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x00007FFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x0000FFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x0000FFFE, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x0001FFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x0003FFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x0007FFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x000FFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x001FFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x003FFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x007FFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x00FFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x01FFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x03FFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x07FFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x0FFFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x1FFFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x3FFFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x7FFFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); // when / then — boundary values - EXPECT_EQ(sut_.findTerminated(static_cast(0xFFFFFFFF), 0), -2); - EXPECT_EQ(sut_.insertIfNotTerminated(static_cast(0xFFFFFFFF), &callback_), -2); + EXPECT_EQ(sut_.findTerminated(static_cast(0xFFFFFFFF), 0), + score::lcm::internal::SafeProcessMapReturnTypes::kInvalidIdError); + EXPECT_EQ(sut_.insertIfNotTerminated(static_cast(0xFFFFFFFF), &callback_), + score::lcm::internal::SafeProcessMapReturnTypes::kInvalidIdError); // when / then — retrieve entries using insertIfNotTerminated NiceMock cb; - EXPECT_EQ(sut_.insertIfNotTerminated(0x0000FFFE, &cb), 1); - EXPECT_EQ(sut_.insertIfNotTerminated(0x00010000, &cb), 0); - EXPECT_EQ(sut_.insertIfNotTerminated(0x0001FFFF, &cb), 1); - EXPECT_EQ(sut_.insertIfNotTerminated(0x00000002, &cb), 1); + EXPECT_EQ(sut_.insertIfNotTerminated(0x0000FFFE, &cb), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.insertIfNotTerminated(0x00010000, &cb), score::lcm::internal::SafeProcessMapReturnTypes::kOk); + EXPECT_EQ(sut_.insertIfNotTerminated(0x0001FFFF, &cb), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.insertIfNotTerminated(0x00000002, &cb), score::lcm::internal::SafeProcessMapReturnTypes::kYield); } // --- Multi-threaded stress tests --- @@ -306,7 +316,7 @@ TEST_F(SafeProcessMapTest, ConcurrentInsertAndFindFromMultipleThreads) constexpr int kIterations = 1000; constexpr int kPidsPerThread = 256; NiceMock stubs[kNumThreads]; - int results[kNumThreads] = {}; + score::lcm::internal::SafeProcessMapReturnTypes results[kNumThreads] = {}; // when std::vector threads; @@ -337,7 +347,7 @@ TEST_F(SafeProcessMapTest, ConcurrentInsertAndFindFromMultipleThreads) // then for (int t = 0; t < kNumThreads; ++t) { - EXPECT_EQ(results[t], 0); + EXPECT_EQ(results[t], score::lcm::internal::SafeProcessMapReturnTypes::kOk); } } @@ -351,7 +361,7 @@ TEST_F(SafeProcessMapTest, ConcurrentFindAndInsertFromMultipleThreads) constexpr int kIterations = 1000; constexpr int kPidsPerThread = 256; NiceMock stubs[kNumThreads]; - int results[kNumThreads] = {}; + score::lcm::internal::SafeProcessMapReturnTypes results[kNumThreads] = {}; // when std::vector threads; @@ -382,7 +392,7 @@ TEST_F(SafeProcessMapTest, ConcurrentFindAndInsertFromMultipleThreads) // then for (int t = 0; t < kNumThreads; ++t) { - EXPECT_EQ(results[t], 1); + EXPECT_EQ(results[t], score::lcm::internal::SafeProcessMapReturnTypes::kYield); } } From 08c2410960ee33d7aef8fbe947f42b2a08d3c28a Mon Sep 17 00:00:00 2001 From: Nemanja Trifunovic Date: Thu, 11 Jun 2026 08:27:02 +0000 Subject: [PATCH 2/3] Adding small fixes --- .../details/os_handler.cpp | 2 +- .../details/oshandler_UT.cpp | 4 +- .../details/process_info_node.cpp | 6 +- .../details/safe_process_map.cpp | 9 +- .../details/safe_process_map.hpp | 40 ++-- .../details/safeprocessmap_UT.cpp | 196 +++++++++++------- 6 files changed, 152 insertions(+), 105 deletions(-) diff --git a/score/launch_manager/daemon/src/process_group_manager/details/os_handler.cpp b/score/launch_manager/daemon/src/process_group_manager/details/os_handler.cpp index 0951588b..f57b1dc5 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/os_handler.cpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/os_handler.cpp @@ -31,7 +31,7 @@ void OsHandler::run(void) if (result.has_value() && result.value() > 0) { - if (score::lcm::internal::SafeProcessMapReturnTypes::kInsertionError == + if (score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kInsertionError == safe_process_map_.findTerminated(result.value(), wait_status)) { LM_LOG_ERROR() << "No more resources available to track process with PID " << result.value() diff --git a/score/launch_manager/daemon/src/process_group_manager/details/oshandler_UT.cpp b/score/launch_manager/daemon/src/process_group_manager/details/oshandler_UT.cpp index 15b43826..997f6bcb 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/oshandler_UT.cpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/oshandler_UT.cpp @@ -155,7 +155,7 @@ TEST_F(OsHandlerTest, WaitReturnsProcessIdBeforeRegistration_LaterRegistrationRe StrictMock callback; EXPECT_CALL(callback, terminated(99)).Times(1); EXPECT_EQ(process_map_.insertIfNotTerminated(4000, &callback), - score::lcm::internal::SafeProcessMapReturnTypes::kYield); + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); sut_.reset(); } @@ -171,7 +171,7 @@ TEST_F(OsHandlerTest, WaitReturnsUnknownPidWhenMapIsFull_OutOfResourcesPathDoesN for (uint32_t i = 0; i < kCapacity; ++i) { ASSERT_EQ(process_map_.insertIfNotTerminated(static_cast(i + 1U), &callbacks[i]), - score::lcm::internal::SafeProcessMapReturnTypes::kOk); + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kOk); } EXPECT_CALL(*sys_wait_mock_, wait(_)) diff --git a/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.cpp b/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.cpp index 9c73e94d..426c9416 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.cpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.cpp @@ -407,11 +407,11 @@ void ProcessInfoNode::handleProcessStarted(uint32_t execution_error_code) { switch (graph_->getProcessGroupManager()->getProcessMap()->insertIfNotTerminated(pid_, this)) { - case score::lcm::internal::SafeProcessMapReturnTypes::kOk: // Normal case, entry was put in - // the map, process still running + case score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kOk: // Normal case, entry was put in + // the map, process still running handleProcessStillStarting(execution_error_code); break; - case score::lcm::internal::SafeProcessMapReturnTypes::kYield: // Process has already exited + case score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield: // Process has already exited handleProcessAlreadyTerminated(execution_error_code); break; default: // Error case when pn == -1 diff --git a/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.cpp b/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.cpp index 2bfd0415..85620404 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.cpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.cpp @@ -302,14 +302,15 @@ int32_t SafeProcessMap::search(osal::ProcessID key, ProcessInfoData data) return ret_value; } -SafeProcessMapReturnTypes SafeProcessMap::findTerminated(osal::ProcessID key, int32_t status) +SafeProcessMap::SafeProcessMapReturnType SafeProcessMap::findTerminated(osal::ProcessID key, int32_t status) { - return static_cast(search(key, {status, nullptr})); + return static_cast(search(key, {status, nullptr})); } -SafeProcessMapReturnTypes SafeProcessMap::insertIfNotTerminated(osal::ProcessID key, ITerminationCallback* object) +SafeProcessMap::SafeProcessMapReturnType SafeProcessMap::insertIfNotTerminated(osal::ProcessID key, + ITerminationCallback* object) { - return static_cast(search(key, {0, object})); + return static_cast(search(key, {0, object})); } } // namespace internal diff --git a/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.hpp b/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.hpp index 85dd7db1..93f83003 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.hpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.hpp @@ -63,30 +63,30 @@ struct ProcessTreeNode ProcessInfoData data_; }; -enum class SafeProcessMapReturnTypes : std::int32_t -{ - /// @brief Method successfully executed. - kOk = 0, - - /// @brief Clash due to PID re-use, method yields until the situation is resolved. - kYield = 1, - - /// @brief An error occurred during insertion (e.g., out of memory). - kInsertionError = -1, - - /// @brief The provided process ID (`key`) is not valid ( < 0). - kInvalidIdError = -2, - - /// @brief The state is not defined. - kUndefined = 2, -}; - /// @brief The SafeProcessMap class provides a thread-safe mapping of unique process IDs (ProcessID) to /// ITerminationCallback pointers. It ensures safe concurrent access and modification of the mapping, using atomic /// operations. class SafeProcessMap final { public: + /// @brief Enum type used for public methods retrun value. + enum class SafeProcessMapReturnType : std::int32_t + { + /// @brief Method successfully executed. + kOk = 0, + + /// @brief Clash due to PID re-use, method yields until the situation is resolved. + kYield = 1, + + /// @brief An error occurred during insertion (e.g., out of memory). + kInsertionError = -1, + + /// @brief The provided process ID (`key`) is not valid ( < 0). + kInvalidIdError = -2, + + /// @brief The state is not defined. + kUndefined = 2, + }; /// @brief Constructs a SafeProcessMap with a specified capacity. /// This constructor initializes the SafeProcessMap with the given capacity. /// @param capacity The maximum number of entries that the SafeProcessMap can hold. @@ -105,7 +105,7 @@ class SafeProcessMap final /// 1 if the process ID was not found and an already-terminated entry was inserted, /// -1 if an error occurred during insertion (e.g., out of memory), /// or -2 if the provided process ID (`key`) is not valid (< 0). - SafeProcessMapReturnTypes findTerminated(osal::ProcessID key, int32_t status); + SafeProcessMapReturnType findTerminated(osal::ProcessID key, int32_t status); /// @brief Inserts a process into the map if it has not already terminated. /// This method is called by a worker thread after starting a process. It attempts to insert the given process ID @@ -118,7 +118,7 @@ class SafeProcessMap final /// 1 if the key was found (indicating the process has terminated), and updated with the provided object, /// -1 if an error occurred during insertion (e.g., out of memory), /// or -2 if the provided process ID (`key`) is not valid ( < 0). - SafeProcessMapReturnTypes insertIfNotTerminated(osal::ProcessID key, ITerminationCallback* object); + SafeProcessMapReturnType insertIfNotTerminated(osal::ProcessID key, ITerminationCallback* object); private: /// @brief Searches for a process with the given process ID (key) in the map. diff --git a/score/launch_manager/daemon/src/process_group_manager/details/safeprocessmap_UT.cpp b/score/launch_manager/daemon/src/process_group_manager/details/safeprocessmap_UT.cpp index a90bcbca..077c8cd7 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/safeprocessmap_UT.cpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/safeprocessmap_UT.cpp @@ -1,14 +1,14 @@ /******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation + * Copyright (c) 2026 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. * * This program and the accompanying materials are made available under the - * terms of the Apache License Version score::lcm::internal::SafeProcessMapReturnTypes::kUndefined.0 which is available - *at https://www.apache.org/licenses/LICENSE-score::lcm::internal::SafeProcessMapReturnTypes::kUndefined.0 + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 * - * SPDX-License-Identifier: Apache-score::lcm::internal::SafeProcessMapReturnTypes::kUndefined.0 + * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ #include @@ -64,14 +64,15 @@ TEST_F(SafeProcessMapTest, ConstructWithZeroCapacity) TEST_F(SafeProcessMapTest, FindTerminatedWithNegativePidReturnsInvalid) { RecordProperty("Description", - "findTerminated returns -score::lcm::internal::SafeProcessMapReturnTypes::kUndefined for a negative " + "findTerminated returns -score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kUndefined " + "for a negative " "process ID."); // when - score::lcm::internal::SafeProcessMapReturnTypes result = sut_.findTerminated(-1, 1000); + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType result = sut_.findTerminated(-1, 1000); // then - EXPECT_EQ(result, score::lcm::internal::SafeProcessMapReturnTypes::kInvalidIdError); + EXPECT_EQ(result, score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kInvalidIdError); } TEST_F(SafeProcessMapTest, FindTerminatedInsertsEntryWhenPidNotPresent) @@ -80,10 +81,10 @@ TEST_F(SafeProcessMapTest, FindTerminatedInsertsEntryWhenPidNotPresent) "findTerminated inserts an entry and returns kYield (1) when the PID is not in the map."); // when - score::lcm::internal::SafeProcessMapReturnTypes result = sut_.findTerminated(1000, 0); + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType result = sut_.findTerminated(1000, 0); // then - EXPECT_EQ(result, score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(result, score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); } TEST_F(SafeProcessMapTest, FindTerminatedMatchesExistingInsertAndCallsCallback) @@ -98,8 +99,8 @@ TEST_F(SafeProcessMapTest, FindTerminatedMatchesExistingInsertAndCallsCallback) EXPECT_CALL(callback_, terminated(42)); // when - score::lcm::internal::SafeProcessMapReturnTypes result = sut_.findTerminated(1000, 42); - EXPECT_EQ(result, score::lcm::internal::SafeProcessMapReturnTypes::kOk); + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType result = sut_.findTerminated(1000, 42); + EXPECT_EQ(result, score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kOk); } // --- insertIfNotTerminated --- @@ -109,10 +110,11 @@ TEST_F(SafeProcessMapTest, InsertIntoEmptyTreeReturnsZero) RecordProperty("Description", "insertIfNotTerminated returns kOk (0) when inserting into an empty tree."); // when - score::lcm::internal::SafeProcessMapReturnTypes result = sut_.insertIfNotTerminated(2000, &callback_); + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType result = + sut_.insertIfNotTerminated(2000, &callback_); // then - EXPECT_EQ(result, score::lcm::internal::SafeProcessMapReturnTypes::kOk); + EXPECT_EQ(result, score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kOk); } TEST_F(SafeProcessMapTest, InsertMatchesExistingFindTerminatedEntry) @@ -127,10 +129,11 @@ TEST_F(SafeProcessMapTest, InsertMatchesExistingFindTerminatedEntry) EXPECT_CALL(callback_, terminated(0)); // when - score::lcm::internal::SafeProcessMapReturnTypes result = sut_.insertIfNotTerminated(1000, &callback_); + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType result = + sut_.insertIfNotTerminated(1000, &callback_); // then - EXPECT_EQ(result, score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(result, score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); } TEST_F(SafeProcessMapTest, InsertMultipleNodesThenFindTerminatedRemovesAll) @@ -149,7 +152,7 @@ TEST_F(SafeProcessMapTest, InsertMultipleNodesThenFindTerminatedRemovesAll) for (uint32_t j = 1; j <= kCapacity; ++j) { EXPECT_EQ(sut_.findTerminated(static_cast(j), 0), - score::lcm::internal::SafeProcessMapReturnTypes::kOk); + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kOk); } } @@ -164,15 +167,15 @@ TEST_F(SafeProcessMapTest, InsertBeyondCapacityReturnsOutOfMemory) for (uint32_t i = 0; i < kCapacity; ++i) { EXPECT_EQ(sut_.insertIfNotTerminated(static_cast(i), &callbacks[i]), - score::lcm::internal::SafeProcessMapReturnTypes::kOk); + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kOk); } // when - score::lcm::internal::SafeProcessMapReturnTypes result = + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType result = sut_.insertIfNotTerminated(static_cast(kCapacity + 1), &callback_); // then - EXPECT_EQ(result, score::lcm::internal::SafeProcessMapReturnTypes::kInsertionError); + EXPECT_EQ(result, score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kInsertionError); } // --- Anomalous (PID reuse) cases --- @@ -184,8 +187,10 @@ TEST_F(SafeProcessMapTest, InsertSamePidTwiceYieldsUntilFindTerminatedResolves) // given std::atomic_bool first_done{false}; - score::lcm::internal::SafeProcessMapReturnTypes ret1 = score::lcm::internal::SafeProcessMapReturnTypes::kUndefined; - score::lcm::internal::SafeProcessMapReturnTypes ret2 = score::lcm::internal::SafeProcessMapReturnTypes::kUndefined; + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType ret1 = + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kUndefined; + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType ret2 = + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kUndefined; NiceMock cb; @@ -201,15 +206,15 @@ TEST_F(SafeProcessMapTest, InsertSamePidTwiceYieldsUntilFindTerminatedResolves) std::this_thread::sleep_for(std::chrono::milliseconds(10)); // then — first succeeded, second is still blocked - EXPECT_EQ(ret1, score::lcm::internal::SafeProcessMapReturnTypes::kOk); - EXPECT_EQ(ret2, score::lcm::internal::SafeProcessMapReturnTypes::kUndefined); + EXPECT_EQ(ret1, score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kOk); + EXPECT_EQ(ret2, score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kUndefined); // when — resolve the anomaly - EXPECT_EQ(sut_.findTerminated(42, 0), score::lcm::internal::SafeProcessMapReturnTypes::kOk); + EXPECT_EQ(sut_.findTerminated(42, 0), score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kOk); inserter.join(); // then - EXPECT_EQ(ret2, score::lcm::internal::SafeProcessMapReturnTypes::kOk); + EXPECT_EQ(ret2, score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kOk); } TEST_F(SafeProcessMapTest, FindTerminatedSamePidTwiceYieldsUntilInsertResolves) @@ -220,8 +225,10 @@ TEST_F(SafeProcessMapTest, FindTerminatedSamePidTwiceYieldsUntilInsertResolves) // given std::atomic_bool first_done{false}; - score::lcm::internal::SafeProcessMapReturnTypes ret1 = score::lcm::internal::SafeProcessMapReturnTypes::kUndefined; - score::lcm::internal::SafeProcessMapReturnTypes ret2 = score::lcm::internal::SafeProcessMapReturnTypes::kUndefined; + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType ret1 = + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kUndefined; + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType ret2 = + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kUndefined; NiceMock cb; @@ -237,15 +244,16 @@ TEST_F(SafeProcessMapTest, FindTerminatedSamePidTwiceYieldsUntilInsertResolves) std::this_thread::sleep_for(std::chrono::milliseconds(10)); // then — first succeeded, second is still blocked - EXPECT_EQ(ret1, score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(ret2, score::lcm::internal::SafeProcessMapReturnTypes::kUndefined); + EXPECT_EQ(ret1, score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(ret2, score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kUndefined); // when — resolve the anomaly - EXPECT_EQ(sut_.insertIfNotTerminated(42, &cb), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.insertIfNotTerminated(42, &cb), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); finder.join(); // then - EXPECT_EQ(ret2, score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(ret2, score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); } // --- Max depth tree --- @@ -255,53 +263,91 @@ TEST_F(SafeProcessMapTest, FindTerminatedWorksAtMaxTreeDepth) RecordProperty("Description", "The binary tree handles maximum depth correctly."); // given — build a deep tree using bit patterns that always branch one way - EXPECT_EQ(sut_.findTerminated(0x00000000, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x00000001, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x00000002, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x00000003, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x00000007, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x0000000F, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x0000001F, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x0000003F, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x0000007F, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x000000FF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x000001FF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x000003FF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x000007FF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x00000FFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x00001FFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x00003FFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x00007FFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x0000FFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x0000FFFE, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x0001FFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x0003FFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x0007FFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x000FFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x001FFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x003FFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x007FFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x00FFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x01FFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x03FFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x07FFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x0FFFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x1FFFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x3FFFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.findTerminated(0x7FFFFFFF, 0), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.findTerminated(0x00000000, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x00000001, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x00000002, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x00000003, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x00000007, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x0000000F, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x0000001F, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x0000003F, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x0000007F, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x000000FF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x000001FF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x000003FF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x000007FF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x00000FFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x00001FFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x00003FFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x00007FFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x0000FFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x0000FFFE, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x0001FFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x0003FFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x0007FFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x000FFFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x001FFFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x003FFFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x007FFFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x00FFFFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x01FFFFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x03FFFFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x07FFFFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x0FFFFFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x1FFFFFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x3FFFFFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.findTerminated(0x7FFFFFFF, 0), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); // when / then — boundary values EXPECT_EQ(sut_.findTerminated(static_cast(0xFFFFFFFF), 0), - score::lcm::internal::SafeProcessMapReturnTypes::kInvalidIdError); + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kInvalidIdError); EXPECT_EQ(sut_.insertIfNotTerminated(static_cast(0xFFFFFFFF), &callback_), - score::lcm::internal::SafeProcessMapReturnTypes::kInvalidIdError); + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kInvalidIdError); // when / then — retrieve entries using insertIfNotTerminated NiceMock cb; - EXPECT_EQ(sut_.insertIfNotTerminated(0x0000FFFE, &cb), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.insertIfNotTerminated(0x00010000, &cb), score::lcm::internal::SafeProcessMapReturnTypes::kOk); - EXPECT_EQ(sut_.insertIfNotTerminated(0x0001FFFF, &cb), score::lcm::internal::SafeProcessMapReturnTypes::kYield); - EXPECT_EQ(sut_.insertIfNotTerminated(0x00000002, &cb), score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(sut_.insertIfNotTerminated(0x0000FFFE, &cb), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.insertIfNotTerminated(0x00010000, &cb), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kOk); + EXPECT_EQ(sut_.insertIfNotTerminated(0x0001FFFF, &cb), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); + EXPECT_EQ(sut_.insertIfNotTerminated(0x00000002, &cb), + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); } // --- Multi-threaded stress tests --- @@ -316,7 +362,7 @@ TEST_F(SafeProcessMapTest, ConcurrentInsertAndFindFromMultipleThreads) constexpr int kIterations = 1000; constexpr int kPidsPerThread = 256; NiceMock stubs[kNumThreads]; - score::lcm::internal::SafeProcessMapReturnTypes results[kNumThreads] = {}; + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType results[kNumThreads] = {}; // when std::vector threads; @@ -347,7 +393,7 @@ TEST_F(SafeProcessMapTest, ConcurrentInsertAndFindFromMultipleThreads) // then for (int t = 0; t < kNumThreads; ++t) { - EXPECT_EQ(results[t], score::lcm::internal::SafeProcessMapReturnTypes::kOk); + EXPECT_EQ(results[t], score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kOk); } } @@ -361,7 +407,7 @@ TEST_F(SafeProcessMapTest, ConcurrentFindAndInsertFromMultipleThreads) constexpr int kIterations = 1000; constexpr int kPidsPerThread = 256; NiceMock stubs[kNumThreads]; - score::lcm::internal::SafeProcessMapReturnTypes results[kNumThreads] = {}; + score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType results[kNumThreads] = {}; // when std::vector threads; @@ -392,7 +438,7 @@ TEST_F(SafeProcessMapTest, ConcurrentFindAndInsertFromMultipleThreads) // then for (int t = 0; t < kNumThreads; ++t) { - EXPECT_EQ(results[t], score::lcm::internal::SafeProcessMapReturnTypes::kYield); + EXPECT_EQ(results[t], score::lcm::internal::SafeProcessMap::SafeProcessMapReturnType::kYield); } } From 956560f77e5affed50a08dcdeeddbd3e718b5c04 Mon Sep 17 00:00:00 2001 From: Nemanja Trifunovic Date: Fri, 12 Jun 2026 13:11:05 +0000 Subject: [PATCH 3/3] Fixing comments --- .../details/safe_process_map.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.hpp b/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.hpp index 93f83003..00d5fdf8 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.hpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/safe_process_map.hpp @@ -101,10 +101,10 @@ class SafeProcessMap final /// as already terminated. /// In the case of a clash due to PID re-use, this method yields until the situation is resolved. /// @param key The process ID to look for in the map. - /// @return 0 if the process ID was found and the registered callback was notified with `status`, - /// 1 if the process ID was not found and an already-terminated entry was inserted, - /// -1 if an error occurred during insertion (e.g., out of memory), - /// or -2 if the provided process ID (`key`) is not valid (< 0). + /// @return kOk if the process ID was found and the registered callback was notified with `status`, + /// kYield if the process ID was not found and an already-terminated entry was inserted, + /// kInsertionError if an error occurred during insertion (e.g., out of memory), + /// or kInvalidIdError if the provided process ID (`key`) is not valid (< 0). SafeProcessMapReturnType findTerminated(osal::ProcessID key, int32_t status); /// @brief Inserts a process into the map if it has not already terminated. @@ -114,10 +114,10 @@ class SafeProcessMap final /// resolved. /// @param key The process ID to insert into the map. /// @param object A pointer to the ITerminationCallback associated with the process. - /// @return 0 if the key (Process ID) was not found and a new entry was made, - /// 1 if the key was found (indicating the process has terminated), and updated with the provided object, - /// -1 if an error occurred during insertion (e.g., out of memory), - /// or -2 if the provided process ID (`key`) is not valid ( < 0). + /// @return kOk if the key (Process ID) was not found and a new entry was made, + /// kYield if the key was found (indicating the process has terminated), and updated with the provided + /// object, kInsertionError if an error occurred during insertion (e.g., out of memory), or kInvalidIdError + /// if the provided process ID (`key`) is not valid ( < 0). SafeProcessMapReturnType insertIfNotTerminated(osal::ProcessID key, ITerminationCallback* object); private: