From 9b3829121bdf6f4e407b72e1b950a1624ac4cf6d Mon Sep 17 00:00:00 2001 From: Timo Steuerwald Date: Thu, 16 Jul 2026 19:01:16 +0200 Subject: [PATCH 1/9] Update requirements list --- tests/integration/switch_run_target/switch_run_target.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration/switch_run_target/switch_run_target.py b/tests/integration/switch_run_target/switch_run_target.py index 849daaf17d..908d58de41 100644 --- a/tests/integration/switch_run_target/switch_run_target.py +++ b/tests/integration/switch_run_target/switch_run_target.py @@ -23,6 +23,7 @@ "comp_req__launch_man__process_state_comm", "feat_req__lifecycle__process_termination", "feat_req__lifecycle__terminationn_dependency", + "feat_req__lifecycle__process_ordering", ], test_type="requirements-based", derivation_technique="requirements-analysis", From f6e99378abc06b97856b5e6d59837376a7048d54 Mon Sep 17 00:00:00 2001 From: Timo Steuerwald Date: Fri, 17 Jul 2026 18:09:36 +0200 Subject: [PATCH 2/9] Replace reporting_process.cpp with component_e.cpp --- tests/integration/switch_run_target/BUILD | 11 +----- .../switch_run_target/component_e.cpp | 36 +++++++++++++++++++ .../switch_run_target/switch_run_target.json | 2 +- 3 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 tests/integration/switch_run_target/component_e.cpp diff --git a/tests/integration/switch_run_target/BUILD b/tests/integration/switch_run_target/BUILD index 714a09b606..53aa0ab998 100644 --- a/tests/integration/switch_run_target/BUILD +++ b/tests/integration/switch_run_target/BUILD @@ -46,19 +46,10 @@ cc_binary( "component_a", "component_b", "component_d", + "component_e", ] ] -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", - ], -) - integration_test( name = "switch_run_target", srcs = ["switch_run_target.py"], diff --git a/tests/integration/switch_run_target/component_e.cpp b/tests/integration/switch_run_target/component_e.cpp new file mode 100644 index 0000000000..f690ccebdd --- /dev/null +++ b/tests/integration/switch_run_target/component_e.cpp @@ -0,0 +1,36 @@ +/******************************************************************************** + * 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 "common.hpp" +#include "tests/utils/test_helper/test_helper.hpp" +#include + +TEST(ComponentE, RunAndVerify) +{ + TEST_STEP("Report running") + { + EXPECT_TRUE(touch_file(e_started)) << "failed to deploy file"; + score::mw::lifecycle::report_running(); + } + while (!TestRunner::exitRequested) + { + pause(); + } + EXPECT_TRUE(touch_file(e_terminating)) << "Failed to deploy file"; +} + +int main() +{ + return TestRunner(__FILE__).RunTests(); +} diff --git a/tests/integration/switch_run_target/switch_run_target.json b/tests/integration/switch_run_target/switch_run_target.json index b9e1825a04..0519f9a908 100644 --- a/tests/integration/switch_run_target/switch_run_target.json +++ b/tests/integration/switch_run_target/switch_run_target.json @@ -83,7 +83,7 @@ }, "component_e": { "component_properties": { - "binary_name": "reporting_process" + "binary_name": "component_e" }, "deployment_config": { "environmental_variables": { From 2baae5e5ef4944f728dff76c5c10fcc0838d48cd Mon Sep 17 00:00:00 2001 From: Timo Steuerwald Date: Fri, 17 Jul 2026 18:52:38 +0200 Subject: [PATCH 3/9] Adapt test to cover switch run target and shutdown test --- .../switch_run_target/control_client_mock.cpp | 45 +++++++++++++++++-- .../switch_run_target/switch_run_target.py | 7 +-- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/tests/integration/switch_run_target/control_client_mock.cpp b/tests/integration/switch_run_target/control_client_mock.cpp index be7cd17043..1f363926ef 100644 --- a/tests/integration/switch_run_target/control_client_mock.cpp +++ b/tests/integration/switch_run_target/control_client_mock.cpp @@ -17,6 +17,23 @@ #include #include +namespace +{ +void resetFilesystem( + std::initializer_list running_processes, + std::initializer_list terminating_processes) +{ + for (const auto proc : running_processes) + { + EXPECT_TRUE(std::filesystem::remove(proc)) << "Failed to remove file " << proc; + } + for (const auto proc : terminating_processes) + { + EXPECT_TRUE(std::filesystem::remove(proc)) << "Failed to remove file " << proc; + } +} +} // namespace + // Given a configuration with the following dependency tree: // - Startup - which is the initial run target - depends on component component_initial // - component_initial: No dependencies @@ -43,7 +60,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; @@ -52,8 +72,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!"; } @@ -65,9 +84,29 @@ TEST(SwitchRunTarget, ControlClientMock) auto result = client.ActivateRunTarget("Startup").Get(stop_token); EXPECT_TRUE(result.has_value()) << "Activating target Startup failed: " << result.error().Message(); } + + resetFilesystem(running_processes, terminating_processes); + + // When we switch run to run target A + // Then + // Processes A and B verify that B is started before A and terminated after A when shutting down + TEST_STEP("Activate run target A") + { + score::cpp::stop_token stop_token; + auto result = client.ActivateRunTarget("run_target_a").Get(stop_token); + EXPECT_TRUE(result.has_value()) << "Activating target run_target_a failed: " << result.error().Message(); + } + TEST_STEP("Verify running processes") + { + for (const auto proc : running_processes) + { + EXPECT_TRUE(std::filesystem::exists(proc)) << "A process depended on by run target A was not started!"; + } + } TEST_STEP("Activate RunTarget Off") { client.ActivateRunTarget("Off"); + // In the whole test, component E should never be launched, since it is not included in any run target EXPECT_FALSE(std::filesystem::exists(e_started)) << "Component E should not be launched"; } } diff --git a/tests/integration/switch_run_target/switch_run_target.py b/tests/integration/switch_run_target/switch_run_target.py index 908d58de41..7d467e0428 100644 --- a/tests/integration/switch_run_target/switch_run_target.py +++ b/tests/integration/switch_run_target/switch_run_target.py @@ -24,16 +24,17 @@ "feat_req__lifecycle__process_termination", "feat_req__lifecycle__terminationn_dependency", "feat_req__lifecycle__process_ordering", + "feat_req__lifecycle__launch_manager_shutdown" ], 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, then again to run_target_a, 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") From bccc0e27ea0fee27687311a5db2683dfbd65ce29 Mon Sep 17 00:00:00 2001 From: Timo Steuerwald Date: Mon, 10 Aug 2026 12:32:37 +0200 Subject: [PATCH 4/9] Fix format --- tests/integration/switch_run_target/switch_run_target.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/switch_run_target/switch_run_target.py b/tests/integration/switch_run_target/switch_run_target.py index 7d467e0428..4b7ebf1c62 100644 --- a/tests/integration/switch_run_target/switch_run_target.py +++ b/tests/integration/switch_run_target/switch_run_target.py @@ -24,7 +24,7 @@ "feat_req__lifecycle__process_termination", "feat_req__lifecycle__terminationn_dependency", "feat_req__lifecycle__process_ordering", - "feat_req__lifecycle__launch_manager_shutdown" + "feat_req__lifecycle__launch_manager_shutdown", ], test_type="requirements-based", derivation_technique="requirements-analysis", From 8939cc409691ebe8d9d646e0ecfa7ad194db8cf3 Mon Sep 17 00:00:00 2001 From: Timo Steuerwald Date: Mon, 10 Aug 2026 12:42:16 +0200 Subject: [PATCH 5/9] Requirement is no longer on feature, but on cmp level --- tests/integration/switch_run_target/switch_run_target.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/switch_run_target/switch_run_target.py b/tests/integration/switch_run_target/switch_run_target.py index 4b7ebf1c62..a81ccd3174 100644 --- a/tests/integration/switch_run_target/switch_run_target.py +++ b/tests/integration/switch_run_target/switch_run_target.py @@ -24,7 +24,7 @@ "feat_req__lifecycle__process_termination", "feat_req__lifecycle__terminationn_dependency", "feat_req__lifecycle__process_ordering", - "feat_req__lifecycle__launch_manager_shutdown", + "comp_req__launch_man__launch_manager_shutdown", ], test_type="requirements-based", derivation_technique="requirements-analysis", From 0332bc8b3e0296b5d1a7bf61574b9bac6bd7ca0e Mon Sep 17 00:00:00 2001 From: Timo Steuerwald Date: Mon, 10 Aug 2026 14:13:56 +0200 Subject: [PATCH 6/9] Remove duplication for cmp d and e --- tests/integration/switch_run_target/BUILD | 21 ++++- .../integration/switch_run_target/common.hpp | 1 - .../switch_run_target/component_d.cpp | 36 --------- .../switch_run_target/component_d_or_e.cpp | 78 +++++++++++++++++++ .../switch_run_target/component_e.cpp | 36 --------- .../switch_run_target/switch_run_target.json | 10 ++- 6 files changed, 105 insertions(+), 77 deletions(-) delete mode 100644 tests/integration/switch_run_target/component_d.cpp create mode 100644 tests/integration/switch_run_target/component_d_or_e.cpp delete mode 100644 tests/integration/switch_run_target/component_e.cpp diff --git a/tests/integration/switch_run_target/BUILD b/tests/integration/switch_run_target/BUILD index 53aa0ab998..58c489b5ba 100644 --- a/tests/integration/switch_run_target/BUILD +++ b/tests/integration/switch_run_target/BUILD @@ -45,8 +45,25 @@ cc_binary( for component in [ "component_a", "component_b", - "component_d", - "component_e", + ] +] + +# 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", ] ] diff --git a/tests/integration/switch_run_target/common.hpp b/tests/integration/switch_run_target/common.hpp index 0f5847e8d4..e876639eb6 100644 --- a/tests/integration/switch_run_target/common.hpp +++ b/tests/integration/switch_run_target/common.hpp @@ -28,5 +28,4 @@ PROC_FILES(d) PROC_FILES(e) #undef PROC_FILES - #endif diff --git a/tests/integration/switch_run_target/component_d.cpp b/tests/integration/switch_run_target/component_d.cpp deleted file mode 100644 index 8e1376e122..0000000000 --- a/tests/integration/switch_run_target/component_d.cpp +++ /dev/null @@ -1,36 +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 "common.hpp" -#include "tests/utils/test_helper/test_helper.hpp" -#include - -TEST(ComponentD, RunAndVerify) -{ - TEST_STEP("Report running") - { - EXPECT_TRUE(touch_file(d_started)) << "failed to deploy file"; - score::mw::lifecycle::report_running(); - } - while (!TestRunner::exitRequested) - { - pause(); - } - EXPECT_TRUE(touch_file(d_terminating)) << "Failed to deploy file"; -} - -int main() -{ - return TestRunner(__FILE__).RunTests(); -} diff --git a/tests/integration/switch_run_target/component_d_or_e.cpp b/tests/integration/switch_run_target/component_d_or_e.cpp new file mode 100644 index 0000000000..e06670a4ec --- /dev/null +++ b/tests/integration/switch_run_target/component_d_or_e.cpp @@ -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 +#include +#include +#include + +#include "common.hpp" +#include "tests/utils/test_helper/test_helper.hpp" +#include + +/// @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 " << 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(); +} diff --git a/tests/integration/switch_run_target/component_e.cpp b/tests/integration/switch_run_target/component_e.cpp deleted file mode 100644 index f690ccebdd..0000000000 --- a/tests/integration/switch_run_target/component_e.cpp +++ /dev/null @@ -1,36 +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 "common.hpp" -#include "tests/utils/test_helper/test_helper.hpp" -#include - -TEST(ComponentE, RunAndVerify) -{ - TEST_STEP("Report running") - { - EXPECT_TRUE(touch_file(e_started)) << "failed to deploy file"; - score::mw::lifecycle::report_running(); - } - while (!TestRunner::exitRequested) - { - pause(); - } - EXPECT_TRUE(touch_file(e_terminating)) << "Failed to deploy file"; -} - -int main() -{ - return TestRunner(__FILE__).RunTests(); -} diff --git a/tests/integration/switch_run_target/switch_run_target.json b/tests/integration/switch_run_target/switch_run_target.json index 0519f9a908..820ddbf0b5 100644 --- a/tests/integration/switch_run_target/switch_run_target.json +++ b/tests/integration/switch_run_target/switch_run_target.json @@ -83,7 +83,10 @@ }, "component_e": { "component_properties": { - "binary_name": "component_e" + "binary_name": "component_e", + "process_arguments": [ + "e" + ] }, "deployment_config": { "environmental_variables": { @@ -93,7 +96,10 @@ }, "component_d": { "component_properties": { - "binary_name": "component_d" + "binary_name": "component_d", + "process_arguments": [ + "d" + ] }, "deployment_config": { "environmental_variables": { From d2dd181f7d411c4da7857e93bb06d16d5f9987cc Mon Sep 17 00:00:00 2001 From: Timo Steuerwald Date: Mon, 10 Aug 2026 14:24:32 +0200 Subject: [PATCH 7/9] Strip down config --- .../switch_run_target/switch_run_target.json | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/tests/integration/switch_run_target/switch_run_target.json b/tests/integration/switch_run_target/switch_run_target.json index 820ddbf0b5..f27c94c503 100644 --- a/tests/integration/switch_run_target/switch_run_target.json +++ b/tests/integration/switch_run_target/switch_run_target.json @@ -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" @@ -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": { @@ -131,9 +109,6 @@ } }, "initial_run_target": "Startup", - "alive_supervision": { - "evaluation_cycle": 0.05 - }, "fallback_run_target": { "depends_on": [] } From 25d8b2c87e47512a74568304275b64b03147f12f Mon Sep 17 00:00:00 2001 From: Timo Steuerwald Date: Mon, 10 Aug 2026 18:32:48 +0200 Subject: [PATCH 8/9] Rework control_client_mock.cpp --- .../switch_run_target/control_client_mock.cpp | 43 +++---------------- 1 file changed, 7 insertions(+), 36 deletions(-) diff --git a/tests/integration/switch_run_target/control_client_mock.cpp b/tests/integration/switch_run_target/control_client_mock.cpp index 1f363926ef..2b3f3f5b51 100644 --- a/tests/integration/switch_run_target/control_client_mock.cpp +++ b/tests/integration/switch_run_target/control_client_mock.cpp @@ -17,23 +17,6 @@ #include #include -namespace -{ -void resetFilesystem( - std::initializer_list running_processes, - std::initializer_list terminating_processes) -{ - for (const auto proc : running_processes) - { - EXPECT_TRUE(std::filesystem::remove(proc)) << "Failed to remove file " << proc; - } - for (const auto proc : terminating_processes) - { - EXPECT_TRUE(std::filesystem::remove(proc)) << "Failed to remove file " << proc; - } -} -} // namespace - // Given a configuration with the following dependency tree: // - Startup - which is the initial run target - depends on component component_initial // - component_initial: No dependencies @@ -85,33 +68,21 @@ TEST(SwitchRunTarget, ControlClientMock) EXPECT_TRUE(result.has_value()) << "Activating target Startup failed: " << result.error().Message(); } - resetFilesystem(running_processes, terminating_processes); - - // When we switch run to run target A - // Then - // Processes A and B verify that B is started before A and terminated after A when shutting down - TEST_STEP("Activate run target A") - { - score::cpp::stop_token stop_token; - auto result = client.ActivateRunTarget("run_target_a").Get(stop_token); - EXPECT_TRUE(result.has_value()) << "Activating target run_target_a failed: " << result.error().Message(); - } - TEST_STEP("Verify running processes") + TEST_STEP("Verify terminated processes") { - for (const auto proc : running_processes) + for (const auto proc : terminating_processes) { - EXPECT_TRUE(std::filesystem::exists(proc)) << "A process depended on by run target A was not started!"; + EXPECT_TRUE(std::filesystem::exists(proc)) << "A process depended on by run target A was not terminated!"; } } - TEST_STEP("Activate RunTarget Off") + + TEST_STEP("Verify that component E was never started") { - client.ActivateRunTarget("Off"); - // In the whole test, component E should never be launched, since it is not included in any run target - 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(); } From b33477c8f217c79497a52baadf947ca910fb641d Mon Sep 17 00:00:00 2001 From: Timo Steuerwald <142218678+TimoSteuerwaldETAS@users.noreply.github.com> Date: Tue, 11 Aug 2026 11:52:56 +0200 Subject: [PATCH 9/9] Update test description to match to latest changes Co-authored-by: WilliamRoebuck <244554584+WilliamRoebuck@users.noreply.github.com> Signed-off-by: Timo Steuerwald <142218678+TimoSteuerwaldETAS@users.noreply.github.com> --- tests/integration/switch_run_target/switch_run_target.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/switch_run_target/switch_run_target.py b/tests/integration/switch_run_target/switch_run_target.py index a81ccd3174..7a458a1258 100644 --- a/tests/integration/switch_run_target/switch_run_target.py +++ b/tests/integration/switch_run_target/switch_run_target.py @@ -33,7 +33,7 @@ def test_switch_run_target(target, setup_test, assert_test_results, remote_test_ """ 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, then again to run_target_a, and then Off. + 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. """