Skip to content

Commit

Permalink
Fix up type_description tests. (#1160)
Browse files Browse the repository at this point in the history
In particular, make sure to match all service_description_init
with the appropriate finis.  While we are in here, also add in
a "service_not_exists" function that will quit much earlier,
speeding up the test.

This is essentially a backport of #1107
and parts of #1112, but adapted
for Iron.

Signed-off-by: Chris Lalancette <clalancette@gmail.com>
  • Loading branch information
clalancette authored Jun 25, 2024
1 parent 900d7f5 commit 3c5b561
Showing 1 changed file with 86 additions and 23 deletions.
109 changes: 86 additions & 23 deletions rcl/test/rcl/test_get_type_description_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

#include <gtest/gtest.h>

#include <chrono>
#include <cstring>
#include <thread>

#include "rcl/error_handling.h"
#include "rcl/graph.h"
Expand Down Expand Up @@ -104,6 +106,55 @@ static bool service_exists(
return type_name_found;
}

static bool service_not_exists(
const rcl_node_t * node_ptr, const char * service_name,
const char * service_type, std::chrono::milliseconds timeout)
{
rcl_allocator_t allocator = rcl_get_default_allocator();

// Wait for a maximum of timeout milliseconds for the service to go away
// Note that this is not just the negation of service_exists; we actually
// want to wait until the service goes away
auto start_time = std::chrono::system_clock::now();
while (std::chrono::system_clock::now() - start_time < timeout) {
rcl_names_and_types_t srv_names_and_types = rcl_get_zero_initialized_names_and_types();

if (
RCL_RET_OK != rcl_get_service_names_and_types(
node_ptr,
&allocator, &srv_names_and_types))
{
return false;
}

OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
{
EXPECT_EQ(RCL_RET_OK, rcl_names_and_types_fini(&srv_names_and_types));
});

if (srv_names_and_types.names.size == 0) {
return true;
}

if (!string_in_array(&(srv_names_and_types.names), service_name)) {
return true;
}

// If we make it here, the service name was in the array. If the *type* isn't, then there is
// another service with this name, which we can ignore.
for (size_t i = 0; i < srv_names_and_types.names.size; ++i) {
if (string_in_array(&(srv_names_and_types.types[i]), service_type)) {
// Both the name and type were here, so the service currently exists. Continue waiting
break;
}
}

std::this_thread::sleep_for(std::chrono::milliseconds(10));
}

return false;
}

class CLASSNAME (TestGetTypeDescSrvFixture, RMW_IMPLEMENTATION) : public ::testing::Test
{
public:
Expand All @@ -119,27 +170,23 @@ class CLASSNAME (TestGetTypeDescSrvFixture, RMW_IMPLEMENTATION) : public ::testi
void SetUp()
{
rcl_ret_t ret;
rcl_init_options_t init_options = rcl_get_zero_initialized_init_options();
ret = rcl_init_options_init(&init_options, rcl_get_default_allocator());
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
{
rcl_init_options_t init_options = rcl_get_zero_initialized_init_options();
ret = rcl_init_options_init(&init_options, rcl_get_default_allocator());
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
{
EXPECT_EQ(RCL_RET_OK, rcl_init_options_fini(&init_options)) << rcl_get_error_string().str;
});
this->context_ptr = new rcl_context_t;
*this->context_ptr = rcl_get_zero_initialized_context();
ret = rcl_init(0, nullptr, &init_options, this->context_ptr);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
}
EXPECT_EQ(RCL_RET_OK, rcl_init_options_fini(&init_options)) << rcl_get_error_string().str;
});
this->context_ptr = new rcl_context_t;
*this->context_ptr = rcl_get_zero_initialized_context();
ret = rcl_init(0, nullptr, &init_options, this->context_ptr);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
this->node_ptr = new rcl_node_t;
*this->node_ptr = rcl_get_zero_initialized_node();
const char * name = "test_service_node";
rcl_node_options_t node_options = rcl_node_get_default_options();
ret = rcl_node_init(this->node_ptr, name, "", this->context_ptr, &node_options);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
ret = rcl_node_type_description_service_init(node_ptr);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;

const char * node_fqn = rcl_node_get_fully_qualified_name(this->node_ptr);
snprintf(
Expand All @@ -165,23 +212,27 @@ class CLASSNAME (TestGetTypeDescSrvFixture, RMW_IMPLEMENTATION) : public ::testi
TEST_F(
CLASSNAME(TestGetTypeDescSrvFixture, RMW_IMPLEMENTATION),
test_service_init_and_fini_functions) {
// Service does not initially exist
EXPECT_TRUE(
service_exists(
service_not_exists(
this->node_ptr, this->get_type_description_service_name,
GET_TYPE_DESCRIPTION_SRV_TYPE_NAME));
EXPECT_EQ(RCL_RET_OK, rcl_node_type_description_service_fini(this->node_ptr));
EXPECT_FALSE(
service_exists(
this->node_ptr, this->get_type_description_service_name,
GET_TYPE_DESCRIPTION_SRV_TYPE_NAME));
EXPECT_EQ(RCL_RET_NOT_INIT, rcl_node_type_description_service_fini(this->node_ptr));
GET_TYPE_DESCRIPTION_SRV_TYPE_NAME, std::chrono::seconds(5)));

// Once the type descrition service is init, then it appear in the graph
EXPECT_EQ(RCL_RET_OK, rcl_node_type_description_service_init(this->node_ptr));
EXPECT_TRUE(
service_exists(
this->node_ptr, this->get_type_description_service_name,
GET_TYPE_DESCRIPTION_SRV_TYPE_NAME));
EXPECT_EQ(RCL_RET_ALREADY_INIT, rcl_node_type_description_service_init(this->node_ptr));

// Once the type description service is fini, then it no longer appears in the graph
EXPECT_EQ(RCL_RET_OK, rcl_node_type_description_service_fini(this->node_ptr));
EXPECT_TRUE(
service_not_exists(
this->node_ptr, this->get_type_description_service_name,
GET_TYPE_DESCRIPTION_SRV_TYPE_NAME, std::chrono::seconds(5)));

EXPECT_EQ(RCL_RET_NOT_INIT, rcl_node_type_description_service_fini(this->node_ptr));
}

/* Basic nominal test of the ~/get_type_description service. */
Expand All @@ -190,6 +241,9 @@ TEST_F(CLASSNAME(TestGetTypeDescSrvFixture, RMW_IMPLEMENTATION), test_service_no
const rosidl_service_type_support_t * ts = ROSIDL_GET_SRV_TYPE_SUPPORT(
type_description_interfaces, srv, GetTypeDescription);

// Create type description service.
EXPECT_EQ(RCL_RET_OK, rcl_node_type_description_service_init(this->node_ptr));

// Create client.
rcl_client_t client = rcl_get_zero_initialized_client();
rcl_client_options_t client_options = rcl_client_get_default_options();
Expand All @@ -201,6 +255,9 @@ TEST_F(CLASSNAME(TestGetTypeDescSrvFixture, RMW_IMPLEMENTATION), test_service_no
{
rcl_ret_t ret = rcl_client_fini(&client, this->node_ptr);
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;

ret = rcl_node_type_description_service_fini(this->node_ptr);
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
});
ASSERT_TRUE(wait_for_server_to_be_available(this->node_ptr, &client, 10, 1000));

Expand Down Expand Up @@ -283,6 +340,9 @@ TEST_F(
const rosidl_service_type_support_t * ts = ROSIDL_GET_SRV_TYPE_SUPPORT(
type_description_interfaces, srv, GetTypeDescription);

// Create type description service.
EXPECT_EQ(RCL_RET_OK, rcl_node_type_description_service_init(this->node_ptr));

// Create client.
rcl_client_t client = rcl_get_zero_initialized_client();
rcl_client_options_t client_options = rcl_client_get_default_options();
Expand All @@ -294,6 +354,9 @@ TEST_F(
{
rcl_ret_t ret = rcl_client_fini(&client, this->node_ptr);
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;

ret = rcl_node_type_description_service_fini(this->node_ptr);
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
});
ASSERT_TRUE(wait_for_server_to_be_available(this->node_ptr, &client, 10, 1000));

Expand Down

0 comments on commit 3c5b561

Please sign in to comment.