From ec547431578aa0cb759f9170efd89c956178cffc Mon Sep 17 00:00:00 2001 From: Julien Enoch Date: Wed, 29 Jul 2026 20:28:37 +0200 Subject: [PATCH] Add RMW isolation to test_launch_ros tests Signed-off-by: Julien Enoch --- test_launch_ros/package.xml | 2 ++ .../actions/test_composable_node_container.py | 4 ++- .../actions/test_load_composable_nodes.py | 31 ++++++++++--------- .../test_launch_ros/actions/test_ros_timer.py | 3 +- .../frontend/test_component_container.py | 4 +++ .../frontend/test_lifecycle_node_frontend.py | 3 ++ .../utilities/test_track_node_names.py | 3 ++ 7 files changed, 34 insertions(+), 16 deletions(-) diff --git a/test_launch_ros/package.xml b/test_launch_ros/package.xml index 45bece3e8..7bafbcf67 100644 --- a/test_launch_ros/package.xml +++ b/test_launch_ros/package.xml @@ -25,6 +25,7 @@ composition demo_nodes_py launch_ros + launch_testing_ros launch_xml launch_yaml lifecycle @@ -34,6 +35,7 @@ python3-yaml rclcpp_components rclpy + rmw_test_fixture_implementation rosgraph_msgs diff --git a/test_launch_ros/test/test_launch_ros/actions/test_composable_node_container.py b/test_launch_ros/test/test_launch_ros/actions/test_composable_node_container.py index 4314d1d65..154cd23b4 100644 --- a/test_launch_ros/test/test_launch_ros/actions/test_composable_node_container.py +++ b/test_launch_ros/test/test_launch_ros/actions/test_composable_node_container.py @@ -25,6 +25,8 @@ from launch_ros.descriptions import ComposableNode from launch_ros.utilities import get_node_name_count +from launch_testing_ros.actions import EnableRmwIsolation + import osrf_pycommon.process_utils TEST_CONTAINER_NAME = 'test_component_container_node_name' @@ -34,7 +36,7 @@ def _assert_launch_no_errors(actions, *, timeout_sec=5): - ld = LaunchDescription(actions) + ld = LaunchDescription([EnableRmwIsolation(), *actions]) ls = LaunchService(debug=True) ls.include_launch_description(ld) diff --git a/test_launch_ros/test/test_launch_ros/actions/test_load_composable_nodes.py b/test_launch_ros/test/test_launch_ros/actions/test_load_composable_nodes.py index bee37809b..8391f1f24 100644 --- a/test_launch_ros/test/test_launch_ros/actions/test_load_composable_nodes.py +++ b/test_launch_ros/test/test_launch_ros/actions/test_load_composable_nodes.py @@ -38,6 +38,8 @@ import rclpy.executors import rclpy.node +from rmw_test_fixture_implementation import RMWTestIsolator + TEST_CONTAINER_NAME = 'mock_component_container' TEST_NODE_NAME = 'test_load_composable_nodes_node' @@ -103,20 +105,21 @@ def _load_composable_node( @pytest.fixture def mock_component_container(): - context = rclpy.context.Context() - with rclpy.init(context=context): - executor = rclpy.executors.SingleThreadedExecutor(context=context) - - container = MockComponentContainer(context) - executor.add_node(container) - - # Start spinning in a thread - thread = threading.Thread(target=lambda executor: executor.spin(), args=(executor,)) - thread.start() - yield container - executor.remove_node(container) - executor.shutdown() - thread.join() + with RMWTestIsolator(): + context = rclpy.context.Context() + with rclpy.init(context=context): + executor = rclpy.executors.SingleThreadedExecutor(context=context) + + container = MockComponentContainer(context) + executor.add_node(container) + + # Start spinning in a thread + thread = threading.Thread(target=lambda executor: executor.spin(), args=(executor,)) + thread.start() + yield container + executor.remove_node(container) + executor.shutdown() + thread.join() def test_load_node(mock_component_container): diff --git a/test_launch_ros/test/test_launch_ros/actions/test_ros_timer.py b/test_launch_ros/test/test_launch_ros/actions/test_ros_timer.py index 7f1c37e7d..482c493bc 100644 --- a/test_launch_ros/test/test_launch_ros/actions/test_ros_timer.py +++ b/test_launch_ros/test/test_launch_ros/actions/test_ros_timer.py @@ -28,6 +28,7 @@ import pytest import rclpy from rclpy.clock import Clock, ClockType +from rmw_test_fixture_implementation import RMWTestIsolator from rosgraph_msgs.msg import Clock as ClockMsg @@ -151,7 +152,7 @@ def test_shutdown_preempts_timers(): @pytest.fixture def rclpy_node(): - with rclpy.init(): + with RMWTestIsolator(), rclpy.init(): node = rclpy.create_node('test_ros_timer_action_node') yield node diff --git a/test_launch_ros/test/test_launch_ros/frontend/test_component_container.py b/test_launch_ros/test/test_launch_ros/frontend/test_component_container.py index 53192632d..735fa9972 100644 --- a/test_launch_ros/test/test_launch_ros/frontend/test_component_container.py +++ b/test_launch_ros/test/test_launch_ros/frontend/test_component_container.py @@ -17,10 +17,12 @@ import io import textwrap +from launch import LaunchDescription from launch import LaunchService from launch.frontend import Parser from launch.utilities import perform_substitutions from launch_ros.utilities import evaluate_parameters +from launch_testing_ros.actions import EnableRmwIsolation import osrf_pycommon.process_utils import pytest @@ -174,6 +176,7 @@ def test_launch_container_executor_modes(file_factory, container_args): root_entity, parser = Parser.load(f) ld = parser.parse_description(root_entity) ls = LaunchService() + ls.include_launch_description(LaunchDescription([EnableRmwIsolation()])) ls.include_launch_description(ld) loop = osrf_pycommon.process_utils.get_loop() @@ -196,6 +199,7 @@ def check_launch_component_container(file): root_entity, parser = Parser.load(file) ld = parser.parse_description(root_entity) ls = LaunchService() + ls.include_launch_description(LaunchDescription([EnableRmwIsolation()])) ls.include_launch_description(ld) loop = osrf_pycommon.process_utils.get_loop() diff --git a/test_launch_ros/test/test_launch_ros/frontend/test_lifecycle_node_frontend.py b/test_launch_ros/test/test_launch_ros/frontend/test_lifecycle_node_frontend.py index 0a5e0ce70..8c1657738 100644 --- a/test_launch_ros/test/test_launch_ros/frontend/test_lifecycle_node_frontend.py +++ b/test_launch_ros/test/test_launch_ros/frontend/test_lifecycle_node_frontend.py @@ -17,11 +17,13 @@ import pathlib import textwrap +from launch import LaunchDescription from launch import LaunchService from launch.frontend import Parser from launch.utilities import type_utils from launch_ros.actions import LifecycleNode from launch_ros.utilities import evaluate_parameters +from launch_testing_ros.actions import EnableRmwIsolation import osrf_pycommon.process_utils yaml_params = str(pathlib.Path(__file__).parent / 'params.yaml') @@ -105,6 +107,7 @@ def check_launch_lifecycle_node(file): root_entity, parser = Parser.load(file) ld = parser.parse_description(root_entity) ls = LaunchService() + ls.include_launch_description(LaunchDescription([EnableRmwIsolation()])) ls.include_launch_description(ld) loop = osrf_pycommon.process_utils.get_loop() diff --git a/test_launch_ros/test/test_launch_ros/utilities/test_track_node_names.py b/test_launch_ros/test/test_launch_ros/utilities/test_track_node_names.py index 9fce6b580..732010d1a 100644 --- a/test_launch_ros/test/test_launch_ros/utilities/test_track_node_names.py +++ b/test_launch_ros/test/test_launch_ros/utilities/test_track_node_names.py @@ -27,6 +27,8 @@ from launch_ros.utilities import add_node_name from launch_ros.utilities import get_node_name_count +from launch_testing_ros.actions import EnableRmwIsolation + import osrf_pycommon.process_utils TEST_NODE_NAMESPACE = '/my_namespace' @@ -46,6 +48,7 @@ def test_node_name_count(): def _launch(launch_description): loop = osrf_pycommon.process_utils.get_loop() ls = LaunchService() + ls.include_launch_description(LaunchDescription([EnableRmwIsolation()])) ls.include_launch_description(launch_description) launch_task = loop.create_task(ls.run_async()) loop.run_until_complete(asyncio.sleep(5))