|
12 | 12 | # See the License for the specific language governing permissions and |
13 | 13 | # limitations under the License. |
14 | 14 |
|
| 15 | +import asyncio |
15 | 16 | from collections.abc import Mapping |
16 | 17 | import os |
17 | 18 | import shutil |
|
28 | 29 | from launch import LaunchService |
29 | 30 | from launch_ros.actions import Node |
30 | 31 | from lttngpy import impl as lttngpy |
| 32 | +import osrf_pycommon.process_utils |
| 33 | +from tracetools_launch.action import Trace |
31 | 34 | from tracetools_read import get_event_name |
32 | 35 | from tracetools_test.mark_process import get_corresponding_trace_test_events |
33 | 36 | from tracetools_test.mark_process import get_trace_test_id |
|
36 | 39 | from tracetools_trace.tools import tracepoints |
37 | 40 | from tracetools_trace.tools.lttng import is_lttng_installed |
38 | 41 | from tracetools_trace.tools.names import DEFAULT_EVENTS_ROS |
| 42 | +from tracetools_trace.tools.names import DEFAULT_INIT_EVENTS_ROS |
39 | 43 |
|
40 | 44 |
|
41 | 45 | def are_tracepoints_included() -> bool: |
@@ -295,6 +299,52 @@ def run_nodes(self, env: Optional[Mapping[str, str]] = None) -> None: |
295 | 299 | exit_code = ls.run() |
296 | 300 | self.assertEqual(0, exit_code) |
297 | 301 |
|
| 302 | + def pre_configure_dual_session_and_run_nodes( |
| 303 | + self, |
| 304 | + base_path: str, |
| 305 | + session_name: str, |
| 306 | + env: Optional[Mapping[str, str]] = None, |
| 307 | + ) -> Tuple[LaunchService, asyncio.Task]: |
| 308 | + # Set trace test ID env var for spawned processes |
| 309 | + additional_env: Dict[str, str] = {} |
| 310 | + if env is not None: |
| 311 | + additional_env.update(env) |
| 312 | + assert self.trace_test_id |
| 313 | + additional_env[TRACE_TEST_ID_ENV_VAR] = self.trace_test_id |
| 314 | + actions = [ |
| 315 | + Trace( |
| 316 | + session_name=session_name, |
| 317 | + dual_session=True, |
| 318 | + base_path=base_path, |
| 319 | + events_ust=DEFAULT_INIT_EVENTS_ROS + [TRACE_TEST_ID_TP_NAME], |
| 320 | + ), |
| 321 | + Node( |
| 322 | + package='test_tracetools', |
| 323 | + executable='test_ping', |
| 324 | + output='screen', |
| 325 | + arguments=['do_more'], # run indefinitely |
| 326 | + additional_env=additional_env, |
| 327 | + ), |
| 328 | + Node( |
| 329 | + package='test_tracetools', |
| 330 | + executable='test_pong', |
| 331 | + output='screen', |
| 332 | + arguments=['do_more'], # run indefinitely |
| 333 | + additional_env=additional_env, |
| 334 | + ), |
| 335 | + ] |
| 336 | + ld = LaunchDescription(actions) |
| 337 | + ls = LaunchService() |
| 338 | + ls.include_launch_description(ld) |
| 339 | + |
| 340 | + loop = osrf_pycommon.process_utils.get_loop() |
| 341 | + launch_task = loop.create_task(ls.run_async()) |
| 342 | + |
| 343 | + # Give the launch service time to start actions |
| 344 | + loop.run_until_complete(asyncio.sleep(1.0)) |
| 345 | + |
| 346 | + return ls, launch_task |
| 347 | + |
298 | 348 | def test_default(self) -> None: |
299 | 349 | tmpdir = self.create_test_tmpdir('test_default') |
300 | 350 |
|
@@ -671,7 +721,7 @@ def test_snapshot_start_pause_resume_stop(self) -> None: |
671 | 721 | ret = self.run_trace_subcommand( |
672 | 722 | [ |
673 | 723 | 'start', session_name, |
674 | | - '--ust', tracepoints.rcl_subscription_init, TRACE_TEST_ID_TP_NAME, |
| 724 | + '--ust', 'ros2:*', TRACE_TEST_ID_TP_NAME, |
675 | 725 | '--path', tmpdir, |
676 | 726 | '--snapshot-mode', |
677 | 727 | ] |
@@ -736,6 +786,97 @@ def test_snapshot_start_pause_resume_stop(self) -> None: |
736 | 786 |
|
737 | 787 | shutil.rmtree(tmpdir) |
738 | 788 |
|
| 789 | + @unittest.skipIf(not are_tracepoints_included(), 'tracepoints are required') |
| 790 | + def test_dual_session_start_pause_resume_stop(self) -> None: |
| 791 | + tmpdir = self.create_test_tmpdir('test_dual_session_start_pause_resume_stop') |
| 792 | + session_name = 'test_dual_session_start_pause_resume_stop' |
| 793 | + |
| 794 | + # Pre-configure dual session, start nodes and check that the snapshot session exists |
| 795 | + ls, launch_task = self.pre_configure_dual_session_and_run_nodes(tmpdir, session_name) |
| 796 | + self.assertTracingSessionExist(session_name+'-snapshot', snapshot_mode=True) |
| 797 | + |
| 798 | + # Start tracing |
| 799 | + ret = self.run_trace_subcommand( |
| 800 | + [ |
| 801 | + 'start', session_name, |
| 802 | + '--ust', 'ros2:*', |
| 803 | + '--path', tmpdir, |
| 804 | + '--dual-session', |
| 805 | + ] |
| 806 | + ) |
| 807 | + self.assertEqual(0, ret) |
| 808 | + trace_dir = os.path.join(tmpdir, session_name) |
| 809 | + snapshot_trace_dir = os.path.join(tmpdir, session_name, 'snapshot') |
| 810 | + runtime_trace_dir = os.path.join(tmpdir, session_name, 'runtime') |
| 811 | + self.assertTraceExist(snapshot_trace_dir) |
| 812 | + self.assertTraceExist(runtime_trace_dir) |
| 813 | + self.assertTracingSessionExist(session_name+'-snapshot', snapshot_mode=True) |
| 814 | + self.assertTracingSessionExist(session_name+'-runtime') |
| 815 | + |
| 816 | + # Pause tracing and check trace |
| 817 | + ret = self.run_trace_subcommand(['pause', session_name, '--dual-session']) |
| 818 | + self.assertEqual(0, ret) |
| 819 | + self.assertTracingSessionExist(session_name+'-snapshot', snapshot_mode=True) |
| 820 | + self.assertTracingSessionExist(session_name+'-runtime') |
| 821 | + expected_trace_data = [ |
| 822 | + ('topic_name', '/ping'), |
| 823 | + ('topic_name', '/pong'), |
| 824 | + ] |
| 825 | + num_events = self.assertTraceContains(trace_dir, expected_field_value=expected_trace_data) |
| 826 | + |
| 827 | + # Pausing again should give an error but not affect anything |
| 828 | + ret = self.run_trace_subcommand(['pause', session_name, '--dual-session']) |
| 829 | + self.assertEqual(1, ret) |
| 830 | + self.assertTracingSessionExist(session_name+'-snapshot', snapshot_mode=True) |
| 831 | + self.assertTracingSessionExist(session_name+'-runtime') |
| 832 | + new_num_events = self.assertTraceContains( |
| 833 | + trace_dir=tmpdir, |
| 834 | + expected_field_value=expected_trace_data, |
| 835 | + ) |
| 836 | + self.assertEqual(num_events, new_num_events, 'unexpected new events in trace') |
| 837 | + |
| 838 | + # Resume tracing |
| 839 | + ret = self.run_trace_subcommand(['resume', session_name, '--dual-session']) |
| 840 | + self.assertEqual(0, ret) |
| 841 | + self.assertTracingSessionExist(session_name+'-snapshot', snapshot_mode=True) |
| 842 | + self.assertTracingSessionExist(session_name+'-runtime') |
| 843 | + |
| 844 | + # Resuming tracing again should give an error but not affect anything |
| 845 | + ret = self.run_trace_subcommand(['resume', session_name, '--dual-session']) |
| 846 | + self.assertEqual(1, ret) |
| 847 | + self.assertTracingSessionExist(session_name+'-snapshot', snapshot_mode=True) |
| 848 | + self.assertTracingSessionExist(session_name+'-runtime') |
| 849 | + |
| 850 | + # Stop tracing and check that trace changed |
| 851 | + ret = self.run_trace_subcommand(['stop', session_name, '--dual-session']) |
| 852 | + self.assertEqual(0, ret) |
| 853 | + # Snapshot session should still exist |
| 854 | + self.assertTracingSessionExist(session_name+'-snapshot', snapshot_mode=True) |
| 855 | + self.assertTracingSessionNotExist(session_name+'-runtime') |
| 856 | + new_num_events = self.assertTraceContains( |
| 857 | + trace_dir, |
| 858 | + expected_field_value=expected_trace_data, |
| 859 | + ) |
| 860 | + self.assertGreater(new_num_events, num_events, 'no new events in trace') |
| 861 | + |
| 862 | + # Stopping tracing again should give an error but not affect anything |
| 863 | + ret = self.run_trace_subcommand(['stop', session_name, '--dual-session']) |
| 864 | + self.assertEqual(1, ret) |
| 865 | + self.assertTracingSessionExist(session_name+'-snapshot', snapshot_mode=True) |
| 866 | + self.assertTracingSessionNotExist(session_name+'-runtime') |
| 867 | + |
| 868 | + # Shutdown launch service |
| 869 | + loop = osrf_pycommon.process_utils.get_loop() |
| 870 | + if not launch_task.done(): |
| 871 | + loop.create_task(ls.shutdown()) |
| 872 | + loop.run_until_complete(launch_task) |
| 873 | + assert 0 == launch_task.result() |
| 874 | + |
| 875 | + # Shutting down the launch service should destroy the snapshot session |
| 876 | + self.assertTracingSessionNotExist(session_name+'-snapshot', snapshot_mode=True) |
| 877 | + |
| 878 | + shutil.rmtree(tmpdir) |
| 879 | + |
739 | 880 | @unittest.skipIf(not are_tracepoints_included(), 'tracepoints are required') |
740 | 881 | def test_runtime_disable(self) -> None: |
741 | 882 | tmpdir = self.create_test_tmpdir('test_runtime_disable') |
|
0 commit comments