Skip to content

Commit

Permalink
Revamp the test_get_type_description_service. (#1095)
Browse files Browse the repository at this point in the history
1. Make it more robust to the network taking time
to do discovery.
2. Shorten the delay time when we expect things to fail.
3. Fix a possible leak during service_exists(), pointed
out by valgrind.
4. Remove unnecessary heap allocations in service_exists()
(we can just use the stack here).
5. Fix a definite leak during test teardown, where we were
forgetting to fini the node_type_description_service.

Signed-off-by: Chris Lalancette <[email protected]>
  • Loading branch information
clalancette authored Aug 24, 2023
1 parent 7c1b387 commit 1a025c6
Showing 1 changed file with 50 additions and 67 deletions.
117 changes: 50 additions & 67 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 @@ -51,87 +53,61 @@ static bool string_in_array(rcutils_string_array_t * array, const char * pattern

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

rcl_names_and_types_t * srv_names_and_types =
static_cast<rcl_names_and_types_t *>(allocator.allocate(
sizeof(rcl_names_and_types_t),
allocator.state));
if (nullptr == srv_names_and_types) {
return false;
}
EXPECT_EQ(RCL_RET_OK, rcl_names_and_types_init(srv_names_and_types, 0, &allocator));
srv_names_and_types->names.data = NULL;
srv_names_and_types->names.size = 0;
srv_names_and_types->types = NULL;

OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
{
EXPECT_EQ(RCL_RET_OK, rcl_names_and_types_fini(srv_names_and_types));
allocator.deallocate(srv_names_and_types, allocator.state);
});

if (
RCL_RET_OK != rcl_get_service_names_and_types(
node_ptr,
&allocator, srv_names_and_types))
{
return false;
}
// Wait for a maximum of timeout seconds for the service to show up
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 (srv_names_and_types->names.size < 1) {
return false;
}

const bool srv_name_found = string_in_array(
&srv_names_and_types->names,
service_name);
if (
RCL_RET_OK != rcl_get_service_names_and_types(
node_ptr,
&allocator, &srv_names_and_types))
{
return false;
}

if (!srv_name_found) {return false;}
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
{
EXPECT_EQ(RCL_RET_OK, rcl_names_and_types_fini(&srv_names_and_types));
});

bool type_name_found = false;
for (size_t i = 0; i < srv_names_and_types->names.size; ++i) {
type_name_found = string_in_array(
&srv_names_and_types->types[i],
service_type);
if (type_name_found) {
break;
if (srv_names_and_types.names.size >= 1) {
if (string_in_array(&(srv_names_and_types.names), service_name)) {
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)) {
return true;
}
}
}
}

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

return type_name_found;
return false;
}

class CLASSNAME (TestGetTypeDescSrvFixture, RMW_IMPLEMENTATION) : public ::testing::Test
{
public:
rcl_context_t * context_ptr;
rcl_node_t * node_ptr;
char get_type_description_service_name[256];

virtual bool get_type_description_service_enabled() const
{
return true;
}

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";
Expand All @@ -149,7 +125,9 @@ class CLASSNAME (TestGetTypeDescSrvFixture, RMW_IMPLEMENTATION) : public ::testi

void TearDown()
{
rcl_ret_t ret = rcl_node_fini(this->node_ptr);
rcl_ret_t ret = rcl_node_type_description_service_fini(node_ptr);
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
ret = rcl_node_fini(this->node_ptr);
delete this->node_ptr;
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
ret = rcl_shutdown(this->context_ptr);
Expand All @@ -158,6 +136,11 @@ class CLASSNAME (TestGetTypeDescSrvFixture, RMW_IMPLEMENTATION) : public ::testi
delete this->context_ptr;
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
}

protected:
rcl_context_t * context_ptr;
rcl_node_t * node_ptr;
char get_type_description_service_name[256];
};


Expand All @@ -168,19 +151,19 @@ TEST_F(
EXPECT_TRUE(
service_exists(
this->node_ptr, this->get_type_description_service_name,
GET_TYPE_DESCRIPTION_SRV_TYPE_NAME));
GET_TYPE_DESCRIPTION_SRV_TYPE_NAME, std::chrono::seconds(5)));
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));
GET_TYPE_DESCRIPTION_SRV_TYPE_NAME, std::chrono::milliseconds(100)));
EXPECT_EQ(RCL_RET_NOT_INIT, rcl_node_type_description_service_fini(this->node_ptr));

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));
GET_TYPE_DESCRIPTION_SRV_TYPE_NAME, std::chrono::seconds(5)));
EXPECT_EQ(RCL_RET_ALREADY_INIT, rcl_node_type_description_service_init(this->node_ptr));
}

Expand Down

0 comments on commit 1a025c6

Please sign in to comment.