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
28 changes: 18 additions & 10 deletions tests/integration/switch_run_target/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,27 @@ cc_binary(
for component in [
"component_a",
"component_b",
"component_d",
]
]

cc_binary(
name = "component_e",
srcs = ["//tests/utils/test_helper:reporting_process.cpp"],
deps = [
"//score/launch_manager:lifecycle_cc",
"//tests/utils/test_helper",
"@googletest//:gtest_main",
],
)
# Components D and E share component_d_or_e.cpp; the component ("d" or "e") is
# passed on the command line (see switch_run_target.json).
[
cc_binary(
name = "component_" + component,
srcs = ["component_d_or_e.cpp"],
deps = [
":switch_run_target_common",
"//score/launch_manager:lifecycle_cc",
"//tests/utils/test_helper",
"@googletest//:gtest_main",
],
)
for component in [
"d",
"e",
]
]

integration_test(
name = "switch_run_target",
Expand Down
1 change: 0 additions & 1 deletion tests/integration/switch_run_target/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,4 @@ PROC_FILES(d)
PROC_FILES(e)

#undef PROC_FILES

#endif
36 changes: 0 additions & 36 deletions tests/integration/switch_run_target/component_d.cpp

This file was deleted.

78 changes: 78 additions & 0 deletions tests/integration/switch_run_target/component_d_or_e.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/********************************************************************************
* 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 <gtest/gtest.h>
#include <iostream>
#include <string>
#include <string_view>

#include "common.hpp"
#include "tests/utils/test_helper/test_helper.hpp"
#include <score/mw/lifecycle/report_running.h>

/// @file component_d_or_e.cpp
/// @brief Shared source for components D and E of the switch_run_target test.
/// The component is selected by the single command line argument "d" or
/// "e"; the process writes its "started" marker once it has reported
/// running and its "terminating" marker just before it exits.

namespace
{
std::string_view g_started;
std::string_view g_terminating;
std::string g_xml_name;
} // namespace

TEST(Component, RunAndVerify)
{
TEST_STEP("Report running")
{
EXPECT_TRUE(touch_file(g_started)) << "failed to deploy file";
score::mw::lifecycle::report_running();
}
while (!TestRunner::exitRequested)
{
pause();
}
EXPECT_TRUE(touch_file(g_terminating)) << "Failed to deploy file";
}

int main(int argc, char** argv)
{
if (argc != 2)
{
std::cerr << "Usage: component_d_or_e <d|e>" << std::endl;
return EXIT_FAILURE;
}

const std::string_view component{argv[1]};
if (component == "d")
{
g_started = d_started;
g_terminating = d_terminating;
}
else if (component == "e")
{
g_started = e_started;
g_terminating = e_terminating;
}
else
{
std::cerr << "Invalid argument '" << component << "', expected 'd' or 'e'" << std::endl;
return EXIT_FAILURE;
}

// Name the GTest XML result file per component so the two binaries built from
// this source write distinct results.
g_xml_name = "component_" + std::string{component};
return TestRunner(g_xml_name).RunTests();
}
24 changes: 17 additions & 7 deletions tests/integration/switch_run_target/control_client_mock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ TEST(SwitchRunTarget, ControlClientMock)
}
// When we switch run to run target A
// Then
// Processes A and B verify that B is started before A and terminated after A.
// Processes A and B verify that B is started before A and terminated after A when switching run targets
const auto running_processes = {a_started, b_started, d_started};
const auto terminating_processes = {a_terminating, b_terminating, d_terminating};

TEST_STEP("Activate run target A")
{
score::cpp::stop_token stop_token;
Expand All @@ -52,8 +55,7 @@ TEST(SwitchRunTarget, ControlClientMock)
}
TEST_STEP("Verify running processes")
{
const auto running = {a_started, b_started, d_started};
for (const auto proc : running)
for (const auto proc : running_processes)
{
EXPECT_TRUE(std::filesystem::exists(proc)) << "A process depended on by run target A was not started!";
}
Expand All @@ -65,14 +67,22 @@ TEST(SwitchRunTarget, ControlClientMock)
auto result = client.ActivateRunTarget("Startup").Get(stop_token);
EXPECT_TRUE(result.has_value()) << "Activating target Startup failed: " << result.error().Message();
}
TEST_STEP("Activate RunTarget Off")

TEST_STEP("Verify terminated processes")
{
for (const auto proc : terminating_processes)
{
EXPECT_TRUE(std::filesystem::exists(proc)) << "A process depended on by run target A was not terminated!";
}
}

TEST_STEP("Verify that component E was never started")
{
client.ActivateRunTarget("Off");
EXPECT_FALSE(std::filesystem::exists(e_started)) << "Component E should not be launched";
EXPECT_FALSE(std::filesystem::exists(e_started)) << "Component E should not have been started!";
}
}

int main()
{
return TestRunner(__FILE__, TerminationBehavior::kWait, TerminationNotification::kTestEnd).RunTests();
return TestRunner(__FILE__, TerminationBehavior::kContinue, TerminationNotification::kTestEnd).RunTests();
}
35 changes: 8 additions & 27 deletions tests/integration/switch_run_target/switch_run_target.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,6 @@
"defaults": {
"deployment_config": {
"bin_dir": "/tmp/tests/switch_run_target",
"ready_timeout": 1.0,
"shutdown_timeout": 1.0,
"ready_recovery_action": {
"restart": {
"number_of_attempts": 0
}
},
"recovery_action": {
"switch_run_target": {
"run_target": "fallback_run_target"
Expand All @@ -24,21 +17,6 @@
"scheduling_policy": "SCHED_OTHER",
"scheduling_priority": 0
}
},
"component_properties": {
"application_profile": {
"application_type": "Reporting",
"is_self_terminating": false,
"alive_supervision": {
"reporting_cycle": 0.1,
"min_indications": 1,
"max_indications": 3,
"failed_cycles_tolerance": 1
}
},
"ready_condition": {
"process_state": "Running"
}
}
},
"components": {
Expand Down Expand Up @@ -83,7 +61,10 @@
},
"component_e": {
"component_properties": {
"binary_name": "reporting_process"
"binary_name": "component_e",
"process_arguments": [
"e"
]
},
"deployment_config": {
"environmental_variables": {
Expand All @@ -93,7 +74,10 @@
},
"component_d": {
"component_properties": {
"binary_name": "component_d"
"binary_name": "component_d",
"process_arguments": [
"d"
]
},
"deployment_config": {
"environmental_variables": {
Expand Down Expand Up @@ -125,9 +109,6 @@
}
},
"initial_run_target": "Startup",
"alive_supervision": {
"evaluation_cycle": 0.05
},
"fallback_run_target": {
"depends_on": []
}
Expand Down
8 changes: 5 additions & 3 deletions tests/integration/switch_run_target/switch_run_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,18 @@
"comp_req__launch_man__process_state_comm",
"feat_req__lifecycle__process_termination",
"feat_req__lifecycle__terminationn_dependency",
"feat_req__lifecycle__process_ordering",
"comp_req__launch_man__launch_manager_shutdown",
Comment thread
TimoSteuerwaldETAS marked this conversation as resolved.
],
test_type="requirements-based",
derivation_technique="requirements-analysis",
)
def test_switch_run_target(target, setup_test, assert_test_results, remote_test_dir):
"""
Objective: Verifies that the launch manager respects component and run target dependencies when switching run targets, enforcing correct startup and termination order.
Objective: Verifies that the launch manager respects component and run target dependencies when switching run targets and shuting down, enforcing correct startup and termination order.

The control client activates run_target_a, which depends on run_target_c (containing component_d) and component_a (which depends on component_b). After activation it switches back to Startup and then Off.
Expected Behaviour: Component B starts before component A, component D is started, component A terminates before component B, and component E (not in the dependency chain) is never launched.
The control client activates run_target_a, which depends on run_target_c (containing component_d) and component_a (which depends on component_b). After activation it switches back to Startup, and then Off.
Expected Behaviour: During activation resp. deactivation of run_target_a, component B starts before component A, component D is started, component A terminates before component B, and component E (not in the dependency chain) is never launched.
"""

config_path = str(remote_test_dir / "etc/switch_run_target.bin")
Expand Down
Loading