Skip to content

Commit

Permalink
Implementing get_qos_for_publishers/subscribers
Browse files Browse the repository at this point in the history
- Implemented the functions defined in ros2#511
  - rcl_get_qos_for_publishers
  - rcl_get_qos_for_subscribers
- Wrote tests for the same

Note: colcon build --packages-up-to rcl && colcon test --packages-select rcl && colcon test-result --verbose --test-result-base build/rcl
runs successfully without any errors or failures.

Signed-off-by: Jaison Titus <jaisontj92@gmail.com>
  • Loading branch information
jaisontj committed Oct 24, 2019
1 parent 3813ade commit 7b5dc34
Show file tree
Hide file tree
Showing 3 changed files with 253 additions and 4 deletions.
12 changes: 8 additions & 4 deletions rcl/include/rcl/graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -562,10 +562,12 @@ rcl_count_subscribers(
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_get_qos_for_publishers(
rcl_get_publishers_info_by_topic(
const rcl_node_t * node,
rcutils_allocator_t * allocator,
const char * topic_name,
rmw_participants_t * publishers);
bool no_mangle,
rmw_topic_info_array_t * publishers_info);

/// Returns a list of all subscribers to a topic.
/// Each element in the list will contain the subscriber's name and its respective qos profile.
Expand Down Expand Up @@ -605,10 +607,12 @@ rcl_get_qos_for_publishers(
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_get_qos_for_subscribers(
rcl_get_subscriptions_info_by_topic(
const rcl_node_t * node,
rcutils_allocator_t * allocator,
const char * topic_name,
rmw_participants_t * subscribers);
bool no_mangle,
rmw_topic_info_array_t * subscriptions_info);


/// Check if a service server is available for the given service client.
Expand Down
67 changes: 67 additions & 0 deletions rcl/src/rcl/graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,73 @@ rcl_count_subscribers(
return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
}


typedef rmw_ret_t (* get_topic_info_func)(
const rcl_node_t * node,
rcutils_allocator_t * allocator,
const char * topic_name,
bool no_mangle,
rmw_topic_info_array_t * info_array);

rcl_ret_t
__rcl_get_info_by_topic(
const rmw_node_t * node,
rcutils_allocator_t * allocator,
const char * topic_name,
bool no_mangle,
rmw_topic_info_array_t * info_array,
get_topic_info_func get_topic_info)
{
if (!rcl_node_is_valid(node)) {
RCL_SET_ERROR_MSG("Invalid node provided.");
return RCL_RET_NODE_INVALID; // error already set
}
const rcl_node_options_t * node_options = rcl_node_get_options(node);
if (!node_options) {
RCL_SET_ERROR_MSG("Node options are invalid.");
return RCL_RET_NODE_INVALID; // shouldn't happen, but error is already set if so
}
RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, "invalid allocator", return RCL_RET_INVALID_ARGUMENT);
RCL_CHECK_ARGUMENT_FOR_NULL(topic_name, RCL_RET_INVALID_ARGUMENT);
RCL_CHECK_ARGUMENT_FOR_NULL(info_array, RCL_RET_INVALID_ARGUMENT);
if (info_array->info_array != NULL) {
RCL_SET_ERROR_MSG("The variable participants inside rmw_participants_t should be set to null. "
"It will be malloc'd where it gets populated.");
return RCL_RET_INVALID_ARGUMENT;
}
rmw_ret_t rmw_ret = get_topic_info(
rcl_node_get_rmw_handle(node),
allocator,
topic_name,
no_mangle,
info_array);
return rcl_convert_rmw_ret_to_rcl_ret(rmw_ret);
}

rcl_ret_t
rcl_get_publishers_info_by_topic(
const rcl_node_t * node,
rcutils_allocator_t * allocator,
const char * topic_name,
bool no_mangle,
rmw_topic_info_array_t * publishers_info)
{
return __rcl_get_info_by_topic(node, allocator, topic_name, no_mangle, publishers_info,
rmw_get_publishers_info_by_topic);
}

rcl_ret_t
rcl_get_subscriptions_info_by_topic(
const rcl_node_t * node,
rcutils_allocator_t * allocator,
const char * topic_name,
bool no_mangle,
rmw_topic_info_array_t * subscriptions_info)
{
return __rcl_get_info_by_topic(node, allocator, topic_name, no_mangle, subscriptions_info,
rmw_get_subscriptions_info_by_topic);
}

rcl_ret_t
rcl_service_server_is_available(
const rcl_node_t * node,
Expand Down
178 changes: 178 additions & 0 deletions rcl/test/rcl/test_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ class CLASSNAME (TestGraphFixture, RMW_IMPLEMENTATION) : public ::testing::Test
rcl_wait_set_t * wait_set_ptr;
const char * test_graph_node_name = "test_graph_node";

rmw_topic_info_array_t * topic_info_array;
const char * topic_name = "valid_topic_name";

void SetUp()
{
rcl_ret_t ret;
Expand Down Expand Up @@ -101,6 +104,12 @@ class CLASSNAME (TestGraphFixture, RMW_IMPLEMENTATION) : public ::testing::Test
ret = rcl_wait_set_init(
this->wait_set_ptr, 0, 1, 0, 0, 0, 0, this->context_ptr, rcl_get_default_allocator());
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;

rmw_topic_info_array_t valid_topic_info_array = {
0, /*count*/
nullptr /*info_array*/
};
this->topic_info_array = &valid_topic_info_array;
}

void TearDown()
Expand Down Expand Up @@ -1321,3 +1330,172 @@ TEST_F(CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION), test_rcl_service_server_
wait_for_service_state_to_change(false, is_available);
ASSERT_FALSE(is_available);
}


/*
* This does not test content of the response.
* It only tests if the return code is the one expected.
*/
TEST_F(CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION),
test_rcl_get_publishers_info_by_topic_null_node)
{
rcl_allocator_t allocator = rcl_get_default_allocator();
auto ret = rcl_get_publishers_info_by_topic(nullptr,
&allocator, this->topic_name, false, this->topic_info_array);
EXPECT_EQ(RCL_RET_NODE_INVALID, ret);
}

/*
* This does not test content of the response.
* It only tests if the return code is the one expected.
*/
TEST_F(CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION),
test_rcl_get_subscriptions_info_by_topic_null_node)
{
rcl_allocator_t allocator = rcl_get_default_allocator();
auto ret = rcl_get_subscriptions_info_by_topic(nullptr,
&allocator, this->topic_name, false, this->topic_info_array);
EXPECT_EQ(RCL_RET_NODE_INVALID, ret);
}

/*
* This does not test content of the response.
* It only tests if the return code is the one expected.
*/
TEST_F(CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION),
test_rcl_get_publishers_info_by_topic_invalid_node)
{
// this->old_node_ptr is a pointer to an invalid node.
rcl_allocator_t allocator = rcl_get_default_allocator();
auto ret = rcl_get_publishers_info_by_topic(this->old_node_ptr,
&allocator, this->topic_name, false, this->topic_info_array);
EXPECT_EQ(RCL_RET_NODE_INVALID, ret);
}

/*
* This does not test content of the response.
* It only tests if the return code is the one expected.
*/
TEST_F(CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION),
test_rcl_get_subscriptions_info_by_topic_invalid_node)
{
// this->old_node_ptr is a pointer to an invalid node.
rcl_allocator_t allocator = rcl_get_default_allocator();
auto ret = rcl_get_subscriptions_info_by_topic(this->old_node_ptr,
&allocator, this->topic_name, false, this->topic_info_array);
EXPECT_EQ(RCL_RET_NODE_INVALID, ret);
}

/*
* This does not test content of the response.
* It only tests if the return code is the one expected.
*/
TEST_F(CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION),
test_rcl_get_publishers_info_by_topic_null_allocator)
{
auto ret = rcl_get_publishers_info_by_topic(this->node_ptr, nullptr, this->topic_name, false,
this->topic_info_array);
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret);
}

/*
* This does not test content of the response.
* It only tests if the return code is the one expected.
*/
TEST_F(CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION),
test_rcl_get_subscriptions_info_by_topic_null_allocator)
{
auto ret = rcl_get_subscriptions_info_by_topic(this->node_ptr, nullptr, this->topic_name, false,
this->topic_info_array);
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret);
}

/*
* This does not test content of the response.
* It only tests if the return code is the one expected.
*/
TEST_F(CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION),
test_rcl_get_publishers_info_by_topic_null_topic)
{
rcl_allocator_t allocator = rcl_get_default_allocator();
auto ret = rcl_get_publishers_info_by_topic(this->node_ptr,
&allocator, nullptr, false, this->topic_info_array);
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret);
}

/*
* This does not test content of the response.
* It only tests if the return code is the one expected.
*/
TEST_F(CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION),
test_rcl_get_subscriptions_info_by_topic_null_topic)
{
rcl_allocator_t allocator = rcl_get_default_allocator();
auto ret = rcl_get_subscriptions_info_by_topic(this->node_ptr,
&allocator, nullptr, false, this->topic_info_array);
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret);
}

/*
* This does not test content of the response.
* It only tests if the return code is the one expected.
*/
TEST_F(CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION),
test_rcl_get_publishers_info_by_topic_null_participants)
{
rcl_allocator_t allocator = rcl_get_default_allocator();
auto ret = rcl_get_publishers_info_by_topic(this->node_ptr,
&allocator, this->topic_name, false, nullptr);
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret);
}

/*
* This does not test content of the response.
* It only tests if the return code is the one expected.
*/
TEST_F(CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION),
test_rcl_get_subscriptions_info_by_topic_null_participants)
{
rcl_allocator_t allocator = rcl_get_default_allocator();
auto ret = rcl_get_subscriptions_info_by_topic(this->node_ptr,
&allocator, this->topic_name, false, nullptr);
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret);
}

/*
* This does not test content of the response.
* It only tests if the return code is the one expected.
*/
TEST_F(CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION),
test_rcl_get_publishers_info_by_topic_invalid_participants)
{
// this participant is invalid as the pointer "participants" inside is expected to be null.
this->topic_info_array->info_array =
reinterpret_cast<rmw_topic_info_t *>(malloc(sizeof(rmw_topic_info_t *)));
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
free(this->topic_info_array->info_array);
});
rcl_allocator_t allocator = rcl_get_default_allocator();
auto ret = rcl_get_publishers_info_by_topic(this->node_ptr,
&allocator, this->topic_name, false, this->topic_info_array);
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret);
}

/*
* This does not test content of the response.
* It only tests if the return code is the one expected.
*/
TEST_F(CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION),
test_rcl_get_subscriptions_info_by_topic_invalid_participants)
{
// this participant is invalid as the pointer "participants" inside is expected to be null.
this->topic_info_array->info_array =
reinterpret_cast<rmw_topic_info_t *>(malloc(sizeof(rmw_topic_info_t *)));
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
free(this->topic_info_array->info_array);
});
rcl_allocator_t allocator = rcl_get_default_allocator();
auto ret = rcl_get_subscriptions_info_by_topic(this->node_ptr,
&allocator, this->topic_name, false, this->topic_info_array);
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret);
}

0 comments on commit 7b5dc34

Please sign in to comment.