def test_pub_times(self, launch_service, proc_info, proc_output): command_action = ExecuteProcess( cmd=([ 'ros2', 'topic', 'pub', '-t', '5', '/clitest/topic/pub_times', 'std_msgs/String', 'data: hello' ]), additional_env={'PYTHONUNBUFFERED': '1'}, output='screen') with launch_testing.tools.launch_process( launch_service, command_action, proc_info, proc_output, output_filter=launch_testing_ros.tools.basic_output_filter( filtered_rmw_implementation= get_rmw_implementation_identifier())) as command: assert command.wait_for_shutdown(timeout=10) assert command.exit_code == launch_testing.asserts.EXIT_OK assert launch_testing.tools.expect_output(expected_lines=[ 'publisher: beginning loop', "publishing #1: std_msgs.msg.String(data='hello')", '', "publishing #2: std_msgs.msg.String(data='hello')", '', "publishing #3: std_msgs.msg.String(data='hello')", '', "publishing #4: std_msgs.msg.String(data='hello')", '', "publishing #5: std_msgs.msg.String(data='hello')", '', ], text=command.output, strict=True)
def setUp(self): self.context = rclpy.context.Context() rclpy.init(context=self.context) self.node = rclpy.create_node('TestQoSEvent', namespace='/rclpy/test', context=self.context) self.is_fastrtps = 'rmw_fastrtps' in get_rmw_implementation_identifier()
def create_permission_file(path: pathlib.Path, domain_id, policy_element) -> None: permissions_xsl_path = get_transport_template('dds', 'permissions.xsl') permissions_xsl = etree.XSLT(etree.parse(str(permissions_xsl_path))) permissions_xsd_path = get_transport_schema('dds', 'permissions.xsd') permissions_xsd = etree.XMLSchema(etree.parse(str(permissions_xsd_path))) kwargs = {} cert_path = path.parent.joinpath('cert.pem') cert_content = _utilities.load_cert(cert_path) kwargs['not_valid_before'] = etree.XSLT.strparam( cert_content.not_valid_before.isoformat()) kwargs['not_valid_after'] = etree.XSLT.strparam( cert_content.not_valid_after.isoformat()) if get_rmw_implementation_identifier() in _RMW_WITH_ROS_GRAPH_INFO_TOPIC: kwargs['allow_ros_discovery_topic'] = etree.XSLT.strparam('1') permissions_xml = permissions_xsl(policy_element, **kwargs) domain_id_elements = permissions_xml.findall( 'permissions/grant/*/domains/id') for domain_id_element in domain_id_elements: domain_id_element.text = domain_id try: permissions_xsd.assertValid(permissions_xml) except etree.DocumentInvalid as e: raise sros2.errors.InvalidPermissionsXMLError(e) from e with open(path, 'wb') as f: f.write(etree.tostring(permissions_xml, pretty_print=True))
def test_echo_filter(self, launch_service, proc_info, proc_output): params = [ ('/clitest/topic/echo_filter_all_pass', "m.data=='hello'", True), ('/clitest/topic/echo_filter_all_filtered', "m.data=='success'", False), ] for topic, filter_expr, has_output in params: with self.subTest(topic=topic, filter_expr=filter_expr, print_count=10): # Check for inconsistent arguments publisher = self.node.create_publisher(String, topic, 10) assert publisher def publish_message(): publisher.publish(String(data='hello')) publish_timer = self.node.create_timer(0.5, publish_message) try: command_action = ExecuteProcess( cmd=(['ros2', 'topic', 'echo'] + ['--filter', filter_expr] + [topic, 'std_msgs/String']), additional_env={'PYTHONUNBUFFERED': '1'}, output='screen') with launch_testing.tools.launch_process( launch_service, command_action, proc_info, proc_output, output_filter=launch_testing_ros.tools. basic_output_filter( filtered_rmw_implementation= get_rmw_implementation_identifier( ))) as command: # The future won't complete - we will hit the timeout self.executor.spin_until_future_complete( rclpy.task.Future(), timeout_sec=5) command.wait_for_shutdown(timeout=10) # Check results if has_output: assert 'hello' in command.output, 'Echo CLI did not output' else: assert 'hello' not in command.output, 'All messages should be filtered out' finally: # Cleanup self.node.destroy_timer(publish_timer) self.node.destroy_publisher(publisher)
def test_echo_raw(self, launch_service, proc_info, proc_output): topic = '/clitest/topic/echo_raw' publisher = self.node.create_publisher(String, topic, 10) assert publisher def publish_message(): publisher.publish(String(data='hello')) publish_timer = self.node.create_timer(0.5, publish_message) try: command_action = ExecuteProcess( cmd=[ 'ros2', 'topic', 'echo', '--raw', topic, 'std_msgs/msg/String' ], additional_env={'PYTHONUNBUFFERED': '1'}, output='screen') with launch_testing.tools.launch_process( launch_service, command_action, proc_info, proc_output, output_filter=launch_testing_ros.tools.basic_output_filter( filtered_rmw_implementation= get_rmw_implementation_identifier())) as command: # The future won't complete - we will hit the timeout self.executor.spin_until_future_complete(rclpy.task.Future(), timeout_sec=5) assert command.wait_for_output( functools.partial( launch_testing.tools.expect_output, expected_lines=[ "b'\\x00\\x01\\x00\\x00\\x06\\x00\\x00\\x00hello\\x00\\x00\\x00'", '---', ], strict=True), timeout=10), 'Echo CLI did not print expected message' assert command.wait_for_shutdown(timeout=10) finally: # Cleanup self.node.destroy_timer(publish_timer) self.node.destroy_publisher(publisher)
def create_permission_file(path, domain_id, policy_element): print('creating permission') permissions_xsl_path = get_transport_template('dds', 'permissions.xsl') permissions_xsl = etree.XSLT(etree.parse(permissions_xsl_path)) permissions_xsd_path = get_transport_schema('dds', 'permissions.xsd') permissions_xsd = etree.XMLSchema(etree.parse(permissions_xsd_path)) kwargs = {} if get_rmw_implementation_identifier() in _RMW_WITH_ROS_GRAPH_INFO_TOPIC: kwargs['allow_ros_discovery_topic'] = etree.XSLT.strparam('1') permissions_xml = permissions_xsl(policy_element, **kwargs) domain_id_elements = permissions_xml.findall('permissions/grant/*/domains/id') for domain_id_element in domain_id_elements: domain_id_element.text = domain_id try: permissions_xsd.assertValid(permissions_xml) except etree.DocumentInvalid as e: raise RuntimeError(str(e)) with open(path, 'wb') as f: f.write(etree.tostring(permissions_xml, pretty_print=True))
def test_pub_basic(self, launch_service, proc_info, proc_output): params = [('/clitest/topic/pub_basic', False, True), ('/clitest/topic/pub_compatible_qos', True, True), ('/clitest/topic/pub_incompatible_qos', True, False)] for topic, provide_qos, compatible_qos in params: with self.subTest(topic=topic, provide_qos=provide_qos, compatible_qos=compatible_qos): # Check for inconsistent arguments assert provide_qos if not compatible_qos else True received_message_count = 0 expected_minimum_message_count = 1 expected_maximum_message_count = 5 pub_extra_options = [] subscription_qos_profile = 10 if provide_qos: if compatible_qos: # For compatible test, put publisher at very high quality # and subscription at low pub_extra_options = [ '--qos-reliability', 'reliable', '--qos-durability', 'transient_local' ] subscription_qos_profile = QoSProfile( depth=10, reliability=ReliabilityPolicy.BEST_EFFORT, durability=DurabilityPolicy.VOLATILE) else: # For an incompatible example, reverse the quality extremes # and expect no messages to arrive pub_extra_options = [ '--qos-reliability', 'best_effort', '--qos-durability', 'volatile' ] subscription_qos_profile = QoSProfile( depth=10, reliability=ReliabilityPolicy.RELIABLE, durability=DurabilityPolicy.TRANSIENT_LOCAL) expected_maximum_message_count = 0 expected_minimum_message_count = 0 future = rclpy.task.Future() def message_callback(msg): """If we receive one message, the test has succeeded.""" nonlocal received_message_count received_message_count += 1 future.set_result(True) subscription = self.node.create_subscription( String, topic, message_callback, subscription_qos_profile) assert subscription try: command_action = ExecuteProcess( cmd=(['ros2', 'topic', 'pub'] + pub_extra_options + [topic, 'std_msgs/String', 'data: hello']), additional_env={'PYTHONUNBUFFERED': '1'}, output='screen') with launch_testing.tools.launch_process( launch_service, command_action, proc_info, proc_output, output_filter=launch_testing_ros.tools. basic_output_filter( filtered_rmw_implementation= get_rmw_implementation_identifier( ))) as command: self.executor.spin_until_future_complete( future, timeout_sec=10) command.wait_for_shutdown(timeout=10) # Check results assert ( received_message_count >= expected_minimum_message_count and received_message_count <= expected_maximum_message_count), \ ('Received {} messages from pub on {},' 'which is not in expected range {}-{}').format( received_message_count, topic, expected_minimum_message_count, expected_maximum_message_count ) finally: # Cleanup self.node.destroy_subscription(subscription)
def test_echo_basic(self, launch_service, proc_info, proc_output): params = [ ('/clitest/topic/echo_basic', False, True, False), ('/clitest/topic/echo_compatible_qos', True, True, False), ('/clitest/topic/echo_incompatible_qos', True, False, False), ('/clitest/topic/echo_message_lost', False, True, True), ] for topic, provide_qos, compatible_qos, message_lost in params: with self.subTest(topic=topic, provide_qos=provide_qos, compatible_qos=compatible_qos): # Check for inconsistent arguments assert provide_qos if not compatible_qos else True echo_extra_options = [] publisher_qos_profile = 10 if provide_qos: if compatible_qos: # For compatible test, put publisher at very high quality # and subscription at low echo_extra_options = [ '--qos-reliability', 'best_effort', '--qos-durability', 'volatile' ] publisher_qos_profile = QoSProfile( depth=10, reliability=ReliabilityPolicy.RELIABLE, durability=DurabilityPolicy.TRANSIENT_LOCAL) else: # For an incompatible example, reverse the quality extremes # and expect no messages to arrive echo_extra_options = [ '--qos-reliability', 'reliable', '--qos-durability', 'transient_local' ] publisher_qos_profile = QoSProfile( depth=10, reliability=ReliabilityPolicy.BEST_EFFORT, durability=DurabilityPolicy.VOLATILE) if message_lost: echo_extra_options.append('--lost-messages') publisher = self.node.create_publisher(String, topic, publisher_qos_profile) assert publisher def publish_message(): publisher.publish(String(data='hello')) publish_timer = self.node.create_timer(0.5, publish_message) try: command_action = ExecuteProcess( cmd=(['ros2', 'topic', 'echo'] + echo_extra_options + [topic, 'std_msgs/String']), additional_env={'PYTHONUNBUFFERED': '1'}, output='screen') with launch_testing.tools.launch_process( launch_service, command_action, proc_info, proc_output, output_filter=launch_testing_ros.tools. basic_output_filter( filtered_rmw_implementation= get_rmw_implementation_identifier( ))) as command: # The future won't complete - we will hit the timeout self.executor.spin_until_future_complete( rclpy.task.Future(), timeout_sec=5) command.wait_for_shutdown(timeout=10) # Check results if compatible_qos: # TODO(ivanpauno): remove special case when FastRTPS implements the feature # https://github.com/ros2/rmw_fastrtps/issues/395 assert command.output, 'Echo CLI printed no output' if message_lost and 'rmw_fastrtps' in get_rmw_implementation_identifier( ): assert 'does not support reporting lost messages' in command.output assert get_rmw_implementation_identifier( ) in command.output return assert 'data: hello' in command.output.splitlines(), ( 'Echo CLI did not print expected message') else: # TODO(mm318): remove special case for FastRTPS when # https://github.com/ros2/rmw_fastrtps/issues/356 is resolved if 'rmw_fastrtps' in get_rmw_implementation_identifier( ): assert not command.output, ( 'Echo CLI should not have received anything with incompatible QoS' ) else: assert command.output, ( 'Echo CLI did not print incompatible QoS warning' ) assert ( 'New publisher discovered on this topic, offering incompatible' ' QoS.' in command.output ), ('Echo CLI did not print expected incompatible QoS warning' ) finally: # Cleanup self.node.destroy_timer(publish_timer) self.node.destroy_publisher(publisher)
class TestClient(unittest.TestCase): @classmethod def setUpClass(cls): cls.context = rclpy.context.Context() rclpy.init(context=cls.context) cls.node = rclpy.create_node('TestClient', context=cls.context) @classmethod def tearDownClass(cls): cls.node.destroy_node() rclpy.shutdown(context=cls.context) def test_wait_for_service_5sec(self): cli = self.node.create_client(GetParameters, 'get/parameters') try: start = time.monotonic() self.assertFalse(cli.wait_for_service(timeout_sec=5.0)) end = time.monotonic() self.assertGreater(5.0, end - start - TIME_FUDGE) self.assertLess(5.0, end - start + TIME_FUDGE) finally: self.node.destroy_client(cli) def test_wait_for_service_nowait(self): cli = self.node.create_client(GetParameters, 'get/parameters') try: start = time.monotonic() self.assertFalse(cli.wait_for_service(timeout_sec=0)) end = time.monotonic() self.assertGreater(0, end - start - TIME_FUDGE) self.assertLess(0, end - start + TIME_FUDGE) finally: self.node.destroy_client(cli) def test_wait_for_service_exists(self): cli = self.node.create_client(GetParameters, 'test_wfs_exists') srv = self.node.create_service(GetParameters, 'test_wfs_exists', lambda request: None) try: start = time.monotonic() self.assertTrue(cli.wait_for_service(timeout_sec=1.0)) end = time.monotonic() self.assertGreater(0, end - start - TIME_FUDGE) self.assertLess(0, end - start + TIME_FUDGE) finally: self.node.destroy_client(cli) self.node.destroy_service(srv) def test_concurrent_calls_to_service(self): cli = self.node.create_client(GetParameters, 'get/parameters') srv = self.node.create_service(GetParameters, 'get/parameters', lambda request, response: response) try: self.assertTrue(cli.wait_for_service(timeout_sec=20)) future1 = cli.call_async(GetParameters.Request()) future2 = cli.call_async(GetParameters.Request()) executor = rclpy.executors.SingleThreadedExecutor( context=self.context) rclpy.spin_until_future_complete(self.node, future1, executor=executor) rclpy.spin_until_future_complete(self.node, future2, executor=executor) self.assertTrue(future1.result() is not None) self.assertTrue(future2.result() is not None) finally: self.node.destroy_client(cli) self.node.destroy_service(srv) @unittest.skipIf( get_rmw_implementation_identifier() == 'rmw_connextdds' and platform.system() == 'Windows', reason='Source timestamp not implemented for Connext on Windows') def test_service_timestamps(self): cli = self.node.create_client(GetParameters, 'get/parameters') srv = self.node.create_service(GetParameters, 'get/parameters', lambda request, response: response) try: self.assertTrue(cli.wait_for_service(timeout_sec=20)) cli.call_async(GetParameters.Request()) cycle_count = 0 while cycle_count < 5: with srv.handle: result = srv.handle.service_take_request( srv.srv_type.Request) if result is not None: request, header = result self.assertTrue(header is not None) self.assertNotEqual(0, header.source_timestamp) return else: time.sleep(0.1) self.fail('Did not get a request in time') finally: self.node.destroy_client(cli) self.node.destroy_service(srv) def test_different_type_raises(self): cli = self.node.create_client(GetParameters, 'get/parameters') srv = self.node.create_service( GetParameters, 'get/parameters', lambda request, response: 'different response type') try: with self.assertRaises(TypeError): cli.call('different request type') with self.assertRaises(TypeError): cli.call_async('different request type') self.assertTrue(cli.wait_for_service(timeout_sec=20)) future = cli.call_async(GetParameters.Request()) executor = rclpy.executors.SingleThreadedExecutor( context=self.context) with self.assertRaises(TypeError): rclpy.spin_until_future_complete(self.node, future, executor=executor) finally: self.node.destroy_client(cli) self.node.destroy_service(srv)
def report(self): rmw_report = Report('RMW MIDDLEWARE') rmw_report.add_to_report('middleware name', get_rmw_implementation_identifier()) return rmw_report