diff --git a/ros2action/test/test_cli.py b/ros2action/test/test_cli.py index 2a3a91042..a44cdd5c3 100644 --- a/ros2action/test/test_cli.py +++ b/ros2action/test/test_cli.py @@ -20,12 +20,17 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.actions import SetEnvironmentVariable +from launch.event_handlers import OnShutdown import launch_testing import launch_testing.actions import launch_testing.asserts import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools import pytest @@ -51,23 +56,35 @@ def generate_test_description(rmw_implementation): os.path.dirname(__file__), 'fixtures', 'fibonacci_action_server.py' ) additional_env = get_rmw_additional_env(rmw_implementation) + set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()] return LaunchDescription([ # Always restart daemon to isolate tests. ExecuteProcess( cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + *set_env_actions, + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + # Use the same isolated environment + additional_env=dict(additional_env), + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start', on_exit=[ ExecuteProcess( cmd=[sys.executable, path_to_action_server_executable], - additional_env=additional_env, ), launch_testing.actions.ReadyToTest() ], - additional_env=additional_env, ) ] ), @@ -115,8 +132,9 @@ def setUpClass( ): @contextlib.contextmanager def launch_action_command(self, arguments): - additional_env = get_rmw_additional_env(rmw_implementation) - additional_env['PYTHONUNBUFFERED'] = '1' + additional_env = { + 'PYTHONUNBUFFERED': '1', + } action_command_action = ExecuteProcess( cmd=['ros2', 'action', *arguments], diff --git a/ros2action/test/test_echo.py b/ros2action/test/test_echo.py index b3cc6bb46..23bc21ae3 100644 --- a/ros2action/test/test_echo.py +++ b/ros2action/test/test_echo.py @@ -21,6 +21,10 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.actions import SetEnvironmentVariable +from launch.event_handlers import OnShutdown import launch_testing import launch_testing.actions @@ -28,6 +32,7 @@ import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools from osrf_pycommon.terminal_color import remove_ansi_escape_sequences @@ -221,23 +226,35 @@ def generate_test_description(rmw_implementation): os.path.dirname(__file__), 'fixtures', 'fibonacci_action_introspection.py' ) additional_env = get_rmw_additional_env(rmw_implementation) + set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()] return LaunchDescription([ # Always restart daemon to isolate tests. ExecuteProcess( cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + *set_env_actions, + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + # Use the same isolated environment + additional_env=dict(additional_env), + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start', on_exit=[ ExecuteProcess( cmd=[sys.executable, path_to_action_server_executable], - additional_env=additional_env ), launch_testing.actions.ReadyToTest() ], - additional_env=additional_env ) ] ), @@ -256,8 +273,9 @@ def setUpClass( ): @contextlib.contextmanager def launch_action_command(self, arguments): - additional_env = get_rmw_additional_env(rmw_implementation) - additional_env['PYTHONUNBUFFERED'] = '1' + additional_env = { + 'PYTHONUNBUFFERED': '1', + } action_command_action = ExecuteProcess( cmd=['ros2', 'action', *arguments], name='ros2action-cli', output='screen', diff --git a/ros2cli/ros2cli/helpers.py b/ros2cli/ros2cli/helpers.py index 6c0c9ba09..abffcd489 100644 --- a/ros2cli/ros2cli/helpers.py +++ b/ros2cli/ros2cli/helpers.py @@ -127,8 +127,6 @@ def get_rmw_additional_env(rmw_implementation: str) -> Dict[str, str]: if rmw_implementation == 'rmw_zenoh_cpp': return { 'RMW_IMPLEMENTATION': rmw_implementation, - 'ZENOH_ROUTER_CHECK_ATTEMPTS': '-1', - 'ZENOH_CONFIG_OVERRIDE': 'scouting/multicast/enabled=true', 'RUST_LOG': 'z=error' } else: diff --git a/ros2doctor/test/test_qos_compatibility.py b/ros2doctor/test/test_qos_compatibility.py index 1a6a580f3..3772fcb76 100644 --- a/ros2doctor/test/test_qos_compatibility.py +++ b/ros2doctor/test/test_qos_compatibility.py @@ -19,6 +19,10 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.actions import SetEnvironmentVariable +from launch.event_handlers import OnShutdown from launch_ros.actions import Node @@ -27,6 +31,7 @@ import launch_testing.asserts import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools import pytest @@ -49,6 +54,7 @@ def generate_test_description(rmw_implementation): path_to_fixtures = os.path.join(os.path.dirname(__file__), 'fixtures') additional_env = get_rmw_additional_env(rmw_implementation) additional_env['PYTHONUNBUFFERED'] = '1' + set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()] path_to_incompatible_talker_node_script = os.path.join( path_to_fixtures, 'talker_node_with_best_effort_qos.py') @@ -62,25 +68,21 @@ def generate_test_description(rmw_implementation): executable=sys.executable, arguments=[path_to_compatible_talker_node_script], remappings=[('chatter', 'compatible_chatter')], - additional_env=additional_env ) listener_node_compatible = Node( executable=sys.executable, arguments=[path_to_listener_node_script], remappings=[('chatter', 'compatible_chatter')], - additional_env=additional_env ) talker_node_incompatible = Node( executable=sys.executable, arguments=[path_to_incompatible_talker_node_script], remappings=[('chatter', 'incompatible_chatter')], - additional_env=additional_env ) listener_node_incompatible = Node( executable=sys.executable, arguments=[path_to_listener_node_script], remappings=[('chatter', 'incompatible_chatter')], - additional_env=additional_env ) return LaunchDescription([ @@ -89,6 +91,19 @@ def generate_test_description(rmw_implementation): cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + *set_env_actions, + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + # Use the same isolated environment + additional_env=dict(additional_env), + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start', @@ -100,7 +115,6 @@ def generate_test_description(rmw_implementation): listener_node_compatible, launch_testing.actions.ReadyToTest() ], - additional_env=additional_env ) ] ), @@ -128,11 +142,8 @@ def setUpClass( @contextlib.contextmanager def launch_doctor_command(self, arguments): - additional_env = get_rmw_additional_env(rmw_implementation) - additional_env['PYTHONUNBUFFERED'] = '1' doctor_command_action = ExecuteProcess( cmd=['ros2', 'doctor', *arguments], - additional_env=additional_env, name='ros2doctor-cli', output='screen' ) diff --git a/ros2lifecycle/test/test_cli.py b/ros2lifecycle/test/test_cli.py index 5e67bfdaa..bcb4a341e 100644 --- a/ros2lifecycle/test/test_cli.py +++ b/ros2lifecycle/test/test_cli.py @@ -18,6 +18,10 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.actions import SetEnvironmentVariable +from launch.event_handlers import OnShutdown from launch_ros.actions import Node import launch_testing @@ -25,6 +29,7 @@ import launch_testing.asserts import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools import pytest @@ -124,12 +129,26 @@ @launch_testing.parametrize('rmw_implementation', get_available_rmw_implementations()) def generate_test_description(rmw_implementation): additional_env = get_rmw_additional_env(rmw_implementation) + set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()] return LaunchDescription([ # Always restart daemon to isolate tests. ExecuteProcess( cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + *set_env_actions, + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + # Use the same isolated environment + additional_env=dict(additional_env), + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start', @@ -140,18 +159,15 @@ def generate_test_description(rmw_implementation): executable='simple_lifecycle_node', name='test_lifecycle_node', output='screen', - additional_env=additional_env ), Node( package='ros2lifecycle_test_fixtures', executable='simple_lifecycle_node', name='_hidden_test_lifecycle_node', output='screen', - additional_env=additional_env ), launch_testing.actions.ReadyToTest() ], - additional_env=additional_env ) ] ), @@ -170,8 +186,9 @@ def setUpClass( ): @contextlib.contextmanager def launch_lifecycle_command(self, arguments): - additional_env = get_rmw_additional_env(rmw_implementation) - additional_env['PYTHONUNBUFFERED'] = '1' + additional_env = { + 'PYTHONUNBUFFERED': '1', + } lifecycle_command_action = ExecuteProcess( cmd=['ros2', 'lifecycle', *arguments], additional_env=additional_env, diff --git a/ros2node/test/test_cli.py b/ros2node/test/test_cli.py index 7777db1b1..bb226ede3 100644 --- a/ros2node/test/test_cli.py +++ b/ros2node/test/test_cli.py @@ -21,6 +21,10 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.actions import SetEnvironmentVariable +from launch.event_handlers import OnShutdown from launch_ros.actions import Node @@ -29,6 +33,7 @@ import launch_testing.asserts import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools import pytest @@ -52,12 +57,26 @@ def generate_test_description(rmw_implementation): os.path.dirname(__file__), 'fixtures', 'complex_node.py' ) additional_env = get_rmw_additional_env(rmw_implementation) + set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()] return LaunchDescription([ # Always restart daemon to isolate tests. ExecuteProcess( cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + *set_env_actions, + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + # Use the same isolated environment + additional_env=dict(additional_env), + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start', @@ -67,17 +86,14 @@ def generate_test_description(rmw_implementation): executable=sys.executable, arguments=[path_to_complex_node_script], name='complex_node', - additional_env=additional_env ), Node( executable=sys.executable, arguments=[path_to_complex_node_script], name='_hidden_complex_node', - additional_env=additional_env ), launch_testing.actions.ReadyToTest() ], - additional_env=additional_env ) ] ), @@ -96,8 +112,9 @@ def setUpClass( ): @contextlib.contextmanager def launch_node_command(self, arguments): - additional_env = get_rmw_additional_env(rmw_implementation) - additional_env['PYTHONUNBUFFERED'] = '1' + additional_env = { + 'PYTHONUNBUFFERED': '1', + } node_command_action = ExecuteProcess( cmd=['ros2', 'node', *arguments], diff --git a/ros2node/test/test_cli_duplicate_node_names.py b/ros2node/test/test_cli_duplicate_node_names.py index 4d37463e3..7b3b7a4d7 100644 --- a/ros2node/test/test_cli_duplicate_node_names.py +++ b/ros2node/test/test_cli_duplicate_node_names.py @@ -19,6 +19,10 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.actions import SetEnvironmentVariable +from launch.event_handlers import OnShutdown from launch_ros.actions import Node @@ -27,6 +31,7 @@ import launch_testing.asserts import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools import pytest @@ -51,12 +56,26 @@ def generate_test_description(rmw_implementation): os.path.dirname(__file__), 'fixtures', 'complex_node.py' ) additional_env = get_rmw_additional_env(rmw_implementation) + set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()] return LaunchDescription([ # Always restart daemon to isolate tests. ExecuteProcess( cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + *set_env_actions, + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + # Use the same isolated environment + additional_env=dict(additional_env), + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start', @@ -66,23 +85,19 @@ def generate_test_description(rmw_implementation): executable=sys.executable, arguments=[path_to_complex_node_script], name='complex_node', - additional_env=additional_env, ), Node( executable=sys.executable, arguments=[path_to_complex_node_script], name='complex_node', - additional_env=additional_env, ), Node( executable=sys.executable, arguments=[path_to_complex_node_script], name='complex_node_2', - additional_env=additional_env, ), launch_testing.actions.ReadyToTest(), ], - additional_env=additional_env ) ] ), @@ -101,8 +116,9 @@ def setUpClass( ): @contextlib.contextmanager def launch_node_command(self, arguments): - additional_env = get_rmw_additional_env(rmw_implementation) - additional_env['PYTHONUNBUFFERED'] = '1' + additional_env = { + 'PYTHONUNBUFFERED': '1', + } node_command_action = ExecuteProcess( cmd=['ros2', 'node', *arguments], additional_env=additional_env, diff --git a/ros2param/test/test_verb_dump.py b/ros2param/test/test_verb_dump.py index 3c1d1b47c..0e7c60471 100644 --- a/ros2param/test/test_verb_dump.py +++ b/ros2param/test/test_verb_dump.py @@ -21,12 +21,17 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.actions import SetEnvironmentVariable +from launch.event_handlers import OnShutdown from launch_ros.actions import Node import launch_testing import launch_testing.actions import launch_testing.asserts import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools import pytest @@ -86,6 +91,7 @@ def generate_test_description(rmw_implementation): path_to_fixtures = os.path.join(os.path.dirname(__file__), 'fixtures') additional_env = get_rmw_additional_env(rmw_implementation) + set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()] # Parameter node test fixture path_to_parameter_node_script = os.path.join(path_to_fixtures, 'parameter_node.py') @@ -94,7 +100,6 @@ def generate_test_description(rmw_implementation): name=TEST_NODE, namespace=TEST_NAMESPACE, arguments=[path_to_parameter_node_script], - additional_env=additional_env ) return LaunchDescription([ @@ -103,6 +108,19 @@ def generate_test_description(rmw_implementation): cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + *set_env_actions, + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + # Use the same isolated environment + additional_env=dict(additional_env), + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start', @@ -110,7 +128,6 @@ def generate_test_description(rmw_implementation): parameter_node, launch_testing.actions.ReadyToTest(), ], - additional_env=additional_env ) ] ), @@ -135,7 +152,6 @@ def setUpClass( def launch_param_dump_command(self, arguments): param_dump_command_action = ExecuteProcess( cmd=['ros2', 'param', 'dump', *arguments], - additional_env=get_rmw_additional_env(rmw_implementation), name='ros2param-dump-cli', output='screen' ) diff --git a/ros2param/test/test_verb_list.py b/ros2param/test/test_verb_list.py index 08ce8702c..7d853399d 100644 --- a/ros2param/test/test_verb_list.py +++ b/ros2param/test/test_verb_list.py @@ -21,12 +21,17 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.actions import SetEnvironmentVariable +from launch.event_handlers import OnShutdown from launch_ros.actions import Node import launch_testing import launch_testing.actions import launch_testing.asserts import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools import pytest @@ -56,6 +61,7 @@ def generate_test_description(rmw_implementation): path_to_fixtures = Path(__file__).parent / 'fixtures' additional_env = get_rmw_additional_env(rmw_implementation) + set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()] # Parameter node test fixture path_to_parameter_node_script = path_to_fixtures / 'parameter_node.py' @@ -64,7 +70,6 @@ def generate_test_description(rmw_implementation): name=TEST_NODE, namespace=TEST_NAMESPACE, arguments=[str(path_to_parameter_node_script)], - additional_env=additional_env ) return LaunchDescription([ @@ -73,6 +78,19 @@ def generate_test_description(rmw_implementation): cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + *set_env_actions, + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + # Use the same isolated environment + additional_env=dict(additional_env), + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start', @@ -80,7 +98,6 @@ def generate_test_description(rmw_implementation): parameter_node, launch_testing.actions.ReadyToTest(), ], - additional_env=additional_env ) ] ), @@ -103,10 +120,8 @@ def setUpClass( @contextlib.contextmanager def launch_param_list_command(self, arguments): - additional_env = get_rmw_additional_env(rmw_implementation) param_list_command_action = ExecuteProcess( cmd=['ros2', 'param', 'list', *arguments], - additional_env=additional_env, name='ros2param-list-cli', output='screen' ) diff --git a/ros2param/test/test_verb_load.py b/ros2param/test/test_verb_load.py index 8bf5895c9..0791d3d1c 100644 --- a/ros2param/test/test_verb_load.py +++ b/ros2param/test/test_verb_load.py @@ -22,12 +22,17 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.actions import SetEnvironmentVariable +from launch.event_handlers import OnShutdown from launch_ros.actions import Node import launch_testing import launch_testing.actions import launch_testing.asserts import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools import pytest @@ -106,6 +111,7 @@ def generate_test_description(rmw_implementation): path_to_fixtures = os.path.join(os.path.dirname(__file__), 'fixtures') additional_env = get_rmw_additional_env(rmw_implementation) + set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()] # Parameter node test fixture path_to_parameter_node_script = os.path.join(path_to_fixtures, 'parameter_node.py') @@ -114,7 +120,6 @@ def generate_test_description(rmw_implementation): name=TEST_NODE, namespace=TEST_NAMESPACE, arguments=[path_to_parameter_node_script], - additional_env=additional_env, ) return LaunchDescription([ @@ -123,6 +128,19 @@ def generate_test_description(rmw_implementation): cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + *set_env_actions, + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + # Use the same isolated environment + additional_env=dict(additional_env), + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start', @@ -130,7 +148,6 @@ def generate_test_description(rmw_implementation): parameter_node, launch_testing.actions.ReadyToTest(), ], - additional_env=additional_env ) ] ), @@ -153,10 +170,8 @@ def setUpClass( @contextlib.contextmanager def launch_param_load_command(self, arguments): - additional_env = get_rmw_additional_env(rmw_implementation) param_load_command_action = ExecuteProcess( cmd=['ros2', 'param', 'load', *arguments], - additional_env=additional_env, name='ros2param-load-cli', output='screen' ) @@ -169,10 +184,8 @@ def launch_param_load_command(self, arguments): @contextlib.contextmanager def launch_param_dump_command(self, arguments): - additional_env = get_rmw_additional_env(rmw_implementation) param_dump_command_action = ExecuteProcess( cmd=['ros2', 'param', 'dump', *arguments], - additional_env=additional_env, name='ros2param-dump-cli', output='screen' ) diff --git a/ros2service/test/test_cli.py b/ros2service/test/test_cli.py index 1d8f97324..30f5aa8a2 100644 --- a/ros2service/test/test_cli.py +++ b/ros2service/test/test_cli.py @@ -21,6 +21,10 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.actions import SetEnvironmentVariable +from launch.event_handlers import OnShutdown from launch_ros.actions import Node import launch_testing @@ -28,6 +32,7 @@ import launch_testing.asserts import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools import pytest @@ -69,12 +74,26 @@ def generate_test_description(rmw_implementation): os.path.dirname(__file__), 'fixtures', 'echo_server.py' ) additional_env = get_rmw_additional_env(rmw_implementation) + set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()] return LaunchDescription([ # Always restart daemon to isolate tests. ExecuteProcess( cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + *set_env_actions, + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + # Use the same isolated environment + additional_env=dict(additional_env), + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start', @@ -85,7 +104,6 @@ def generate_test_description(rmw_implementation): arguments=[path_to_echo_server_script], name='echo_server', namespace='my_ns', - additional_env=additional_env, ), Node( executable=sys.executable, @@ -93,11 +111,9 @@ def generate_test_description(rmw_implementation): name='_hidden_echo_server', namespace='my_ns', remappings=[('echo', '_echo')], - additional_env=additional_env, ), launch_testing.actions.ReadyToTest() ], - additional_env=additional_env ) ] ), @@ -126,8 +142,9 @@ def setUpClass( ): @contextlib.contextmanager def launch_service_command(self, arguments): - additional_env = get_rmw_additional_env(rmw_implementation) - additional_env['PYTHONUNBUFFERED'] = '1' + additional_env = { + 'PYTHONUNBUFFERED': '1', + } service_command_action = ExecuteProcess( cmd=['ros2', 'service', *arguments], additional_env=additional_env, diff --git a/ros2service/test/test_echo.py b/ros2service/test/test_echo.py index b9537aa9b..8eb3e181c 100644 --- a/ros2service/test/test_echo.py +++ b/ros2service/test/test_echo.py @@ -21,6 +21,10 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.actions import SetEnvironmentVariable +from launch.event_handlers import OnShutdown from launch_ros.actions import Node import launch_testing @@ -28,6 +32,7 @@ import launch_testing.asserts import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools import pytest @@ -93,12 +98,26 @@ def generate_test_description(rmw_implementation): os.path.dirname(__file__), 'fixtures', 'introspectable.py' ) additional_env = get_rmw_additional_env(rmw_implementation) + set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()] return LaunchDescription([ # Always restart daemon to isolate tests. ExecuteProcess( cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + *set_env_actions, + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + # Use the same isolated environment + additional_env=dict(additional_env), + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start', @@ -108,11 +127,9 @@ def generate_test_description(rmw_implementation): executable=sys.executable, arguments=[path_to_introspectable_script], name='introspectable_service', - additional_env=additional_env, ), launch_testing.actions.ReadyToTest() ], - additional_env=additional_env ) ] ), @@ -131,8 +148,9 @@ def setUpClass( ): @contextlib.contextmanager def launch_service_command(self, arguments): - additional_env = get_rmw_additional_env(rmw_implementation) - additional_env['PYTHONUNBUFFERED'] = '1' + additional_env = { + 'PYTHONUNBUFFERED': '1', + } service_command_action = ExecuteProcess( cmd=['ros2', 'service', *arguments], additional_env=additional_env, diff --git a/ros2topic/test/test_bw_delay_hz.py b/ros2topic/test/test_bw_delay_hz.py index c4b72f03b..2afa3234a 100644 --- a/ros2topic/test/test_bw_delay_hz.py +++ b/ros2topic/test/test_bw_delay_hz.py @@ -20,12 +20,16 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.event_handlers import OnShutdown import launch_testing import launch_testing.actions import launch_testing.asserts import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools import pytest @@ -61,6 +65,16 @@ def generate_test_description(): cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start', diff --git a/ros2topic/test/test_cli.py b/ros2topic/test/test_cli.py index f04c70743..1db77cd84 100644 --- a/ros2topic/test/test_cli.py +++ b/ros2topic/test/test_cli.py @@ -22,6 +22,10 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.actions import SetEnvironmentVariable +from launch.event_handlers import OnShutdown from launch_ros.actions import Node @@ -30,6 +34,7 @@ import launch_testing.asserts import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools import pytest @@ -52,6 +57,7 @@ def generate_test_description(rmw_implementation): path_to_fixtures = os.path.join(os.path.dirname(__file__), 'fixtures') additional_env = get_rmw_additional_env(rmw_implementation) additional_env['PYTHONUNBUFFERED'] = '1' + set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()] path_to_talker_node_script = os.path.join(path_to_fixtures, 'talker_node.py') path_to_listener_node_script = os.path.join(path_to_fixtures, 'listener_node.py') @@ -59,18 +65,15 @@ def generate_test_description(rmw_implementation): executable=sys.executable, arguments=[path_to_talker_node_script], remappings=[('chatter', '_hidden_chatter')], - additional_env=additional_env ) talker_node_action = Node( executable=sys.executable, arguments=[path_to_talker_node_script], - additional_env=additional_env ) listener_node_action = Node( executable=sys.executable, arguments=[path_to_listener_node_script], remappings=[('chatter', 'chit_chatter')], - additional_env=additional_env ) path_to_repeater_node_script = os.path.join(path_to_fixtures, 'repeater_node.py') @@ -81,14 +84,12 @@ def generate_test_description(rmw_implementation): name='array_repeater', remappings=[('/array_repeater/output', '/arrays')], output='screen', - additional_env=additional_env ) defaults_repeater_node_action = Node( executable=sys.executable, arguments=[path_to_repeater_node_script, 'test_msgs/msg/Defaults'], name='defaults_repeater', remappings=[('/defaults_repeater/output', '/defaults')], - additional_env=additional_env, ) bounded_sequences_repeater_node_action = Node( executable=sys.executable, @@ -97,7 +98,6 @@ def generate_test_description(rmw_implementation): ], name='bounded_sequences_repeater', remappings=[('/bounded_sequences_repeater/output', '/bounded_sequences')], - additional_env=additional_env ) unbounded_sequences_repeater_node_action = Node( executable=sys.executable, @@ -106,7 +106,6 @@ def generate_test_description(rmw_implementation): ], name='unbounded_sequences_repeater', remappings=[('/unbounded_sequences_repeater/output', '/unbounded_sequences')], - additional_env=additional_env ) path_to_controller_node_script = os.path.join(path_to_fixtures, 'controller_node.py') @@ -114,7 +113,6 @@ def generate_test_description(rmw_implementation): cmd_vel_controller_node_action = Node( executable=sys.executable, arguments=[path_to_controller_node_script], - additional_env=additional_env ) return LaunchDescription([ @@ -123,6 +121,19 @@ def generate_test_description(rmw_implementation): cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + *set_env_actions, + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + # Use the same isolated environment + additional_env=dict(additional_env), + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start', @@ -141,7 +152,6 @@ def generate_test_description(rmw_implementation): cmd_vel_controller_node_action, launch_testing.actions.ReadyToTest() ], - additional_env=additional_env ) ] ), @@ -166,11 +176,8 @@ def setUpClass( @contextlib.contextmanager def launch_topic_command(self, arguments): - additional_env = get_rmw_additional_env(rmw_implementation) - additional_env['PYTHONUNBUFFERED'] = '1' topic_command_action = ExecuteProcess( cmd=['ros2', 'topic', *arguments], - additional_env=additional_env, name='ros2topic-cli', output='screen' ) @@ -842,13 +849,12 @@ def test_topic_pub_once(self): assert topic_command.exit_code == launch_testing.asserts.EXIT_OK def test_topic_pub_once_matching_two_listeners( - self, launch_service, proc_info, proc_output, path_to_listener_node_script, additional_env + self, launch_service, proc_info, proc_output, path_to_listener_node_script ): second_listener_node_action = Node( executable=sys.executable, arguments=[path_to_listener_node_script], remappings=[('chatter', 'chit_chatter')], - additional_env=additional_env, name='second_listener', ) with launch_testing.tools.launch_process( diff --git a/ros2topic/test/test_echo_pub.py b/ros2topic/test/test_echo_pub.py index eea198a0f..12404c56b 100644 --- a/ros2topic/test/test_echo_pub.py +++ b/ros2topic/test/test_echo_pub.py @@ -20,12 +20,16 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.event_handlers import OnShutdown import launch_testing import launch_testing.actions import launch_testing.asserts import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools import pytest @@ -65,6 +69,16 @@ def generate_test_description(): cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start', diff --git a/ros2topic/test/test_use_sim_time.py b/ros2topic/test/test_use_sim_time.py index 64f3bcc3a..287fe5313 100644 --- a/ros2topic/test/test_use_sim_time.py +++ b/ros2topic/test/test_use_sim_time.py @@ -20,12 +20,16 @@ from launch import LaunchDescription from launch.actions import ExecuteProcess +from launch.actions import RegisterEventHandler +from launch.actions import ResetEnvironment +from launch.event_handlers import OnShutdown import launch_testing import launch_testing.actions import launch_testing.asserts import launch_testing.markers import launch_testing.tools +from launch_testing_ros.actions import EnableRmwIsolation import launch_testing_ros.tools import pytest @@ -59,6 +63,16 @@ def generate_test_description(): cmd=['ros2', 'daemon', 'stop'], name='daemon-stop', on_exit=[ + EnableRmwIsolation(), + RegisterEventHandler(OnShutdown(on_shutdown=[ + # Stop daemon in isolated environment with proper ROS_DOMAIN_ID + ExecuteProcess( + cmd=['ros2', 'daemon', 'stop'], + name='daemon-stop-isolated', + ), + # This must be done after stopping the daemon in the isolated environment + ResetEnvironment(), + ])), ExecuteProcess( cmd=['ros2', 'daemon', 'start'], name='daemon-start',