Rosnode list (#108)

* expose list of nodes

* add test

* review comments

* add test for get_node_names

* fix unsigned comparison

* extend year of copyright
This commit is contained in:
Karsten Knese 2017-01-30 10:30:26 -08:00 committed by GitHub
parent 88db558aa3
commit 0291f4e351
5 changed files with 203 additions and 2 deletions

View file

@ -1,4 +1,4 @@
// Copyright 2016 Open Source Robotics Foundation, Inc. // Copyright 2016-2017 Open Source Robotics Foundation, Inc.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -31,6 +31,7 @@ extern "C"
#include "rcl/visibility_control.h" #include "rcl/visibility_control.h"
typedef rmw_topic_names_and_types_t rcl_topic_names_and_types_t; typedef rmw_topic_names_and_types_t rcl_topic_names_and_types_t;
typedef rmw_string_array_t rcl_string_array_t;
/// Return a rcl_topic_names_and_types_t struct with members initialized to `NULL`. /// Return a rcl_topic_names_and_types_t struct with members initialized to `NULL`.
@ -39,6 +40,12 @@ RCL_WARN_UNUSED
rcl_topic_names_and_types_t rcl_topic_names_and_types_t
rcl_get_zero_initialized_topic_names_and_types(void); rcl_get_zero_initialized_topic_names_and_types(void);
/// Return a rcl_node_names_t struct with members initialized to `NULL`.
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_string_array_t
rcl_get_zero_initialized_string_array(void);
/// Return a list of topic names and their types. /// Return a list of topic names and their types.
/** /**
* This function returns a list of topic names in the ROS graph and their types. * This function returns a list of topic names in the ROS graph and their types.
@ -100,6 +107,19 @@ rcl_ret_t
rcl_destroy_topic_names_and_types( rcl_destroy_topic_names_and_types(
rcl_topic_names_and_types_t * topic_names_and_types); rcl_topic_names_and_types_t * topic_names_and_types);
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_get_node_names(
const rcl_node_t * node,
rcl_string_array_t * node_names);
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_destroy_node_names(
rcl_string_array_t * node_names);
/// Return the number of publishers on a given topic. /// Return the number of publishers on a given topic.
/** /**
* This function returns the number of publishers on a given topic. * This function returns the number of publishers on a given topic.

View file

@ -1,4 +1,4 @@
// Copyright 2016 Open Source Robotics Foundation, Inc. // Copyright 2016-2017 Open Source Robotics Foundation, Inc.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -28,6 +28,13 @@ rcl_get_zero_initialized_topic_names_and_types(void)
return null_topic_names_and_types; return null_topic_names_and_types;
} }
rcl_string_array_t
rcl_get_zero_initialized_string_array(void)
{
const rcl_string_array_t null_string_array = {0, NULL};
return null_string_array;
}
rcl_ret_t rcl_ret_t
rcl_get_topic_names_and_types( rcl_get_topic_names_and_types(
const rcl_node_t * node, const rcl_node_t * node,
@ -64,6 +71,37 @@ rcl_destroy_topic_names_and_types(
return rmw_destroy_topic_names_and_types(topic_names_and_types); return rmw_destroy_topic_names_and_types(topic_names_and_types);
} }
rcl_ret_t
rcl_get_node_names(
const rcl_node_t * node,
rcl_string_array_t * node_names)
{
RCL_CHECK_ARGUMENT_FOR_NULL(node, RCL_RET_INVALID_ARGUMENT);
if (!rcl_node_is_valid(node)) {
return RCL_RET_NODE_INVALID;
}
RCL_CHECK_ARGUMENT_FOR_NULL(node_names, RCL_RET_INVALID_ARGUMENT);
if (node_names->size != 0) {
RCL_SET_ERROR_MSG("node_names size is not zero");
return RCL_RET_INVALID_ARGUMENT;
}
if (node_names->data) {
RCL_SET_ERROR_MSG("node_names is not null");
return RCL_RET_INVALID_ARGUMENT;
}
return rmw_get_node_names(
rcl_node_get_rmw_handle(node),
node_names);
}
rcl_ret_t
rcl_destroy_node_names(
rcl_string_array_t * node_names)
{
RCL_CHECK_ARGUMENT_FOR_NULL(node_names, RCL_RET_INVALID_ARGUMENT);
return rmw_destroy_node_names(node_names);
}
rcl_ret_t rcl_ret_t
rcl_count_publishers( rcl_count_publishers(
const rcl_node_t * node, const rcl_node_t * node,

View file

@ -63,6 +63,17 @@ function(test_target_function)
AMENT_DEPENDENCIES ${rmw_implementation} AMENT_DEPENDENCIES ${rmw_implementation}
) )
rcl_add_custom_gtest(test_get_node_names${target_suffix}
SRCS rcl/test_get_node_names.cpp
ENV
${extra_test_env}
EMPTY_TEST=
NORMAL_TEST=foo
APPEND_LIBRARY_DIRS ${extra_lib_dirs}
LIBRARIES ${PROJECT_NAME} ${extra_test_libraries}
AMENT_DEPENDENCIES ${rmw_implementation}
)
set(SKIP_TEST "") set(SKIP_TEST "")
# TODO(wjwwood): remove this when the graph API works properly for FastRTPS # TODO(wjwwood): remove this when the graph API works properly for FastRTPS
if( if(

View file

@ -0,0 +1,96 @@
// Copyright 2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <gtest/gtest.h>
#include <chrono>
#include <thread>
#include "rcl/graph.h"
#include "rcl/rcl.h"
#include "rmw/rmw.h"
#include "../memory_tools/memory_tools.hpp"
#include "rcl/error_handling.h"
#ifdef RMW_IMPLEMENTATION
# define CLASSNAME_(NAME, SUFFIX) NAME ## __ ## SUFFIX
# define CLASSNAME(NAME, SUFFIX) CLASSNAME_(NAME, SUFFIX)
#else
# define CLASSNAME(NAME, SUFFIX) NAME
#endif
using namespace std::chrono_literals;
class CLASSNAME (TestGetNodeNames, RMW_IMPLEMENTATION) : public ::testing::Test
{
public:
void SetUp()
{
set_on_unexpected_malloc_callback([]() {ASSERT_FALSE(true) << "UNEXPECTED MALLOC";});
set_on_unexpected_realloc_callback([]() {ASSERT_FALSE(true) << "UNEXPECTED REALLOC";});
set_on_unexpected_free_callback([]() {ASSERT_FALSE(true) << "UNEXPECTED FREE";});
start_memory_checking();
}
void TearDown()
{
assert_no_malloc_end();
assert_no_realloc_end();
assert_no_free_end();
stop_memory_checking();
set_on_unexpected_malloc_callback(nullptr);
set_on_unexpected_realloc_callback(nullptr);
set_on_unexpected_free_callback(nullptr);
}
};
TEST_F(CLASSNAME(TestGetNodeNames, RMW_IMPLEMENTATION), test_rcl_get_node_names) {
auto ret = rcl_init(0, nullptr, rcl_get_default_allocator());
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
auto node1_ptr = new rcl_node_t;
*node1_ptr = rcl_get_zero_initialized_node();
const char * node1_name = "node1";
rcl_node_options_t node1_options = rcl_node_get_default_options();
ret = rcl_node_init(node1_ptr, node1_name, &node1_options);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
auto node2_ptr = new rcl_node_t;
*node2_ptr = rcl_get_zero_initialized_node();
const char * node2_name = "node2";
rcl_node_options_t node2_options = rcl_node_get_default_options();
ret = rcl_node_init(node2_ptr, node2_name, &node2_options);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
std::this_thread::sleep_for(1s);
rcl_string_array_t node_names = rcl_get_zero_initialized_string_array();
ret = rcl_get_node_names(node1_ptr, &node_names);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
EXPECT_EQ(size_t(2), node_names.size);
EXPECT_EQ(0, strcmp(node1_name, node_names.data[0]));
EXPECT_EQ(0, strcmp(node2_name, node_names.data[1]));
ret = rcl_node_fini(node1_ptr);
delete node1_ptr;
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
ret = rcl_node_fini(node2_ptr);
delete node2_ptr;
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
ret = rcl_shutdown();
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
}

View file

@ -150,6 +150,42 @@ TEST_F(
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe(); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
} }
/* Test the rcl_get_topic_names_and_types and rcl_destroy_topic_names_and_types functions.
*
* This does not test content of the rcl_topic_names_and_types_t structure.
*/
TEST_F(
CLASSNAME(TestGraphFixture, RMW_IMPLEMENTATION),
test_rcl_get_and_destroy_node_names) {
stop_memory_checking();
rcl_ret_t ret;
rcl_string_array_t node_names {};
rcl_node_t zero_node = rcl_get_zero_initialized_node();
// invalid node
ret = rcl_get_node_names(nullptr, &node_names);
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string_safe();
rcl_reset_error();
ret = rcl_get_node_names(&zero_node, &node_names);
EXPECT_EQ(RCL_RET_NODE_INVALID, ret) << rcl_get_error_string_safe();
rcl_reset_error();
ret = rcl_get_node_names(this->old_node_ptr, &node_names);
EXPECT_EQ(RCL_RET_NODE_INVALID, ret) << rcl_get_error_string_safe();
rcl_reset_error();
// invalid topic_names_and_types
ret = rcl_get_node_names(this->node_ptr, nullptr);
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string_safe();
rcl_reset_error();
// invalid argument to rcl_destroy_topic_names_and_types
ret = rcl_destroy_node_names(nullptr);
EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string_safe();
rcl_reset_error();
// valid calls
ret = rcl_get_node_names(this->node_ptr, &node_names);
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
ret = rcl_destroy_node_names(&node_names);
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string_safe();
}
/* Test the rcl_count_publishers function. /* Test the rcl_count_publishers function.
* *
* This does not test content the response. * This does not test content the response.