Skip to content

Commit 3227c00

Browse files
mergify[bot]cottsayfujitatomoyaBlast545
authored
Use rmw_test_fixture to isolate ros2cli tests (backport #1062) (#1106)
* Use rmw_test_fixture to isolate ros2cli tests (#1062) Signed-off-by: Scott K Logan <[email protected]> (cherry picked from commit 75e004a) * Fujitatomoya/clearup isolated ros2daemon (#1098) * Enable RMW isolation for ros2doctor.test_report. Signed-off-by: Tomoya Fujita <[email protected]> * ResetEnvironment on shutdown is missing. Signed-off-by: Tomoya Fujita <[email protected]> * Clean up isolated ros2 daemon process when tests complete. Signed-off-by: Tomoya Fujita <[email protected]> * Clean up isolated ros2 daemon process for ros2topic. Signed-off-by: Tomoya Fujita <[email protected]> * Clean up isolated ros2 daemon process for ros2action. Signed-off-by: Tomoya Fujita <[email protected]> * Clean up isolated ros2 daemon process for ros2doctor. Signed-off-by: Tomoya Fujita <[email protected]> * Clean up isolated ros2 daemon process for ros2lifecycle and ros2node. Signed-off-by: Tomoya Fujita <[email protected]> * Clean up isolated ros2 daemon process for ros2param. Signed-off-by: Tomoya Fujita <[email protected]> --------- Signed-off-by: Tomoya Fujita <[email protected]> * Missing backport Signed-off-by: Jorge J. Perez <[email protected]> * Fix extra backport Signed-off-by: Jorge J. Perez <[email protected]> * Add missing import Signed-off-by: Jorge J. Perez <[email protected]> --------- Signed-off-by: Scott K Logan <[email protected]> Signed-off-by: Tomoya Fujita <[email protected]> Signed-off-by: Jorge J. Perez <[email protected]> Co-authored-by: Scott K Logan <[email protected]> Co-authored-by: Tomoya Fujita <[email protected]> Co-authored-by: Jorge J. Perez <[email protected]>
1 parent 2e51f95 commit 3227c00

File tree

16 files changed

+292
-70
lines changed

16 files changed

+292
-70
lines changed

ros2action/test/test_cli.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,17 @@
2020

2121
from launch import LaunchDescription
2222
from launch.actions import ExecuteProcess
23+
from launch.actions import RegisterEventHandler
24+
from launch.actions import ResetEnvironment
25+
from launch.actions import SetEnvironmentVariable
26+
from launch.event_handlers import OnShutdown
2327

2428
import launch_testing
2529
import launch_testing.actions
2630
import launch_testing.asserts
2731
import launch_testing.markers
2832
import launch_testing.tools
33+
from launch_testing_ros.actions import EnableRmwIsolation
2934
import launch_testing_ros.tools
3035

3136
import pytest
@@ -51,23 +56,35 @@ def generate_test_description(rmw_implementation):
5156
os.path.dirname(__file__), 'fixtures', 'fibonacci_action_server.py'
5257
)
5358
additional_env = get_rmw_additional_env(rmw_implementation)
59+
set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()]
5460
return LaunchDescription([
5561
# Always restart daemon to isolate tests.
5662
ExecuteProcess(
5763
cmd=['ros2', 'daemon', 'stop'],
5864
name='daemon-stop',
5965
on_exit=[
66+
*set_env_actions,
67+
EnableRmwIsolation(),
68+
RegisterEventHandler(OnShutdown(on_shutdown=[
69+
# Stop daemon in isolated environment with proper ROS_DOMAIN_ID
70+
ExecuteProcess(
71+
cmd=['ros2', 'daemon', 'stop'],
72+
name='daemon-stop-isolated',
73+
# Use the same isolated environment
74+
additional_env=dict(additional_env),
75+
),
76+
# This must be done after stopping the daemon in the isolated environment
77+
ResetEnvironment(),
78+
])),
6079
ExecuteProcess(
6180
cmd=['ros2', 'daemon', 'start'],
6281
name='daemon-start',
6382
on_exit=[
6483
ExecuteProcess(
6584
cmd=[sys.executable, path_to_action_server_executable],
66-
additional_env=additional_env,
6785
),
6886
launch_testing.actions.ReadyToTest()
6987
],
70-
additional_env=additional_env,
7188
)
7289
]
7390
),
@@ -115,8 +132,9 @@ def setUpClass(
115132
):
116133
@contextlib.contextmanager
117134
def launch_action_command(self, arguments):
118-
additional_env = get_rmw_additional_env(rmw_implementation)
119-
additional_env['PYTHONUNBUFFERED'] = '1'
135+
additional_env = {
136+
'PYTHONUNBUFFERED': '1',
137+
}
120138

121139
action_command_action = ExecuteProcess(
122140
cmd=['ros2', 'action', *arguments],

ros2action/test/test_echo.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,18 @@
2121

2222
from launch import LaunchDescription
2323
from launch.actions import ExecuteProcess
24+
from launch.actions import RegisterEventHandler
25+
from launch.actions import ResetEnvironment
26+
from launch.actions import SetEnvironmentVariable
27+
from launch.event_handlers import OnShutdown
2428

2529
import launch_testing
2630
import launch_testing.actions
2731
import launch_testing.asserts
2832
import launch_testing.markers
2933
import launch_testing.tools
3034

35+
from launch_testing_ros.actions import EnableRmwIsolation
3136
import launch_testing_ros.tools
3237

3338
from osrf_pycommon.terminal_color import remove_ansi_escape_sequences
@@ -221,23 +226,35 @@ def generate_test_description(rmw_implementation):
221226
os.path.dirname(__file__), 'fixtures', 'fibonacci_action_introspection.py'
222227
)
223228
additional_env = get_rmw_additional_env(rmw_implementation)
229+
set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()]
224230
return LaunchDescription([
225231
# Always restart daemon to isolate tests.
226232
ExecuteProcess(
227233
cmd=['ros2', 'daemon', 'stop'],
228234
name='daemon-stop',
229235
on_exit=[
236+
*set_env_actions,
237+
EnableRmwIsolation(),
238+
RegisterEventHandler(OnShutdown(on_shutdown=[
239+
# Stop daemon in isolated environment with proper ROS_DOMAIN_ID
240+
ExecuteProcess(
241+
cmd=['ros2', 'daemon', 'stop'],
242+
name='daemon-stop-isolated',
243+
# Use the same isolated environment
244+
additional_env=dict(additional_env),
245+
),
246+
# This must be done after stopping the daemon in the isolated environment
247+
ResetEnvironment(),
248+
])),
230249
ExecuteProcess(
231250
cmd=['ros2', 'daemon', 'start'],
232251
name='daemon-start',
233252
on_exit=[
234253
ExecuteProcess(
235254
cmd=[sys.executable, path_to_action_server_executable],
236-
additional_env=additional_env
237255
),
238256
launch_testing.actions.ReadyToTest()
239257
],
240-
additional_env=additional_env
241258
)
242259
]
243260
),
@@ -256,8 +273,9 @@ def setUpClass(
256273
):
257274
@contextlib.contextmanager
258275
def launch_action_command(self, arguments):
259-
additional_env = get_rmw_additional_env(rmw_implementation)
260-
additional_env['PYTHONUNBUFFERED'] = '1'
276+
additional_env = {
277+
'PYTHONUNBUFFERED': '1',
278+
}
261279
action_command_action = ExecuteProcess(
262280
cmd=['ros2', 'action', *arguments],
263281
name='ros2action-cli', output='screen',

ros2cli/ros2cli/helpers.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,6 @@ def get_rmw_additional_env(rmw_implementation: str) -> Dict[str, str]:
127127
if rmw_implementation == 'rmw_zenoh_cpp':
128128
return {
129129
'RMW_IMPLEMENTATION': rmw_implementation,
130-
'ZENOH_ROUTER_CHECK_ATTEMPTS': '-1',
131-
'ZENOH_CONFIG_OVERRIDE': 'scouting/multicast/enabled=true',
132130
'RUST_LOG': 'z=error'
133131
}
134132
else:

ros2doctor/test/test_qos_compatibility.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919

2020
from launch import LaunchDescription
2121
from launch.actions import ExecuteProcess
22+
from launch.actions import RegisterEventHandler
23+
from launch.actions import ResetEnvironment
24+
from launch.actions import SetEnvironmentVariable
25+
from launch.event_handlers import OnShutdown
2226

2327
from launch_ros.actions import Node
2428

@@ -27,6 +31,7 @@
2731
import launch_testing.asserts
2832
import launch_testing.markers
2933
import launch_testing.tools
34+
from launch_testing_ros.actions import EnableRmwIsolation
3035
import launch_testing_ros.tools
3136

3237
import pytest
@@ -49,6 +54,7 @@ def generate_test_description(rmw_implementation):
4954
path_to_fixtures = os.path.join(os.path.dirname(__file__), 'fixtures')
5055
additional_env = get_rmw_additional_env(rmw_implementation)
5156
additional_env['PYTHONUNBUFFERED'] = '1'
57+
set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()]
5258

5359
path_to_incompatible_talker_node_script = os.path.join(
5460
path_to_fixtures, 'talker_node_with_best_effort_qos.py')
@@ -62,25 +68,21 @@ def generate_test_description(rmw_implementation):
6268
executable=sys.executable,
6369
arguments=[path_to_compatible_talker_node_script],
6470
remappings=[('chatter', 'compatible_chatter')],
65-
additional_env=additional_env
6671
)
6772
listener_node_compatible = Node(
6873
executable=sys.executable,
6974
arguments=[path_to_listener_node_script],
7075
remappings=[('chatter', 'compatible_chatter')],
71-
additional_env=additional_env
7276
)
7377
talker_node_incompatible = Node(
7478
executable=sys.executable,
7579
arguments=[path_to_incompatible_talker_node_script],
7680
remappings=[('chatter', 'incompatible_chatter')],
77-
additional_env=additional_env
7881
)
7982
listener_node_incompatible = Node(
8083
executable=sys.executable,
8184
arguments=[path_to_listener_node_script],
8285
remappings=[('chatter', 'incompatible_chatter')],
83-
additional_env=additional_env
8486
)
8587

8688
return LaunchDescription([
@@ -89,6 +91,19 @@ def generate_test_description(rmw_implementation):
8991
cmd=['ros2', 'daemon', 'stop'],
9092
name='daemon-stop',
9193
on_exit=[
94+
*set_env_actions,
95+
EnableRmwIsolation(),
96+
RegisterEventHandler(OnShutdown(on_shutdown=[
97+
# Stop daemon in isolated environment with proper ROS_DOMAIN_ID
98+
ExecuteProcess(
99+
cmd=['ros2', 'daemon', 'stop'],
100+
name='daemon-stop-isolated',
101+
# Use the same isolated environment
102+
additional_env=dict(additional_env),
103+
),
104+
# This must be done after stopping the daemon in the isolated environment
105+
ResetEnvironment(),
106+
])),
92107
ExecuteProcess(
93108
cmd=['ros2', 'daemon', 'start'],
94109
name='daemon-start',
@@ -100,7 +115,6 @@ def generate_test_description(rmw_implementation):
100115
listener_node_compatible,
101116
launch_testing.actions.ReadyToTest()
102117
],
103-
additional_env=additional_env
104118
)
105119
]
106120
),
@@ -128,11 +142,8 @@ def setUpClass(
128142

129143
@contextlib.contextmanager
130144
def launch_doctor_command(self, arguments):
131-
additional_env = get_rmw_additional_env(rmw_implementation)
132-
additional_env['PYTHONUNBUFFERED'] = '1'
133145
doctor_command_action = ExecuteProcess(
134146
cmd=['ros2', 'doctor', *arguments],
135-
additional_env=additional_env,
136147
name='ros2doctor-cli',
137148
output='screen'
138149
)

ros2lifecycle/test/test_cli.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,18 @@
1818

1919
from launch import LaunchDescription
2020
from launch.actions import ExecuteProcess
21+
from launch.actions import RegisterEventHandler
22+
from launch.actions import ResetEnvironment
23+
from launch.actions import SetEnvironmentVariable
24+
from launch.event_handlers import OnShutdown
2125
from launch_ros.actions import Node
2226

2327
import launch_testing
2428
import launch_testing.actions
2529
import launch_testing.asserts
2630
import launch_testing.markers
2731
import launch_testing.tools
32+
from launch_testing_ros.actions import EnableRmwIsolation
2833
import launch_testing_ros.tools
2934

3035
import pytest
@@ -124,12 +129,26 @@
124129
@launch_testing.parametrize('rmw_implementation', get_available_rmw_implementations())
125130
def generate_test_description(rmw_implementation):
126131
additional_env = get_rmw_additional_env(rmw_implementation)
132+
set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()]
127133
return LaunchDescription([
128134
# Always restart daemon to isolate tests.
129135
ExecuteProcess(
130136
cmd=['ros2', 'daemon', 'stop'],
131137
name='daemon-stop',
132138
on_exit=[
139+
*set_env_actions,
140+
EnableRmwIsolation(),
141+
RegisterEventHandler(OnShutdown(on_shutdown=[
142+
# Stop daemon in isolated environment with proper ROS_DOMAIN_ID
143+
ExecuteProcess(
144+
cmd=['ros2', 'daemon', 'stop'],
145+
name='daemon-stop-isolated',
146+
# Use the same isolated environment
147+
additional_env=dict(additional_env),
148+
),
149+
# This must be done after stopping the daemon in the isolated environment
150+
ResetEnvironment(),
151+
])),
133152
ExecuteProcess(
134153
cmd=['ros2', 'daemon', 'start'],
135154
name='daemon-start',
@@ -140,18 +159,15 @@ def generate_test_description(rmw_implementation):
140159
executable='simple_lifecycle_node',
141160
name='test_lifecycle_node',
142161
output='screen',
143-
additional_env=additional_env
144162
),
145163
Node(
146164
package='ros2lifecycle_test_fixtures',
147165
executable='simple_lifecycle_node',
148166
name='_hidden_test_lifecycle_node',
149167
output='screen',
150-
additional_env=additional_env
151168
),
152169
launch_testing.actions.ReadyToTest()
153170
],
154-
additional_env=additional_env
155171
)
156172
]
157173
),
@@ -170,8 +186,9 @@ def setUpClass(
170186
):
171187
@contextlib.contextmanager
172188
def launch_lifecycle_command(self, arguments):
173-
additional_env = get_rmw_additional_env(rmw_implementation)
174-
additional_env['PYTHONUNBUFFERED'] = '1'
189+
additional_env = {
190+
'PYTHONUNBUFFERED': '1',
191+
}
175192
lifecycle_command_action = ExecuteProcess(
176193
cmd=['ros2', 'lifecycle', *arguments],
177194
additional_env=additional_env,

ros2node/test/test_cli.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121

2222
from launch import LaunchDescription
2323
from launch.actions import ExecuteProcess
24+
from launch.actions import RegisterEventHandler
25+
from launch.actions import ResetEnvironment
26+
from launch.actions import SetEnvironmentVariable
27+
from launch.event_handlers import OnShutdown
2428

2529
from launch_ros.actions import Node
2630

@@ -29,6 +33,7 @@
2933
import launch_testing.asserts
3034
import launch_testing.markers
3135
import launch_testing.tools
36+
from launch_testing_ros.actions import EnableRmwIsolation
3237
import launch_testing_ros.tools
3338

3439
import pytest
@@ -52,12 +57,26 @@ def generate_test_description(rmw_implementation):
5257
os.path.dirname(__file__), 'fixtures', 'complex_node.py'
5358
)
5459
additional_env = get_rmw_additional_env(rmw_implementation)
60+
set_env_actions = [SetEnvironmentVariable(k, v) for k, v in additional_env.items()]
5561
return LaunchDescription([
5662
# Always restart daemon to isolate tests.
5763
ExecuteProcess(
5864
cmd=['ros2', 'daemon', 'stop'],
5965
name='daemon-stop',
6066
on_exit=[
67+
*set_env_actions,
68+
EnableRmwIsolation(),
69+
RegisterEventHandler(OnShutdown(on_shutdown=[
70+
# Stop daemon in isolated environment with proper ROS_DOMAIN_ID
71+
ExecuteProcess(
72+
cmd=['ros2', 'daemon', 'stop'],
73+
name='daemon-stop-isolated',
74+
# Use the same isolated environment
75+
additional_env=dict(additional_env),
76+
),
77+
# This must be done after stopping the daemon in the isolated environment
78+
ResetEnvironment(),
79+
])),
6180
ExecuteProcess(
6281
cmd=['ros2', 'daemon', 'start'],
6382
name='daemon-start',
@@ -67,17 +86,14 @@ def generate_test_description(rmw_implementation):
6786
executable=sys.executable,
6887
arguments=[path_to_complex_node_script],
6988
name='complex_node',
70-
additional_env=additional_env
7189
),
7290
Node(
7391
executable=sys.executable,
7492
arguments=[path_to_complex_node_script],
7593
name='_hidden_complex_node',
76-
additional_env=additional_env
7794
),
7895
launch_testing.actions.ReadyToTest()
7996
],
80-
additional_env=additional_env
8197
)
8298
]
8399
),
@@ -96,8 +112,9 @@ def setUpClass(
96112
):
97113
@contextlib.contextmanager
98114
def launch_node_command(self, arguments):
99-
additional_env = get_rmw_additional_env(rmw_implementation)
100-
additional_env['PYTHONUNBUFFERED'] = '1'
115+
additional_env = {
116+
'PYTHONUNBUFFERED': '1',
117+
}
101118

102119
node_command_action = ExecuteProcess(
103120
cmd=['ros2', 'node', *arguments],

0 commit comments

Comments
 (0)