From 956a7d7bf49ae2119a1a5ab0967a49df8d735d8d Mon Sep 17 00:00:00 2001 From: "Empting Eelco (ETAS-ECM/XPC-Fe2)" Date: Fri, 16 Jan 2026 09:27:42 +0000 Subject: [PATCH 1/6] Bring in changes --- .devcontainer/devcontainer.json | 4 +- MODULE.bazel | 2 +- examples/run.sh | 6 +- src/launch_manager_daemon/BUILD | 1 + .../lcm/saf/daemon/HealthMonitorImpl.cpp | 8 +- .../lcm/saf/daemon/HealthMonitorImpl.hpp | 5 +- .../src/score/lcm/saf/daemon/PhmDaemon.cpp | 54 ++++++------- .../src/score/lcm/saf/daemon/PhmDaemon.hpp | 3 +- .../score/lcm/saf/factory/FlatCfgFactory.cpp | 2 - .../lcm/saf/ifexm/ProcessStateReader.cpp | 55 +++---------- .../lcm/saf/ifexm/ProcessStateReader.hpp | 49 ++++-------- .../process_state_client_lib/BUILD | 8 +- .../score/lcm/iprocessstatenotifier.hpp | 53 +++++++++++++ .../score/lcm/iprocessstatereceiver.hpp | 45 +++++++++++ .../include/score/lcm/posixprocess.hpp | 9 +-- .../include/score/lcm/processstateclient.hpp | 77 ------------------- .../score/lcm}/processstatenotifier.hpp | 24 +++--- .../score/lcm/processstatereceiver.hpp | 71 +++++++++++++++++ .../src}/processstatenotifier.cpp | 27 +++---- ...ateclient.cpp => processstatereceiver.cpp} | 43 ++++------- src/launch_manager_daemon/src/main/main.cpp | 6 +- .../processgroupmanager.cpp | 6 +- .../processgroupmanager.hpp | 9 ++- 23 files changed, 300 insertions(+), 267 deletions(-) create mode 100644 src/launch_manager_daemon/process_state_client_lib/include/score/lcm/iprocessstatenotifier.hpp create mode 100644 src/launch_manager_daemon/process_state_client_lib/include/score/lcm/iprocessstatereceiver.hpp delete mode 100644 src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstateclient.hpp rename src/launch_manager_daemon/{src/process_group_manager => process_state_client_lib/include/score/lcm}/processstatenotifier.hpp (79%) create mode 100644 src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstatereceiver.hpp rename src/launch_manager_daemon/{src/process_group_manager => process_state_client_lib/src}/processstatenotifier.cpp (63%) rename src/launch_manager_daemon/process_state_client_lib/src/{processstateclient.cpp => processstatereceiver.cpp} (51%) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 1585f1e6..539b6e06 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -31,5 +31,7 @@ "onCreateCommand": { "update certificates & install dependencies": "sudo apt update && sudo apt install -y --no-install-recommends ca-certificates-java openjdk-17-jre-headless libacl1-dev tmux && sudo update-ca-certificates", "bazel use system trust store": "echo 'startup --host_jvm_args=-Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts --host_jvm_args=-Djavax.net.ssl.trustStorePassword=changeit' | sudo tee --append /etc/bazel.bazelrc" - } + }, + + "runArgs": ["--network", "host"] } diff --git a/MODULE.bazel b/MODULE.bazel index c8a8abc9..5d5c25b1 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -47,7 +47,7 @@ bazel_dep(name = "score_crates", version = "0.0.6") # Overrides git_override( module_name = "score_tooling", - commit = "612d6f180a9bb6338de5f0e6667fcf83068d9c37", #until 1.0.5 is released + commit = "a6636c20dacdfa44b65ab7f249e7d1c8b8e15e4b", #until 1.0.5 is released remote = "https://github.com/eclipse-score/tooling.git", ) diff --git a/examples/run.sh b/examples/run.sh index 073592db..65cfc7f9 100755 --- a/examples/run.sh +++ b/examples/run.sh @@ -47,15 +47,15 @@ rm -rf tmp rm -rf config/tmp mkdir config/tmp python3 config/gen_health_monitor_process_cfg.py -c "$NUMBER_OF_CPP_PROCESSES_PER_PROCESS_GROUP" -r "$NUMBER_OF_RUST_PROCESSES_PER_PROCESS_GROUP" $PROCESS_GROUPS -o config/tmp/ -../bazel-bin/external/flatbuffers+/flatc --binary -o config/tmp ../src/health_monitor_lib/config/hm_flatcfg.fbs config/tmp/health_monitor_process_cfg_*.json +../bazel-bin/external/flatbuffers+/flatc --binary -o config/tmp ../src/launch_manager_daemon/health_monitor_lib/config/hm_flatcfg.fbs config/tmp/health_monitor_process_cfg_*.json python3 config/gen_health_monitor_cfg.py -c "$NUMBER_OF_CPP_PROCESSES_PER_PROCESS_GROUP" -r "$NUMBER_OF_RUST_PROCESSES_PER_PROCESS_GROUP" $PROCESS_GROUPS -o config/tmp/ -../bazel-bin/external/flatbuffers+/flatc --binary -o config/tmp ../src/health_monitor_lib/config/hm_flatcfg.fbs config/tmp/hm_demo.json +../bazel-bin/external/flatbuffers+/flatc --binary -o config/tmp ../src/launch_manager_daemon/health_monitor_lib/config/hm_flatcfg.fbs config/tmp/hm_demo.json python3 config/gen_launch_manager_cfg.py -c "$NUMBER_OF_CPP_PROCESSES_PER_PROCESS_GROUP" -r "$NUMBER_OF_RUST_PROCESSES_PER_PROCESS_GROUP" -n "$NUMBER_OF_NON_SUPERVISED_CPP_PROCESSES_PER_PROCESS_GROUP" $PROCESS_GROUPS -o config/tmp/ ../bazel-bin/external/flatbuffers+/flatc --binary -o config/tmp ../src/launch_manager_daemon/config/lm_flatcfg.fbs config/tmp/lm_demo.json -../bazel-bin/external/flatbuffers+/flatc --binary -o config/tmp ../src/health_monitor_lib/config/hmcore_flatcfg.fbs config/hmcore.json +../bazel-bin/external/flatbuffers+/flatc --binary -o config/tmp ../src/launch_manager_daemon/health_monitor_lib/config/hmcore_flatcfg.fbs config/hmcore.json mkdir -p tmp/launch_manager/etc cp $LM_BINARY tmp/launch_manager/launch_manager diff --git a/src/launch_manager_daemon/BUILD b/src/launch_manager_daemon/BUILD index e82e4a5a..b6b48ef7 100644 --- a/src/launch_manager_daemon/BUILD +++ b/src/launch_manager_daemon/BUILD @@ -43,6 +43,7 @@ cc_binary_with_common_opts( "//src/launch_manager_daemon/common:lifecycle_error", "//src/launch_manager_daemon/common:log", "//src/launch_manager_daemon/health_monitor_lib:health_monitor", + "//src/launch_manager_daemon/process_state_client_lib:process_state_client", "@flatbuffers", "@score_baselibs//score/mw/log", "@score_baselibs//score/result", diff --git a/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/HealthMonitorImpl.cpp b/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/HealthMonitorImpl.cpp index 468a6de8..ab49c3e3 100644 --- a/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/HealthMonitorImpl.cpp +++ b/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/HealthMonitorImpl.cpp @@ -24,15 +24,15 @@ namespace lcm { namespace saf { namespace daemon { -HealthMonitorImpl::HealthMonitorImpl(std::shared_ptr recovery_client, std::unique_ptr watchdog) - : m_recovery_client(recovery_client), m_watchdog(std::move(watchdog)), m_logger{score::lcm::saf::logging::PhmLogger::getLogger(score::lcm::saf::logging::PhmLogger::EContext::factory)} {} +HealthMonitorImpl::HealthMonitorImpl(std::shared_ptr recovery_client, std::unique_ptr watchdog, std::unique_ptr process_state_receiver) + : m_recovery_client(recovery_client), m_watchdog(std::move(watchdog)), m_logger{score::lcm::saf::logging::PhmLogger::getLogger(score::lcm::saf::logging::PhmLogger::EContext::factory)}, m_process_state_receiver{std::move(process_state_receiver)} {} EInitCode HealthMonitorImpl::init() noexcept { score::lcm::saf::daemon::EInitCode initResult{score::lcm::saf::daemon::EInitCode::kGeneralError}; try { m_osClock.startMeasurement(); - m_daemon = std::make_unique(m_osClock, m_logger, std::move(m_watchdog)); + m_daemon = std::make_unique(m_osClock, m_logger, std::move(m_watchdog), std::move(m_process_state_receiver)); initResult = m_daemon->init(m_recovery_client); if (initResult == score::lcm::saf::daemon::EInitCode::kNoError) { @@ -60,4 +60,4 @@ bool HealthMonitorImpl::run(std::atomic_bool& cancel_thread) noexcept { } // namespace daemon } // namespace saf } // namespace lcm -} // namespace score \ No newline at end of file +} // namespace score diff --git a/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/HealthMonitorImpl.hpp b/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/HealthMonitorImpl.hpp index 8652e46c..c96b035f 100644 --- a/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/HealthMonitorImpl.hpp +++ b/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/HealthMonitorImpl.hpp @@ -33,7 +33,7 @@ namespace daemon { class HealthMonitorImpl : public IHealthMonitor { public: - HealthMonitorImpl(std::shared_ptr recovery_client, std::unique_ptr watchdog); + HealthMonitorImpl(std::shared_ptr recovery_client, std::unique_ptr watchdog, std::unique_ptr process_state_receiver); EInitCode init() noexcept override; @@ -45,6 +45,7 @@ class HealthMonitorImpl : public IHealthMonitor { score::lcm::saf::logging::PhmLogger& m_logger; std::unique_ptr m_daemon{nullptr}; score::lcm::saf::timers::OsClockInterface m_osClock{}; + std::unique_ptr m_process_state_receiver; }; } // namespace daemon @@ -52,4 +53,4 @@ class HealthMonitorImpl : public IHealthMonitor { } // namespace lcm } // namespace score -#endif \ No newline at end of file +#endif diff --git a/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/PhmDaemon.cpp b/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/PhmDaemon.cpp index 60508d51..69c84308 100644 --- a/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/PhmDaemon.cpp +++ b/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/PhmDaemon.cpp @@ -36,8 +36,8 @@ namespace daemon /* RULECHECKER_comment(0, 4, check_incomplete_data_member_construction, "Default constructor is used for\ processStateReader.", true_no_defect) */ PhmDaemon::PhmDaemon(score::lcm::saf::timers::OsClockInterface& f_osClock, logging::PhmLogger& f_logger_r, - std::unique_ptr f_watchdog) : - osClock{f_osClock}, cycleTimer{&osClock}, logger_r{f_logger_r}, swClusterHandlers{}, watchdog(std::move(f_watchdog)) + std::unique_ptr f_watchdog, std::unique_ptr f_process_state_receiver) : + osClock{f_osClock}, cycleTimer{&osClock}, logger_r{f_logger_r}, swClusterHandlers{}, watchdog(std::move(f_watchdog)), processStateReader{std::move(f_process_state_receiver)} { static_cast(f_osClock); } @@ -84,40 +84,36 @@ void PhmDaemon::performCyclicTriggers(void) bool PhmDaemon::construct(const factory::MachineConfigFactory::SupervisionBufferConfig& f_bufferConfig_r) noexcept( false) { - bool isSuccess{processStateReader.init()}; + bool isSuccess{true}; - if (isSuccess) + score::Result> listSwClustersPhm{{"MainCluster"}}; + if (!listSwClustersPhm.has_value()) { - - score::Result> listSwClustersPhm{{"MainCluster"}}; - if (!listSwClustersPhm.has_value()) + logger_r.LogError() + << "Phm Daemon: retrieving the list of PHM software cluster configurations failed with error:" + << listSwClustersPhm.error().Message(); + isSuccess = false; + } + else + { + if (listSwClustersPhm.value().size() == 0U) { - logger_r.LogError() - << "Phm Daemon: retrieving the list of PHM software cluster configurations failed with error:" - << listSwClustersPhm.error().Message(); - isSuccess = false; + logger_r.LogWarn() << "Phm Daemon: is starting without any software cluster configurations!"; } - else - { - if (listSwClustersPhm.value().size() == 0U) - { - logger_r.LogWarn() << "Phm Daemon: is starting without any software cluster configurations!"; - } - // Reserve the vector swClusterHandlers obtained from flatcfg before constructing the SwClusters - swClusterHandlers.reserve(listSwClustersPhm.value().size()); + // Reserve the vector swClusterHandlers obtained from flatcfg before constructing the SwClusters + swClusterHandlers.reserve(listSwClustersPhm.value().size()); - for (auto strSwClusterName : listSwClustersPhm.value()) + for (auto strSwClusterName : listSwClustersPhm.value()) + { + swClusterHandlers.emplace_back(strSwClusterName); + isSuccess = + swClusterHandlers.back().constructWorkers(recoveryClient, processStateReader, f_bufferConfig_r); + if (!isSuccess) { - swClusterHandlers.emplace_back(strSwClusterName); - isSuccess = - swClusterHandlers.back().constructWorkers(recoveryClient, processStateReader, f_bufferConfig_r); - if (!isSuccess) - { - logger_r.LogError() << "Phm Daemon: failed to create worker objects for swclusterhandler:" - << strSwClusterName; - break; - } + logger_r.LogError() << "Phm Daemon: failed to create worker objects for swclusterhandler:" + << strSwClusterName; + break; } } } diff --git a/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/PhmDaemon.hpp b/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/PhmDaemon.hpp index bfdd7080..7728155d 100644 --- a/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/PhmDaemon.hpp +++ b/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/daemon/PhmDaemon.hpp @@ -66,10 +66,11 @@ class PhmDaemon /// @param[in] f_osClock Access to the system clock (dependency injection possible in tests) /// @param[in] f_logger_r Reference to the logger (dependency injection possible in tests) /// @param[in] f_watchdog watchdog implementation (dependency injection possible in tests) + /// @param[in] f_process_state_receiver process state receiver implementation (dependency injection possible in tests) /* RULECHECKER_comment(3,1, check_expensive_to_copy_in_parameter, "Move only types cannot be passed by const ref", true_no_defect) */ PhmDaemon(score::lcm::saf::timers::OsClockInterface& f_osClock, logging::PhmLogger& f_logger_r, - std::unique_ptr f_watchdog); + std::unique_ptr f_watchdog, std::unique_ptr f_process_state_receiver); /* RULECHECKER_comment(0, 4, check_min_instructions, "Default destructor is not provided\ a function body", true_no_defect) */ diff --git a/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/factory/FlatCfgFactory.cpp b/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/factory/FlatCfgFactory.cpp index 9dd4697e..ea8cbf3c 100644 --- a/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/factory/FlatCfgFactory.cpp +++ b/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/factory/FlatCfgFactory.cpp @@ -177,8 +177,6 @@ bool FlatCfgFactory::createProcessStates(std::vector& f_pro f_processStates_r.emplace_back(processCfg); f_processStates_r.back().setProcessGroupState(mainPGStartupId); - - f_processStateReader_r.registerExmProcessState(f_processStates_r.back()); } const std::string processShortNameRead{f_processStates_r.back().getConfigName()}; diff --git a/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/ifexm/ProcessStateReader.cpp b/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/ifexm/ProcessStateReader.cpp index ab040226..1b1bf1a9 100644 --- a/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/ifexm/ProcessStateReader.cpp +++ b/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/ifexm/ProcessStateReader.cpp @@ -24,28 +24,12 @@ namespace saf namespace ifexm { -/* RULECHECKER_comment(0, 3, check_incomplete_data_member_construction, "Member processStateClientPhm is \ -initialized using other member functions instead of member initializer list.", true_no_defect) */ -ProcessStateReader::ProcessStateReader() : +ProcessStateReader::ProcessStateReader(std::unique_ptr f_process_state_receiver) : + processStateReceiverHM(std::move(f_process_state_receiver)), logger_r(logging::PhmLogger::getLogger(logging::PhmLogger::EContext::supervision)) { } -bool ProcessStateReader::init() noexcept(false) -{ - bool flagInitSuccess{true}; - - score::Result initResult{processStateClientPhm.init()}; - if (!initResult.has_value()) - { - logger_r.LogError() << "Process State Reader failed with initialization error (Process State Client):" - << initResult.error().Message(); - flagInitSuccess = false; - } - - return flagInitSuccess; -} - bool ProcessStateReader::registerProcessState(ProcessState& f_processState_r, const common::ProcessId f_processId) noexcept(false) { @@ -63,11 +47,6 @@ bool ProcessStateReader::registerProcessState(ProcessState& f_processState_r, return flagSuccess; } -void ProcessStateReader::registerExmProcessState(ProcessState& f_processState_r) noexcept(false) -{ - exmProcessStateVector.push_back(&f_processState_r); -} - void ProcessStateReader::deregisterProcessState(const common::ProcessId f_processId) noexcept { std::map::iterator processMapIterator{processStateMap.find(f_processId)}; @@ -91,8 +70,8 @@ bool ProcessStateReader::distributeChanges(const timers::NanoSecondType f_syncTi bool flagContinue{true}; do { - score::Result> resultChangedProcess{ - processStateClientPhm.getNextChangedPosixProcess() + score::Result> resultChangedProcess{ + processStateReceiverHM->getNextChangedPosixProcess() }; if (resultChangedProcess) @@ -123,17 +102,7 @@ bool ProcessStateReader::distributeChanges(const timers::NanoSecondType f_syncTi return flagSuccess; } -void ProcessStateReader::distributeExmActivation(const timers::NanoSecondType f_timestamp) noexcept -{ - for (auto& exmProcess : exmProcessStateVector) - { - exmProcess->setState(ProcessState::EProcState::running); - exmProcess->setTimestamp(f_timestamp); - exmProcess->pushData(); - } -} - -bool ProcessStateReader::pushUpdateTill(const ProcessStateReader::ExmPosixProcess& f_changedPosixProcess_r, +bool ProcessStateReader::pushUpdateTill(const ProcessStateReader::LcmPosixProcess& f_changedPosixProcess_r, const timers::NanoSecondType f_syncTimestamp) noexcept { bool isSyncTimestampReached{false}; @@ -166,25 +135,25 @@ bool ProcessStateReader::pushUpdateTill(const ProcessStateReader::ExmPosixProces } constexpr ProcessState::EProcState ProcessStateReader::translateProcessState( - const ProcessStateReader::ExmProcessState f_processStateExm) noexcept + const ProcessStateReader::LcmProcessState f_processStateLcm) noexcept { // Following static assertion ensures consistency of process states in EXM and PHM static_assert(static_cast(ProcessState::EProcState::idle) == static_cast(score::lcm::ProcessState::kIdle), - "EXM State Enum and ProcessState::EProcState Enum do not match."); + "Lcm State Enum and ProcessState::EProcState Enum do not match."); static_assert(static_cast(ProcessState::EProcState::starting) == static_cast(score::lcm::ProcessState::kStarting), - "EXM State Enum and ProcessState::EProcState Enum do not match."); + "Lcm State Enum and ProcessState::EProcState Enum do not match."); static_assert(static_cast(ProcessState::EProcState::running) == static_cast(score::lcm::ProcessState::kRunning), - "EXM State Enum and ProcessState::EProcState Enum do not match."); + "Lcm State Enum and ProcessState::EProcState Enum do not match."); static_assert(static_cast(ProcessState::EProcState::sigterm) == static_cast(score::lcm::ProcessState::kTerminating), - "EXM State Enum and ProcessState::EProcState Enum do not match."); + "Lcm State Enum and ProcessState::EProcState Enum do not match."); static_assert(static_cast(ProcessState::EProcState::off) == static_cast(score::lcm::ProcessState::kTerminated), - "EXM State Enum and ProcessState::EProcState Enum do not match."); - return static_cast(f_processStateExm); + "Lcm State Enum and ProcessState::EProcState Enum do not match."); + return static_cast(f_processStateLcm); } } // namespace ifexm diff --git a/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/ifexm/ProcessStateReader.hpp b/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/ifexm/ProcessStateReader.hpp index 862e3831..dc179afa 100644 --- a/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/ifexm/ProcessStateReader.hpp +++ b/src/launch_manager_daemon/health_monitor_lib/src/score/lcm/saf/ifexm/ProcessStateReader.hpp @@ -21,7 +21,7 @@ #include "score/lcm/saf/logging/PhmLogger.hpp" #include "score/lcm/saf/timers/Timers_OsClock.hpp" #include "score/lcm/posixprocess.hpp" -#include "score/lcm/processstateclient.hpp" +#include "score/lcm/iprocessstatereceiver.hpp" namespace score { @@ -33,17 +33,18 @@ namespace ifexm { /// @brief Process State reader -/// @details The Process State reader fetches process state updates via the exm library and distributes +/// @details The Process State reader fetches process state updates via the lcm library and distributes /// the information to the Process State classes. class ProcessStateReader { public: - using ExmProcessState = score::lcm::ProcessState; - using ExmPosixProcess = score::lcm::PosixProcess; - using ExmProcessStateClient = score::lcm::ProcessStateClient; + using LcmProcessState = score::lcm::ProcessState; + using LcmPosixProcess = score::lcm::PosixProcess; + using LcmProcessStateReceiver = score::lcm::IProcessStateReceiver; - /// @brief Default Constructor - ProcessStateReader(); + /// @brief Constructor + /// @param [in] f_process_state_receiver Process state receiver implementation + ProcessStateReader(std::unique_ptr f_process_state_receiver); /// @brief No Copy Constructor ProcessStateReader(const ProcessStateReader&) = delete; @@ -57,23 +58,12 @@ class ProcessStateReader /// @brief Default Destructor virtual ~ProcessStateReader() = default; - /// @brief Initialize Process State Reader - /// @details Initialize Process State Reader by calling initialization function of EXM-state-client. - /// @return true (successful initialization), false (failed initialization) - bool init(void) noexcept(false); - /// @brief Register process states for reader /// @param [in] f_processState_r Process state to be registered /// @param [in] f_processId Process ID /// @return true (registered), false (not registered) bool registerProcessState(ProcessState& f_processState_r, const common::ProcessId f_processId) noexcept(false); - /// @brief Register Exm process state - /// @details Processes registered via EXM process can never be deregistered. - /// They are also not affected by method distributeChanges(). - /// @param [in] f_processState_r Process state to be registered which is representing EXM - void registerExmProcessState(ProcessState& f_processState_r) noexcept(false); - /// @brief Deregister process states from reader /// @param [in] f_processId Process ID to deregister the particular process void deregisterProcessState(const common::ProcessId f_processId) noexcept; @@ -83,28 +73,21 @@ class ProcessStateReader /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization /// @return true (successful process state distribution), false (failed process state distribution) bool distributeChanges(const timers::NanoSecondType f_syncTimestamp) noexcept; - - /// @brief Distribute EXM process activation event - /// @details EXM process(es) are already running and do not receive updates from processStateClientPhm. - /// Therefore, the activation event is simulated on purpose. - /// @param [in] f_timestamp Timestamp used for activation event - void distributeExmActivation(const timers::NanoSecondType f_timestamp) noexcept; - private: /// @brief Push update for changed registered process /// @param [in] f_changedPosixProcess_r Posix Process for which push update is needed /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization /// @return true (sync timestamp is reached), false (sync timestamp is not yet reached) - bool pushUpdateTill(const ProcessStateReader::ExmPosixProcess& f_changedPosixProcess_r, + bool pushUpdateTill(const ProcessStateReader::LcmPosixProcess& f_changedPosixProcess_r, const timers::NanoSecondType f_syncTimestamp) noexcept; - /// @brief Translate EXM State to ProcessState::EProcState - /// @param [in] f_processStateExm Process state from EXM + /// @brief Translate Lcm State to ProcessState::EProcState + /// @param [in] f_processStateLcm Process state from Lcm /// @return Process state (e.g: idle, running, off) - static constexpr ProcessState::EProcState translateProcessState(const ExmProcessState f_processStateExm) noexcept; + static constexpr ProcessState::EProcState translateProcessState(const LcmProcessState f_processStateLcm) noexcept; - /// @brief Process state client for PHM daemon - ProcessStateReader::ExmProcessStateClient processStateClientPhm; + /// @brief Process state receiver for HM thread + std::unique_ptr processStateReceiverHM; /// @brief Logger logging::PhmLogger& logger_r; @@ -112,10 +95,6 @@ class ProcessStateReader /// @brief Map for process id and process state object std::map processStateMap{}; - /// @brief Process state objects for EXM - /// @details 1 is expected, support for multiple EXM processes is implemented - std::vector exmProcessStateVector{}; - /// @brief Flag for pending pushData from previous distribution of process state changes bool isPushPending{false}; diff --git a/src/launch_manager_daemon/process_state_client_lib/BUILD b/src/launch_manager_daemon/process_state_client_lib/BUILD index a950eedb..18865f53 100644 --- a/src/launch_manager_daemon/process_state_client_lib/BUILD +++ b/src/launch_manager_daemon/process_state_client_lib/BUILD @@ -13,11 +13,15 @@ cc_library( name = "process_state_client", srcs = [ - "src/processstateclient.cpp", + "src/processstatenotifier.cpp", + "src/processstatereceiver.cpp", ], hdrs = [ + "include/score/lcm/iprocessstatenotifier.hpp", + "include/score/lcm/iprocessstatereceiver.hpp", "include/score/lcm/posixprocess.hpp", - "include/score/lcm/processstateclient.hpp", + "include/score/lcm/processstatenotifier.hpp", + "include/score/lcm/processstatereceiver.hpp", ], includes = ["include"], visibility = ["//visibility:public"], diff --git a/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/iprocessstatenotifier.hpp b/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/iprocessstatenotifier.hpp new file mode 100644 index 00000000..843204cf --- /dev/null +++ b/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/iprocessstatenotifier.hpp @@ -0,0 +1,53 @@ +/******************************************************************************** + * 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 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef IPROCESSSTATE_NOTIFIER_HPP_INCLUDED +#define IPROCESSSTATE_NOTIFIER_HPP_INCLUDED + +#include +#include "iprocessstatereceiver.hpp" + +namespace score { + +namespace lcm { + +/// +/// @brief IProcessStateNotifier interface for handling the information about each Process current state. +/// Launch Manager (LCM) shall use this interface in order to properly store +/// information about the current state from the posix processes running in the scope of an Adaptive Machine. +/// Each posix process state change is stored by Launch Manager (LCM) and can be read by HM. +/// + +class IProcessStateNotifier { + public: + + /// @brief Destructor. + virtual ~IProcessStateNotifier() noexcept = default; + + /// @brief Construct and return the Process State Receiver instance used to receive process state changes. + /// @return Process State Receiver instance + virtual std::unique_ptr constructReceiver() = 0; + + /// @brief Writes via IPC the latests Process State change, so that PHM can be informed about it. + /// @details the PosixProcess structure should be complete at his moment. That means: + /// ProcessGroupStateId, ProcessModelled Id, current ProcessState, timestamp are known and set. + /// if no more free shared memory, the PosixProcess is not sent. + /// @param[in] f_posixProcess The PosixProcess to be queued + /// @returns True on success, false for failure (corresponding to kCommunicationError). + virtual bool queuePosixProcess(const score::lcm::PosixProcess& f_posixProcess) noexcept = 0; +}; + +} // namespace lcm + +} // namespace score + +#endif diff --git a/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/iprocessstatereceiver.hpp b/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/iprocessstatereceiver.hpp new file mode 100644 index 00000000..c594155c --- /dev/null +++ b/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/iprocessstatereceiver.hpp @@ -0,0 +1,45 @@ +/******************************************************************************** + * 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 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#ifndef IPROCESSSTATERECEIVER_HPP_INCLUDED +#define IPROCESSSTATERECEIVER_HPP_INCLUDED + +#include +#include "score/result/result.h" +#include +#include + +#include + +namespace score { + +namespace lcm { + +/// @brief IProcessStateReceiver interface for handling the information about each Process current state. +/// Health Monitor (HM) shall use this interface in order to properly receive +/// information about the current state from the posix processes running in the scope of an Adaptive Machine. +/// Each posix process state change is sent by Launch Manager (LCM) and can be read by HM. + +class IProcessStateReceiver { + public: + virtual ~IProcessStateReceiver() noexcept = default; + + /// @brief Returns a queued PosixProcess that has not yet been parsed. + /// @returns Result containing PosixProcess in case of success, or ExecError in case of failure. + virtual score::Result> getNextChangedPosixProcess() noexcept = 0; +}; + +} // namespace lcm + +} // namespace score + +#endif diff --git a/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/posixprocess.hpp b/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/posixprocess.hpp index 87c10d1f..8b61c0dd 100644 --- a/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/posixprocess.hpp +++ b/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/posixprocess.hpp @@ -35,7 +35,7 @@ enum class ProcessState : std::uint_least8_t { /// @details This structure will be probably populated in steps, since some Software Components know about the current ProcessGroupStateId /// and Process Modelled Id (like ProcessGroupManager); meanwhile others know about the process state changes from a specific /// posix process (like application launcher). The timestamp shall show when the process state changed. -/// Finally the ProcessStateClient knows if the PosixProcess was already read by PHM or not. +/// Finally the ProcessStateReceiver knows if the PosixProcess was already read by PHM or not. /// // RULECHECKER_comment(1, 1, check_incomplete_data_member_construction, "wi 45913 - This struct is POD, which doesn't have user-declared constructor. The rule doesn’t apply.", false) @@ -59,11 +59,10 @@ struct PosixProcess { timespec systemClockTimestamp; }; -enum class PipcConstants : size_t { - PIPC_MAXPAYLOAD = sizeof(PosixProcess), ///< ipc_dropin::Socket max payload size - // The pipc queue size must be a power of 2 by the pipc specification. +enum class BufferConstants : size_t { + BUFFER_MAXPAYLOAD = sizeof(PosixProcess), ///< Ringbuffer max payload size // (PROCESS_MAX number (1024) * Transition pattern (4, STARTING/RUNNING/TERMINATING/TERMINATED) - PIPC_QUEUE_SIZE = 4096UL // ipc_dropin::Socket queue size + BUFFER_QUEUE_SIZE = 4096UL // Ringbuffer queue size }; } // namespace lcm diff --git a/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstateclient.hpp b/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstateclient.hpp deleted file mode 100644 index 75cc03cf..00000000 --- a/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstateclient.hpp +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 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 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - - -#ifndef PROCESSSTATECLIENT_HPP_INCLUDED -#define PROCESSSTATECLIENT_HPP_INCLUDED - -#include -#include "score/result/result.h" -#include "score/lcm/exec_error_domain.h" - -#include "score/lcm/posixprocess.hpp" -#include "ipc_dropin/socket.hpp" - -namespace score { - -namespace lcm { - -/// @brief ProcessStateClient implementation for handling the information about current state of each Process. -class ProcessStateClient final { - public: - /// @brief Constructor that creates the ProcessStateClient - ProcessStateClient() noexcept; - - /// @brief Copy constructor that creates the ProcessStateClient. It is disabled. - ProcessStateClient(ProcessStateClient const&) noexcept = delete; - - /// @brief Move constructor that creates the ProcessStateClient. It is disabled. - ProcessStateClient(ProcessStateClient&&) noexcept = delete; - - /// @brief Disable copy-assign another ProcessStateClient to this instance. - /// @param other the other instance - /// @returns *this, containing the contents of @a other - ProcessStateClient& operator=(const ProcessStateClient& other) = delete; - - /// @brief Move operation disabled for this class. - /// @param other the other instance - /// @returns *this, containing the contents of @a other - ProcessStateClient& operator=(ProcessStateClient&& other) = delete; - - /// @brief Destructor. - ~ProcessStateClient() noexcept; - - /// @brief Opens the communication channel (e.g. POSIX shared memory) for parsing the ProcessState PosixProcess changes. - /// @returns An instance of score::Result. The instance holds an score::lcm::ExecErrc error code - kCommunicationError - /// or a void-value if no error occured. - score::Result init() noexcept; - - /// @brief Returns the queued PosixProcess, which changed and PHM has not yet parsed. - /// @returns Returns the queued PosixProcess, which PHM has not yet parsed. - /// "std::nullopt" is returned in case there is no new information. - /// "score::lcm::ExecErrc::kCommunicationError" is returned in case of queue Overflow, queue state corruption or queue payload corruption. - /// "score::lcm::ExecErrc::kGeneralError" is returned in case of any other error. - score::Result> getNextChangedPosixProcess() noexcept; - - private: - /// @brief ipc_dropin::pimp::Socket through which we retrieve process state updates from LCM - ipc_dropin::Socket(PipcConstants::PIPC_MAXPAYLOAD), - static_cast(PipcConstants::PIPC_QUEUE_SIZE)> - m_LCM_PHM_socket; -}; - -} // namespace lcm - -} // namespace score - -#endif // PROCESSSTATECLIENT_HPP_INCLUDED diff --git a/src/launch_manager_daemon/src/process_group_manager/processstatenotifier.hpp b/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstatenotifier.hpp similarity index 79% rename from src/launch_manager_daemon/src/process_group_manager/processstatenotifier.hpp rename to src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstatenotifier.hpp index c0f3c861..d6f209c6 100644 --- a/src/launch_manager_daemon/src/process_group_manager/processstatenotifier.hpp +++ b/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstatenotifier.hpp @@ -15,9 +15,8 @@ #ifndef PROCESSSTATE_NOTIFIER_HPP_INCLUDED #define PROCESSSTATE_NOTIFIER_HPP_INCLUDED -#include -#include -#include "ipc_dropin/socket.hpp" +#include "score/lcm/iprocessstatenotifier.hpp" +#include "ipc_dropin/ringbuffer.hpp" namespace score { @@ -31,7 +30,7 @@ namespace internal { /// information about the current state from the posix processes running in the scope of an Adaptive Machine. /// Each posix process state change is stored by Launch Manager (LCM) and can be read by PHM. /// -class ProcessStateNotifier final { +class ProcessStateNotifier final : public IProcessStateNotifier { public: /// @brief Constructor that creates the ProcessStateNotifier. /// @details LCM shall create an instance of this class to write the process state changes via the provided API. @@ -56,9 +55,9 @@ class ProcessStateNotifier final { /// @brief Destructor. ~ProcessStateNotifier() noexcept; - /// @brief Opens the communication channel (e.g. POSIX shared memory) for writing the PosixProcess. - /// @returns True on success, false for failure (corresponding to kCommunicationError). - bool init() noexcept; + /// @brief Construct and return the Process State Receiver instance used to receive process state changes. + /// @return Process State Receiver instance + std::unique_ptr constructReceiver() noexcept override; /// @brief Writes via IPC the latests Process State change, so that PHM can be informed about it. /// @details the PosixProcess structure should be complete at his moment. That means: @@ -66,13 +65,14 @@ class ProcessStateNotifier final { /// if no more free shared memory, the PosixProcess is not sent. /// @param[in] f_posixProcess The PosixProcess to be queued /// @returns True on success, false for failure (corresponding to kCommunicationError). - bool queuePosixProcess(const score::lcm::PosixProcess& f_posixProcess) noexcept; + bool queuePosixProcess(const score::lcm::PosixProcess& f_posixProcess) noexcept override; private: - /// @brief ipc_dropin::Socket through which we retrieve process state updates from LCM - ipc_dropin::Socket(score::lcm::PipcConstants::PIPC_MAXPAYLOAD), - static_cast(score::lcm::PipcConstants::PIPC_QUEUE_SIZE)> - m_LCM_PHM_socket{}; + /// @brief ipc_dropin::RingBuffer through which we retrieve process state updates from LCM + std::shared_ptr(score::lcm::BufferConstants::BUFFER_QUEUE_SIZE), + static_cast(score::lcm::BufferConstants::BUFFER_MAXPAYLOAD) + >> + ring_buffer_{}; }; } // namespace lcm diff --git a/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstatereceiver.hpp b/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstatereceiver.hpp new file mode 100644 index 00000000..0ed6fc82 --- /dev/null +++ b/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstatereceiver.hpp @@ -0,0 +1,71 @@ +/******************************************************************************** + * Copyright (c) 2025 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 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + + +#ifndef PROCESSSTATERECEIVER_HPP_INCLUDED +#define PROCESSSTATERECEIVER_HPP_INCLUDED + +#include "iprocessstatereceiver.hpp" +#include "ipc_dropin/ringbuffer.hpp" + +namespace score { + +namespace lcm { + +using BufferP = std::shared_ptr(score::lcm::BufferConstants::BUFFER_QUEUE_SIZE), + static_cast(score::lcm::BufferConstants::BUFFER_MAXPAYLOAD) + >>; + +/// @brief ProcessStateReceiver implementation for handling the information about current state of each Process. +class ProcessStateReceiver final : public IProcessStateReceiver { + public: + /// @brief Constructor that creates the ProcessStateReceiver + /// @param ring_buffer Shared pointer to the ring buffer used to receive process state updates from LCM + ProcessStateReceiver(BufferP ring_buffer) noexcept; + + /// @brief Copy constructor that creates the ProcessStateReceiver. It is disabled. + ProcessStateReceiver(ProcessStateReceiver const&) noexcept = delete; + + /// @brief Move constructor that creates the ProcessStateReceiver. It is disabled. + ProcessStateReceiver(ProcessStateReceiver&&) noexcept = delete; + + /// @brief Disable copy-assign another ProcessStateReceiver to this instance. + /// @param other the other instance + /// @returns *this, containing the contents of @a other + ProcessStateReceiver& operator=(const ProcessStateReceiver& other) = delete; + + /// @brief Move operation disabled for this class. + /// @param other the other instance + /// @returns *this, containing the contents of @a other + ProcessStateReceiver& operator=(ProcessStateReceiver&& other) = delete; + + /// @brief Destructor. + ~ProcessStateReceiver() noexcept; + + /// @brief Returns the queued PosixProcess, which changed and PHM has not yet parsed. + /// @returns Returns the queued PosixProcess, which PHM has not yet parsed. + /// "std::nullopt" is returned in case there is no new information. + /// "score::lcm::ExecErrc::kGeneralError" is returned in case of any other error. + score::Result> getNextChangedPosixProcess() noexcept override; + + private: + /// @brief ipc_dropin::RingBuffer through which we retrieve process state updates from LCM + BufferP ring_buffer_{}; +}; + +} // namespace lcm + +} // namespace score + +#endif // PROCESSSTATERECEIVER_HPP_INCLUDED diff --git a/src/launch_manager_daemon/src/process_group_manager/processstatenotifier.cpp b/src/launch_manager_daemon/process_state_client_lib/src/processstatenotifier.cpp similarity index 63% rename from src/launch_manager_daemon/src/process_group_manager/processstatenotifier.cpp rename to src/launch_manager_daemon/process_state_client_lib/src/processstatenotifier.cpp index 6222d323..af130204 100644 --- a/src/launch_manager_daemon/src/process_group_manager/processstatenotifier.cpp +++ b/src/launch_manager_daemon/process_state_client_lib/src/processstatenotifier.cpp @@ -12,34 +12,27 @@ ********************************************************************************/ #include -#include +#include +#include namespace score { namespace lcm { namespace internal { ProcessStateNotifier::ProcessStateNotifier() noexcept { -} + ring_buffer_ = std::make_shared(score::lcm::BufferConstants::BUFFER_QUEUE_SIZE), + static_cast(score::lcm::BufferConstants::BUFFER_MAXPAYLOAD)>>(); -ProcessStateNotifier::~ProcessStateNotifier() noexcept { - static_cast(m_LCM_PHM_socket.close()); + ring_buffer_->initialize(); } -bool ProcessStateNotifier::init() noexcept { - bool ret = true; - /* RULECHECKER_comment(1, 1, check_octal_constant, "The API takes as a parameter an octal constant", true); */ - if (m_LCM_PHM_socket.create("ProcessState", 0260U) != ipc_dropin::ReturnCode::kOk) { - LM_LOG_ERROR() << "Failed to create LCM-PHM socket"; - ret = false; - } else { - LM_LOG_DEBUG() << "ProcessStateNotifier::init successfully executed"; - } - return ret; +ProcessStateNotifier::~ProcessStateNotifier() noexcept { } bool ProcessStateNotifier::queuePosixProcess(const score::lcm::PosixProcess& f_posixProcess) noexcept { bool ret = true; - if (m_LCM_PHM_socket.trySend(f_posixProcess) == ipc_dropin::ReturnCode::kOk) { + if (ring_buffer_->tryEnqueue(f_posixProcess)) { // nothing } else { LM_LOG_ERROR() << "Failed to queue posix process"; @@ -48,6 +41,10 @@ bool ProcessStateNotifier::queuePosixProcess(const score::lcm::PosixProcess& f_p return ret; } +std::unique_ptr ProcessStateNotifier::constructReceiver() noexcept { + return std::make_unique(ring_buffer_); +} + } // namespace lcm } // namespace internal } // namespace score diff --git a/src/launch_manager_daemon/process_state_client_lib/src/processstateclient.cpp b/src/launch_manager_daemon/process_state_client_lib/src/processstatereceiver.cpp similarity index 51% rename from src/launch_manager_daemon/process_state_client_lib/src/processstateclient.cpp rename to src/launch_manager_daemon/process_state_client_lib/src/processstatereceiver.cpp index d4b7dd1b..5629f23f 100644 --- a/src/launch_manager_daemon/process_state_client_lib/src/processstateclient.cpp +++ b/src/launch_manager_daemon/process_state_client_lib/src/processstatereceiver.cpp @@ -11,47 +11,38 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -#include "score/lcm/processstateclient.hpp" +#include "score/lcm/processstatereceiver.hpp" #include "score/lcm/internal/log.hpp" namespace score { namespace lcm { -ProcessStateClient::ProcessStateClient() noexcept : m_LCM_PHM_socket{} {} -ProcessStateClient::~ProcessStateClient() noexcept { - static_cast(m_LCM_PHM_socket.close()); +ProcessStateReceiver::ProcessStateReceiver(BufferP ring_buffer) noexcept : ring_buffer_(ring_buffer) { } -score::Result ProcessStateClient::init() noexcept { - if (m_LCM_PHM_socket.connect("ProcessState") != ipc_dropin::ReturnCode::kOk) { - return score::Result{ - score::MakeUnexpected(score::lcm::ExecErrc::kCommunicationError)}; - } else { - return score::Result{}; - } + +ProcessStateReceiver::~ProcessStateReceiver() noexcept { } + score::Result> -ProcessStateClient::getNextChangedPosixProcess() noexcept { +ProcessStateReceiver::getNextChangedPosixProcess() noexcept { score::lcm::PosixProcess changedProcess; - if (m_LCM_PHM_socket.getOverflowFlag()) { + if (ring_buffer_->getOverflowFlag()) { LM_LOG_ERROR() - << "ProcessStateClient::getNextChangedPosixProcess: Overflow occurred, " + << "ProcessStateReceiver::getNextChangedPosixProcess: Overflow occurred, " "will be reported as kCommunicationError"; return score::Result>{ score::MakeUnexpected(score::lcm::ExecErrc::kCommunicationError)}; } - auto res = m_LCM_PHM_socket.tryReceive(changedProcess); - switch (res) { - case ipc_dropin::ReturnCode::kOk: - return score::Result>{ - changedProcess}; - case ipc_dropin::ReturnCode::kQueueStateCorrupt: - return score::Result>{ - score::MakeUnexpected(score::lcm::ExecErrc::kCommunicationError)}; - case ipc_dropin::ReturnCode::kQueueEmpty: + + if (ring_buffer_->empty()) { return score::Result>{std::nullopt}; - default: - return score::Result>{ - score::MakeUnexpected(score::lcm::ExecErrc::kGeneralError)}; + } + + auto res = ring_buffer_->tryDequeue(changedProcess); + if (res) { + return score::Result>{changedProcess}; + } else { + return score::Result>{score::MakeUnexpected(score::lcm::ExecErrc::kGeneralError)}; } } } // namespace lcm diff --git a/src/launch_manager_daemon/src/main/main.cpp b/src/launch_manager_daemon/src/main/main.cpp index 324c2839..94f35f14 100644 --- a/src/launch_manager_daemon/src/main/main.cpp +++ b/src/launch_manager_daemon/src/main/main.cpp @@ -21,6 +21,7 @@ #include #include #include +#include using namespace std; using namespace score::lcm::internal; @@ -90,11 +91,12 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] char const* argv[]) { LM_LOG_DEBUG() << "Launch Manager Started !!!!"; std::shared_ptr recoveryClient{std::make_shared()}; std::unique_ptr watchdog{std::make_unique()}; - std::unique_ptr healthMonitor{std::make_unique(recoveryClient, std::move(watchdog))}; + auto process_state_notifier = std::make_unique(); + std::unique_ptr healthMonitor{std::make_unique(recoveryClient, std::move(watchdog), process_state_notifier->constructReceiver())}; std::unique_ptr healthMonitorThread{ std::make_unique(std::move(healthMonitor))}; - std::unique_ptr process_group_manager = std::make_unique(std::move(healthMonitorThread), recoveryClient); + std::unique_ptr process_group_manager = std::make_unique(std::move(healthMonitorThread), recoveryClient, std::move(process_state_notifier)); if (initializeLCMDaemon(*process_group_manager)) { if (runLCMDaemon(*process_group_manager)) { diff --git a/src/launch_manager_daemon/src/process_group_manager/processgroupmanager.cpp b/src/launch_manager_daemon/src/process_group_manager/processgroupmanager.cpp index 04d35d5a..dde42d37 100644 --- a/src/launch_manager_daemon/src/process_group_manager/processgroupmanager.cpp +++ b/src/launch_manager_daemon/src/process_group_manager/processgroupmanager.cpp @@ -38,7 +38,7 @@ void ProcessGroupManager::cancel() { my_signal_handler(SIGTERM); } -ProcessGroupManager::ProcessGroupManager(std::unique_ptr health_monitor, std::shared_ptr recovery_client) +ProcessGroupManager::ProcessGroupManager(std::unique_ptr health_monitor, std::shared_ptr recovery_client, std::unique_ptr process_state_notifier) : configuration_manager_(), process_interface_(), process_map_(nullptr), @@ -47,7 +47,7 @@ ProcessGroupManager::ProcessGroupManager(std::unique_ptr h total_processes_(0U), num_process_groups_(0U), process_groups_(), - process_state_notifier_(), + process_state_notifier_(std::move(process_state_notifier)), health_monitor_thread_(std::move(health_monitor)), recovery_client_(recovery_client) //, //ucm_polling_thread_( @@ -86,7 +86,7 @@ bool ProcessGroupManager::initialize() { sigaction(SIGUSR2, &action, NULL); sigaction(SIGVTALRM, &action, NULL); - success = initializeControlClientHandler() && initializeProcessGroups() && process_state_notifier_.init(); + success = initializeControlClientHandler() && initializeProcessGroups(); if (success) { LM_LOG_DEBUG() << "Process Group initialization done"; diff --git a/src/launch_manager_daemon/src/process_group_manager/processgroupmanager.hpp b/src/launch_manager_daemon/src/process_group_manager/processgroupmanager.hpp index c67ff8d9..fd72bcb6 100644 --- a/src/launch_manager_daemon/src/process_group_manager/processgroupmanager.hpp +++ b/src/launch_manager_daemon/src/process_group_manager/processgroupmanager.hpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -59,7 +59,8 @@ class ProcessGroupManager final { /// setting up any necessary internal state and preparing it for use. /// @param health_monitor A unique pointer to an IHealthMonitor instance for managing health monitoring. /// @param recovery_client A shared pointer to an IRecoveryClient instance for handling recovery operations. - ProcessGroupManager(std::unique_ptr health_monitor, std::shared_ptr recovery_client); + /// @param process_state_notifier A unique pointer to an IProcessStateNotifier instance for notifying the HM thread of process state changes. + ProcessGroupManager(std::unique_ptr health_monitor, std::shared_ptr recovery_client, std::unique_ptr process_state_notifier); /// @brief Initializes the process group manager. /// Loads the flat configuration through ConfigurationManager. @@ -128,7 +129,7 @@ class ProcessGroupManager final { /// @param[in] f_posixProcess The PosixProcess to be queued /// @returns True on success, false for failure (corresponding to kCommunicationError). bool queuePosixProcess(const score::lcm::PosixProcess& f_posixProcess) { - return process_state_notifier_.queuePosixProcess(f_posixProcess); + return process_state_notifier_->queuePosixProcess(f_posixProcess); } /// @brief Cancels processGroupManager main routine as though SIGTERM had been sent @@ -293,7 +294,7 @@ class ProcessGroupManager final { std::shared_ptr machine_process_group_{nullptr}; /// @brief Process state notifier object used to send data to PHM - ProcessStateNotifier process_state_notifier_; + std::unique_ptr process_state_notifier_; /// @brief pointer to the configuration for Launch Manager const OsProcess* launch_manager_config_{nullptr}; From 33abfb859f55319a934e7039f269132e61e0191d Mon Sep 17 00:00:00 2001 From: "Empting Eelco (ETAS-ECM/XPC-Fe2)" Date: Fri, 16 Jan 2026 10:58:14 +0000 Subject: [PATCH 2/6] Rmove noexcept --- .../include/score/lcm/processstatenotifier.hpp | 2 +- .../process_state_client_lib/src/processstatenotifier.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstatenotifier.hpp b/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstatenotifier.hpp index d6f209c6..500abaf7 100644 --- a/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstatenotifier.hpp +++ b/src/launch_manager_daemon/process_state_client_lib/include/score/lcm/processstatenotifier.hpp @@ -57,7 +57,7 @@ class ProcessStateNotifier final : public IProcessStateNotifier { /// @brief Construct and return the Process State Receiver instance used to receive process state changes. /// @return Process State Receiver instance - std::unique_ptr constructReceiver() noexcept override; + std::unique_ptr constructReceiver() override; /// @brief Writes via IPC the latests Process State change, so that PHM can be informed about it. /// @details the PosixProcess structure should be complete at his moment. That means: diff --git a/src/launch_manager_daemon/process_state_client_lib/src/processstatenotifier.cpp b/src/launch_manager_daemon/process_state_client_lib/src/processstatenotifier.cpp index af130204..4fe0fe22 100644 --- a/src/launch_manager_daemon/process_state_client_lib/src/processstatenotifier.cpp +++ b/src/launch_manager_daemon/process_state_client_lib/src/processstatenotifier.cpp @@ -41,7 +41,7 @@ bool ProcessStateNotifier::queuePosixProcess(const score::lcm::PosixProcess& f_p return ret; } -std::unique_ptr ProcessStateNotifier::constructReceiver() noexcept { +std::unique_ptr ProcessStateNotifier::constructReceiver() { return std::make_unique(ring_buffer_); } From 24e283d4195accfbd335746ae411cf0b8ab161e0 Mon Sep 17 00:00:00 2001 From: WilliamRoebuck Date: Mon, 19 Jan 2026 12:49:47 +0000 Subject: [PATCH 3/6] Initial unit test setup * Add basic infrastructure for unit tests and mocking * Updated copyright checker to fix 2026 failures --- .gitignore | 2 ++ BUILD | 9 +----- MODULE.bazel | 11 ++----- MODULE.bazel.lock | 4 +++ examples/rust_supervised_app/src/main.rs | 25 +++++++-------- src/health_monitoring_lib/src/lib.rs | 6 ++-- src/launch_manager_daemon/BUILD | 32 +++++++++++++++++++ .../rust_bindings/src/errors.rs | 25 +++++++-------- .../rust_bindings/src/lib.rs | 25 +++++++-------- .../rust_bindings/src/monitor.rs | 25 +++++++-------- .../rust_bindings/src/lib.rs | 25 +++++++-------- .../rust_bindings/src/lifecycle.rs | 25 +++++++-------- tests/ut/BUILD | 21 ++++++++++++ 13 files changed, 138 insertions(+), 97 deletions(-) create mode 100644 tests/ut/BUILD diff --git a/.gitignore b/.gitignore index 3997f18a..48dfbfc4 100644 --- a/.gitignore +++ b/.gitignore @@ -77,3 +77,5 @@ _build/ .clwb .idea external +compile_commands.json +.clangd \ No newline at end of file diff --git a/BUILD b/BUILD index f7fcb4c2..38e53208 100644 --- a/BUILD +++ b/BUILD @@ -25,6 +25,7 @@ copyright_checker( srcs = [ "examples", "src", + "tests", "//:BUILD", "//:MODULE.bazel", ], @@ -58,11 +59,3 @@ docs( ], source_dir = "docs", ) - -# Test suites -test_suite( - name = "unit_tests", - testonly = True, - tests = [ - ], -) diff --git a/MODULE.bazel b/MODULE.bazel index 5d5c25b1..ce4628bf 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -28,7 +28,7 @@ bazel_dep(name = "download_utils", version = "1.0.1") # S-CORE process rules bazel_dep(name = "score_bazel_platforms", version = "0.0.3") bazel_dep(name = "score_docs_as_code", version = "2.2.0") -bazel_dep(name = "score_tooling", version = "1.0.4") +bazel_dep(name = "score_tooling", version = "1.0.5") bazel_dep(name = "score_rust_policies", version = "0.0.3") bazel_dep(name = "score_baselibs", version = "0.2.2") @@ -41,16 +41,11 @@ bazel_dep(name = "score_toolchains_qnx", version = "0.0.6", dev_dependency = Tru bazel_dep(name = "rust_qnx8_toolchain", version = "1.2.0", dev_dependency = True) bazel_dep(name = "score_toolchains_rust", version = "0.1.1", dev_dependency = True) +bazel_dep(name = "googletest", version = "1.17.0.bcr.1") + # S-CORE crates bazel_dep(name = "score_crates", version = "0.0.6") -# Overrides -git_override( - module_name = "score_tooling", - commit = "a6636c20dacdfa44b65ab7f249e7d1c8b8e15e4b", #until 1.0.5 is released - remote = "https://github.com/eclipse-score/tooling.git", -) - git_override( module_name = "score_toolchains_rust", commit = "bcf8e5364f72cf136ec81960350a82e2b5c45449", diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 40af38c1..aeae9504 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -777,6 +777,10 @@ "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_toolchains_gcc/0.5/source.json": "ff39ecf33a53216332e28c6955da8df1ba2c7d3353923de64bd096f3f6fd1cff", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_toolchains_qnx/0.0.6/MODULE.bazel": "9f6cdf3ca09a7a52105e23fd473c9671204ebd716a5dbc169486914995c66caa", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_toolchains_qnx/0.0.6/source.json": "459673e5cd66199e19c736b5708f7b89b1eebf534be255142c18f666634e6526", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_tooling/1.0.2/MODULE.bazel": "e70f396375b9d612b4f41ebceff7f18f68ab423b14625c138a354cc01bc62a10", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_tooling/1.0.4/MODULE.bazel": "89da6c5a0a5fab61ff842648bc9d7d26e4a389ba33b459a9f5449257ddd04c5a", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_tooling/1.0.5/MODULE.bazel": "6fec53b129ecebbc2eaf00504b71cc680c62e2603b220c6ab3e0f80296d1d036", + "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/score_tooling/1.0.5/source.json": "9ac918d380de24f95ee8d62a996559717084239b1651ad7cfaa202523bfcff4f", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/stardoc/0.5.0/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/stardoc/0.5.1/MODULE.bazel": "not found", "https://raw.githubusercontent.com/eclipse-score/bazel_registry/main/modules/stardoc/0.5.3/MODULE.bazel": "not found", diff --git a/examples/rust_supervised_app/src/main.rs b/examples/rust_supervised_app/src/main.rs index 74f95ad9..564e50f1 100644 --- a/examples/rust_supervised_app/src/main.rs +++ b/examples/rust_supervised_app/src/main.rs @@ -1,16 +1,15 @@ -/******************************************************************************** - * Copyright (c) 2025 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 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - +// ******************************************************************************* +// 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 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* use clap::Parser; use libc::{c_long, nanosleep, time_t, timespec}; use signal_hook::flag; diff --git a/src/health_monitoring_lib/src/lib.rs b/src/health_monitoring_lib/src/lib.rs index c61d0eb5..bf081458 100644 --- a/src/health_monitoring_lib/src/lib.rs +++ b/src/health_monitoring_lib/src/lib.rs @@ -1,5 +1,5 @@ -// -// 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. @@ -9,4 +9,4 @@ // // // SPDX-License-Identifier: Apache-2.0 -// +// ******************************************************************************* diff --git a/src/launch_manager_daemon/BUILD b/src/launch_manager_daemon/BUILD index b6b48ef7..eb69e23f 100644 --- a/src/launch_manager_daemon/BUILD +++ b/src/launch_manager_daemon/BUILD @@ -49,3 +49,35 @@ cc_binary_with_common_opts( "@score_baselibs//score/result", ], ) + +# FOR TESTING + +cc_library( + name = "headers", + hdrs = glob( + [ + "src/**/*.h", + "src/**/*.hpp", + ], + allow_empty = True, # "src/**/*.h" is empty as of now + ), + includes = [ + "include", + "src", + ], + visibility = ["//tests:__subpackages__"], + deps = [ + # Must match launch_manager deps + ":config", + "//externals/ipc_dropin", + "//src/launch_manager_daemon/common", + "//src/launch_manager_daemon/common:control_client_channel", + "//src/launch_manager_daemon/common:identifier_hash", + "//src/launch_manager_daemon/common:lifecycle_error", + "//src/launch_manager_daemon/common:log", + "//src/launch_manager_daemon/health_monitor_lib:health_monitor", + "@flatbuffers", + "@score_baselibs//score/mw/log", + "@score_baselibs//score/result", + ], +) diff --git a/src/launch_manager_daemon/health_monitor_lib/rust_bindings/src/errors.rs b/src/launch_manager_daemon/health_monitor_lib/rust_bindings/src/errors.rs index 3073ec1a..6b08025c 100644 --- a/src/launch_manager_daemon/health_monitor_lib/rust_bindings/src/errors.rs +++ b/src/launch_manager_daemon/health_monitor_lib/rust_bindings/src/errors.rs @@ -1,16 +1,15 @@ -/******************************************************************************** - * Copyright (c) 2025 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 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - +// ******************************************************************************* +// 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 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* use std::fmt; #[derive(Debug, Clone)] diff --git a/src/launch_manager_daemon/health_monitor_lib/rust_bindings/src/lib.rs b/src/launch_manager_daemon/health_monitor_lib/rust_bindings/src/lib.rs index 1f941d9d..fe010c73 100644 --- a/src/launch_manager_daemon/health_monitor_lib/rust_bindings/src/lib.rs +++ b/src/launch_manager_daemon/health_monitor_lib/rust_bindings/src/lib.rs @@ -1,16 +1,15 @@ -/******************************************************************************** - * Copyright (c) 2025 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 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - +// ******************************************************************************* +// 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 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* pub mod errors; pub mod monitor; diff --git a/src/launch_manager_daemon/health_monitor_lib/rust_bindings/src/monitor.rs b/src/launch_manager_daemon/health_monitor_lib/rust_bindings/src/monitor.rs index d4a40cb8..ea6e2899 100644 --- a/src/launch_manager_daemon/health_monitor_lib/rust_bindings/src/monitor.rs +++ b/src/launch_manager_daemon/health_monitor_lib/rust_bindings/src/monitor.rs @@ -1,16 +1,15 @@ -/******************************************************************************** - * Copyright (c) 2025 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 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - +// ******************************************************************************* +// 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 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* use crate::errors; use libc::{c_char, c_uint, c_void}; use std::ffi::CString; diff --git a/src/launch_manager_daemon/lifecycle_client_lib/rust_bindings/src/lib.rs b/src/launch_manager_daemon/lifecycle_client_lib/rust_bindings/src/lib.rs index cb369abc..b483b5f5 100644 --- a/src/launch_manager_daemon/lifecycle_client_lib/rust_bindings/src/lib.rs +++ b/src/launch_manager_daemon/lifecycle_client_lib/rust_bindings/src/lib.rs @@ -1,16 +1,15 @@ -/******************************************************************************** - * Copyright (c) 2025 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 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - +// ******************************************************************************* +// 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 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* pub mod lifecycle; pub use lifecycle::report_execution_state_running; diff --git a/src/launch_manager_daemon/lifecycle_client_lib/rust_bindings/src/lifecycle.rs b/src/launch_manager_daemon/lifecycle_client_lib/rust_bindings/src/lifecycle.rs index f22b6e0b..589c0371 100644 --- a/src/launch_manager_daemon/lifecycle_client_lib/rust_bindings/src/lifecycle.rs +++ b/src/launch_manager_daemon/lifecycle_client_lib/rust_bindings/src/lifecycle.rs @@ -1,16 +1,15 @@ -/******************************************************************************** - * Copyright (c) 2025 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 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - +// ******************************************************************************* +// 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 2.0 which is available at +// +// +// SPDX-License-Identifier: Apache-2.0 +// ******************************************************************************* use libc::c_int; #[link(name = "lifecycle_client")] diff --git a/tests/ut/BUILD b/tests/ut/BUILD new file mode 100644 index 00000000..ced888c3 --- /dev/null +++ b/tests/ut/BUILD @@ -0,0 +1,21 @@ +# ******************************************************************************* +# 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 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +load("@rules_cc//cc:defs.bzl", "cc_library") + +# Define mock cc libraries here if needed + +test_suite( + name = "ut", + tests = [ + ], +) From 613806df5ce4771ec0a38996f39e9da31c0271de Mon Sep 17 00:00:00 2001 From: William Roebuck Date: Mon, 19 Jan 2026 15:36:31 +0000 Subject: [PATCH 4/6] Added initial scaffold for unit test --- .gitignore | 3 +- .../process_state_client_lib/BUILD | 28 ++++++++++++++++++ tests/ut/BUILD | 6 ---- tests/ut/processstatereceiver_UT/BUILD | 24 +++++++++++++++ .../processstatereceiver_UT.cpp | 29 +++++++++++++++++++ 5 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 tests/ut/processstatereceiver_UT/BUILD create mode 100644 tests/ut/processstatereceiver_UT/processstatereceiver_UT.cpp diff --git a/.gitignore b/.gitignore index 48dfbfc4..d68c542c 100644 --- a/.gitignore +++ b/.gitignore @@ -78,4 +78,5 @@ _build/ .idea external compile_commands.json -.clangd \ No newline at end of file +.clangd +.cache \ No newline at end of file diff --git a/src/launch_manager_daemon/process_state_client_lib/BUILD b/src/launch_manager_daemon/process_state_client_lib/BUILD index 18865f53..117e53de 100644 --- a/src/launch_manager_daemon/process_state_client_lib/BUILD +++ b/src/launch_manager_daemon/process_state_client_lib/BUILD @@ -10,6 +10,8 @@ # # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* +package(default_visibility = ["//tests:__subpackages__"]) + cc_library( name = "process_state_client", srcs = [ @@ -35,3 +37,29 @@ cc_library( "@score_baselibs//score/result", ], ) + +cc_library( + name = "headers", + hdrs = glob( + [ + "include/score/lcm/**/*.h", + "include/score/lcm/**/*.hpp", + ], + allow_empty = True, # "include/score/lcm/**/*.h" is empty as of now + ), + includes = [ + "include", + "src", + ], + visibility = ["//tests:__subpackages__"], + deps = [ + # Must match process_state_client deps + "//externals/ipc_dropin", + "//src/launch_manager_daemon/common", + "//src/launch_manager_daemon/common:identifier_hash", + "//src/launch_manager_daemon/common:lifecycle_error", + "//src/launch_manager_daemon/common:log", + "@score_baselibs//score/mw/log", + "@score_baselibs//score/result", + ], +) diff --git a/tests/ut/BUILD b/tests/ut/BUILD index ced888c3..7997e0ea 100644 --- a/tests/ut/BUILD +++ b/tests/ut/BUILD @@ -13,9 +13,3 @@ load("@rules_cc//cc:defs.bzl", "cc_library") # Define mock cc libraries here if needed - -test_suite( - name = "ut", - tests = [ - ], -) diff --git a/tests/ut/processstatereceiver_UT/BUILD b/tests/ut/processstatereceiver_UT/BUILD new file mode 100644 index 00000000..88c9ddba --- /dev/null +++ b/tests/ut/processstatereceiver_UT/BUILD @@ -0,0 +1,24 @@ +# ******************************************************************************* +# 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 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +cc_test( + name = "processstatereceiver_UT", + srcs = [ + "processstatereceiver_UT.cpp", + "//src/launch_manager_daemon/process_state_client_lib:src/processstatereceiver.cpp", + ], + visibility = ["//tests:__subpackages__"], + deps = [ + "//src/launch_manager_daemon/process_state_client_lib:headers", + "@googletest//:gtest_main", + ], +) diff --git a/tests/ut/processstatereceiver_UT/processstatereceiver_UT.cpp b/tests/ut/processstatereceiver_UT/processstatereceiver_UT.cpp new file mode 100644 index 00000000..09fab340 --- /dev/null +++ b/tests/ut/processstatereceiver_UT/processstatereceiver_UT.cpp @@ -0,0 +1,29 @@ +/******************************************************************************** + * 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 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include +#include + +using namespace testing; +using namespace score::lcm; + +// To do + +class ProcessStateReceiver_UT : public ::testing::Test { + public: +}; + +TEST_F(ProcessStateReceiver_UT, Smoke) { + auto buffer = std::make_shared(BufferConstants::BUFFER_QUEUE_SIZE), static_cast(BufferConstants::BUFFER_MAXPAYLOAD)>>(); + auto psr = ProcessStateReceiver(buffer); + SUCCEED(); +} \ No newline at end of file From b9f1b028d65d469525f2dae519f67a28dcf0e9dc Mon Sep 17 00:00:00 2001 From: "Empting Eelco (ETAS-ECM/XPC-Fe2)" Date: Wed, 21 Jan 2026 08:55:50 +0000 Subject: [PATCH 5/6] Implement basic UTs --- .../BUILD | 5 +- .../processstateclient_UT.cpp | 121 ++++++++++++++++++ .../processstatereceiver_UT.cpp | 29 ----- 3 files changed, 124 insertions(+), 31 deletions(-) rename tests/ut/{processstatereceiver_UT => processstateclient_UT}/BUILD (83%) create mode 100644 tests/ut/processstateclient_UT/processstateclient_UT.cpp delete mode 100644 tests/ut/processstatereceiver_UT/processstatereceiver_UT.cpp diff --git a/tests/ut/processstatereceiver_UT/BUILD b/tests/ut/processstateclient_UT/BUILD similarity index 83% rename from tests/ut/processstatereceiver_UT/BUILD rename to tests/ut/processstateclient_UT/BUILD index 88c9ddba..cc732a20 100644 --- a/tests/ut/processstatereceiver_UT/BUILD +++ b/tests/ut/processstateclient_UT/BUILD @@ -11,10 +11,11 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* cc_test( - name = "processstatereceiver_UT", + name = "processstateclient_UT", srcs = [ - "processstatereceiver_UT.cpp", + "processstateclient_UT.cpp", "//src/launch_manager_daemon/process_state_client_lib:src/processstatereceiver.cpp", + "//src/launch_manager_daemon/process_state_client_lib:src/processstatenotifier.cpp", ], visibility = ["//tests:__subpackages__"], deps = [ diff --git a/tests/ut/processstateclient_UT/processstateclient_UT.cpp b/tests/ut/processstateclient_UT/processstateclient_UT.cpp new file mode 100644 index 00000000..83eba4b1 --- /dev/null +++ b/tests/ut/processstateclient_UT/processstateclient_UT.cpp @@ -0,0 +1,121 @@ +/******************************************************************************** + * 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 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include +#include +#include +#include + +using namespace testing; +using namespace score::lcm; + +using score::lcm::internal::ProcessStateNotifier; +using score::lcm::ProcessStateReceiver; + +class ProcessStateClient_UT : public ::testing::Test { + protected: + void SetUp() override { + notifier_ = std::make_unique(); + receiver_ = notifier_->constructReceiver(); + } + void TearDown() override { + receiver_.reset(); + notifier_.reset(); + } + std::unique_ptr notifier_; + std::unique_ptr receiver_; + +}; + +TEST_F(ProcessStateClient_UT, ProcessStateClient_ConstructReceiver_Succeeds) { + ASSERT_NE(notifier_, nullptr); + ASSERT_NE(receiver_, nullptr); +} + +TEST_F(ProcessStateClient_UT, ProcessStateClient_QueueOneProcess_Succeeds) { + PosixProcess process1{ + .id = score::lcm::IdentifierHash("Process1"), + .processStateId = score::lcm::ProcessState::kRunning, + .processGroupStateId = score::lcm::IdentifierHash("PGState1"), + }; + + // Queue one process + bool queued = notifier_->queuePosixProcess(process1); + ASSERT_TRUE(queued); + + // Retrieve the queued process via the receiver + auto result = receiver_->getNextChangedPosixProcess(); + ASSERT_TRUE(result.has_value()); // Result contains Optional value + ASSERT_TRUE(result->has_value()); // Optional contains PosixProcess + EXPECT_EQ(result->value().id, process1.id); + EXPECT_EQ(result->value().processStateId, process1.processStateId); + EXPECT_EQ(result->value().processGroupStateId, process1.processGroupStateId); + + // Ensure no more processes are queued + auto no_more = receiver_->getNextChangedPosixProcess(); + ASSERT_TRUE(no_more.has_value()); // Result contains Optional value + ASSERT_FALSE(no_more->has_value()); // Optional is empty +} + +TEST_F(ProcessStateClient_UT, ProcessStateClient_QueueMaxNumberOfProcesses_Succeeds) { + // Queue maximum number of processes + for (size_t i = 0; i < static_cast(BufferConstants::BUFFER_QUEUE_SIZE); ++i) { + PosixProcess process{ + .id = score::lcm::IdentifierHash("Process" + std::to_string(i)), + .processStateId = score::lcm::ProcessState::kRunning, + .processGroupStateId = score::lcm::IdentifierHash("PGState" + std::to_string(i)), + }; + bool queued = notifier_->queuePosixProcess(process); + ASSERT_TRUE(queued) << "Failed to queue process at index " << i; + } + + // Retrieve and verify all queued processes + for (size_t i = 0; i < static_cast(BufferConstants::BUFFER_QUEUE_SIZE); ++i) { + auto result = receiver_->getNextChangedPosixProcess(); + ASSERT_TRUE(result.has_value()); + ASSERT_TRUE(result->has_value()); + EXPECT_EQ(result->value().id, score::lcm::IdentifierHash("Process" + std::to_string(i))); + } + + // Ensure no more processes are queued + auto no_more = receiver_->getNextChangedPosixProcess(); + ASSERT_TRUE(no_more.has_value()); + ASSERT_FALSE(no_more->has_value()); +} + +TEST_F(ProcessStateClient_UT, ProcessStateClient_QueueOneProcessTooMany_Fails) { + PosixProcess process1{ + .id = score::lcm::IdentifierHash("Process1"), + .processStateId = score::lcm::ProcessState::kRunning, + .processGroupStateId = score::lcm::IdentifierHash("PGState1"), + }; + + // Fill the buffer to capacity + for (size_t i = 0; i < static_cast(BufferConstants::BUFFER_QUEUE_SIZE); ++i) { + PosixProcess proc{ + .id = score::lcm::IdentifierHash("Process" + std::to_string(i)), + .processStateId = score::lcm::ProcessState::kRunning, + .processGroupStateId = score::lcm::IdentifierHash("PGState" + std::to_string(i)), + }; + bool queued = notifier_->queuePosixProcess(proc); + ASSERT_TRUE(queued) << "Failed to queue process at index " << i; + } + + // Attempt to queue one more process + bool queued = notifier_->queuePosixProcess(process1); + ASSERT_FALSE(queued) << "Expected queuing to fail due to full buffer"; + + // Ensure that no processes can be retrieved + auto result = receiver_->getNextChangedPosixProcess(); + ASSERT_FALSE(result.has_value()) << "Expected no processes to be retrievable"; + EXPECT_EQ(result.error(), score::lcm::ExecErrc::kCommunicationError); +} diff --git a/tests/ut/processstatereceiver_UT/processstatereceiver_UT.cpp b/tests/ut/processstatereceiver_UT/processstatereceiver_UT.cpp deleted file mode 100644 index 09fab340..00000000 --- a/tests/ut/processstatereceiver_UT/processstatereceiver_UT.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************************** - * 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 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -#include -#include - -using namespace testing; -using namespace score::lcm; - -// To do - -class ProcessStateReceiver_UT : public ::testing::Test { - public: -}; - -TEST_F(ProcessStateReceiver_UT, Smoke) { - auto buffer = std::make_shared(BufferConstants::BUFFER_QUEUE_SIZE), static_cast(BufferConstants::BUFFER_MAXPAYLOAD)>>(); - auto psr = ProcessStateReceiver(buffer); - SUCCEED(); -} \ No newline at end of file From 63da2b6c394e2cf76477f75a1af147ad54ee0453 Mon Sep 17 00:00:00 2001 From: "Empting Eelco (ETAS-ECM/XPC-Fe2)" Date: Wed, 21 Jan 2026 09:04:09 +0000 Subject: [PATCH 6/6] Fix formatting --- tests/ut/processstateclient_UT/BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ut/processstateclient_UT/BUILD b/tests/ut/processstateclient_UT/BUILD index cc732a20..1eece866 100644 --- a/tests/ut/processstateclient_UT/BUILD +++ b/tests/ut/processstateclient_UT/BUILD @@ -14,8 +14,8 @@ cc_test( name = "processstateclient_UT", srcs = [ "processstateclient_UT.cpp", - "//src/launch_manager_daemon/process_state_client_lib:src/processstatereceiver.cpp", "//src/launch_manager_daemon/process_state_client_lib:src/processstatenotifier.cpp", + "//src/launch_manager_daemon/process_state_client_lib:src/processstatereceiver.cpp", ], visibility = ["//tests:__subpackages__"], deps = [