Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@
namespace score::mw::lifecycle::internal::saf::factory
{

using RecoveryClient = score::mw::lifecycle::IRecoveryClient;
using IdentifierHash = score::mw::lifecycle::IdentifierHash;

AliveWorkerFactory::AliveWorkerFactory() : IAliveWorkerFactory()
{
}
Expand Down Expand Up @@ -73,7 +70,7 @@ bool EmplaceAndAttach(
bool AliveWorkerFactory::createObservableEvent(
std::vector<ifexm::ObservableEvent>& events,
const IdentifierHash component_id,
ifexm::ObservableEventReader& event_reader_)
ifexm::IObservableEventReader& event_reader_)
{
try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class AliveWorkerFactory : public IAliveWorkerFactory
bool createObservableEvent(
std::vector<ifexm::ObservableEvent>& events,
const IdentifierHash component_id,
ifexm::ObservableEventReader& event_reader_) override;
ifexm::IObservableEventReader& event_reader_) override;

/// Refer to the description of the base class (IAliveWorkerFactory)
bool createAliveIfIpc(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
/********************************************************************************
* 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 <gmock/gmock.h>
#include <gtest/gtest.h>

#include "score/mw/launch_manager/alive_monitor/details/factory/AliveWorkerFactory.hpp"
#include "score/mw/launch_manager/alive_monitor/details/ifexm/MockObservableEventReader.hpp"
#include "score/mw/launch_manager/recovery_client/mock_recovery_client.h"

using namespace testing;

namespace score::mw::lifecycle::internal::saf
{

namespace ifappl
{
std::unique_ptr<MockCheckpointIpcServer> g_mock_checkpoint_ipc_server;
std::unique_ptr<MockMonitorIfDaemon> g_mock_monitor_if_daemon;
} // namespace ifappl

namespace supervision
{
std::unique_ptr<MockAlive> g_mock_alive_supervision;
}

namespace factory
{

struct FactoryException : public std::exception
{
explicit FactoryException(std::string_view reason) : reason_(reason) {};

std::string_view reason_;

const char* what() const noexcept override
{
return reason_.data();
}
};

class AliveWorkerFactoryTest : public ::testing::Test
{
protected:
void SetUp() override
{
RecordProperty("TestType", "interface-test");
RecordProperty("DerivationTechnique", "explorative-testing");

config_.reporting_cycle_ms = 100;

ipc_ = std::make_unique<ifappl::CheckpointIpcServer>();
interface_ = std::make_unique<ifappl::MonitorIfDaemon>(*ipc_, "/dev/null");
ifappl::g_mock_checkpoint_ipc_server = std::make_unique<ifappl::MockCheckpointIpcServer>();
ifappl::g_mock_monitor_if_daemon = std::make_unique<ifappl::MockMonitorIfDaemon>();
supervision::g_mock_alive_supervision = std::make_unique<supervision::MockAlive>();

EXPECT_CALL(*ifappl::g_mock_checkpoint_ipc_server, getPath)
.Times(AnyNumber())
.WillRepeatedly(Return("/dev/null"));

EXPECT_CALL(*supervision::g_mock_alive_supervision, getIdentifier)
.Times(AnyNumber())
.WillRepeatedly(Return(component_id_));
}

void TearDown() override
{
ifappl::g_mock_checkpoint_ipc_server.reset(); // GMock destructor verifies and clears expectations
ifappl::g_mock_monitor_if_daemon.reset();
supervision::g_mock_alive_supervision.reset();
}

AliveWorkerFactory factory{};

const IdentifierHash component_id_{"Component"};
std::unique_ptr<ifappl::CheckpointIpcServer> ipc_;
std::unique_ptr<ifappl::MonitorIfDaemon> interface_;
ifexm::ObservableEvent event_{component_id_};
std::shared_ptr<MockRecoveryClient> mock_recovery_client_ = std::make_shared<MockRecoveryClient>();
ComponentAliveSupervision config_{};
};

TEST_F(AliveWorkerFactoryTest, createObservableEventFails)
{
RecordProperty(
"Description",
"Verify that exceptions thrown while creating an observable event are caught and a failure is returned");

ifexm::MockObservableEventReader reader{};
std::vector<ifexm::ObservableEvent> out{};
bool create_result = true;

EXPECT_CALL(reader, registerObservableEvent).WillOnce(Throw(FactoryException{"Exception during registration"}));

EXPECT_NO_THROW(create_result = factory.createObservableEvent(out, component_id_, reader));
EXPECT_FALSE(create_result);
}

TEST_F(AliveWorkerFactoryTest, createObservableEventSucceeds)
{
RecordProperty(
"Description",
"Verify that createObservableEvent creates and attaches an observable event with the correct information");

ifexm::MockObservableEventReader reader{};
std::vector<ifexm::ObservableEvent> out{};
bool create_result = false;
PolymorphicMatcher event_matcher =
Field(&ifexm::ObservableEvent::event, Field(&SupervisionEvent::id, Eq(component_id_)));

EXPECT_CALL(reader, registerObservableEvent(event_matcher, component_id_)).WillOnce(Return(true));

create_result = factory.createObservableEvent(out, component_id_, reader);

EXPECT_TRUE(create_result);
EXPECT_THAT(out.back(), event_matcher);
}

TEST_F(AliveWorkerFactoryTest, createAliveIfIpcThrows)
{
RecordProperty(
"Description",
"Verify that exceptions thrown while creating an ipc server are caught and a failure is returned");

std::vector<ifappl::CheckpointIpcServer> out{};
bool create_result = true;

EXPECT_CALL(*ifappl::g_mock_checkpoint_ipc_server, init).WillOnce(Throw(FactoryException{"IPC init error"}));

EXPECT_NO_THROW(create_result = factory.createAliveIfIpc(out, component_id_, 0));
EXPECT_FALSE(create_result);
}

TEST_F(AliveWorkerFactoryTest, createAliveIfIpcInitFails)
{
RecordProperty("Description", "Verify that a failure to initialise an ipc server fails the method");

std::vector<ifappl::CheckpointIpcServer> out{};
bool create_result = true;

EXPECT_CALL(*ifappl::g_mock_checkpoint_ipc_server, init)
.WillOnce(Return(ifappl::CheckpointIpcServer::EIpcInitResult::kFailed));

EXPECT_NO_THROW(create_result = factory.createAliveIfIpc(out, component_id_, 0));
EXPECT_FALSE(create_result);
}

TEST_F(AliveWorkerFactoryTest, createAliveIfIpcSetAccessFails)
{
RecordProperty("Description", "Verify that a failure to set access rights on an ipc server fails the method");

std::vector<ifappl::CheckpointIpcServer> out{};
bool create_result = true;

EXPECT_CALL(*ifappl::g_mock_checkpoint_ipc_server, init)
.WillOnce(Return(ifappl::CheckpointIpcServer::EIpcInitResult::kOk));
EXPECT_CALL(*ifappl::g_mock_checkpoint_ipc_server, setAccessRights).WillOnce(Return(false));

EXPECT_NO_THROW(create_result = factory.createAliveIfIpc(out, component_id_, 0));
EXPECT_FALSE(create_result);
}

TEST_F(AliveWorkerFactoryTest, createAliveIfIpcSucceeds)
{
RecordProperty("Description", "Verify that createAliveIfIpc creates an ipc server with the correct information");

std::vector<ifappl::CheckpointIpcServer> out{};
bool create_result = true;
const uid_t uid = 151;

EXPECT_CALL(*ifappl::g_mock_checkpoint_ipc_server, init)
.WillOnce(Return(ifappl::CheckpointIpcServer::EIpcInitResult::kOk));
EXPECT_CALL(*ifappl::g_mock_checkpoint_ipc_server, setAccessRights(uid)).WillOnce(Return(true));

create_result = factory.createAliveIfIpc(out, component_id_, uid);
EXPECT_TRUE(create_result);
EXPECT_EQ(out.size(), 1);
}

TEST_F(AliveWorkerFactoryTest, createAliveIfFails)
{
RecordProperty(
"Description",
"Verify that exceptions thrown while creating an alive interface are caught and a failure is returned");

std::vector<ifappl::MonitorIfDaemon> out{};
bool create_result = true;

EXPECT_CALL(*ifappl::g_mock_monitor_if_daemon, ctor)
.WillOnce(Throw(FactoryException{"Exception during construction"}));
EXPECT_CALL(*ifappl::g_mock_checkpoint_ipc_server, getPath).WillOnce(Return("/dev/null"));

EXPECT_NO_THROW(create_result = factory.createAliveIf(out, *ipc_, event_));
EXPECT_FALSE(create_result);
}

TEST_F(AliveWorkerFactoryTest, createAliveIfSucceeds)
{
RecordProperty("Description", "Verify that createAliveIf creates an alive interface with the correct information");

std::vector<ifappl::MonitorIfDaemon> out{};
bool create_result = true;

EXPECT_CALL(*ifappl::g_mock_monitor_if_daemon, ctor);
EXPECT_CALL(*ifappl::g_mock_checkpoint_ipc_server, getPath).WillOnce(Return("/dev/null"));

create_result = factory.createAliveIf(out, *ipc_, event_);
EXPECT_TRUE(create_result);
EXPECT_EQ(out.size(), 1);
}

TEST_F(AliveWorkerFactoryTest, createAliveSupervisionFails)
{
RecordProperty(
"Description",
"Verify that exceptions thrown while creating an alive supervision are caught and a failure is returned");

std::vector<supervision::Alive> out{};
bool create_result = true;
EXPECT_CALL(*supervision::g_mock_alive_supervision, ctor)
.WillOnce(Throw(FactoryException{"Exception during construction"}));

EXPECT_NO_THROW(
create_result =
factory.createAliveSupervision(out, *interface_, event_, mock_recovery_client_, component_id_, config_));
EXPECT_FALSE(create_result);
}

TEST_F(AliveWorkerFactoryTest, createAliveSupervisionSucceeds)
{
RecordProperty(
"Description", "Verify that createAliveSupervision creates an alive supervision with the correct information");

std::vector<supervision::Alive> out{};
bool create_result = true;
EXPECT_CALL(*supervision::g_mock_alive_supervision, ctor(component_id_, _, _, _, _));

create_result =
factory.createAliveSupervision(out, *interface_, event_, mock_recovery_client_, component_id_, config_);
EXPECT_TRUE(create_result);
EXPECT_EQ(out.size(), 1);
}

} // namespace factory

} // namespace score::mw::lifecycle::internal::saf
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# SPDX-License-Identifier: Apache-2.0
# *******************************************************************************
load("@rules_cc//cc:defs.bzl", "cc_library")
load("//tests/utils/bazel:unit_test.bzl", "lm_cc_test")

cc_library(
name = "i_alive_worker_factory",
Expand All @@ -20,6 +21,9 @@ cc_library(
visibility = ["//score/launch_manager/src/daemon/src/alive_monitor:__subpackages__"],
deps = [
"//score/launch_manager/src/daemon/src/alive_monitor/details/ifappl:data_structures",
"//score/launch_manager/src/daemon/src/alive_monitor/details/ifappl:monitor_if_daemon",
"//score/launch_manager/src/daemon/src/alive_monitor/details/ifexm:i_observable_event_reader",
"//score/launch_manager/src/daemon/src/alive_monitor/details/supervision:alive",
],
)

Expand All @@ -33,7 +37,6 @@ cc_library(
deps = [
":i_alive_worker_factory",
"//score/launch_manager/src/daemon/src/alive_monitor/details/ifappl:checkpoint",
"//score/launch_manager/src/daemon/src/alive_monitor/details/ifappl:monitor_if_daemon",
"//score/launch_manager/src/daemon/src/alive_monitor/details/ifexm:observable_event",
"//score/launch_manager/src/daemon/src/alive_monitor/details/ifexm:observable_event_reader",
"//score/launch_manager/src/daemon/src/alive_monitor/details/supervision:alive",
Expand All @@ -50,3 +53,55 @@ cc_library(
"@platforms//os:linux": ["//externals/acl"],
}),
)

cc_library(
name = "mockable_i_alive_worker_factory",
testonly = True,
hdrs = ["IAliveWorkerFactory.hpp"],
include_prefix = "score/mw/launch_manager/alive_monitor/details/factory",
strip_include_prefix = "/score/launch_manager/src/daemon/src/alive_monitor/details/factory",
visibility = ["//score/launch_manager/src/daemon/src/alive_monitor:__subpackages__"],
deps = [
"//score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/injection_mocks:mock_data_structures",
"//score/launch_manager/src/daemon/src/alive_monitor/details/ifappl/injection_mocks:mock_monitor_if_daemon",
"//score/launch_manager/src/daemon/src/alive_monitor/details/ifexm:i_observable_event_reader",
"//score/launch_manager/src/daemon/src/alive_monitor/details/supervision/injection_mocks:mock_alive",
],
)

cc_library(
name = "mockable_alive_worker_factory",
testonly = True,
srcs = ["AliveWorkerFactory.cpp"],
hdrs = ["AliveWorkerFactory.hpp"],
include_prefix = "score/mw/launch_manager/alive_monitor/details/factory",
strip_include_prefix = "/score/launch_manager/src/daemon/src/alive_monitor/details/factory",
visibility = ["//score/launch_manager/src/daemon/src/alive_monitor:__subpackages__"],
deps = [
":mockable_i_alive_worker_factory",
"//score/launch_manager/src/daemon/src/alive_monitor/details/ifappl:checkpoint",
"//score/launch_manager/src/daemon/src/alive_monitor/details/ifexm:observable_event",
"//score/launch_manager/src/daemon/src/alive_monitor/details/ifexm:observable_event_reader",
"//score/launch_manager/src/daemon/src/alive_monitor/details/timers:time_conversion",
"//score/launch_manager/src/daemon/src/alive_monitor/details/timers:timers_os_clock",
"//score/launch_manager/src/daemon/src/common:alive_interface_path",
"//score/launch_manager/src/daemon/src/common:constants",
"//score/launch_manager/src/daemon/src/common:identifier_hash",
"//score/launch_manager/src/daemon/src/common:log",
"//score/launch_manager/src/daemon/src/configuration:config",
"@score_baselibs//score/language/futurecpp",
],
)

lm_cc_test(
name = "alive_worker_factory_UT",
srcs = [
"AliveWorkerFactory_UT.cpp",
],
deps = [
":mockable_alive_worker_factory",
"//score/launch_manager/src/daemon/src/alive_monitor/details/ifexm:mock_observable_event_reader",
"//score/launch_manager/src/daemon/src/recovery_client:mock_recovery_client",
"@googletest//:gtest_main",
],
)
Loading
Loading