@@ -408,3 +408,87 @@ TEST_F(CLASSNAME(TestService, RMW_IMPLEMENTATION), send_reponse_with_bad_argumen
408408 rmw_reset_error ();
409409 srv->implementation_identifier = implementation_identifier;
410410}
411+
412+ TEST_F (CLASSNAME(TestService, RMW_IMPLEMENTATION), send_reponse_with_client_gone) {
413+ constexpr char service_name[] = " /test" ;
414+ const rosidl_service_type_support_t * ts =
415+ ROSIDL_GET_SRV_TYPE_SUPPORT (test_msgs, srv, BasicTypes);
416+ test_msgs__srv__BasicTypes_Response service_response;
417+ ASSERT_TRUE (test_msgs__srv__BasicTypes_Response__init (&service_response));
418+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
419+ {
420+ test_msgs__srv__BasicTypes_Response__fini (&service_response);
421+ });
422+ service_response.bool_value = false ;
423+ service_response.uint8_value = 1 ;
424+ service_response.uint32_value = 2 ;
425+ test_msgs__srv__BasicTypes_Request request;
426+ ASSERT_TRUE (test_msgs__srv__BasicTypes_Request__init (&request));
427+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
428+ {
429+ test_msgs__srv__BasicTypes_Request__fini (&request);
430+ });
431+ request.bool_value = false ;
432+ request.uint8_value = 1 ;
433+ request.uint32_value = 2 ;
434+ int64_t sequence_number;
435+ rmw_service_info_t header;
436+ rmw_service_t * srv =
437+ rmw_create_service (node, ts, service_name, &rmw_qos_profile_default);
438+ ASSERT_NE (nullptr , srv) << rmw_get_error_string ().str ;
439+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
440+ {
441+ rmw_ret_t ret = rmw_destroy_service (node, srv);
442+ EXPECT_EQ (RMW_RET_OK, ret) << rcutils_get_error_string ().str ;
443+ });
444+ bool destroy_client = true ;
445+ rmw_client_t * client =
446+ rmw_create_client (node, ts, service_name, &rmw_qos_profile_default);
447+ ASSERT_NE (nullptr , client) << rmw_get_error_string ().str ;
448+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
449+ {
450+ if (destroy_client) {
451+ rmw_ret_t ret = rmw_destroy_client (node, client);
452+ EXPECT_EQ (RMW_RET_OK, ret) << rcutils_get_error_string ().str ;
453+ }
454+ });
455+
456+ rmw_ret_t ret = rmw_send_request (client, &request, &sequence_number);
457+ ASSERT_EQ (RMW_RET_OK, ret) << rmw_get_error_string ().str ;
458+
459+ size_t number_of_services = 1u ;
460+ rmw_wait_set_t * wait_set = rmw_create_wait_set (&context, number_of_services);
461+ ASSERT_NE (nullptr , wait_set) << rmw_get_error_string ().str ;
462+ OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT (
463+ {
464+ rmw_ret_t ret = rmw_destroy_wait_set (wait_set);
465+ EXPECT_EQ (RMW_RET_OK, ret) << rcutils_get_error_string ().str ;
466+ });
467+ void * array[1 ];
468+ array[0 ] = srv->data ;
469+ rmw_services_t srv_array;
470+ srv_array.service_count = 1u ;
471+ srv_array.services = array;
472+ rmw_time_t timeout;
473+ auto rmw_intraprocess_discovery_delay_in_nanoseconds =
474+ std::chrono::duration_cast<std::chrono::nanoseconds>(
475+ rmw_intraprocess_discovery_delay * 10 ).count ();
476+ timeout.sec = rmw_intraprocess_discovery_delay_in_nanoseconds / 1000000000 ;
477+ timeout.nsec = rmw_intraprocess_discovery_delay_in_nanoseconds % 1000000000 ;
478+ ret = rmw_wait (nullptr , nullptr , &srv_array, nullptr , nullptr , wait_set, &timeout);
479+ ASSERT_EQ (RMW_RET_OK, ret) << rmw_get_error_string ().str ;
480+ ASSERT_NE (nullptr , srv_array.services [0 ]);
481+
482+ bool taken = false ;
483+ ret = rmw_take_request (srv, &header, &request, &taken);
484+ ASSERT_EQ (RMW_RET_OK, ret) << rmw_get_error_string ().str ;
485+ ASSERT_EQ (true , taken);
486+
487+ // Remove client
488+ ret = rmw_destroy_client (node, client);
489+ destroy_client = false ;
490+
491+ // RMW_RET_OK is returned even if the client is gone
492+ ret = rmw_send_response (srv, &header.request_id , &service_response);
493+ EXPECT_EQ (RMW_RET_OK, ret);
494+ }
0 commit comments