Compare commits
24 Commits
3.0.0
...
peterpena/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4fe5a5c8c | ||
|
|
425a794eb1 | ||
|
|
c0f7eb3c45 | ||
|
|
39c7ca3b69 | ||
|
|
44efcf7744 | ||
|
|
7b1335dd1d | ||
|
|
84ae5a1897 | ||
|
|
05e6b96847 | ||
|
|
860a9e0e4d | ||
|
|
f125c78fa8 | ||
|
|
a8cd936239 | ||
|
|
c92f3b7ff9 | ||
|
|
c0b96616bb | ||
|
|
55fccffc89 | ||
|
|
873a3d5cd0 | ||
|
|
a9d5a3feb9 | ||
|
|
c23572fa14 | ||
|
|
8245808c0e | ||
|
|
35c27e8250 | ||
|
|
8a62104ea7 | ||
|
|
c63060c42d | ||
|
|
2a7b722d5f | ||
|
|
a6741a4f8e | ||
|
|
40f0040f0d |
@@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(rclcpp)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
find_package(ament_cmake_ros REQUIRED)
|
||||
find_package(builtin_interfaces REQUIRED)
|
||||
find_package(libstatistics_collector REQUIRED)
|
||||
@@ -23,7 +25,11 @@ if(NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
endif()
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_compile_options(-Wall -Wextra -Wpedantic -Wnon-virtual-dtor -Woverloaded-virtual)
|
||||
# About -Wno-sign-conversion: With Clang, -Wconversion implies -Wsign-conversion. There are a number of
|
||||
# implicit sign conversions in rclcpp and gtest.cc, see https://ci.ros2.org/job/ci_osx/9265/.
|
||||
# Hence disabling -Wsign-conversion for now until all those have eventually been fixed.
|
||||
# (from https://github.com/ros2/rclcpp/pull/1188#issuecomment-650229140)
|
||||
add_compile_options(-Wall -Wextra -Wconversion -Wno-sign-conversion -Wpedantic -Wnon-virtual-dtor -Woverloaded-virtual)
|
||||
endif()
|
||||
|
||||
set(${PROJECT_NAME}_SRCS
|
||||
@@ -166,6 +172,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:include>")
|
||||
target_link_libraries(${PROJECT_NAME} ${CMAKE_THREAD_LIBS_INIT})
|
||||
# specific order: dependents before dependencies
|
||||
ament_target_dependencies(${PROJECT_NAME}
|
||||
"libstatistics_collector"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
This document is a declaration of software quality for the `rclcpp` package, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
|
||||
# `rclcpp` Quality Declaration
|
||||
# rclcpp Quality Declaration
|
||||
|
||||
The package `rclcpp` claims to be in the **Quality Level 4** category.
|
||||
The package `rclcpp` claims to be in the **Quality Level 3** category.
|
||||
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Quality Categories in REP-2004](https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#package-quality-categories) of the ROS2 developer guide.
|
||||
|
||||
@@ -10,7 +10,7 @@ Below are the rationales, notes, and caveats for this claim, organized by each r
|
||||
|
||||
### Version Scheme [1.i]
|
||||
|
||||
`rclcpp` uses `semver` according to the recommendation for ROS Core packages in the [ROS 2 Developer Guide](https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#versioning)
|
||||
`rclcpp` uses `semver` according to the recommendation for ROS Core packages in the [ROS 2 Developer Guide](https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#versioning).
|
||||
|
||||
### Version Stability [1.ii]
|
||||
|
||||
@@ -76,19 +76,19 @@ All pull requests must resolve related documentation changes before merging.
|
||||
|
||||
### Public API Documentation [3.ii]
|
||||
|
||||
The API is publicly available in the [ROS 2 API documentation](http://docs.ros2.org/latest/api/rclcpp/).
|
||||
The API is publicly available in its [ROS 2 API documentation](http://docs.ros2.org/latest/api/rclcpp/).
|
||||
|
||||
### License [3.iii]
|
||||
|
||||
The license for `rclcpp` is Apache 2.0, and a summary is in each source file, the type is declared in the [`package.xml`](./package.xml) manifest file, and a full copy of the license is in the [`LICENSE`](../LICENSE) file.
|
||||
|
||||
There is an automated test which runs a linter that ensures each file has a license statement. [Here](http://build.ros2.org/view/Epr/job/Epr__rclcpp__ubuntu_bionic_amd64/lastBuild/testReport/rclcpp/) can be found a list with the latest results of the various linters being run on the package.
|
||||
There is an automated test which runs a linter that ensures each file has a license statement. [Here](http://build.ros2.org/view/Fpr/job/Fpr__rclcpp__ubuntu_focal_amd64/lastSuccessfulBuild/testReport/rclcpp/) can be found a list with the latest results of the various linters being run on the package.
|
||||
|
||||
### Copyright Statements [3.iv]
|
||||
|
||||
The copyright holders each provide a statement of copyright in each source code file in `rclcpp`.
|
||||
|
||||
There is an automated test which runs a linter that ensures each file has at least one copyright statement. Latest linter result report can be seen [here](http://build.ros2.org/view/Epr/job/Epr__rclcpp__ubuntu_bionic_amd64/lastBuild/testReport/rclcpp/copyright/).
|
||||
There is an automated test which runs a linter that ensures each file has at least one copyright statement. Latest linter result report can be seen [here](http://build.ros2.org/view/Fpr/job/Fpr__rclcpp__ubuntu_focal_amd64/lastSuccessfulBuild/testReport/rclcpp/copyright/).
|
||||
|
||||
## Testing [4]
|
||||
|
||||
@@ -121,6 +121,8 @@ This includes:
|
||||
|
||||
Changes are required to make a best effort to keep or increase coverage before being accepted, but decreases are allowed if properly justified and accepted by reviewers.
|
||||
|
||||
Current coverage statistics can be viewed [here](https://ci.ros2.org/job/nightly_linux_coverage/lastSuccessfulBuild/cobertura/src_ros2_rclcpp_rclcpp_src_rclcpp/). A description of how coverage statistics are calculated is summarized in this page ["ROS 2 Onboarding Guide"](https://index.ros.org/doc/ros2/Contributing/ROS-2-On-boarding-Guide/#note-on-coverage-runs).
|
||||
|
||||
### Performance [4.iv]
|
||||
|
||||
It is not yet defined if this package requires performance testing and how addresses this topic.
|
||||
@@ -151,49 +153,49 @@ It also has several test dependencies, which do not affect the resulting quality
|
||||
|
||||
The `libstatistics_collector` package provides lightweight aggregation utilities to collect statistics and measure message metrics.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros-tooling/libstatistics_collector/tree/master/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ros-tooling/libstatistics_collector/tree/master/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rcl`
|
||||
|
||||
`rcl` a library to support implementation of language specific ROS 2 Client Libraries.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rcl/blob/master/rcl/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ros2/rcl/blob/master/rcl/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rcl_yaml_param_parser`
|
||||
|
||||
The `rcl_yaml_param_parser` package provides an API that is used to parse YAML configuration files which may be used to configure ROS and specific nodes.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rcl/tree/master/rcl_yaml_param_parser/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ros2/rcl/tree/master/rcl_yaml_param_parser/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rcpputils`
|
||||
|
||||
The `rcpputils` package provides an API which contains common utilities and data structures useful when programming in C++.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rcpputils/blob/master/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 2**, see its [Quality Declaration document](https://github.com/ros2/rcpputils/blob/master/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rcutils`
|
||||
|
||||
The `rcutils` package provides an API which contains common utilities and data structures useful when programming in C.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rcutils/blob/master/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 2**, see its [Quality Declaration document](https://github.com/ros2/rcutils/blob/master/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rmw`
|
||||
|
||||
`rmw` is the ROS 2 middleware library.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rmw/blob/master/rmw/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 2**, see its [Quality Declaration document](https://github.com/ros2/rmw/blob/master/rmw/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `statistics_msgs`
|
||||
|
||||
The `statistics_msgs` package contains ROS 2 message definitions for reporting statistics for topics and system resources.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rcl_interfaces/blob/master/statistics_msgs/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ros2/rcl_interfaces/blob/master/statistics_msgs/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `tracetools`
|
||||
|
||||
The `tracetools` package provides utilities for instrumenting the code in `rclcpp` so that it may be traced for debugging and performance analysis.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://gitlab.com/micro-ROS/ros_tracing/ros2_tracing/-/blob/master/tracetools/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 2**, see its [Quality Declaration document](https://gitlab.com/micro-ROS/ros_tracing/ros2_tracing/-/blob/master/tracetools/QUALITY_DECLARATION.md).
|
||||
|
||||
### Direct Runtime non-ROS Dependency [5.iii]
|
||||
|
||||
|
||||
@@ -6,4 +6,4 @@ Visit the [rclcpp API documentation](http://docs.ros2.org/latest/api/rclcpp/) fo
|
||||
|
||||
## Quality Declaration
|
||||
|
||||
This package claims to be in the **Quality Level 4** category, see the [Quality Declaration](QUALITY_DECLARATION.md) for more details.
|
||||
This package claims to be in the **Quality Level 3** category, see the [Quality Declaration](QUALITY_DECLARATION.md) for more details.
|
||||
|
||||
@@ -361,7 +361,8 @@ public:
|
||||
SharedPromiseWithRequest promise = std::make_shared<PromiseWithRequest>();
|
||||
SharedFutureWithRequest future_with_request(promise->get_future());
|
||||
|
||||
auto wrapping_cb = [future_with_request, promise, request, &cb](SharedFuture future) {
|
||||
auto wrapping_cb = [future_with_request, promise, request,
|
||||
cb = std::forward<CallbackWithRequestType>(cb)](SharedFuture future) {
|
||||
auto response = future.get();
|
||||
promise->set_value(std::make_pair(request, response));
|
||||
cb(future_with_request);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "rclcpp/node_interfaces/node_timers_interface.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics_interface.hpp"
|
||||
|
||||
#include "rclcpp/create_publisher.hpp"
|
||||
#include "rclcpp/create_timer.hpp"
|
||||
#include "rclcpp/qos.hpp"
|
||||
#include "rclcpp/subscription_factory.hpp"
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
operator=(const Duration & rhs);
|
||||
|
||||
Duration &
|
||||
operator=(const builtin_interfaces::msg::Duration & Duration_msg);
|
||||
operator=(const builtin_interfaces::msg::Duration & duration_msg);
|
||||
|
||||
bool
|
||||
operator==(const rclcpp::Duration & rhs) const;
|
||||
|
||||
@@ -82,6 +82,7 @@ private:
|
||||
RCLCPP_DISABLE_COPY(MultiThreadedExecutor)
|
||||
|
||||
std::mutex wait_mutex_;
|
||||
std::mutex scheduled_timers_mutex_;
|
||||
size_t number_of_threads_;
|
||||
bool yield_before_execute_;
|
||||
std::chrono::nanoseconds next_exec_timeout_;
|
||||
|
||||
@@ -842,26 +842,6 @@ public:
|
||||
void
|
||||
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler);
|
||||
|
||||
/// Register a callback to be called anytime a parameter is about to be changed.
|
||||
/**
|
||||
* \deprecated Use add_on_set_parameters_callback instead.
|
||||
* With this method, only one callback can be set at a time. The callback that was previously
|
||||
* set by this method is returned or `nullptr` if no callback was previously set.
|
||||
*
|
||||
* The callbacks added with `add_on_set_parameters_callback` are stored in a different place.
|
||||
* `remove_on_set_parameters_callback` can't be used with the callbacks registered with this
|
||||
* method. For removing it, use `set_on_parameters_set_callback(nullptr)`.
|
||||
*
|
||||
* \param[in] callback The callback to be called when the value for a
|
||||
* parameter is about to be set.
|
||||
* \return The previous callback that was registered, if there was one,
|
||||
* otherwise nullptr.
|
||||
*/
|
||||
[[deprecated("use add_on_set_parameters_callback(OnParametersSetCallbackType callback) instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
OnParametersSetCallbackType
|
||||
set_on_parameters_set_callback(rclcpp::Node::OnParametersSetCallbackType callback);
|
||||
|
||||
/// Get the fully-qualified names of all available nodes.
|
||||
/**
|
||||
* The fully-qualified name includes the local namespace and name of the node.
|
||||
|
||||
@@ -167,11 +167,6 @@ public:
|
||||
void
|
||||
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler) override;
|
||||
|
||||
[[deprecated("use add_on_set_parameters_callback(OnParametersSetCallbackType callback) instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
OnParametersSetCallbackType
|
||||
set_on_parameters_set_callback(OnParametersSetCallbackType callback) override;
|
||||
|
||||
RCLCPP_PUBLIC
|
||||
const std::map<std::string, rclcpp::ParameterValue> &
|
||||
get_parameter_overrides() const override;
|
||||
|
||||
@@ -191,17 +191,6 @@ public:
|
||||
void
|
||||
remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * const handler) = 0;
|
||||
|
||||
/// Register a callback for when parameters are being set, return an existing one.
|
||||
/**
|
||||
* \deprecated Use add_on_set_parameters_callback instead.
|
||||
* \sa rclcpp::Node::set_on_parameters_set_callback
|
||||
*/
|
||||
[[deprecated("use add_on_set_parameters_callback(OnParametersSetCallbackType callback) instead")]]
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
OnParametersSetCallbackType
|
||||
set_on_parameters_set_callback(OnParametersSetCallbackType callback) = 0;
|
||||
|
||||
/// Return the initial parameter values used by the NodeParameters to override default values.
|
||||
RCLCPP_PUBLIC
|
||||
virtual
|
||||
|
||||
@@ -327,11 +327,6 @@ public:
|
||||
NodeOptions &
|
||||
allocator(rcl_allocator_t allocator);
|
||||
|
||||
protected:
|
||||
/// Retrieve the ROS_DOMAIN_ID environment variable and populate options.
|
||||
size_t
|
||||
get_domain_id_from_env() const;
|
||||
|
||||
private:
|
||||
// This is mutable to allow for a const accessor which lazily creates the node options instance.
|
||||
/// Underlying rcl_node_options structure.
|
||||
|
||||
@@ -48,10 +48,10 @@ public:
|
||||
/// Time constructor
|
||||
/**
|
||||
* \param nanoseconds since time epoch
|
||||
* \param clock clock type
|
||||
* \param clock_type clock type
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
explicit Time(int64_t nanoseconds = 0, rcl_clock_type_t clock = RCL_SYSTEM_TIME);
|
||||
explicit Time(int64_t nanoseconds = 0, rcl_clock_type_t clock_type = RCL_SYSTEM_TIME);
|
||||
|
||||
/// Copy constructor
|
||||
RCLCPP_PUBLIC
|
||||
@@ -60,13 +60,13 @@ public:
|
||||
/// Time constructor
|
||||
/**
|
||||
* \param time_msg builtin_interfaces time message to copy
|
||||
* \param ros_time clock type
|
||||
* \param clock_type clock type
|
||||
* \throws std::runtime_error if seconds are negative
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
Time(
|
||||
const builtin_interfaces::msg::Time & time_msg,
|
||||
rcl_clock_type_t ros_time = RCL_ROS_TIME);
|
||||
rcl_clock_type_t clock_type = RCL_ROS_TIME);
|
||||
|
||||
/// Time constructor
|
||||
/**
|
||||
@@ -90,6 +90,12 @@ public:
|
||||
Time &
|
||||
operator=(const Time & rhs);
|
||||
|
||||
/**
|
||||
* Assign Time from a builtin_interfaces::msg::Time instance.
|
||||
* The clock_type will be reset to RCL_ROS_TIME.
|
||||
* Equivalent to *this = Time(time_msg, RCL_ROS_TIME).
|
||||
* \throws std::runtime_error if seconds are negative
|
||||
*/
|
||||
RCLCPP_PUBLIC
|
||||
Time &
|
||||
operator=(const builtin_interfaces::msg::Time & time_msg);
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
{
|
||||
rcl_ret_t ret = rcl_clock_init(clock_type, &rcl_clock_, &allocator_);
|
||||
if (ret != RCL_RET_OK) {
|
||||
exceptions::throw_from_rcl_error(ret, "could not get current time stamp");
|
||||
exceptions::throw_from_rcl_error(ret, "failed to initialize rcl clock");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,17 +47,14 @@ Duration::Duration(std::chrono::nanoseconds nanoseconds)
|
||||
rcl_duration_.nanoseconds = nanoseconds.count();
|
||||
}
|
||||
|
||||
Duration::Duration(const Duration & rhs)
|
||||
{
|
||||
rcl_duration_.nanoseconds = rhs.rcl_duration_.nanoseconds;
|
||||
}
|
||||
Duration::Duration(const Duration & rhs) = default;
|
||||
|
||||
Duration::Duration(
|
||||
const builtin_interfaces::msg::Duration & duration_msg)
|
||||
{
|
||||
rcl_duration_.nanoseconds =
|
||||
static_cast<rcl_duration_value_t>(RCL_S_TO_NS(duration_msg.sec));
|
||||
rcl_duration_.nanoseconds += duration_msg.nanosec;
|
||||
RCL_S_TO_NS(static_cast<rcl_duration_value_t>(duration_msg.sec));
|
||||
rcl_duration_.nanoseconds += static_cast<rcl_duration_value_t>(duration_msg.nanosec);
|
||||
}
|
||||
|
||||
Duration::Duration(const rcl_duration_t & duration)
|
||||
@@ -69,24 +66,25 @@ Duration::Duration(const rcl_duration_t & duration)
|
||||
Duration::operator builtin_interfaces::msg::Duration() const
|
||||
{
|
||||
builtin_interfaces::msg::Duration msg_duration;
|
||||
msg_duration.sec = static_cast<std::int32_t>(RCL_NS_TO_S(rcl_duration_.nanoseconds));
|
||||
msg_duration.nanosec =
|
||||
static_cast<std::uint32_t>(rcl_duration_.nanoseconds % (1000 * 1000 * 1000));
|
||||
constexpr rcl_duration_value_t kDivisor = RCL_S_TO_NS(1);
|
||||
const auto result = std::div(rcl_duration_.nanoseconds, kDivisor);
|
||||
if (result.rem >= 0) {
|
||||
msg_duration.sec = static_cast<std::int32_t>(result.quot);
|
||||
msg_duration.nanosec = static_cast<std::uint32_t>(result.rem);
|
||||
} else {
|
||||
msg_duration.sec = static_cast<std::int32_t>(result.quot - 1);
|
||||
msg_duration.nanosec = static_cast<std::uint32_t>(kDivisor + result.rem);
|
||||
}
|
||||
return msg_duration;
|
||||
}
|
||||
|
||||
Duration &
|
||||
Duration::operator=(const Duration & rhs)
|
||||
{
|
||||
rcl_duration_.nanoseconds = rhs.rcl_duration_.nanoseconds;
|
||||
return *this;
|
||||
}
|
||||
Duration::operator=(const Duration & rhs) = default;
|
||||
|
||||
Duration &
|
||||
Duration::operator=(const builtin_interfaces::msg::Duration & duration_msg)
|
||||
{
|
||||
rcl_duration_.nanoseconds = RCL_S_TO_NS(static_cast<int64_t>(duration_msg.sec));
|
||||
rcl_duration_.nanoseconds += duration_msg.nanosec;
|
||||
*this = Duration(duration_msg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -230,6 +228,10 @@ Duration::seconds() const
|
||||
rmw_time_t
|
||||
Duration::to_rmw_time() const
|
||||
{
|
||||
if (rcl_duration_.nanoseconds < 0) {
|
||||
throw std::runtime_error("rmw_time_t cannot be negative");
|
||||
}
|
||||
|
||||
// reuse conversion logic from msg creation
|
||||
builtin_interfaces::msg::Duration msg = *this;
|
||||
rmw_time_t result;
|
||||
|
||||
@@ -83,19 +83,22 @@ MultiThreadedExecutor::run(size_t)
|
||||
if (!get_next_executable(any_exec, next_exec_timeout_)) {
|
||||
continue;
|
||||
}
|
||||
if (any_exec.timer) {
|
||||
// Guard against multiple threads getting the same timer.
|
||||
if (scheduled_timers_.count(any_exec.timer) != 0) {
|
||||
// Make sure that any_exec's callback group is reset before
|
||||
// the lock is released.
|
||||
if (any_exec.callback_group) {
|
||||
any_exec.callback_group->can_be_taken_from().store(true);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
scheduled_timers_.insert(any_exec.timer);
|
||||
}
|
||||
}
|
||||
|
||||
if (any_exec.timer) {
|
||||
std::lock_guard<std::mutex> wait_lock(scheduled_timers_mutex_);
|
||||
// Guard against multiple threads getting the same timer.
|
||||
if (scheduled_timers_.count(any_exec.timer) != 0) {
|
||||
// Make sure that any_exec's callback group is reset before
|
||||
// the lock is released.
|
||||
if (any_exec.callback_group) {
|
||||
any_exec.callback_group->can_be_taken_from().store(true);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
scheduled_timers_.insert(any_exec.timer);
|
||||
}
|
||||
|
||||
if (yield_before_execute_) {
|
||||
std::this_thread::yield();
|
||||
}
|
||||
@@ -103,7 +106,7 @@ MultiThreadedExecutor::run(size_t)
|
||||
execute_any_executable(any_exec);
|
||||
|
||||
if (any_exec.timer) {
|
||||
std::lock_guard<std::mutex> wait_lock(wait_mutex_);
|
||||
std::lock_guard<std::mutex> wait_lock(scheduled_timers_mutex_);
|
||||
auto it = scheduled_timers_.find(any_exec.timer);
|
||||
if (it != scheduled_timers_.end()) {
|
||||
scheduled_timers_.erase(it);
|
||||
|
||||
@@ -328,28 +328,6 @@ Node::remove_on_set_parameters_callback(const OnSetParametersCallbackHandle * co
|
||||
return node_parameters_->remove_on_set_parameters_callback(callback);
|
||||
}
|
||||
|
||||
// suppress deprecated function warning
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
rclcpp::Node::OnParametersSetCallbackType
|
||||
Node::set_on_parameters_set_callback(rclcpp::Node::OnParametersSetCallbackType callback)
|
||||
{
|
||||
return node_parameters_->set_on_parameters_set_callback(callback);
|
||||
}
|
||||
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
std::vector<std::string>
|
||||
Node::get_node_names() const
|
||||
{
|
||||
|
||||
@@ -159,7 +159,7 @@ __lockless_has_parameter(
|
||||
// see https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon
|
||||
RCLCPP_LOCAL
|
||||
bool
|
||||
__are_doubles_equal(double x, double y, size_t ulp = 100)
|
||||
__are_doubles_equal(double x, double y, double ulp = 100.0)
|
||||
{
|
||||
return std::abs(x - y) <= std::numeric_limits<double>::epsilon() * std::abs(x + y) * ulp;
|
||||
}
|
||||
@@ -874,18 +874,6 @@ NodeParameters::add_on_set_parameters_callback(OnParametersSetCallbackType callb
|
||||
return handle;
|
||||
}
|
||||
|
||||
NodeParameters::OnParametersSetCallbackType
|
||||
NodeParameters::set_on_parameters_set_callback(OnParametersSetCallbackType callback)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||
|
||||
ParameterMutationRecursionGuard guard(parameter_modification_enabled_);
|
||||
|
||||
auto existing_callback = on_parameters_set_callback_;
|
||||
on_parameters_set_callback_ = callback;
|
||||
return existing_callback;
|
||||
}
|
||||
|
||||
const std::map<std::string, rclcpp::ParameterValue> &
|
||||
NodeParameters::get_parameter_overrides() const
|
||||
{
|
||||
|
||||
@@ -79,6 +79,7 @@ NodeOptions::operator=(const NodeOptions & other)
|
||||
this->allow_undeclared_parameters_ = other.allow_undeclared_parameters_;
|
||||
this->automatically_declare_parameters_from_overrides_ =
|
||||
other.automatically_declare_parameters_from_overrides_;
|
||||
this->node_options_.reset();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -92,7 +93,6 @@ NodeOptions::get_rcl_node_options() const
|
||||
*node_options_ = rcl_node_get_default_options();
|
||||
node_options_->allocator = this->allocator_;
|
||||
node_options_->use_global_arguments = this->use_global_arguments_;
|
||||
node_options_->domain_id = this->get_domain_id_from_env();
|
||||
node_options_->enable_rosout = this->enable_rosout_;
|
||||
|
||||
int c_argc = 0;
|
||||
@@ -176,7 +176,7 @@ NodeOptions::parameter_overrides(const std::vector<rclcpp::Parameter> & paramete
|
||||
bool
|
||||
NodeOptions::use_global_arguments() const
|
||||
{
|
||||
return this->node_options_->use_global_arguments;
|
||||
return this->use_global_arguments_;
|
||||
}
|
||||
|
||||
NodeOptions &
|
||||
@@ -322,36 +322,4 @@ NodeOptions::allocator(rcl_allocator_t allocator)
|
||||
return *this;
|
||||
}
|
||||
|
||||
// TODO(wjwwood): reuse rcutils_get_env() to avoid code duplication.
|
||||
// See also: https://github.com/ros2/rcl/issues/119
|
||||
size_t
|
||||
NodeOptions::get_domain_id_from_env() const
|
||||
{
|
||||
// Determine the domain id based on the options and the ROS_DOMAIN_ID env variable.
|
||||
size_t domain_id = std::numeric_limits<size_t>::max();
|
||||
char * ros_domain_id = nullptr;
|
||||
const char * env_var = "ROS_DOMAIN_ID";
|
||||
#ifndef _WIN32
|
||||
ros_domain_id = getenv(env_var);
|
||||
#else
|
||||
size_t ros_domain_id_size;
|
||||
_dupenv_s(&ros_domain_id, &ros_domain_id_size, env_var);
|
||||
#endif
|
||||
if (ros_domain_id) {
|
||||
uint32_t number = strtoul(ros_domain_id, NULL, 0);
|
||||
if (number == (std::numeric_limits<uint32_t>::max)()) {
|
||||
#ifdef _WIN32
|
||||
// free the ros_domain_id before throwing, if getenv was used on Windows
|
||||
free(ros_domain_id);
|
||||
#endif
|
||||
throw std::runtime_error("failed to interpret ROS_DOMAIN_ID as integral number");
|
||||
}
|
||||
domain_id = static_cast<size_t>(number);
|
||||
#ifdef _WIN32
|
||||
free(ros_domain_id);
|
||||
#endif
|
||||
}
|
||||
return domain_id;
|
||||
}
|
||||
|
||||
} // namespace rclcpp
|
||||
|
||||
@@ -63,17 +63,13 @@ Time::Time(int64_t nanoseconds, rcl_clock_type_t clock_type)
|
||||
rcl_time_.nanoseconds = nanoseconds;
|
||||
}
|
||||
|
||||
Time::Time(const Time & rhs)
|
||||
: rcl_time_(rhs.rcl_time_)
|
||||
{
|
||||
rcl_time_.nanoseconds = rhs.rcl_time_.nanoseconds;
|
||||
}
|
||||
Time::Time(const Time & rhs) = default;
|
||||
|
||||
Time::Time(
|
||||
const builtin_interfaces::msg::Time & time_msg,
|
||||
rcl_clock_type_t ros_time)
|
||||
rcl_clock_type_t clock_type)
|
||||
: rcl_time_(init_time_point(clock_type))
|
||||
{
|
||||
rcl_time_ = init_time_point(ros_time);
|
||||
if (time_msg.sec < 0) {
|
||||
throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
|
||||
}
|
||||
@@ -95,31 +91,25 @@ Time::~Time()
|
||||
Time::operator builtin_interfaces::msg::Time() const
|
||||
{
|
||||
builtin_interfaces::msg::Time msg_time;
|
||||
msg_time.sec = static_cast<std::int32_t>(RCL_NS_TO_S(rcl_time_.nanoseconds));
|
||||
msg_time.nanosec = static_cast<std::uint32_t>(rcl_time_.nanoseconds % (1000 * 1000 * 1000));
|
||||
constexpr rcl_time_point_value_t kRemainder = RCL_S_TO_NS(1);
|
||||
const auto result = std::div(rcl_time_.nanoseconds, kRemainder);
|
||||
if (result.rem >= 0) {
|
||||
msg_time.sec = static_cast<std::int32_t>(result.quot);
|
||||
msg_time.nanosec = static_cast<std::uint32_t>(result.rem);
|
||||
} else {
|
||||
msg_time.sec = static_cast<std::int32_t>(result.quot - 1);
|
||||
msg_time.nanosec = static_cast<std::uint32_t>(kRemainder + result.rem);
|
||||
}
|
||||
return msg_time;
|
||||
}
|
||||
|
||||
Time &
|
||||
Time::operator=(const Time & rhs)
|
||||
{
|
||||
rcl_time_ = rhs.rcl_time_;
|
||||
return *this;
|
||||
}
|
||||
Time::operator=(const Time & rhs) = default;
|
||||
|
||||
Time &
|
||||
Time::operator=(const builtin_interfaces::msg::Time & time_msg)
|
||||
{
|
||||
if (time_msg.sec < 0) {
|
||||
throw std::runtime_error("cannot store a negative time point in rclcpp::Time");
|
||||
}
|
||||
|
||||
|
||||
rcl_clock_type_t ros_time = RCL_ROS_TIME;
|
||||
rcl_time_ = init_time_point(ros_time); // TODO(tfoote) hard coded ROS here
|
||||
|
||||
rcl_time_.nanoseconds = RCL_S_TO_NS(static_cast<int64_t>(time_msg.sec));
|
||||
rcl_time_.nanoseconds += time_msg.nanosec;
|
||||
*this = Time(time_msg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,15 +61,11 @@ TimerBase::TimerBase(
|
||||
rcl_clock_t * clock_handle = clock_->get_clock_handle();
|
||||
{
|
||||
std::lock_guard<std::mutex> clock_guard(clock_->get_clock_mutex());
|
||||
if (
|
||||
rcl_timer_init(
|
||||
timer_handle_.get(), clock_handle, rcl_context.get(), period.count(), nullptr,
|
||||
rcl_get_default_allocator()) != RCL_RET_OK)
|
||||
{
|
||||
RCUTILS_LOG_ERROR_NAMED(
|
||||
"rclcpp",
|
||||
"Couldn't initialize rcl timer handle: %s\n", rcl_get_error_string().str);
|
||||
rcl_reset_error();
|
||||
rcl_ret_t ret = rcl_timer_init(
|
||||
timer_handle_.get(), clock_handle, rcl_context.get(), period.count(), nullptr,
|
||||
rcl_get_default_allocator());
|
||||
if (ret != RCL_RET_OK) {
|
||||
rclcpp::exceptions::throw_from_rcl_error(ret, "Couldn't initialize rcl timer handle");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,20 @@ rosidl_generate_interfaces(${PROJECT_NAME}_test_msgs
|
||||
SKIP_INSTALL
|
||||
)
|
||||
|
||||
ament_add_gtest(test_any_service_callback rclcpp/test_any_service_callback.cpp)
|
||||
if(TARGET test_any_service_callback)
|
||||
ament_target_dependencies(test_any_service_callback
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_any_service_callback ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_any_subscription_callback rclcpp/test_any_subscription_callback.cpp)
|
||||
if(TARGET test_any_subscription_callback)
|
||||
ament_target_dependencies(test_any_subscription_callback
|
||||
"test_msgs"
|
||||
)
|
||||
target_link_libraries(test_any_subscription_callback ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_client rclcpp/test_client.cpp)
|
||||
if(TARGET test_client)
|
||||
ament_target_dependencies(test_client
|
||||
@@ -39,6 +53,13 @@ if(TARGET test_create_timer)
|
||||
target_link_libraries(test_create_timer ${PROJECT_NAME})
|
||||
target_include_directories(test_create_timer PRIVATE rclcpp/)
|
||||
endif()
|
||||
ament_add_gtest(test_create_subscription rclcpp/test_create_subscription.cpp)
|
||||
if(TARGET test_create_subscription)
|
||||
target_link_libraries(test_create_subscription ${PROJECT_NAME})
|
||||
ament_target_dependencies(test_create_subscription
|
||||
"test_msgs"
|
||||
)
|
||||
endif()
|
||||
ament_add_gtest(test_expand_topic_or_service_name rclcpp/test_expand_topic_or_service_name.cpp)
|
||||
if(TARGET test_expand_topic_or_service_name)
|
||||
ament_target_dependencies(test_expand_topic_or_service_name
|
||||
@@ -115,6 +136,52 @@ ament_add_gtest(test_node_interfaces__get_node_interfaces
|
||||
if(TARGET test_node_interfaces__get_node_interfaces)
|
||||
target_link_libraries(test_node_interfaces__get_node_interfaces ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_base
|
||||
rclcpp/node_interfaces/test_node_base.cpp)
|
||||
if(TARGET test_node_interfaces__node_base)
|
||||
target_link_libraries(test_node_interfaces__node_base ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_clock
|
||||
rclcpp/node_interfaces/test_node_clock.cpp)
|
||||
if(TARGET test_node_interfaces__node_clock)
|
||||
target_link_libraries(test_node_interfaces__node_clock ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_graph
|
||||
rclcpp/node_interfaces/test_node_graph.cpp)
|
||||
if(TARGET test_node_interfaces__node_graph)
|
||||
ament_target_dependencies(
|
||||
test_node_interfaces__node_graph
|
||||
"test_msgs")
|
||||
target_link_libraries(test_node_interfaces__node_graph ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_parameters
|
||||
rclcpp/node_interfaces/test_node_parameters.cpp)
|
||||
if(TARGET test_node_interfaces__node_parameters)
|
||||
target_link_libraries(test_node_interfaces__node_parameters ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_services
|
||||
rclcpp/node_interfaces/test_node_services.cpp)
|
||||
if(TARGET test_node_interfaces__node_services)
|
||||
target_link_libraries(test_node_interfaces__node_services ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_timers
|
||||
rclcpp/node_interfaces/test_node_timers.cpp)
|
||||
if(TARGET test_node_interfaces__node_timers)
|
||||
target_link_libraries(test_node_interfaces__node_timers ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_topics
|
||||
rclcpp/node_interfaces/test_node_topics.cpp)
|
||||
if(TARGET test_node_interfaces__node_topics)
|
||||
ament_target_dependencies(
|
||||
test_node_interfaces__node_topics
|
||||
"test_msgs")
|
||||
target_link_libraries(test_node_interfaces__node_topics ${PROJECT_NAME})
|
||||
endif()
|
||||
ament_add_gtest(test_node_interfaces__node_waitables
|
||||
rclcpp/node_interfaces/test_node_waitables.cpp)
|
||||
if(TARGET test_node_interfaces__node_waitables)
|
||||
target_link_libraries(test_node_interfaces__node_waitables ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
# TODO(wjwwood): reenable these build failure tests when I can get Jenkins to ignore their output
|
||||
# rclcpp_add_build_failure_test(build_failure__get_node_topics_interface_const_ref_rclcpp_node
|
||||
@@ -397,6 +464,12 @@ if(TARGET test_guard_condition)
|
||||
target_link_libraries(test_guard_condition ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_timer_count rclcpp/test_timer_call_count.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_timer_count)
|
||||
target_link_libraries(test_timer_count ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
ament_add_gtest(test_wait_set rclcpp/test_wait_set.cpp
|
||||
APPEND_LIBRARY_DIRS "${append_library_dirs}")
|
||||
if(TARGET test_wait_set)
|
||||
|
||||
@@ -83,7 +83,7 @@ TEST_F(TestMultiThreadedExecutor, timer_over_take) {
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(last_mutex);
|
||||
double diff = std::abs((now - last).nanoseconds()) / 1.0e9;
|
||||
double diff = static_cast<double>(std::abs((now - last).nanoseconds())) / 1.0e9;
|
||||
last = now;
|
||||
|
||||
if (diff < PERIOD - TOLERANCE) {
|
||||
|
||||
60
rclcpp/test/rclcpp/node_interfaces/test_node_base.cpp
Normal file
60
rclcpp/test/rclcpp/node_interfaces/test_node_base.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2020 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 <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rcl/node_options.h"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
class TestNodeBase : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestNodeBase, construct_from_node)
|
||||
{
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
// This dynamic cast is not necessary for the unittest itself, but instead is used to ensure
|
||||
// the proper type is being tested and covered.
|
||||
auto * node_base =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeBase *>(node->get_node_base_interface().get());
|
||||
ASSERT_NE(nullptr, node_base);
|
||||
|
||||
EXPECT_STREQ("node", node_base->get_name());
|
||||
EXPECT_STREQ("/ns", node_base->get_namespace());
|
||||
|
||||
EXPECT_STREQ("/ns/node", node_base->get_fully_qualified_name());
|
||||
EXPECT_NE(nullptr, node_base->get_context());
|
||||
EXPECT_NE(nullptr, node_base->get_rcl_node_handle());
|
||||
EXPECT_NE(nullptr, node_base->get_shared_rcl_node_handle());
|
||||
|
||||
const auto * const_node_base = node_base;
|
||||
EXPECT_NE(nullptr, const_node_base->get_rcl_node_handle());
|
||||
EXPECT_NE(nullptr, const_node_base->get_shared_rcl_node_handle());
|
||||
}
|
||||
49
rclcpp/test/rclcpp/node_interfaces/test_node_clock.cpp
Normal file
49
rclcpp/test/rclcpp/node_interfaces/test_node_clock.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2020 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 <memory>
|
||||
|
||||
#include "rclcpp/node_interfaces/node_clock.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
|
||||
class TestNodeClock : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestNodeClock, construct_from_node)
|
||||
{
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
// This dynamic cast is not necessary for the unittest itself, but instead is used to ensure
|
||||
// the proper type is being tested and covered.
|
||||
auto * node_clock =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeClock *>(node->get_node_clock_interface().get());
|
||||
ASSERT_NE(nullptr, node_clock);
|
||||
EXPECT_NE(nullptr, node_clock->get_clock());
|
||||
|
||||
const auto * const_node_clock = node_clock;
|
||||
EXPECT_NE(nullptr, const_node_clock->get_clock());
|
||||
}
|
||||
186
rclcpp/test/rclcpp/node_interfaces/test_node_graph.cpp
Normal file
186
rclcpp/test/rclcpp/node_interfaces/test_node_graph.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
// Copyright 2020 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 <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "rcl/node_options.h"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/node_interfaces/node_base.hpp"
|
||||
#include "rclcpp/node_interfaces/node_graph.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "test_msgs/msg/empty.hpp"
|
||||
|
||||
class TestNodeGraph : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestNodeGraph, construct_from_node)
|
||||
{
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
// This dynamic cast is not necessary for the unittest itself, but instead is used to ensure
|
||||
// the proper type is being tested and covered.
|
||||
const auto * node_graph =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeGraph *>(node->get_node_graph_interface().get());
|
||||
ASSERT_NE(nullptr, node_graph);
|
||||
|
||||
auto topic_names_and_types = node_graph->get_topic_names_and_types(false);
|
||||
EXPECT_LT(0u, topic_names_and_types.size());
|
||||
|
||||
auto service_names_and_types = node_graph->get_service_names_and_types();
|
||||
EXPECT_LT(0u, service_names_and_types.size());
|
||||
|
||||
auto names = node_graph->get_node_names();
|
||||
EXPECT_EQ(1u, names.size());
|
||||
|
||||
auto names_and_namespaces = node_graph->get_node_names_and_namespaces();
|
||||
EXPECT_EQ(1u, names_and_namespaces.size());
|
||||
|
||||
EXPECT_EQ(0u, node_graph->count_publishers("not_a_topic"));
|
||||
EXPECT_EQ(0u, node_graph->count_subscribers("not_a_topic"));
|
||||
}
|
||||
|
||||
TEST_F(TestNodeGraph, get_topic_names_and_types)
|
||||
{
|
||||
auto node = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
const auto * node_graph =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeGraph *>(node->get_node_graph_interface().get());
|
||||
ASSERT_NE(nullptr, node_graph);
|
||||
auto topic_names_and_types = node_graph->get_topic_names_and_types();
|
||||
EXPECT_LT(0u, topic_names_and_types.size());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeGraph, get_service_names_and_types)
|
||||
{
|
||||
auto node = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
const auto * node_graph =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeGraph *>(node->get_node_graph_interface().get());
|
||||
ASSERT_NE(nullptr, node_graph);
|
||||
auto service_names_and_types = node_graph->get_service_names_and_types();
|
||||
EXPECT_LT(0u, service_names_and_types.size());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeGraph, get_service_names_and_types_by_node)
|
||||
{
|
||||
auto node1 = std::make_shared<rclcpp::Node>("node1", "ns");
|
||||
auto node2 = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
const auto * node_graph =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeGraph *>(node1->get_node_graph_interface().get());
|
||||
ASSERT_NE(nullptr, node_graph);
|
||||
|
||||
EXPECT_THROW(
|
||||
node_graph->get_service_names_and_types_by_node("not_a_node", "not_absolute_namespace"),
|
||||
std::runtime_error);
|
||||
auto service_names_and_types1 = node_graph->get_service_names_and_types_by_node("node1", "/ns");
|
||||
auto service_names_and_types2 = node_graph->get_service_names_and_types_by_node("node2", "/ns");
|
||||
EXPECT_EQ(service_names_and_types1.size(), service_names_and_types2.size());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeGraph, get_node_names_and_namespaces)
|
||||
{
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
const auto * node_graph =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeGraph *>(node->get_node_graph_interface().get());
|
||||
ASSERT_NE(nullptr, node_graph);
|
||||
|
||||
auto names_and_namespaces = node_graph->get_node_names_and_namespaces();
|
||||
EXPECT_EQ(1u, names_and_namespaces.size());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeGraph, notify_shutdown)
|
||||
{
|
||||
auto node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
auto * node_graph =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeGraph *>(node->get_node_graph_interface().get());
|
||||
ASSERT_NE(nullptr, node_graph);
|
||||
|
||||
EXPECT_NO_THROW(node_graph->notify_shutdown());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeGraph, wait_for_graph_change)
|
||||
{
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
auto * node_graph =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeGraph *>(node->get_node_graph_interface().get());
|
||||
ASSERT_NE(nullptr, node_graph);
|
||||
|
||||
EXPECT_NO_THROW(node_graph->notify_graph_change());
|
||||
EXPECT_THROW(
|
||||
node_graph->wait_for_graph_change(nullptr, std::chrono::milliseconds(1)),
|
||||
rclcpp::exceptions::InvalidEventError);
|
||||
|
||||
auto event = std::make_shared<rclcpp::Event>();
|
||||
EXPECT_THROW(
|
||||
node_graph->wait_for_graph_change(event, std::chrono::milliseconds(0)),
|
||||
rclcpp::exceptions::EventNotRegisteredError);
|
||||
}
|
||||
|
||||
TEST_F(TestNodeGraph, get_info_by_topic)
|
||||
{
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
const rclcpp::QoS publisher_qos(1);
|
||||
auto publisher = node->create_publisher<test_msgs::msg::Empty>("topic", publisher_qos);
|
||||
auto callback = [](const test_msgs::msg::Empty::SharedPtr) {};
|
||||
|
||||
const rclcpp::QoS subscriber_qos(10);
|
||||
auto subscription =
|
||||
node->create_subscription<test_msgs::msg::Empty>(
|
||||
"topic", subscriber_qos, std::move(callback));
|
||||
|
||||
const auto * node_graph =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeGraph *>(node->get_node_graph_interface().get());
|
||||
ASSERT_NE(nullptr, node_graph);
|
||||
|
||||
auto publishers = node_graph->get_publishers_info_by_topic("topic", false);
|
||||
ASSERT_EQ(1u, publishers.size());
|
||||
|
||||
auto publisher_endpoint_info = publishers[0];
|
||||
const auto const_publisher_endpoint_info = publisher_endpoint_info;
|
||||
EXPECT_STREQ("node", publisher_endpoint_info.node_name().c_str());
|
||||
EXPECT_STREQ("node", const_publisher_endpoint_info.node_name().c_str());
|
||||
EXPECT_STREQ("/ns", publisher_endpoint_info.node_namespace().c_str());
|
||||
EXPECT_STREQ("/ns", const_publisher_endpoint_info.node_namespace().c_str());
|
||||
EXPECT_STREQ("test_msgs/msg/Empty", publisher_endpoint_info.topic_type().c_str());
|
||||
EXPECT_STREQ("test_msgs/msg/Empty", const_publisher_endpoint_info.topic_type().c_str());
|
||||
EXPECT_EQ(rclcpp::EndpointType::Publisher, publisher_endpoint_info.endpoint_type());
|
||||
EXPECT_EQ(rclcpp::EndpointType::Publisher, const_publisher_endpoint_info.endpoint_type());
|
||||
|
||||
rclcpp::QoS actual_qos = publisher_endpoint_info.qos_profile();
|
||||
EXPECT_EQ(0u, actual_qos.get_rmw_qos_profile().depth);
|
||||
|
||||
rclcpp::QoS const_actual_qos = const_publisher_endpoint_info.qos_profile();
|
||||
EXPECT_EQ(0u, const_actual_qos.get_rmw_qos_profile().depth);
|
||||
|
||||
auto endpoint_gid = publisher_endpoint_info.endpoint_gid();
|
||||
auto const_endpoint_gid = const_publisher_endpoint_info.endpoint_gid();
|
||||
bool endpoint_gid_is_all_zeros = true;
|
||||
for (size_t i = 0; i < RMW_GID_STORAGE_SIZE; ++i) {
|
||||
endpoint_gid_is_all_zeros &= (endpoint_gid[i] == 0);
|
||||
EXPECT_EQ(endpoint_gid[i], const_endpoint_gid[i]);
|
||||
}
|
||||
EXPECT_FALSE(endpoint_gid_is_all_zeros);
|
||||
}
|
||||
89
rclcpp/test/rclcpp/node_interfaces/test_node_parameters.cpp
Normal file
89
rclcpp/test/rclcpp/node_interfaces/test_node_parameters.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
/**
|
||||
* NodeParameters is a complicated interface with lots of code, but it is tested elsewhere
|
||||
* very thoroughly. This currently just includes unittests for the currently uncovered
|
||||
* functionality.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/node_interfaces/node_parameters.hpp"
|
||||
|
||||
class TestNodeParameters : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestNodeParameters, list_parameters)
|
||||
{
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
// This dynamic cast is not necessary for the unittest itself, but instead is used to ensure
|
||||
// the proper type is being tested and covered.
|
||||
auto * node_parameters =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||
node->get_node_parameters_interface().get());
|
||||
ASSERT_NE(nullptr, node_parameters);
|
||||
|
||||
std::vector<std::string> prefixes;
|
||||
const auto list_result = node_parameters->list_parameters(prefixes, 1u);
|
||||
|
||||
// Currently the only default parameter is 'use_sim_time', but that may change.
|
||||
size_t number_of_parameters = list_result.names.size();
|
||||
EXPECT_GE(1u, number_of_parameters);
|
||||
|
||||
const std::string parameter_name = "new_parameter";
|
||||
const rclcpp::ParameterValue value(true);
|
||||
const rcl_interfaces::msg::ParameterDescriptor descriptor;
|
||||
const auto added_parameter_value =
|
||||
node_parameters->declare_parameter(parameter_name, value, descriptor, false);
|
||||
EXPECT_EQ(value.get<bool>(), added_parameter_value.get<bool>());
|
||||
|
||||
auto list_result2 = node_parameters->list_parameters(prefixes, 1u);
|
||||
EXPECT_EQ(number_of_parameters + 1u, list_result2.names.size());
|
||||
|
||||
EXPECT_NE(
|
||||
std::find(list_result2.names.begin(), list_result2.names.end(), parameter_name),
|
||||
list_result2.names.end());
|
||||
}
|
||||
|
||||
TEST_F(TestNodeParameters, parameter_overrides)
|
||||
{
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
auto * node_parameters =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeParameters *>(
|
||||
node->get_node_parameters_interface().get());
|
||||
ASSERT_NE(nullptr, node_parameters);
|
||||
|
||||
const auto & parameter_overrides = node_parameters->get_parameter_overrides();
|
||||
EXPECT_EQ(0u, parameter_overrides.size());
|
||||
}
|
||||
111
rclcpp/test/rclcpp/node_interfaces/test_node_services.cpp
Normal file
111
rclcpp/test/rclcpp/node_interfaces/test_node_services.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright 2020 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 <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rcl/node_options.h"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/node_interfaces/node_services.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
class TestService : public rclcpp::ServiceBase
|
||||
{
|
||||
public:
|
||||
explicit TestService(rclcpp::Node * node)
|
||||
: rclcpp::ServiceBase(node->get_node_base_interface()->get_shared_rcl_node_handle()) {}
|
||||
|
||||
std::shared_ptr<void> create_request() override {return nullptr;}
|
||||
std::shared_ptr<rmw_request_id_t> create_request_header() override {return nullptr;}
|
||||
void handle_request(std::shared_ptr<rmw_request_id_t>, std::shared_ptr<void>) override {}
|
||||
};
|
||||
|
||||
class TestClient : public rclcpp::ClientBase
|
||||
{
|
||||
public:
|
||||
explicit TestClient(rclcpp::Node * node)
|
||||
: rclcpp::ClientBase(node->get_node_base_interface().get(), node->get_node_graph_interface()) {}
|
||||
|
||||
std::shared_ptr<void> create_response() override {return nullptr;}
|
||||
std::shared_ptr<rmw_request_id_t> create_request_header() override {return nullptr;}
|
||||
void handle_response(
|
||||
std::shared_ptr<rmw_request_id_t>, std::shared_ptr<void>) override {}
|
||||
};
|
||||
|
||||
class TestNodeService : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestNodeService, add_service)
|
||||
{
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
// This dynamic cast is not necessary for the unittest itself, but instead is used to ensure
|
||||
// the proper type is being tested and covered.
|
||||
auto * node_services =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeServices *>(
|
||||
node->get_node_services_interface().get());
|
||||
ASSERT_NE(nullptr, node_services);
|
||||
|
||||
auto service = std::make_shared<TestService>(node.get());
|
||||
auto callback_group = node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
EXPECT_NO_THROW(
|
||||
node_services->add_service(service, callback_group));
|
||||
|
||||
// Check that adding a service from node to a callback group of different_node throws exception.
|
||||
std::shared_ptr<rclcpp::Node> different_node = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
|
||||
auto callback_group_in_different_node =
|
||||
different_node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
EXPECT_THROW(
|
||||
node_services->add_service(service, callback_group_in_different_node),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST_F(TestNodeService, add_client)
|
||||
{
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
// This dynamic cast is not necessary for the unittest itself, but instead is used to ensure
|
||||
// the proper type is being tested and covered.
|
||||
auto * node_services =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeServices *>(
|
||||
node->get_node_services_interface().get());
|
||||
ASSERT_NE(nullptr, node_services);
|
||||
|
||||
auto client = std::make_shared<TestClient>(node.get());
|
||||
auto callback_group = node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
EXPECT_NO_THROW(node_services->add_client(client, callback_group));
|
||||
|
||||
// Check that adding a client from node to a callback group of different_node throws exception.
|
||||
std::shared_ptr<rclcpp::Node> different_node = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
|
||||
auto callback_group_in_different_node =
|
||||
different_node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
EXPECT_THROW(
|
||||
node_services->add_client(client, callback_group_in_different_node),
|
||||
std::runtime_error);
|
||||
}
|
||||
71
rclcpp/test/rclcpp/node_interfaces/test_node_timers.cpp
Normal file
71
rclcpp/test/rclcpp/node_interfaces/test_node_timers.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2020 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 <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rcl/node_options.h"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/node_interfaces/node_timers.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
class TestTimer : public rclcpp::TimerBase
|
||||
{
|
||||
public:
|
||||
explicit TestTimer(rclcpp::Node * node)
|
||||
: TimerBase(node->get_clock(), std::chrono::nanoseconds(1),
|
||||
node->get_node_base_interface()->get_context()) {}
|
||||
|
||||
void execute_callback() override {}
|
||||
bool is_steady() override {return false;}
|
||||
};
|
||||
|
||||
class TestNodeTimers : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestNodeTimers, add_timer)
|
||||
{
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
// This dynamic cast is not necessary for the unittest itself, but instead is used to ensure
|
||||
// the proper type is being tested and covered.
|
||||
auto node_timers =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeTimers *>(node->get_node_timers_interface().get());
|
||||
ASSERT_NE(nullptr, node_timers);
|
||||
auto timer = std::make_shared<TestTimer>(node.get());
|
||||
auto callback_group = node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
EXPECT_NO_THROW(node_timers->add_timer(timer, callback_group));
|
||||
|
||||
// Check that adding timer from node to callback group in different_node throws exception.
|
||||
std::shared_ptr<rclcpp::Node> different_node = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
|
||||
auto callback_group_in_different_node =
|
||||
different_node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
EXPECT_THROW(
|
||||
node_timers->add_timer(timer, callback_group_in_different_node),
|
||||
std::runtime_error);
|
||||
}
|
||||
129
rclcpp/test/rclcpp/node_interfaces/test_node_topics.cpp
Normal file
129
rclcpp/test/rclcpp/node_interfaces/test_node_topics.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
// Copyright 2020 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 <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "rcl/node_options.h"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/node_interfaces/node_topics.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "test_msgs/msg/empty.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const rosidl_message_type_support_t EmptyTypeSupport()
|
||||
{
|
||||
return *rosidl_typesupport_cpp::get_message_type_support_handle<test_msgs::msg::Empty>();
|
||||
}
|
||||
|
||||
const rcl_publisher_options_t PublisherOptions()
|
||||
{
|
||||
return rclcpp::PublisherOptionsWithAllocator<std::allocator<void>>().template
|
||||
to_rcl_publisher_options<test_msgs::msg::Empty>(rclcpp::QoS(10));
|
||||
}
|
||||
|
||||
const rcl_subscription_options_t SubscriptionOptions()
|
||||
{
|
||||
return rclcpp::SubscriptionOptionsWithAllocator<std::allocator<void>>().template
|
||||
to_rcl_subscription_options<test_msgs::msg::Empty>(rclcpp::QoS(10));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class TestPublisher : public rclcpp::PublisherBase
|
||||
{
|
||||
public:
|
||||
explicit TestPublisher(rclcpp::Node * node)
|
||||
: rclcpp::PublisherBase(
|
||||
node->get_node_base_interface().get(), "topic", EmptyTypeSupport(), PublisherOptions()) {}
|
||||
};
|
||||
|
||||
class TestSubscription : public rclcpp::SubscriptionBase
|
||||
{
|
||||
public:
|
||||
explicit TestSubscription(rclcpp::Node * node)
|
||||
: rclcpp::SubscriptionBase(
|
||||
node->get_node_base_interface().get(), EmptyTypeSupport(), "topic", SubscriptionOptions()) {}
|
||||
std::shared_ptr<void> create_message() override {return nullptr;}
|
||||
|
||||
std::shared_ptr<rclcpp::SerializedMessage>
|
||||
create_serialized_message() override {return nullptr;}
|
||||
|
||||
void handle_message(std::shared_ptr<void> &, const rclcpp::MessageInfo &) override {}
|
||||
void handle_loaned_message(void *, const rclcpp::MessageInfo &) override {}
|
||||
void return_message(std::shared_ptr<void> &) override {}
|
||||
void return_serialized_message(std::shared_ptr<rclcpp::SerializedMessage> &) override {}
|
||||
};
|
||||
|
||||
class TestNodeTopics : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestNodeTopics, add_publisher)
|
||||
{
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
// This dynamic cast is not necessary for the unittest itself, but instead is used to ensure
|
||||
// the proper type is being tested and covered.
|
||||
auto * node_topics =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeTopics *>(node->get_node_topics_interface().get());
|
||||
ASSERT_NE(nullptr, node_topics);
|
||||
auto publisher = std::make_shared<TestPublisher>(node.get());
|
||||
auto callback_group = node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
EXPECT_NO_THROW(node_topics->add_publisher(publisher, callback_group));
|
||||
|
||||
// Check that adding publisher from node to a callback group in different_node throws exception.
|
||||
std::shared_ptr<rclcpp::Node> different_node = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
|
||||
auto callback_group_in_different_node =
|
||||
different_node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
EXPECT_THROW(
|
||||
node_topics->add_publisher(publisher, callback_group_in_different_node),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST_F(TestNodeTopics, add_subscription)
|
||||
{
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
auto * node_topics =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeTopics *>(node->get_node_topics_interface().get());
|
||||
ASSERT_NE(nullptr, node_topics);
|
||||
auto subscription = std::make_shared<TestSubscription>(node.get());
|
||||
auto callback_group = node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
EXPECT_NO_THROW(node_topics->add_subscription(subscription, callback_group));
|
||||
|
||||
// Check that adding subscription from node to callback group in different_node throws exception.
|
||||
std::shared_ptr<rclcpp::Node> different_node = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
|
||||
auto callback_group_in_different_node =
|
||||
different_node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
EXPECT_THROW(
|
||||
node_topics->add_subscription(subscription, callback_group_in_different_node),
|
||||
std::runtime_error);
|
||||
}
|
||||
68
rclcpp/test/rclcpp/node_interfaces/test_node_waitables.cpp
Normal file
68
rclcpp/test/rclcpp/node_interfaces/test_node_waitables.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright 2020 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 <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rcl/node_options.h"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/node_interfaces/node_waitables.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
class TestWaitable : public rclcpp::Waitable
|
||||
{
|
||||
public:
|
||||
bool add_to_wait_set(rcl_wait_set_t *) override {return false;}
|
||||
bool is_ready(rcl_wait_set_t *) override {return false;}
|
||||
void execute() override {}
|
||||
};
|
||||
|
||||
class TestNodeWaitables : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
void TearDown()
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestNodeWaitables, add_remove_waitable)
|
||||
{
|
||||
std::shared_ptr<rclcpp::Node> node = std::make_shared<rclcpp::Node>("node", "ns");
|
||||
|
||||
auto * node_waitables =
|
||||
dynamic_cast<rclcpp::node_interfaces::NodeWaitables *>(
|
||||
node->get_node_waitables_interface().get());
|
||||
ASSERT_NE(nullptr, node_waitables);
|
||||
|
||||
std::shared_ptr<rclcpp::Node> node2 = std::make_shared<rclcpp::Node>("node2", "ns");
|
||||
|
||||
auto callback_group1 = node->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
auto callback_group2 = node2->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
|
||||
auto waitable = std::make_shared<TestWaitable>();
|
||||
EXPECT_NO_THROW(
|
||||
node_waitables->add_waitable(waitable, callback_group1));
|
||||
EXPECT_THROW(
|
||||
node_waitables->add_waitable(waitable, callback_group2),
|
||||
std::runtime_error);
|
||||
EXPECT_NO_THROW(node_waitables->remove_waitable(waitable, callback_group1));
|
||||
EXPECT_NO_THROW(node_waitables->remove_waitable(waitable, callback_group2));
|
||||
}
|
||||
78
rclcpp/test/rclcpp/test_any_service_callback.cpp
Normal file
78
rclcpp/test/rclcpp/test_any_service_callback.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
// This file includes basic API tests for the AnyServiceCallback class.
|
||||
// It is also tested in test_externally_defined_services.cpp
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/any_service_callback.hpp"
|
||||
#include "test_msgs/srv/empty.hpp"
|
||||
#include "test_msgs/srv/empty.h"
|
||||
|
||||
class TestAnyServiceCallback : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp()
|
||||
{
|
||||
request_header_ = std::make_shared<rmw_request_id_t>();
|
||||
request_ = std::make_shared<test_msgs::srv::Empty::Request>();
|
||||
response_ = std::make_shared<test_msgs::srv::Empty::Response>();
|
||||
}
|
||||
|
||||
protected:
|
||||
rclcpp::AnyServiceCallback<test_msgs::srv::Empty> any_service_callback_;
|
||||
std::shared_ptr<rmw_request_id_t> request_header_;
|
||||
std::shared_ptr<test_msgs::srv::Empty::Request> request_;
|
||||
std::shared_ptr<test_msgs::srv::Empty::Response> response_;
|
||||
};
|
||||
|
||||
TEST_F(TestAnyServiceCallback, no_set_and_dispatch_throw) {
|
||||
EXPECT_THROW(
|
||||
any_service_callback_.dispatch(request_header_, request_, response_),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST_F(TestAnyServiceCallback, set_and_dispatch_no_header) {
|
||||
int callback_calls = 0;
|
||||
auto callback = [&callback_calls](const std::shared_ptr<test_msgs::srv::Empty::Request>,
|
||||
std::shared_ptr<test_msgs::srv::Empty::Response>) {
|
||||
callback_calls++;
|
||||
};
|
||||
|
||||
any_service_callback_.set(callback);
|
||||
EXPECT_NO_THROW(
|
||||
any_service_callback_.dispatch(request_header_, request_, response_));
|
||||
EXPECT_EQ(callback_calls, 1);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TestAnyServiceCallback, set_and_dispatch_header) {
|
||||
int callback_with_header_calls = 0;
|
||||
auto callback_with_header =
|
||||
[&callback_with_header_calls](const std::shared_ptr<rmw_request_id_t>,
|
||||
const std::shared_ptr<test_msgs::srv::Empty::Request>,
|
||||
std::shared_ptr<test_msgs::srv::Empty::Response>) {
|
||||
callback_with_header_calls++;
|
||||
};
|
||||
|
||||
any_service_callback_.set(callback_with_header);
|
||||
EXPECT_NO_THROW(
|
||||
any_service_callback_.dispatch(request_header_, request_, response_));
|
||||
EXPECT_EQ(callback_with_header_calls, 1);
|
||||
}
|
||||
205
rclcpp/test/rclcpp/test_any_subscription_callback.cpp
Normal file
205
rclcpp/test/rclcpp/test_any_subscription_callback.cpp
Normal file
@@ -0,0 +1,205 @@
|
||||
// Copyright 2020 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 <functional>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "rclcpp/any_subscription_callback.hpp"
|
||||
#include "test_msgs/msg/empty.hpp"
|
||||
#include "test_msgs/msg/empty.h"
|
||||
|
||||
class TestAnySubscriptionCallback : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
TestAnySubscriptionCallback()
|
||||
: any_subscription_callback_(allocator_) {}
|
||||
void SetUp()
|
||||
{
|
||||
msg_shared_ptr_ = std::make_shared<test_msgs::msg::Empty>();
|
||||
msg_const_shared_ptr_ = std::make_shared<const test_msgs::msg::Empty>();
|
||||
msg_unique_ptr_ = std::make_unique<test_msgs::msg::Empty>();
|
||||
}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<std::allocator<void>> allocator_;
|
||||
rclcpp::AnySubscriptionCallback<test_msgs::msg::Empty, std::allocator<void>>
|
||||
any_subscription_callback_;
|
||||
|
||||
std::shared_ptr<test_msgs::msg::Empty> msg_shared_ptr_;
|
||||
std::shared_ptr<const test_msgs::msg::Empty> msg_const_shared_ptr_;
|
||||
std::unique_ptr<test_msgs::msg::Empty> msg_unique_ptr_;
|
||||
rclcpp::MessageInfo message_info_;
|
||||
};
|
||||
|
||||
TEST_F(TestAnySubscriptionCallback, construct_destruct) {
|
||||
}
|
||||
|
||||
TEST_F(TestAnySubscriptionCallback, unset_dispatch_throw) {
|
||||
EXPECT_THROW(
|
||||
any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_),
|
||||
std::runtime_error);
|
||||
EXPECT_THROW(
|
||||
any_subscription_callback_.dispatch_intra_process(msg_const_shared_ptr_, message_info_),
|
||||
std::runtime_error);
|
||||
EXPECT_THROW(
|
||||
any_subscription_callback_.dispatch_intra_process(std::move(msg_unique_ptr_), message_info_),
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST_F(TestAnySubscriptionCallback, set_dispatch_shared_ptr) {
|
||||
int callback_count = 0;
|
||||
auto shared_ptr_callback = [&callback_count](
|
||||
const std::shared_ptr<test_msgs::msg::Empty>) {
|
||||
callback_count++;
|
||||
};
|
||||
|
||||
any_subscription_callback_.set(shared_ptr_callback);
|
||||
EXPECT_NO_THROW(any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_));
|
||||
EXPECT_EQ(callback_count, 1);
|
||||
|
||||
// Can't convert ConstSharedPtr to SharedPtr
|
||||
EXPECT_THROW(
|
||||
any_subscription_callback_.dispatch_intra_process(msg_const_shared_ptr_, message_info_),
|
||||
std::runtime_error);
|
||||
EXPECT_EQ(callback_count, 1);
|
||||
|
||||
// Promotes Unique into SharedPtr
|
||||
EXPECT_NO_THROW(
|
||||
any_subscription_callback_.dispatch_intra_process(std::move(msg_unique_ptr_), message_info_));
|
||||
EXPECT_EQ(callback_count, 2);
|
||||
}
|
||||
|
||||
TEST_F(TestAnySubscriptionCallback, set_dispatch_shared_ptr_w_info) {
|
||||
int callback_count = 0;
|
||||
auto shared_ptr_w_info_callback = [&callback_count](
|
||||
const std::shared_ptr<test_msgs::msg::Empty>, const rclcpp::MessageInfo &) {
|
||||
callback_count++;
|
||||
};
|
||||
|
||||
any_subscription_callback_.set(shared_ptr_w_info_callback);
|
||||
|
||||
EXPECT_NO_THROW(any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_));
|
||||
EXPECT_EQ(callback_count, 1);
|
||||
|
||||
// Can't convert ConstSharedPtr to SharedPtr
|
||||
EXPECT_THROW(
|
||||
any_subscription_callback_.dispatch_intra_process(msg_const_shared_ptr_, message_info_),
|
||||
std::runtime_error);
|
||||
EXPECT_EQ(callback_count, 1);
|
||||
|
||||
// Promotes Unique into SharedPtr
|
||||
EXPECT_NO_THROW(
|
||||
any_subscription_callback_.dispatch_intra_process(std::move(msg_unique_ptr_), message_info_));
|
||||
EXPECT_EQ(callback_count, 2);
|
||||
}
|
||||
|
||||
TEST_F(TestAnySubscriptionCallback, set_dispatch_const_shared_ptr) {
|
||||
int callback_count = 0;
|
||||
auto const_shared_ptr_callback = [&callback_count](
|
||||
std::shared_ptr<const test_msgs::msg::Empty>) {
|
||||
callback_count++;
|
||||
};
|
||||
|
||||
any_subscription_callback_.set(const_shared_ptr_callback);
|
||||
|
||||
// Ok to promote shared_ptr to ConstSharedPtr
|
||||
EXPECT_NO_THROW(any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_));
|
||||
EXPECT_EQ(callback_count, 1);
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
any_subscription_callback_.dispatch_intra_process(msg_const_shared_ptr_, message_info_));
|
||||
EXPECT_EQ(callback_count, 2);
|
||||
|
||||
// Not allowed to convert unique_ptr to const shared_ptr
|
||||
EXPECT_THROW(
|
||||
any_subscription_callback_.dispatch_intra_process(std::move(msg_unique_ptr_), message_info_),
|
||||
std::runtime_error);
|
||||
EXPECT_EQ(callback_count, 2);
|
||||
}
|
||||
|
||||
TEST_F(TestAnySubscriptionCallback, set_dispatch_const_shared_ptr_w_info) {
|
||||
int callback_count = 0;
|
||||
auto const_shared_ptr_callback = [&callback_count](
|
||||
std::shared_ptr<const test_msgs::msg::Empty>, const rclcpp::MessageInfo &) {
|
||||
callback_count++;
|
||||
};
|
||||
|
||||
any_subscription_callback_.set(
|
||||
std::move(const_shared_ptr_callback));
|
||||
|
||||
// Ok to promote shared_ptr to ConstSharedPtr
|
||||
EXPECT_NO_THROW(any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_));
|
||||
EXPECT_EQ(callback_count, 1);
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
any_subscription_callback_.dispatch_intra_process(msg_const_shared_ptr_, message_info_));
|
||||
EXPECT_EQ(callback_count, 2);
|
||||
|
||||
// Not allowed to convert unique_ptr to const shared_ptr
|
||||
EXPECT_THROW(
|
||||
any_subscription_callback_.dispatch_intra_process(std::move(msg_unique_ptr_), message_info_),
|
||||
std::runtime_error);
|
||||
EXPECT_EQ(callback_count, 2);
|
||||
}
|
||||
|
||||
TEST_F(TestAnySubscriptionCallback, set_dispatch_unique_ptr) {
|
||||
int callback_count = 0;
|
||||
auto unique_ptr_callback = [&callback_count](
|
||||
std::unique_ptr<test_msgs::msg::Empty>) {
|
||||
callback_count++;
|
||||
};
|
||||
|
||||
any_subscription_callback_.set(unique_ptr_callback);
|
||||
|
||||
// Message is copied into unique_ptr
|
||||
EXPECT_NO_THROW(any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_));
|
||||
EXPECT_EQ(callback_count, 1);
|
||||
|
||||
EXPECT_THROW(
|
||||
any_subscription_callback_.dispatch_intra_process(msg_const_shared_ptr_, message_info_),
|
||||
std::runtime_error);
|
||||
EXPECT_EQ(callback_count, 1);
|
||||
|
||||
// Unique_ptr is_moved
|
||||
EXPECT_NO_THROW(
|
||||
any_subscription_callback_.dispatch_intra_process(std::move(msg_unique_ptr_), message_info_));
|
||||
EXPECT_EQ(callback_count, 2);
|
||||
}
|
||||
|
||||
TEST_F(TestAnySubscriptionCallback, set_dispatch_unique_ptr_w_info) {
|
||||
int callback_count = 0;
|
||||
auto unique_ptr_callback = [&callback_count](
|
||||
std::unique_ptr<test_msgs::msg::Empty>, const rclcpp::MessageInfo &) {
|
||||
callback_count++;
|
||||
};
|
||||
|
||||
any_subscription_callback_.set(unique_ptr_callback);
|
||||
|
||||
// Message is copied into unique_ptr
|
||||
EXPECT_NO_THROW(any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_));
|
||||
EXPECT_EQ(callback_count, 1);
|
||||
|
||||
EXPECT_THROW(
|
||||
any_subscription_callback_.dispatch_intra_process(msg_const_shared_ptr_, message_info_),
|
||||
std::runtime_error);
|
||||
EXPECT_EQ(callback_count, 1);
|
||||
|
||||
// Unique_ptr is_moved
|
||||
EXPECT_NO_THROW(
|
||||
any_subscription_callback_.dispatch_intra_process(std::move(msg_unique_ptr_), message_info_));
|
||||
EXPECT_EQ(callback_count, 2);
|
||||
}
|
||||
67
rclcpp/test/rclcpp/test_create_subscription.cpp
Normal file
67
rclcpp/test/rclcpp/test_create_subscription.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2020 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 <memory>
|
||||
|
||||
#include "rclcpp/create_subscription.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "test_msgs/msg/empty.hpp"
|
||||
#include "test_msgs/msg/empty.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
class TestCreateSubscription : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
void SetUp() override
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TestCreateSubscription, create) {
|
||||
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns");
|
||||
const rclcpp::QoS qos(10);
|
||||
auto options = rclcpp::SubscriptionOptions();
|
||||
auto callback = [](const test_msgs::msg::Empty::SharedPtr) {};
|
||||
auto subscription =
|
||||
rclcpp::create_subscription<test_msgs::msg::Empty>(node, "topic_name", qos, callback, options);
|
||||
|
||||
ASSERT_NE(nullptr, subscription);
|
||||
EXPECT_STREQ("/ns/topic_name", subscription->get_topic_name());
|
||||
}
|
||||
|
||||
TEST_F(TestCreateSubscription, create_with_statistics) {
|
||||
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns");
|
||||
const rclcpp::QoS qos(10);
|
||||
auto options = rclcpp::SubscriptionOptions();
|
||||
options.topic_stats_options.state = rclcpp::TopicStatisticsState::Enable;
|
||||
options.topic_stats_options.publish_topic = "topic_statistics";
|
||||
options.topic_stats_options.publish_period = 5min;
|
||||
|
||||
auto callback = [](const test_msgs::msg::Empty::SharedPtr) {};
|
||||
auto subscription =
|
||||
rclcpp::create_subscription<test_msgs::msg::Empty>(node, "topic_name", qos, callback, options);
|
||||
|
||||
ASSERT_NE(nullptr, subscription);
|
||||
EXPECT_STREQ("/ns/topic_name", subscription->get_topic_name());
|
||||
}
|
||||
@@ -32,11 +32,7 @@ class TestDuration : public ::testing::Test
|
||||
{
|
||||
};
|
||||
|
||||
// TEST(TestDuration, conversions) {
|
||||
// TODO(tfoote) Implement conversion methods
|
||||
// }
|
||||
|
||||
TEST(TestDuration, operators) {
|
||||
TEST_F(TestDuration, operators) {
|
||||
rclcpp::Duration old(1, 0);
|
||||
rclcpp::Duration young(2, 0);
|
||||
|
||||
@@ -67,7 +63,7 @@ TEST(TestDuration, operators) {
|
||||
EXPECT_TRUE(time == assignment_op_duration);
|
||||
}
|
||||
|
||||
TEST(TestDuration, chrono_overloads) {
|
||||
TEST_F(TestDuration, chrono_overloads) {
|
||||
int64_t ns = 123456789l;
|
||||
auto chrono_ns = std::chrono::nanoseconds(ns);
|
||||
auto d1 = rclcpp::Duration(ns);
|
||||
@@ -86,7 +82,7 @@ TEST(TestDuration, chrono_overloads) {
|
||||
EXPECT_EQ(chrono_float_seconds, d5.to_chrono<decltype(chrono_float_seconds)>());
|
||||
}
|
||||
|
||||
TEST(TestDuration, overflows) {
|
||||
TEST_F(TestDuration, overflows) {
|
||||
rclcpp::Duration max(std::numeric_limits<rcl_duration_value_t>::max());
|
||||
rclcpp::Duration min(std::numeric_limits<rcl_duration_value_t>::min());
|
||||
|
||||
@@ -107,7 +103,7 @@ TEST(TestDuration, overflows) {
|
||||
EXPECT_THROW(base_d_neg * 4, std::underflow_error);
|
||||
}
|
||||
|
||||
TEST(TestDuration, negative_duration) {
|
||||
TEST_F(TestDuration, negative_duration) {
|
||||
rclcpp::Duration assignable_duration = rclcpp::Duration(0) - rclcpp::Duration(5, 0);
|
||||
|
||||
{
|
||||
@@ -130,7 +126,7 @@ TEST(TestDuration, negative_duration) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestDuration, maximum_duration) {
|
||||
TEST_F(TestDuration, maximum_duration) {
|
||||
rclcpp::Duration max_duration = rclcpp::Duration::max();
|
||||
rclcpp::Duration max(std::numeric_limits<int32_t>::max(), 999999999);
|
||||
|
||||
@@ -138,18 +134,105 @@ TEST(TestDuration, maximum_duration) {
|
||||
}
|
||||
|
||||
static const int64_t HALF_SEC_IN_NS = 500 * 1000 * 1000;
|
||||
static const int64_t ONE_SEC_IN_NS = 1000 * 1000 * 1000;
|
||||
static const int64_t ONE_AND_HALF_SEC_IN_NS = 3 * HALF_SEC_IN_NS;
|
||||
|
||||
TEST(TestDuration, from_seconds) {
|
||||
TEST_F(TestDuration, from_seconds) {
|
||||
EXPECT_EQ(rclcpp::Duration(0), rclcpp::Duration::from_seconds(0.0));
|
||||
EXPECT_EQ(rclcpp::Duration(0), rclcpp::Duration::from_seconds(0));
|
||||
EXPECT_EQ(rclcpp::Duration(1, HALF_SEC_IN_NS), rclcpp::Duration::from_seconds(1.5));
|
||||
EXPECT_EQ(rclcpp::Duration(-ONE_AND_HALF_SEC_IN_NS), rclcpp::Duration::from_seconds(-1.5));
|
||||
}
|
||||
|
||||
TEST(TestDuration, std_chrono_constructors) {
|
||||
TEST_F(TestDuration, std_chrono_constructors) {
|
||||
EXPECT_EQ(rclcpp::Duration(0), rclcpp::Duration(0.0s));
|
||||
EXPECT_EQ(rclcpp::Duration(0), rclcpp::Duration(0s));
|
||||
EXPECT_EQ(rclcpp::Duration(1, HALF_SEC_IN_NS), rclcpp::Duration(1.5s));
|
||||
EXPECT_EQ(rclcpp::Duration(-1, 0), rclcpp::Duration(-1s));
|
||||
}
|
||||
|
||||
TEST_F(TestDuration, conversions) {
|
||||
{
|
||||
const rclcpp::Duration duration(HALF_SEC_IN_NS);
|
||||
const auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, 0);
|
||||
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), HALF_SEC_IN_NS);
|
||||
|
||||
const auto rmw_time = duration.to_rmw_time();
|
||||
EXPECT_EQ(rmw_time.sec, 0u);
|
||||
EXPECT_EQ(rmw_time.nsec, static_cast<uint64_t>(HALF_SEC_IN_NS));
|
||||
|
||||
const auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Duration duration(ONE_SEC_IN_NS);
|
||||
const auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, 1);
|
||||
EXPECT_EQ(duration_msg.nanosec, 0u);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), ONE_SEC_IN_NS);
|
||||
|
||||
const auto rmw_time = duration.to_rmw_time();
|
||||
EXPECT_EQ(rmw_time.sec, 1u);
|
||||
EXPECT_EQ(rmw_time.nsec, 0u);
|
||||
|
||||
const auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), ONE_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Duration duration(ONE_AND_HALF_SEC_IN_NS);
|
||||
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, 1);
|
||||
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), ONE_AND_HALF_SEC_IN_NS);
|
||||
|
||||
auto rmw_time = duration.to_rmw_time();
|
||||
EXPECT_EQ(rmw_time.sec, 1u);
|
||||
EXPECT_EQ(rmw_time.nsec, static_cast<uint64_t>(HALF_SEC_IN_NS));
|
||||
|
||||
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), ONE_AND_HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
rclcpp::Duration duration(-HALF_SEC_IN_NS);
|
||||
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, -1);
|
||||
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), -HALF_SEC_IN_NS);
|
||||
|
||||
EXPECT_THROW(duration.to_rmw_time(), std::runtime_error);
|
||||
|
||||
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), -HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
rclcpp::Duration duration(-ONE_SEC_IN_NS);
|
||||
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, -1);
|
||||
EXPECT_EQ(duration_msg.nanosec, 0u);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), -ONE_SEC_IN_NS);
|
||||
|
||||
EXPECT_THROW(duration.to_rmw_time(), std::runtime_error);
|
||||
|
||||
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), -ONE_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
rclcpp::Duration duration(-ONE_AND_HALF_SEC_IN_NS);
|
||||
auto duration_msg = static_cast<builtin_interfaces::msg::Duration>(duration);
|
||||
EXPECT_EQ(duration_msg.sec, -2);
|
||||
EXPECT_EQ(duration_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Duration(duration_msg).nanoseconds(), -ONE_AND_HALF_SEC_IN_NS);
|
||||
|
||||
EXPECT_THROW(duration.to_rmw_time(), std::runtime_error);
|
||||
|
||||
auto chrono_duration = duration.to_chrono<std::chrono::nanoseconds>();
|
||||
EXPECT_EQ(chrono_duration.count(), -ONE_AND_HALF_SEC_IN_NS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rclcpp/logger.hpp"
|
||||
#include "rclcpp/logging.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
|
||||
TEST(TestLogger, factory_functions) {
|
||||
rclcpp::Logger logger = rclcpp::get_logger("test_logger");
|
||||
@@ -33,3 +35,15 @@ TEST(TestLogger, hierarchy) {
|
||||
rclcpp::Logger subsublogger = sublogger.get_child("grandchild");
|
||||
EXPECT_STREQ("test_logger.child.grandchild", subsublogger.get_name());
|
||||
}
|
||||
|
||||
TEST(TestLogger, get_node_logger) {
|
||||
rclcpp::init(0, nullptr);
|
||||
auto node = std::make_shared<rclcpp::Node>("my_node", "/ns");
|
||||
auto node_base = rclcpp::node_interfaces::get_node_base_interface(node);
|
||||
auto logger = rclcpp::get_node_logger(node_base->get_rcl_node_handle());
|
||||
EXPECT_STREQ(logger.get_name(), "ns.my_node");
|
||||
|
||||
logger = rclcpp::get_node_logger(nullptr);
|
||||
EXPECT_STREQ(logger.get_name(), "rclcpp");
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
|
||||
@@ -2329,206 +2329,6 @@ TEST_F(TestNode, get_parameter_types_undeclared_parameters_allowed) {
|
||||
}
|
||||
}
|
||||
|
||||
// suppress deprecated function test warnings
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
// test that it is possible to call get_parameter within the set_callback
|
||||
TEST_F(TestNode, set_on_parameters_set_callback_get_parameter) {
|
||||
auto node = std::make_shared<rclcpp::Node>("test_set_callback_get_parameter_node"_unq);
|
||||
|
||||
int64_t intval = node->declare_parameter("intparam", 42);
|
||||
EXPECT_EQ(intval, 42);
|
||||
double floatval = node->declare_parameter("floatparam", 5.4);
|
||||
EXPECT_EQ(floatval, 5.4);
|
||||
|
||||
double floatout;
|
||||
RCLCPP_SCOPE_EXIT({node->set_on_parameters_set_callback(nullptr);}); // always reset
|
||||
auto on_set_parameters =
|
||||
[&node, &floatout](const std::vector<rclcpp::Parameter> & parameters) {
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
result.successful = true;
|
||||
if (parameters.size() != 1) {
|
||||
result.successful = false;
|
||||
}
|
||||
|
||||
if (parameters[0].get_value<int>() != 40) {
|
||||
result.successful = false;
|
||||
}
|
||||
|
||||
rclcpp::Parameter floatparam = node->get_parameter("floatparam");
|
||||
if (floatparam.get_value<double>() != 5.4) {
|
||||
result.successful = false;
|
||||
}
|
||||
floatout = floatparam.get_value<double>();
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
EXPECT_EQ(node->set_on_parameters_set_callback(on_set_parameters), nullptr);
|
||||
ASSERT_NO_THROW(node->set_parameter({"intparam", 40}));
|
||||
ASSERT_EQ(floatout, 5.4);
|
||||
}
|
||||
|
||||
// test that calling set_parameter inside of a set_callback throws an exception
|
||||
TEST_F(TestNode, set_on_parameters_set_callback_set_parameter) {
|
||||
auto node = std::make_shared<rclcpp::Node>("test_set_callback_set_parameter_node"_unq);
|
||||
|
||||
int64_t intval = node->declare_parameter("intparam", 42);
|
||||
EXPECT_EQ(intval, 42);
|
||||
double floatval = node->declare_parameter("floatparam", 5.4);
|
||||
EXPECT_EQ(floatval, 5.4);
|
||||
|
||||
RCLCPP_SCOPE_EXIT({node->set_on_parameters_set_callback(nullptr);}); // always reset
|
||||
auto on_set_parameters =
|
||||
[&node](const std::vector<rclcpp::Parameter> & parameters) {
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
result.successful = true;
|
||||
if (parameters.size() != 1) {
|
||||
result.successful = false;
|
||||
}
|
||||
|
||||
if (parameters[0].get_value<int>() != 40) {
|
||||
result.successful = false;
|
||||
}
|
||||
|
||||
// This should throw an exception
|
||||
node->set_parameter({"floatparam", 5.6});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
EXPECT_EQ(node->set_on_parameters_set_callback(on_set_parameters), nullptr);
|
||||
EXPECT_THROW(
|
||||
{
|
||||
node->set_parameter(rclcpp::Parameter("intparam", 40));
|
||||
}, rclcpp::exceptions::ParameterModifiedInCallbackException);
|
||||
}
|
||||
|
||||
// test that calling declare_parameter inside of a set_callback throws an exception
|
||||
TEST_F(TestNode, set_on_parameters_set_callback_declare_parameter) {
|
||||
auto node = std::make_shared<rclcpp::Node>("test_set_callback_declare_parameter_node"_unq);
|
||||
|
||||
int64_t intval = node->declare_parameter("intparam", 42);
|
||||
EXPECT_EQ(intval, 42);
|
||||
double floatval = node->declare_parameter("floatparam", 5.4);
|
||||
EXPECT_EQ(floatval, 5.4);
|
||||
|
||||
RCLCPP_SCOPE_EXIT({node->set_on_parameters_set_callback(nullptr);}); // always reset
|
||||
auto on_set_parameters =
|
||||
[&node](const std::vector<rclcpp::Parameter> & parameters) {
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
result.successful = true;
|
||||
if (parameters.size() != 1) {
|
||||
result.successful = false;
|
||||
}
|
||||
|
||||
if (parameters[0].get_value<int>() != 40) {
|
||||
result.successful = false;
|
||||
}
|
||||
|
||||
// This should throw an exception
|
||||
node->declare_parameter("floatparam2", 5.6);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
EXPECT_EQ(node->set_on_parameters_set_callback(on_set_parameters), nullptr);
|
||||
EXPECT_THROW(
|
||||
{
|
||||
node->set_parameter(rclcpp::Parameter("intparam", 40));
|
||||
}, rclcpp::exceptions::ParameterModifiedInCallbackException);
|
||||
}
|
||||
|
||||
// test that calling undeclare_parameter inside a set_callback throws an exception
|
||||
TEST_F(TestNode, set_on_parameters_set_callback_undeclare_parameter) {
|
||||
auto node = std::make_shared<rclcpp::Node>("test_set_callback_undeclare_parameter_node"_unq);
|
||||
|
||||
int64_t intval = node->declare_parameter("intparam", 42);
|
||||
EXPECT_EQ(intval, 42);
|
||||
double floatval = node->declare_parameter("floatparam", 5.4);
|
||||
EXPECT_EQ(floatval, 5.4);
|
||||
|
||||
RCLCPP_SCOPE_EXIT({node->set_on_parameters_set_callback(nullptr);}); // always reset
|
||||
auto on_set_parameters =
|
||||
[&node](const std::vector<rclcpp::Parameter> & parameters) {
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
result.successful = true;
|
||||
if (parameters.size() != 1) {
|
||||
result.successful = false;
|
||||
}
|
||||
|
||||
if (parameters[0].get_value<int>() != 40) {
|
||||
result.successful = false;
|
||||
}
|
||||
|
||||
// This should throw an exception
|
||||
node->undeclare_parameter("floatparam");
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
EXPECT_EQ(node->set_on_parameters_set_callback(on_set_parameters), nullptr);
|
||||
EXPECT_THROW(
|
||||
{
|
||||
node->set_parameter(rclcpp::Parameter("intparam", 40));
|
||||
}, rclcpp::exceptions::ParameterModifiedInCallbackException);
|
||||
}
|
||||
|
||||
// test that calling set_on_parameters_set_callback from a set_callback throws an exception
|
||||
TEST_F(TestNode, set_on_parameters_set_callback_set_on_parameters_set_callback) {
|
||||
auto node = std::make_shared<rclcpp::Node>("test_set_callback_set_callback_node"_unq);
|
||||
|
||||
int64_t intval = node->declare_parameter("intparam", 42);
|
||||
EXPECT_EQ(intval, 42);
|
||||
double floatval = node->declare_parameter("floatparam", 5.4);
|
||||
EXPECT_EQ(floatval, 5.4);
|
||||
|
||||
RCLCPP_SCOPE_EXIT({node->set_on_parameters_set_callback(nullptr);}); // always reset
|
||||
auto on_set_parameters =
|
||||
[&node](const std::vector<rclcpp::Parameter> & parameters) {
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
result.successful = true;
|
||||
if (parameters.size() != 1) {
|
||||
result.successful = false;
|
||||
}
|
||||
|
||||
if (parameters[0].get_value<int>() != 40) {
|
||||
result.successful = false;
|
||||
}
|
||||
|
||||
auto bad_parameters =
|
||||
[](const std::vector<rclcpp::Parameter> & parameters) {
|
||||
(void)parameters;
|
||||
rcl_interfaces::msg::SetParametersResult result;
|
||||
return result;
|
||||
};
|
||||
|
||||
// This should throw an exception
|
||||
node->set_on_parameters_set_callback(bad_parameters);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
EXPECT_EQ(node->set_on_parameters_set_callback(on_set_parameters), nullptr);
|
||||
EXPECT_THROW(
|
||||
{
|
||||
node->set_parameter(rclcpp::Parameter("intparam", 40));
|
||||
}, rclcpp::exceptions::ParameterModifiedInCallbackException);
|
||||
}
|
||||
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
void expect_qos_profile_eq(
|
||||
const rmw_qos_profile_t & qos1, const rmw_qos_profile_t & qos2, bool is_publisher)
|
||||
{
|
||||
|
||||
@@ -105,6 +105,38 @@ TEST(TestNodeOptions, bad_ros_args) {
|
||||
rclcpp::exceptions::UnknownROSArgsError);
|
||||
}
|
||||
|
||||
TEST(TestNodeOptions, use_global_arguments) {
|
||||
{
|
||||
auto options = rclcpp::NodeOptions();
|
||||
EXPECT_TRUE(options.use_global_arguments());
|
||||
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
|
||||
}
|
||||
|
||||
{
|
||||
auto options = rclcpp::NodeOptions().use_global_arguments(false);
|
||||
EXPECT_FALSE(options.use_global_arguments());
|
||||
EXPECT_FALSE(options.get_rcl_node_options()->use_global_arguments);
|
||||
}
|
||||
|
||||
{
|
||||
auto options = rclcpp::NodeOptions().use_global_arguments(true);
|
||||
EXPECT_TRUE(options.use_global_arguments());
|
||||
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
|
||||
}
|
||||
|
||||
{
|
||||
auto options = rclcpp::NodeOptions();
|
||||
EXPECT_TRUE(options.use_global_arguments());
|
||||
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
|
||||
options.use_global_arguments(false);
|
||||
EXPECT_FALSE(options.use_global_arguments());
|
||||
EXPECT_FALSE(options.get_rcl_node_options()->use_global_arguments);
|
||||
options.use_global_arguments(true);
|
||||
EXPECT_TRUE(options.use_global_arguments());
|
||||
EXPECT_TRUE(options.get_rcl_node_options()->use_global_arguments);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestNodeOptions, enable_rosout) {
|
||||
{
|
||||
auto options = rclcpp::NodeOptions();
|
||||
@@ -136,3 +168,33 @@ TEST(TestNodeOptions, enable_rosout) {
|
||||
EXPECT_TRUE(options.get_rcl_node_options()->enable_rosout);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestNodeOptions, copy) {
|
||||
std::vector<std::string> expected_args{"--unknown-flag", "arg"};
|
||||
auto options = rclcpp::NodeOptions().arguments(expected_args).use_global_arguments(false);
|
||||
const rcl_node_options_t * rcl_options = options.get_rcl_node_options();
|
||||
|
||||
{
|
||||
rclcpp::NodeOptions copied_options = options;
|
||||
EXPECT_FALSE(copied_options.use_global_arguments());
|
||||
EXPECT_EQ(expected_args, copied_options.arguments());
|
||||
const rcl_node_options_t * copied_rcl_options = copied_options.get_rcl_node_options();
|
||||
EXPECT_EQ(copied_rcl_options->use_global_arguments, rcl_options->use_global_arguments);
|
||||
EXPECT_EQ(
|
||||
rcl_arguments_get_count_unparsed(&copied_rcl_options->arguments),
|
||||
rcl_arguments_get_count_unparsed(&rcl_options->arguments));
|
||||
}
|
||||
|
||||
{
|
||||
auto other_options = rclcpp::NodeOptions().use_global_arguments(true);
|
||||
(void)other_options.get_rcl_node_options(); // force C structure initialization
|
||||
other_options = options;
|
||||
EXPECT_FALSE(other_options.use_global_arguments());
|
||||
EXPECT_EQ(expected_args, other_options.arguments());
|
||||
const rcl_node_options_t * other_rcl_options = other_options.get_rcl_node_options();
|
||||
EXPECT_EQ(other_rcl_options->use_global_arguments, rcl_options->use_global_arguments);
|
||||
EXPECT_EQ(
|
||||
rcl_arguments_get_count_unparsed(&other_rcl_options->arguments),
|
||||
rcl_arguments_get_count_unparsed(&rcl_options->arguments));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TestParameter, not_set_variant) {
|
||||
TEST_F(TestParameter, not_set_variant) {
|
||||
// Direct instantiation
|
||||
rclcpp::Parameter not_set_variant;
|
||||
EXPECT_EQ(rclcpp::PARAMETER_NOT_SET, not_set_variant.get_type());
|
||||
@@ -58,7 +58,7 @@ TEST(TestParameter, not_set_variant) {
|
||||
rclcpp::Parameter::from_parameter_msg(not_set_param).get_type());
|
||||
}
|
||||
|
||||
TEST(TestParameter, bool_variant) {
|
||||
TEST_F(TestParameter, bool_variant) {
|
||||
// Direct instantiation
|
||||
rclcpp::Parameter bool_variant_true("bool_param", true);
|
||||
EXPECT_EQ("bool_param", bool_variant_true.get_name());
|
||||
@@ -116,7 +116,7 @@ TEST(TestParameter, bool_variant) {
|
||||
bool_variant_false.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, integer_variant) {
|
||||
TEST_F(TestParameter, integer_variant) {
|
||||
const int TEST_VALUE {42};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -164,7 +164,7 @@ TEST(TestParameter, integer_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, long_integer_variant) {
|
||||
TEST_F(TestParameter, long_integer_variant) {
|
||||
const int64_t TEST_VALUE {std::numeric_limits<int64_t>::max()};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -212,7 +212,7 @@ TEST(TestParameter, long_integer_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, float_variant) {
|
||||
TEST_F(TestParameter, float_variant) {
|
||||
const float TEST_VALUE {42.0f};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -260,7 +260,7 @@ TEST(TestParameter, float_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, double_variant) {
|
||||
TEST_F(TestParameter, double_variant) {
|
||||
const double TEST_VALUE {-42.1};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -308,7 +308,7 @@ TEST(TestParameter, double_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, string_variant) {
|
||||
TEST_F(TestParameter, string_variant) {
|
||||
const std::string TEST_VALUE {"ROS2"};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -354,7 +354,7 @@ TEST(TestParameter, string_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, byte_array_variant) {
|
||||
TEST_F(TestParameter, byte_array_variant) {
|
||||
const std::vector<uint8_t> TEST_VALUE {0x52, 0x4f, 0x53, 0x32};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -402,7 +402,7 @@ TEST(TestParameter, byte_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, bool_array_variant) {
|
||||
TEST_F(TestParameter, bool_array_variant) {
|
||||
const std::vector<bool> TEST_VALUE {false, true, true, false, false, true};
|
||||
|
||||
// Direct instantiation
|
||||
@@ -450,7 +450,7 @@ TEST(TestParameter, bool_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, integer_array_variant) {
|
||||
TEST_F(TestParameter, integer_array_variant) {
|
||||
const std::vector<int> TEST_VALUE
|
||||
{42, -99, std::numeric_limits<int>::max(), std::numeric_limits<int>::lowest(), 0};
|
||||
|
||||
@@ -529,7 +529,7 @@ TEST(TestParameter, integer_array_variant) {
|
||||
rcl_interfaces::msg::ParameterType::PARAMETER_INTEGER_ARRAY);
|
||||
}
|
||||
|
||||
TEST(TestParameter, long_integer_array_variant) {
|
||||
TEST_F(TestParameter, long_integer_array_variant) {
|
||||
const std::vector<int64_t> TEST_VALUE
|
||||
{42, -99, std::numeric_limits<int64_t>::max(), std::numeric_limits<int64_t>::lowest(), 0};
|
||||
|
||||
@@ -583,7 +583,7 @@ TEST(TestParameter, long_integer_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, float_array_variant) {
|
||||
TEST_F(TestParameter, float_array_variant) {
|
||||
const std::vector<float> TEST_VALUE
|
||||
{42.1f, -99.1f, std::numeric_limits<float>::max(), std::numeric_limits<float>::lowest(), 0.1f};
|
||||
|
||||
@@ -662,7 +662,7 @@ TEST(TestParameter, float_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, double_array_variant) {
|
||||
TEST_F(TestParameter, double_array_variant) {
|
||||
const std::vector<double> TEST_VALUE
|
||||
{42.1, -99.1, std::numeric_limits<double>::max(), std::numeric_limits<double>::lowest(), 0.1};
|
||||
|
||||
@@ -716,7 +716,7 @@ TEST(TestParameter, double_array_variant) {
|
||||
from_msg.get_value_message().type);
|
||||
}
|
||||
|
||||
TEST(TestParameter, string_array_variant) {
|
||||
TEST_F(TestParameter, string_array_variant) {
|
||||
const std::vector<std::string> TEST_VALUE {"R", "O", "S2"};
|
||||
|
||||
// Direct instantiation
|
||||
|
||||
@@ -24,27 +24,92 @@
|
||||
|
||||
#include "test_msgs/msg/empty.hpp"
|
||||
|
||||
using test_msgs::msg::Empty;
|
||||
|
||||
/**
|
||||
* Parameterized test.
|
||||
* The first param are the NodeOptions used to create the nodes.
|
||||
* The second param are the expect intraprocess count results.
|
||||
*/
|
||||
struct TestParameters
|
||||
namespace
|
||||
{
|
||||
rclcpp::NodeOptions node_options[2];
|
||||
uint64_t intraprocess_count_results[2];
|
||||
std::string description;
|
||||
|
||||
|
||||
template<typename ... Ts>
|
||||
class NodeCreationPolicy
|
||||
{
|
||||
public:
|
||||
rclcpp::NodeOptions & node_options()
|
||||
{
|
||||
return options_;
|
||||
}
|
||||
|
||||
private:
|
||||
rclcpp::NodeOptions options_;
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, const TestParameters & params)
|
||||
template<typename T, typename ... Ts>
|
||||
class NodeCreationPolicy<T, Ts...>
|
||||
{
|
||||
out << params.description;
|
||||
return out;
|
||||
}
|
||||
public:
|
||||
NodeCreationPolicy()
|
||||
{
|
||||
gather<T, Ts...>(options_);
|
||||
}
|
||||
|
||||
class TestPublisherSubscriptionCount : public ::testing::TestWithParam<TestParameters>
|
||||
rclcpp::NodeOptions & node_options()
|
||||
{
|
||||
return options_;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename U>
|
||||
static rclcpp::NodeOptions &
|
||||
gather(rclcpp::NodeOptions & options)
|
||||
{
|
||||
return U::gather(options);
|
||||
}
|
||||
|
||||
template<typename U, typename V, typename ... Ws>
|
||||
static rclcpp::NodeOptions &
|
||||
gather(rclcpp::NodeOptions & options)
|
||||
{
|
||||
return gather<V, Ws...>(U::gather(options));
|
||||
}
|
||||
|
||||
rclcpp::NodeOptions options_;
|
||||
};
|
||||
|
||||
template<bool value>
|
||||
struct ShouldUseIntraprocess
|
||||
{
|
||||
static rclcpp::NodeOptions & gather(rclcpp::NodeOptions & options)
|
||||
{
|
||||
return options.use_intra_process_comms(value);
|
||||
}
|
||||
};
|
||||
|
||||
using UseIntraprocess = ShouldUseIntraprocess<true>;
|
||||
using DoNotUseIntraprocess = ShouldUseIntraprocess<false>;
|
||||
|
||||
struct UseCustomContext
|
||||
{
|
||||
static rclcpp::NodeOptions & gather(rclcpp::NodeOptions & options)
|
||||
{
|
||||
auto context = rclcpp::Context::make_shared();
|
||||
context->init(0, nullptr);
|
||||
return options.context(context);
|
||||
}
|
||||
};
|
||||
|
||||
struct PrintTestDescription
|
||||
{
|
||||
template<typename T>
|
||||
static std::string GetName(int i)
|
||||
{
|
||||
static_cast<void>(i);
|
||||
return T::description;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
template<typename TestDescription>
|
||||
class TestPublisherSubscriptionCount : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
@@ -57,126 +122,128 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetUp() {}
|
||||
static void OnMessage(const test_msgs::msg::Empty::SharedPtr msg)
|
||||
{
|
||||
(void)msg;
|
||||
}
|
||||
|
||||
void TearDown() {}
|
||||
|
||||
static std::chrono::milliseconds offset;
|
||||
std::chrono::milliseconds offset{2000};
|
||||
};
|
||||
|
||||
std::chrono::milliseconds TestPublisherSubscriptionCount::offset = std::chrono::milliseconds(2000);
|
||||
|
||||
void OnMessage(const test_msgs::msg::Empty::SharedPtr msg)
|
||||
/* Testing publisher subscription count api and internal process subscription count.
|
||||
* Two subscriptions in the same topic, both using intraprocess comm.
|
||||
*/
|
||||
struct TwoSubscriptionsIntraprocessComm
|
||||
{
|
||||
(void)msg;
|
||||
}
|
||||
static constexpr const char * description =
|
||||
"two_subscriptions_intraprocess_comm";
|
||||
using FirstNodeCreationPolicy = NodeCreationPolicy<UseIntraprocess>;
|
||||
using SecondNodeCreationPolicy = NodeCreationPolicy<UseIntraprocess>;
|
||||
|
||||
TEST_P(TestPublisherSubscriptionCount, increasing_and_decreasing_counts)
|
||||
static constexpr bool first_node_talks_intraprocess{true};
|
||||
static constexpr bool both_nodes_talk_intraprocess{true};
|
||||
};
|
||||
|
||||
/* Testing publisher subscription count api and internal process subscription count.
|
||||
* Two subscriptions, one using intra-process comm and the other not using it.
|
||||
*/
|
||||
struct TwoSubscriptionsOneIntraprocessOneNot
|
||||
{
|
||||
TestParameters parameters = GetParam();
|
||||
static constexpr const char * description =
|
||||
"two_subscriptions_one_intraprocess_one_not";
|
||||
using FirstNodeCreationPolicy = NodeCreationPolicy<UseIntraprocess>;
|
||||
using SecondNodeCreationPolicy = NodeCreationPolicy<>;
|
||||
|
||||
static constexpr bool first_node_talks_intraprocess{true};
|
||||
static constexpr bool both_nodes_talk_intraprocess{false};
|
||||
};
|
||||
|
||||
/* Testing publisher subscription count api and internal process subscription count.
|
||||
* Two contexts, both using intra-process.
|
||||
*/
|
||||
struct TwoSubscriptionsInTwoContextsWithIntraprocessComm
|
||||
{
|
||||
static constexpr const char * description =
|
||||
"two_subscriptions_in_two_contexts_with_intraprocess_comm";
|
||||
using FirstNodeCreationPolicy = NodeCreationPolicy<UseIntraprocess>;
|
||||
using SecondNodeCreationPolicy = NodeCreationPolicy<UseCustomContext, UseIntraprocess>;
|
||||
|
||||
static constexpr bool first_node_talks_intraprocess{true};
|
||||
static constexpr bool both_nodes_talk_intraprocess{false};
|
||||
};
|
||||
|
||||
/* Testing publisher subscription count api and internal process subscription count.
|
||||
* Two contexts, both of them not using intra-process comm.
|
||||
*/
|
||||
struct TwoSubscriptionsInTwoContextsWithoutIntraprocessComm
|
||||
{
|
||||
static constexpr const char * description =
|
||||
"two_subscriptions_in_two_contexts_without_intraprocess_comm";
|
||||
using FirstNodeCreationPolicy = NodeCreationPolicy<>;
|
||||
using SecondNodeCreationPolicy = NodeCreationPolicy<UseCustomContext>;
|
||||
|
||||
static constexpr bool first_node_talks_intraprocess{false};
|
||||
static constexpr bool both_nodes_talk_intraprocess{false};
|
||||
};
|
||||
|
||||
using AllTestDescriptions = ::testing::Types<
|
||||
TwoSubscriptionsIntraprocessComm,
|
||||
TwoSubscriptionsOneIntraprocessOneNot,
|
||||
TwoSubscriptionsInTwoContextsWithIntraprocessComm,
|
||||
TwoSubscriptionsInTwoContextsWithoutIntraprocessComm
|
||||
>;
|
||||
TYPED_TEST_CASE(TestPublisherSubscriptionCount, AllTestDescriptions, PrintTestDescription);
|
||||
|
||||
|
||||
using test_msgs::msg::Empty;
|
||||
|
||||
TYPED_TEST(TestPublisherSubscriptionCount, increasing_and_decreasing_counts)
|
||||
{
|
||||
using TestDescription = TypeParam;
|
||||
typename TestDescription::FirstNodeCreationPolicy my_node_creation_policy;
|
||||
rclcpp::Node::SharedPtr node = std::make_shared<rclcpp::Node>(
|
||||
"my_node",
|
||||
"/ns",
|
||||
parameters.node_options[0]);
|
||||
my_node_creation_policy.node_options());
|
||||
auto publisher = node->create_publisher<Empty>("/topic", 10);
|
||||
|
||||
EXPECT_EQ(publisher->get_subscription_count(), 0u);
|
||||
EXPECT_EQ(publisher->get_intra_process_subscription_count(), 0u);
|
||||
{
|
||||
auto sub = node->create_subscription<Empty>("/topic", 10, &OnMessage);
|
||||
rclcpp::sleep_for(offset);
|
||||
auto sub = node->create_subscription<Empty>(
|
||||
"/topic", 10, &TestPublisherSubscriptionCount<TestDescription>::OnMessage);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(publisher->get_subscription_count(), 1u);
|
||||
EXPECT_EQ(
|
||||
publisher->get_intra_process_subscription_count(),
|
||||
parameters.intraprocess_count_results[0]);
|
||||
(TestDescription::first_node_talks_intraprocess ? 1u : 0u));
|
||||
{
|
||||
typename TestDescription::SecondNodeCreationPolicy another_node_creation_policy;
|
||||
rclcpp::Node::SharedPtr another_node = std::make_shared<rclcpp::Node>(
|
||||
"another_node",
|
||||
"/ns",
|
||||
parameters.node_options[1]);
|
||||
auto another_sub =
|
||||
another_node->create_subscription<Empty>("/topic", 10, &OnMessage);
|
||||
another_node_creation_policy.node_options());
|
||||
auto another_sub = another_node->create_subscription<Empty>(
|
||||
"/topic", 10, &TestPublisherSubscriptionCount<TestDescription>::OnMessage);
|
||||
|
||||
rclcpp::sleep_for(offset);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(publisher->get_subscription_count(), 2u);
|
||||
EXPECT_EQ(
|
||||
publisher->get_intra_process_subscription_count(),
|
||||
parameters.intraprocess_count_results[1]);
|
||||
(TestDescription::first_node_talks_intraprocess ? 1u : 0u) +
|
||||
(TestDescription::both_nodes_talk_intraprocess ? 1u : 0u));
|
||||
}
|
||||
rclcpp::sleep_for(offset);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(publisher->get_subscription_count(), 1u);
|
||||
EXPECT_EQ(
|
||||
publisher->get_intra_process_subscription_count(),
|
||||
parameters.intraprocess_count_results[0]);
|
||||
(TestDescription::first_node_talks_intraprocess ? 1u : 0u));
|
||||
}
|
||||
/**
|
||||
* Counts should be zero here, as all are subscriptions are out of scope.
|
||||
* Subscriptions count checking is always preceeded with an sleep, as random failures had been
|
||||
* detected without it. */
|
||||
rclcpp::sleep_for(offset);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(publisher->get_subscription_count(), 0u);
|
||||
EXPECT_EQ(publisher->get_intra_process_subscription_count(), 0u);
|
||||
}
|
||||
|
||||
auto get_new_context()
|
||||
{
|
||||
auto context = rclcpp::Context::make_shared();
|
||||
context->init(0, nullptr);
|
||||
return context;
|
||||
}
|
||||
|
||||
TestParameters parameters[] = {
|
||||
/*
|
||||
Testing publisher subscription count api and internal process subscription count.
|
||||
Two subscriptions in the same topic, both using intraprocess comm.
|
||||
*/
|
||||
{
|
||||
{
|
||||
rclcpp::NodeOptions().use_intra_process_comms(true),
|
||||
rclcpp::NodeOptions().use_intra_process_comms(true)
|
||||
},
|
||||
{1u, 2u},
|
||||
"two_subscriptions_intraprocess_comm"
|
||||
},
|
||||
/*
|
||||
Testing publisher subscription count api and internal process subscription count.
|
||||
Two subscriptions, one using intra-process comm and the other not using it.
|
||||
*/
|
||||
{
|
||||
{
|
||||
rclcpp::NodeOptions().use_intra_process_comms(true),
|
||||
rclcpp::NodeOptions().use_intra_process_comms(false)
|
||||
},
|
||||
{1u, 1u},
|
||||
"two_subscriptions_one_intraprocess_one_not"
|
||||
},
|
||||
/*
|
||||
Testing publisher subscription count api and internal process subscription count.
|
||||
Two contexts, both using intra-process.
|
||||
*/
|
||||
{
|
||||
{
|
||||
rclcpp::NodeOptions().use_intra_process_comms(true),
|
||||
rclcpp::NodeOptions().context(get_new_context()).use_intra_process_comms(true)
|
||||
},
|
||||
{1u, 1u},
|
||||
"two_subscriptions_in_two_contexts_with_intraprocess_comm"
|
||||
},
|
||||
/*
|
||||
Testing publisher subscription count api and internal process subscription count.
|
||||
Two contexts, both of them not using intra-process comm.
|
||||
*/
|
||||
{
|
||||
{
|
||||
rclcpp::NodeOptions().use_intra_process_comms(false),
|
||||
rclcpp::NodeOptions().context(get_new_context()).use_intra_process_comms(false)
|
||||
},
|
||||
{0u, 0u},
|
||||
"two_subscriptions_in_two_contexts_without_intraprocess_comm"
|
||||
}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
TestWithDifferentNodeOptions, TestPublisherSubscriptionCount,
|
||||
::testing::ValuesIn(parameters),
|
||||
::testing::PrintToStringParamName());
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2019 Open Source Robotics Foundation, Inc.
|
||||
// Copyright 2019-2020 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.
|
||||
@@ -23,21 +23,79 @@
|
||||
|
||||
#include "test_msgs/msg/empty.hpp"
|
||||
|
||||
using test_msgs::msg::Empty;
|
||||
|
||||
struct TestParameters
|
||||
namespace
|
||||
{
|
||||
rclcpp::NodeOptions node_options;
|
||||
std::string description;
|
||||
|
||||
template<typename ... Ts>
|
||||
class NodeCreationPolicy
|
||||
{
|
||||
public:
|
||||
rclcpp::NodeOptions & node_options()
|
||||
{
|
||||
return options_;
|
||||
}
|
||||
|
||||
private:
|
||||
rclcpp::NodeOptions options_;
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, const TestParameters & params)
|
||||
template<typename T, typename ... Ts>
|
||||
class NodeCreationPolicy<T, Ts...>
|
||||
{
|
||||
out << params.description;
|
||||
return out;
|
||||
}
|
||||
public:
|
||||
NodeCreationPolicy()
|
||||
{
|
||||
gather<T, Ts...>(options_);
|
||||
}
|
||||
|
||||
class TestSubscriptionPublisherCount : public ::testing::TestWithParam<TestParameters>
|
||||
rclcpp::NodeOptions & node_options()
|
||||
{
|
||||
return options_;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename U>
|
||||
static rclcpp::NodeOptions &
|
||||
gather(rclcpp::NodeOptions & options)
|
||||
{
|
||||
return U::gather(options);
|
||||
}
|
||||
|
||||
template<typename U, typename V, typename ... Ws>
|
||||
static rclcpp::NodeOptions &
|
||||
gather(rclcpp::NodeOptions & options)
|
||||
{
|
||||
return gather<V, Ws...>(U::gather(options));
|
||||
}
|
||||
|
||||
rclcpp::NodeOptions options_;
|
||||
};
|
||||
|
||||
struct UseCustomContext
|
||||
{
|
||||
static rclcpp::NodeOptions & gather(rclcpp::NodeOptions & options)
|
||||
{
|
||||
auto context = rclcpp::Context::make_shared();
|
||||
context->init(0, nullptr);
|
||||
return options.context(context);
|
||||
}
|
||||
};
|
||||
|
||||
struct PrintTestDescription
|
||||
{
|
||||
template<typename T>
|
||||
static std::string GetName(int i)
|
||||
{
|
||||
static_cast<void>(i);
|
||||
return T::description;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
template<typename TestDescription>
|
||||
class TestSubscriptionPublisherCount : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
@@ -50,78 +108,59 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetUp() {}
|
||||
void TearDown() {}
|
||||
static std::chrono::milliseconds offset;
|
||||
static void OnMessage(const test_msgs::msg::Empty::SharedPtr msg)
|
||||
{
|
||||
(void)msg;
|
||||
}
|
||||
|
||||
std::chrono::milliseconds offset{2000};
|
||||
};
|
||||
|
||||
std::chrono::milliseconds TestSubscriptionPublisherCount::offset = std::chrono::milliseconds(2000);
|
||||
|
||||
void OnMessage(const test_msgs::msg::Empty::SharedPtr msg)
|
||||
struct OneContextPerTest
|
||||
{
|
||||
(void)msg;
|
||||
}
|
||||
static constexpr const char * description = "one_context_test";
|
||||
using NodeCreationPolicy = ::NodeCreationPolicy<>;
|
||||
};
|
||||
|
||||
TEST_P(TestSubscriptionPublisherCount, increasing_and_decreasing_counts)
|
||||
struct TwoContextsPerTest
|
||||
{
|
||||
rclcpp::NodeOptions node_options = GetParam().node_options;
|
||||
rclcpp::Node::SharedPtr node = std::make_shared<rclcpp::Node>(
|
||||
"my_node",
|
||||
"/ns",
|
||||
node_options);
|
||||
auto subscription = node->create_subscription<Empty>("/topic", 10, &OnMessage);
|
||||
static constexpr const char * description = "two_contexts_test";
|
||||
using NodeCreationPolicy = ::NodeCreationPolicy<UseCustomContext>;
|
||||
};
|
||||
|
||||
using AllTestDescriptions = ::testing::Types<OneContextPerTest, TwoContextsPerTest>;
|
||||
TYPED_TEST_CASE(TestSubscriptionPublisherCount, AllTestDescriptions, PrintTestDescription);
|
||||
|
||||
|
||||
using test_msgs::msg::Empty;
|
||||
|
||||
TYPED_TEST(TestSubscriptionPublisherCount, increasing_and_decreasing_counts)
|
||||
{
|
||||
using TestDescription = TypeParam;
|
||||
rclcpp::Node::SharedPtr node = std::make_shared<rclcpp::Node>("my_node", "/ns");
|
||||
auto subscription = node->create_subscription<Empty>(
|
||||
"/topic", 10, &TestSubscriptionPublisherCount<TestDescription>::OnMessage);
|
||||
|
||||
EXPECT_EQ(subscription->get_publisher_count(), 0u);
|
||||
{
|
||||
auto pub = node->create_publisher<Empty>("/topic", 10);
|
||||
rclcpp::sleep_for(offset);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(subscription->get_publisher_count(), 1u);
|
||||
{
|
||||
typename TestDescription::NodeCreationPolicy node_creation_policy;
|
||||
rclcpp::Node::SharedPtr another_node = std::make_shared<rclcpp::Node>(
|
||||
"another_node",
|
||||
"/ns",
|
||||
node_options);
|
||||
node_creation_policy.node_options());
|
||||
auto another_pub =
|
||||
another_node->create_publisher<Empty>("/topic", 10);
|
||||
|
||||
rclcpp::sleep_for(offset);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(subscription->get_publisher_count(), 2u);
|
||||
}
|
||||
rclcpp::sleep_for(offset);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(subscription->get_publisher_count(), 1u);
|
||||
}
|
||||
rclcpp::sleep_for(offset);
|
||||
rclcpp::sleep_for(this->offset);
|
||||
EXPECT_EQ(subscription->get_publisher_count(), 0u);
|
||||
}
|
||||
|
||||
auto get_new_context()
|
||||
{
|
||||
auto context = rclcpp::Context::make_shared();
|
||||
context->init(0, nullptr);
|
||||
return context;
|
||||
}
|
||||
|
||||
TestParameters parameters[] = {
|
||||
/*
|
||||
Testing subscription publisher count api.
|
||||
One context.
|
||||
*/
|
||||
{
|
||||
rclcpp::NodeOptions(),
|
||||
"one_context_test"
|
||||
},
|
||||
/*
|
||||
Testing subscription publisher count api.
|
||||
Two contexts.
|
||||
*/
|
||||
{
|
||||
rclcpp::NodeOptions().context(get_new_context()),
|
||||
"two_contexts_test"
|
||||
}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
TestWithDifferentNodeOptions,
|
||||
TestSubscriptionPublisherCount,
|
||||
testing::ValuesIn(parameters),
|
||||
testing::PrintToStringParamName());
|
||||
|
||||
@@ -45,7 +45,7 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TestTime, clock_type_access) {
|
||||
TEST_F(TestTime, clock_type_access) {
|
||||
rclcpp::Clock ros_clock(RCL_ROS_TIME);
|
||||
EXPECT_EQ(RCL_ROS_TIME, ros_clock.get_clock_type());
|
||||
|
||||
@@ -57,7 +57,7 @@ TEST(TestTime, clock_type_access) {
|
||||
}
|
||||
|
||||
// Check that the clock may go out of the scope before the jump callback without leading in UB.
|
||||
TEST(TestTime, clock_jump_callback_destruction_order) {
|
||||
TEST_F(TestTime, clock_jump_callback_destruction_order) {
|
||||
rclcpp::JumpHandler::SharedPtr handler;
|
||||
{
|
||||
rclcpp::Clock ros_clock(RCL_ROS_TIME);
|
||||
@@ -68,7 +68,7 @@ TEST(TestTime, clock_jump_callback_destruction_order) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestTime, time_sources) {
|
||||
TEST_F(TestTime, time_sources) {
|
||||
using builtin_interfaces::msg::Time;
|
||||
rclcpp::Clock ros_clock(RCL_ROS_TIME);
|
||||
Time ros_now = ros_clock.now();
|
||||
@@ -86,44 +86,124 @@ TEST(TestTime, time_sources) {
|
||||
EXPECT_NE(0u, steady_now.nanosec);
|
||||
}
|
||||
|
||||
TEST(TestTime, conversions) {
|
||||
static const int64_t HALF_SEC_IN_NS = 500 * 1000 * 1000;
|
||||
static const int64_t ONE_SEC_IN_NS = 1000 * 1000 * 1000;
|
||||
static const int64_t ONE_AND_HALF_SEC_IN_NS = 3 * HALF_SEC_IN_NS;
|
||||
|
||||
TEST_F(TestTime, conversions) {
|
||||
rclcpp::Clock system_clock(RCL_SYSTEM_TIME);
|
||||
|
||||
rclcpp::Time now = system_clock.now();
|
||||
builtin_interfaces::msg::Time now_msg = now;
|
||||
|
||||
rclcpp::Time now_again = now_msg;
|
||||
EXPECT_EQ(now.nanoseconds(), now_again.nanoseconds());
|
||||
|
||||
builtin_interfaces::msg::Time msg;
|
||||
msg.sec = 12345;
|
||||
msg.nanosec = 67890;
|
||||
|
||||
rclcpp::Time time = msg;
|
||||
EXPECT_EQ(
|
||||
RCL_S_TO_NS(static_cast<int64_t>(msg.sec)) + static_cast<int64_t>(msg.nanosec),
|
||||
time.nanoseconds());
|
||||
EXPECT_EQ(static_cast<int64_t>(msg.sec), RCL_NS_TO_S(time.nanoseconds()));
|
||||
|
||||
builtin_interfaces::msg::Time negative_time_msg;
|
||||
negative_time_msg.sec = -1;
|
||||
negative_time_msg.nanosec = 1;
|
||||
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time negative_time = negative_time_msg;
|
||||
});
|
||||
rclcpp::Time now = system_clock.now();
|
||||
builtin_interfaces::msg::Time now_msg = now;
|
||||
|
||||
EXPECT_ANY_THROW(rclcpp::Time(-1, 1));
|
||||
rclcpp::Time now_again = now_msg;
|
||||
EXPECT_EQ(now.nanoseconds(), now_again.nanoseconds());
|
||||
}
|
||||
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time assignment(1, 2);
|
||||
assignment = negative_time_msg;
|
||||
});
|
||||
rclcpp::Time positive_time = rclcpp::Time(12345, 67890u);
|
||||
|
||||
builtin_interfaces::msg::Time msg = positive_time;
|
||||
EXPECT_EQ(msg.sec, 12345);
|
||||
EXPECT_EQ(msg.nanosec, 67890u);
|
||||
|
||||
rclcpp::Time time = msg;
|
||||
EXPECT_EQ(time.nanoseconds(), positive_time.nanoseconds());
|
||||
EXPECT_EQ(
|
||||
RCL_S_TO_NS(static_cast<int64_t>(msg.sec)) + static_cast<int64_t>(msg.nanosec),
|
||||
time.nanoseconds());
|
||||
EXPECT_EQ(static_cast<int64_t>(msg.sec), RCL_NS_TO_S(time.nanoseconds()));
|
||||
}
|
||||
|
||||
// throw on construction/assignment of negative times
|
||||
{
|
||||
builtin_interfaces::msg::Time negative_time_msg;
|
||||
negative_time_msg.sec = -1;
|
||||
negative_time_msg.nanosec = 1;
|
||||
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time negative_time = negative_time_msg;
|
||||
});
|
||||
|
||||
EXPECT_ANY_THROW(rclcpp::Time(-1, 1));
|
||||
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time assignment(1, 2);
|
||||
assignment = negative_time_msg;
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Time time(HALF_SEC_IN_NS);
|
||||
const auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, 0);
|
||||
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Time(time_msg).nanoseconds(), HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Time time(ONE_SEC_IN_NS);
|
||||
const auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, 1);
|
||||
EXPECT_EQ(time_msg.nanosec, 0u);
|
||||
EXPECT_EQ(rclcpp::Time(time_msg).nanoseconds(), ONE_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
const rclcpp::Time time(ONE_AND_HALF_SEC_IN_NS);
|
||||
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, 1);
|
||||
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
|
||||
EXPECT_EQ(rclcpp::Time(time_msg).nanoseconds(), ONE_AND_HALF_SEC_IN_NS);
|
||||
}
|
||||
|
||||
{
|
||||
// Can rclcpp::Time be negative or not? The following constructor works:
|
||||
rclcpp::Time time(-HALF_SEC_IN_NS);
|
||||
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, -1);
|
||||
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
|
||||
|
||||
// The opposite conversion throws...
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time negative_time(time_msg);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// Can rclcpp::Time be negative or not? The following constructor works:
|
||||
rclcpp::Time time(-ONE_SEC_IN_NS);
|
||||
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, -1);
|
||||
EXPECT_EQ(time_msg.nanosec, 0u);
|
||||
|
||||
// The opposite conversion throws...
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time negative_time(time_msg);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
// Can rclcpp::Time be negative or not? The following constructor works:
|
||||
rclcpp::Time time(-ONE_AND_HALF_SEC_IN_NS);
|
||||
auto time_msg = static_cast<builtin_interfaces::msg::Time>(time);
|
||||
EXPECT_EQ(time_msg.sec, -2);
|
||||
EXPECT_EQ(time_msg.nanosec, HALF_SEC_IN_NS);
|
||||
|
||||
// The opposite conversion throws...
|
||||
EXPECT_ANY_THROW(
|
||||
{
|
||||
rclcpp::Time negative_time(time_msg);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestTime, operators) {
|
||||
TEST_F(TestTime, operators) {
|
||||
rclcpp::Time old(1, 0);
|
||||
rclcpp::Time young(2, 0);
|
||||
|
||||
@@ -178,7 +258,7 @@ TEST(TestTime, operators) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestTime, overflow_detectors) {
|
||||
TEST_F(TestTime, overflow_detectors) {
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Test logical_eq call first:
|
||||
EXPECT_TRUE(logical_eq(false, false));
|
||||
@@ -198,8 +278,8 @@ TEST(TestTime, overflow_detectors) {
|
||||
// 256 * 256 = 64K total loops, should be pretty fast on everything
|
||||
for (big_type_t y = min_val; y <= max_val; ++y) {
|
||||
for (big_type_t x = min_val; x <= max_val; ++x) {
|
||||
const big_type_t sum = x + y;
|
||||
const big_type_t diff = x - y;
|
||||
const big_type_t sum = static_cast<big_type_t>(x + y);
|
||||
const big_type_t diff = static_cast<big_type_t>(x - y);
|
||||
|
||||
const bool add_will_overflow =
|
||||
rclcpp::add_will_overflow(test_type_t(x), test_type_t(y));
|
||||
@@ -235,7 +315,7 @@ TEST(TestTime, overflow_detectors) {
|
||||
EXPECT_TRUE(rclcpp::sub_will_underflow<int64_t>(INT64_MIN, 1));
|
||||
}
|
||||
|
||||
TEST(TestTime, overflows) {
|
||||
TEST_F(TestTime, overflows) {
|
||||
rclcpp::Time max_time(std::numeric_limits<rcl_time_point_value_t>::max());
|
||||
rclcpp::Time min_time(std::numeric_limits<rcl_time_point_value_t>::min());
|
||||
rclcpp::Duration one(1);
|
||||
@@ -267,7 +347,7 @@ TEST(TestTime, overflows) {
|
||||
EXPECT_NO_THROW(one_time - two_time);
|
||||
}
|
||||
|
||||
TEST(TestTime, seconds) {
|
||||
TEST_F(TestTime, seconds) {
|
||||
EXPECT_DOUBLE_EQ(0.0, rclcpp::Time(0, 0).seconds());
|
||||
EXPECT_DOUBLE_EQ(4.5, rclcpp::Time(4, 500000000).seconds());
|
||||
EXPECT_DOUBLE_EQ(2.5, rclcpp::Time(0, 2500000000).seconds());
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <chrono>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "rcl/timer.h"
|
||||
|
||||
@@ -151,3 +152,42 @@ TEST_F(TestTimer, test_run_cancel_timer)
|
||||
EXPECT_TRUE(has_timer_run.load());
|
||||
EXPECT_TRUE(timer->is_canceled());
|
||||
}
|
||||
|
||||
TEST_F(TestTimer, test_bad_arguments) {
|
||||
auto node_base = rclcpp::node_interfaces::get_node_base_interface(test_node);
|
||||
auto context = node_base->get_context();
|
||||
|
||||
auto steady_clock = std::make_shared<rclcpp::Clock>(RCL_STEADY_TIME);
|
||||
|
||||
// Negative period
|
||||
EXPECT_THROW(
|
||||
rclcpp::GenericTimer<void (*)()>(steady_clock, -1ms, []() {}, context),
|
||||
rclcpp::exceptions::RCLInvalidArgument);
|
||||
|
||||
// Very negative period
|
||||
constexpr auto nanoseconds_min = std::chrono::nanoseconds::min();
|
||||
EXPECT_THROW(
|
||||
rclcpp::GenericTimer<void (*)()>(
|
||||
steady_clock, nanoseconds_min, []() {}, context),
|
||||
rclcpp::exceptions::RCLInvalidArgument);
|
||||
|
||||
// nanoseconds max, should be ok
|
||||
constexpr auto nanoseconds_max = std::chrono::nanoseconds::max();
|
||||
EXPECT_NO_THROW(
|
||||
rclcpp::GenericTimer<void (*)()>(
|
||||
steady_clock, nanoseconds_max, []() {}, context));
|
||||
|
||||
// 0 duration period, should be ok
|
||||
EXPECT_NO_THROW(
|
||||
rclcpp::GenericTimer<void (*)()>(steady_clock, 0ms, []() {}, context));
|
||||
|
||||
// context is null, which resorts to default
|
||||
EXPECT_NO_THROW(
|
||||
rclcpp::GenericTimer<void (*)()>(steady_clock, 1ms, []() {}, nullptr));
|
||||
|
||||
// Clock is unitialized
|
||||
auto unitialized_clock = std::make_shared<rclcpp::Clock>(RCL_CLOCK_UNINITIALIZED);
|
||||
EXPECT_THROW(
|
||||
rclcpp::GenericTimer<void (*)()>(unitialized_clock, 1us, []() {}, context),
|
||||
rclcpp::exceptions::RCLError);
|
||||
}
|
||||
|
||||
116
rclcpp/test/rclcpp/test_timer_call_count.cpp
Normal file
116
rclcpp/test/rclcpp/test_timer_call_count.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright 2020 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 <string>
|
||||
#include <memory>
|
||||
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "rclcpp/exceptions.hpp"
|
||||
#include "rclcpp/node.hpp"
|
||||
#include "rclcpp/executors.hpp"
|
||||
#include "rclcpp/executor.hpp"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
class TestTimerCount : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr int EXECUTION_COUNT = 5;
|
||||
constexpr rcl_duration_value_t TIME_ELAPSED = 12;
|
||||
/*
|
||||
Test timer wait mutex with multithreaded executor.
|
||||
After 5 call
|
||||
*/
|
||||
|
||||
TEST_F(TestTimerCount, timer_call_count_multi_threaded) {
|
||||
rclcpp::executors::MultiThreadedExecutor executor;
|
||||
|
||||
std::shared_ptr<rclcpp::Node> node =
|
||||
std::make_shared<rclcpp::Node>("timer_call_count_multi_threaded");
|
||||
|
||||
auto cbg = node->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
|
||||
|
||||
rclcpp::Clock system_clock(RCL_STEADY_TIME);
|
||||
std::mutex last_mutex;
|
||||
rclcpp::Time initial = system_clock.now();
|
||||
|
||||
std::atomic_int timer_count {0};
|
||||
|
||||
auto timer_callback = [&timer_count, &executor, &system_clock, &last_mutex, &initial]() {
|
||||
rclcpp::Time now = system_clock.now();
|
||||
timer_count++;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(last_mutex);
|
||||
rcl_duration_value_t diff = (now - initial).nanoseconds() / (rcl_duration_value_t)1.0e9;
|
||||
|
||||
if (diff > TIME_ELAPSED) {
|
||||
executor.cancel();
|
||||
ASSERT_GT(timer_count, EXECUTION_COUNT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto timer_ = node->create_wall_timer(
|
||||
2s, timer_callback, cbg);
|
||||
|
||||
executor.add_node(node);
|
||||
executor.spin();
|
||||
}
|
||||
|
||||
/*
|
||||
Test timer wait mutex with singlethreaded executor
|
||||
*/
|
||||
TEST_F(TestTimerCount, timer_call_count_single_threaded) {
|
||||
rclcpp::executors::SingleThreadedExecutor executor;
|
||||
|
||||
std::shared_ptr<rclcpp::Node> node =
|
||||
std::make_shared<rclcpp::Node>("timer_call_count_single_threaded");
|
||||
|
||||
rclcpp::Clock system_clock(RCL_STEADY_TIME);
|
||||
std::mutex last_mutex;
|
||||
rclcpp::Time initial = system_clock.now();
|
||||
|
||||
std::atomic_int timer_count {0};
|
||||
|
||||
auto timer_callback = [&timer_count, &executor, &system_clock, &last_mutex, &initial]() {
|
||||
rclcpp::Time now = system_clock.now();
|
||||
timer_count++;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(last_mutex);
|
||||
rcl_duration_value_t diff = (now - initial).nanoseconds() / (rcl_duration_value_t)1.0e9;
|
||||
|
||||
if (diff > TIME_ELAPSED) {
|
||||
executor.cancel();
|
||||
ASSERT_GT(timer_count, EXECUTION_COUNT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto timer_ = node->create_wall_timer(
|
||||
2s, timer_callback);
|
||||
|
||||
executor.add_node(node);
|
||||
executor.spin();
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
This document is a declaration of software quality for the `rclcpp_action` package, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
|
||||
# `rclcpp_action` Quality Declaration
|
||||
# rclcpp_action Quality Declaration
|
||||
|
||||
The package `rclcpp_action` claims to be in the **Quality Level 4** category.
|
||||
The package `rclcpp_action` claims to be in the **Quality Level 3** category.
|
||||
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Quality Categories in REP-2004](https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#package-quality-categories) of the ROS2 developer guide.
|
||||
|
||||
@@ -10,7 +10,7 @@ Below are the rationales, notes, and caveats for this claim, organized by each r
|
||||
|
||||
### Version Scheme [1.i]
|
||||
|
||||
`rclcpp_action` uses `semver` according to the recommendation for ROS Core packages in the [ROS 2 Developer Guide](https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#versioning)
|
||||
`rclcpp_action` uses `semver` according to the recommendation for ROS Core packages in the [ROS 2 Developer Guide](https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#versioning).
|
||||
|
||||
### Version Stability [1.ii]
|
||||
|
||||
@@ -74,19 +74,19 @@ All pull requests must resolve related documentation changes before merging.
|
||||
|
||||
### Public API Documentation [3.ii]
|
||||
|
||||
The API is publicly available in the [ROS 2 API documentation](http://docs.ros2.org/latest/api/rclcpp_action/).
|
||||
The API is publicly available in its [ROS 2 API documentation](http://docs.ros2.org/latest/api/rclcpp_action/).
|
||||
|
||||
### License [3.iii]
|
||||
|
||||
The license for `rclcpp_action` is Apache 2.0, and a summary is in each source file, the type is declared in the [`package.xml`](./package.xml) manifest file, and a full copy of the license is in the [`LICENSE`](../LICENSE) file.
|
||||
|
||||
There is an automated test which runs a linter that ensures each file has a license statement. [Here](http://build.ros2.org/view/Epr/job/Epr__rclcpp_action__ubuntu_bionic_amd64/lastBuild/testReport/rclcpp_action/) can be found a list with the latest results of the various linters being run on the package.
|
||||
There is an automated test which runs a linter that ensures each file has a license statement. [Here](http://build.ros2.org/view/Fpr/job/Fpr__rclcpp__ubuntu_focal_amd64/lastSuccessfulBuild/testReport/rclcpp_action/) can be found a list with the latest results of the various linters being run on the package.
|
||||
|
||||
### Copyright Statements [3.iv]
|
||||
|
||||
The copyright holders each provide a statement of copyright in each source code file in `rclcpp_action`.
|
||||
|
||||
There is an automated test which runs a linter that ensures each file has at least one copyright statement. Latest linter result report can be seen [here](http://build.ros2.org/view/Epr/job/Epr__rclcpp_action__ubuntu_bionic_amd64/lastBuild/testReport/rclcpp_action/copyright/).
|
||||
There is an automated test which runs a linter that ensures each file has at least one copyright statement. Latest linter result report can be seen [here](http://build.ros2.org/view/Fpr/job/Fpr__rclcpp__ubuntu_focal_amd64/lastSuccessfulBuild/testReport/rclcpp_action/copyright/).
|
||||
|
||||
## Testing [4]
|
||||
|
||||
@@ -119,6 +119,8 @@ This includes:
|
||||
|
||||
Changes are required to make a best effort to keep or increase coverage before being accepted, but decreases are allowed if properly justified and accepted by reviewers.
|
||||
|
||||
Current coverage statistics can be viewed [here](https://ci.ros2.org/job/nightly_linux_coverage/lastSuccessfulBuild/cobertura/src_ros2_rclcpp_rclcpp_action_src/). A description of how coverage statistics are calculated is summarized in this page ["ROS 2 Onboarding Guide"](https://index.ros.org/doc/ros2/Contributing/ROS-2-On-boarding-Guide/#note-on-coverage-runs).
|
||||
|
||||
### Performance [4.iv]
|
||||
|
||||
It is not yet defined if this package requires performance testing and how addresses this topic.
|
||||
@@ -149,19 +151,19 @@ It also has several test dependencies, which do not affect the resulting quality
|
||||
|
||||
`action_msgs` provides messages and services for ROS 2 actions.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rcl_interfaces/blob/master/action_msgs/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ros2/rcl_interfaces/blob/master/action_msgs/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rclcpp`
|
||||
|
||||
The `rclcpp` package provides the ROS client library in C++.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rclcpp/blob/master/rclcpp/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ros2/rclcpp/blob/master/rclcpp/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rcl_action`
|
||||
|
||||
The `rcl_action` package provides C-based ROS action implementation.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rcl/blob/master/rcl_action/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ros2/rcl/blob/master/rcl_action/QUALITY_DECLARATION.md).
|
||||
|
||||
### Direct Runtime non-ROS Dependency [5.iii]
|
||||
|
||||
|
||||
@@ -6,4 +6,4 @@ Visit the [rclcpp_action API documentation](http://docs.ros2.org/latest/api/rclc
|
||||
|
||||
## Quality Declaration
|
||||
|
||||
This package claims to be in the **Quality Level 4** category, see the [Quality Declaration](QUALITY_DECLARATION.md) for more details.
|
||||
This package claims to be in the **Quality Level 3** category, see the [Quality Declaration](QUALITY_DECLARATION.md) for more details.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
This document is a declaration of software quality for the `rclcpp_components` package, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
|
||||
# `rclcpp_components` Quality Declaration
|
||||
# rclcpp_components Quality Declaration
|
||||
|
||||
The package `rclcpp_components` claims to be in the **Quality Level 4** category.
|
||||
The package `rclcpp_components` claims to be in the **Quality Level 3** category.
|
||||
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Quality Categories in REP-2004](https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#package-quality-categories) of the ROS2 developer guide.
|
||||
|
||||
@@ -10,7 +10,7 @@ Below are the rationales, notes, and caveats for this claim, organized by each r
|
||||
|
||||
### Version Scheme [1.i]
|
||||
|
||||
`rclcpp_components` uses `semver` according to the recommendation for ROS Core packages in the [ROS 2 Developer Guide](https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#versioning)
|
||||
`rclcpp_components` uses `semver` according to the recommendation for ROS Core packages in the [ROS 2 Developer Guide](https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#versioning).
|
||||
|
||||
### Version Stability [1.ii]
|
||||
|
||||
@@ -70,25 +70,23 @@ All pull requests must resolve related documentation changes before merging.
|
||||
|
||||
### Feature Documentation [3.i]
|
||||
|
||||
`rclcpp_components` does not have a documented feature list.
|
||||
`rclcpp_components` has a [feature list](http://docs.ros2.org/latest/api/rclcpp_components/) and each item in the list links to the corresponding feature documentation. There is documentation for all of the features, and new features require documentation before being added.
|
||||
|
||||
### Public API Documentation [3.ii]
|
||||
|
||||
`rclcpp_components` does not cover a public API documentation.
|
||||
|
||||
The API is publicly available in the [ROS 2 API documentation](http://docs.ros2.org/latest/api/rclcpp_components/).
|
||||
The API is publicly available in its [ROS 2 API documentation](http://docs.ros2.org/latest/api/rclcpp_components/).
|
||||
|
||||
### License [3.iii]
|
||||
|
||||
The license for `rclcpp_components` is Apache 2.0, and a summary is in each source file, the type is declared in the [`package.xml`](./package.xml) manifest file, and a full copy of the license is in the [`LICENSE`](../LICENSE) file.
|
||||
|
||||
There is an automated test which runs a linter that ensures each file has a license statement. [Here](http://build.ros2.org/view/Epr/job/Epr__rclcpp_components__ubuntu_bionic_amd64/lastBuild/testReport/rclcpp_components/) can be found a list with the latest results of the various linters being run on the package.
|
||||
There is an automated test which runs a linter that ensures each file has a license statement. [Here](http://build.ros2.org/view/Fpr/job/Fpr__rclcpp__ubuntu_focal_amd64/lastSuccessfulBuild/testReport/rclcpp_components/) can be found a list with the latest results of the various linters being run on the package.
|
||||
|
||||
### Copyright Statements [3.iv]
|
||||
|
||||
The copyright holders each provide a statement of copyright in each source code file in `rclcpp_components`.
|
||||
|
||||
There is an automated test which runs a linter that ensures each file has at least one copyright statement. Latest linter result report can be seen [here](http://build.ros2.org/view/Epr/job/Epr__rclcpp_components__ubuntu_bionic_amd64/lastBuild/testReport/rclcpp_components/copyright/).
|
||||
There is an automated test which runs a linter that ensures each file has at least one copyright statement. Latest linter result report can be seen [here](http://build.ros2.org/view/Fpr/job/Fpr__rclcpp__ubuntu_focal_amd64/lastSuccessfulBuild/testReport/rclcpp_components/copyright).
|
||||
|
||||
## Testing [4]
|
||||
|
||||
@@ -121,6 +119,8 @@ This includes:
|
||||
|
||||
Changes are required to make a best effort to keep or increase coverage before being accepted, but decreases are allowed if properly justified and accepted by reviewers.
|
||||
|
||||
Current coverage statistics can be viewed [here](https://ci.ros2.org/job/nightly_linux_coverage/lastSuccessfulBuild/cobertura/src_ros2_rclcpp_rclcpp_components_src/). A description of how coverage statistics are calculated is summarized in this page ["ROS 2 Onboarding Guide"](https://index.ros.org/doc/ros2/Contributing/ROS-2-On-boarding-Guide/#note-on-coverage-runs).
|
||||
|
||||
### Performance [4.iv]
|
||||
|
||||
It is not yet defined if this package requires performance testing and how addresses this topic.
|
||||
@@ -151,25 +151,31 @@ It also has several test dependencies, which do not affect the resulting quality
|
||||
|
||||
The `ament_index_cpp` package provides a C++ API to access the ament resource index.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ament/ament_index/blob/master/ament_index_cpp/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ament/ament_index/blob/master/ament_index_cpp/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `class_loader`
|
||||
|
||||
The `class_loader` package provides a ROS-independent package for loading plugins during runtime
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros/class_loader/blob/ros2/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ros/class_loader/blob/ros2/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `composition_interfaces`
|
||||
|
||||
The `composition_interfaces` package contains message and service definitions for managing composable nodes in a container process.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rcl_interfaces/blob/master/composition_interfaces/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ros2/rcl_interfaces/blob/master/composition_interfaces/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rclcpp`
|
||||
|
||||
The `rclcpp` package provides the ROS client library in C++.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rclcpp/blob/master/rclcpp/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ros2/rclcpp/blob/master/rclcpp/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rcpputils`
|
||||
|
||||
The `rcpputils` package provides an API which contains common utilities and data structures useful when programming in C++.
|
||||
|
||||
It is **Quality Level 2**, see its [Quality Declaration document](https://github.com/ros2/rcpputils/blob/master/QUALITY_DECLARATION.md).
|
||||
|
||||
### Direct Runtime non-ROS Dependency [5.iii]
|
||||
|
||||
|
||||
@@ -6,4 +6,4 @@ Visit the [rclcpp_components API documentation](http://docs.ros2.org/latest/api/
|
||||
|
||||
## Quality Declaration
|
||||
|
||||
This package claims to be in the **Quality Level 4** category, see the [Quality Declaration](QUALITY_DECLARATION.md) for more details.
|
||||
This package claims to be in the **Quality Level 3** category, see the [Quality Declaration](QUALITY_DECLARATION.md) for more details.
|
||||
|
||||
@@ -196,6 +196,11 @@ ComponentManager::OnLoadNode(
|
||||
|
||||
try {
|
||||
node_wrappers_[node_id] = factory->create_node_instance(options);
|
||||
} catch (const std::exception & ex) {
|
||||
// In the case that the component constructor throws an exception,
|
||||
// rethrow into the following catch block.
|
||||
throw ComponentManagerException(
|
||||
"Component constructor threw an exception: " + std::string(ex.what()));
|
||||
} catch (...) {
|
||||
// In the case that the component constructor throws an exception,
|
||||
// rethrow into the following catch block.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
This document is a declaration of software quality for the `rclcpp_lifecycle` package, based on the guidelines in [REP-2004](https://www.ros.org/reps/rep-2004.html).
|
||||
|
||||
# `rclcpp_lifecycle` Quality Declaration
|
||||
# rclcpp_lifecycle Quality Declaration
|
||||
|
||||
The package `rclcpp_lifecycle` claims to be in the **Quality Level 4** category.
|
||||
The package `rclcpp_lifecycle` claims to be in the **Quality Level 3** category.
|
||||
|
||||
Below are the rationales, notes, and caveats for this claim, organized by each requirement listed in the [Package Quality Categories in REP-2004](https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#package-quality-categories) of the ROS2 developer guide.
|
||||
|
||||
@@ -10,7 +10,7 @@ Below are the rationales, notes, and caveats for this claim, organized by each r
|
||||
|
||||
### Version Scheme [1.i]
|
||||
|
||||
`rclcpp_lifecycle` uses `semver` according to the recommendation for ROS Core packages in the [ROS 2 Developer Guide](https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#versioning)
|
||||
`rclcpp_lifecycle` uses `semver` according to the recommendation for ROS Core packages in the [ROS 2 Developer Guide](https://index.ros.org/doc/ros2/Contributing/Developer-Guide/#versioning).
|
||||
|
||||
### Version Stability [1.ii]
|
||||
|
||||
@@ -70,23 +70,23 @@ All pull requests must resolve related documentation changes before merging.
|
||||
|
||||
### Feature Documentation [3.i]
|
||||
|
||||
`rclcpp_lifecycle` does not have a documented feature list.
|
||||
`rclcpp_lifecycle` has a [feature list](http://docs.ros2.org/latest/api/rclcpp_lifecycle/index.html) and each item in the list links to the corresponding feature documentation. There is documentation for all of the features, and new features require documentation before being added.
|
||||
|
||||
### Public API Documentation [3.ii]
|
||||
|
||||
`rclcpp_lifecycle` does not cover a public API documentation.
|
||||
The API is publicly available in its [ROS 2 API documentation](http://docs.ros2.org/latest/api/rclcpp_lyfecycle/).
|
||||
|
||||
### License [3.iii]
|
||||
|
||||
The license for `rclcpp_lifecycle` is Apache 2.0, and a summary is in each source file, the type is declared in the [`package.xml`](./package.xml) manifest file, and a full copy of the license is in the [`LICENSE`](../LICENSE) file.
|
||||
|
||||
There is an automated test which runs a linter that ensures each file has a license statement. [Here](http://build.ros2.org/view/Epr/job/Epr__rclcpp_lifecycle__ubuntu_bionic_amd64/lastBuild/testReport/rclcpp_lifecycle/) can be found a list with the latest results of the various linters being run on the package.
|
||||
There is an automated test which runs a linter that ensures each file has a license statement. [Here](http://build.ros2.org/view/Fpr/job/Fpr__rclcpp__ubuntu_focal_amd64/lastSuccessfulBuild/testReport/rclcpp_lifecycle/) can be found a list with the latest results of the various linters being run on the package.
|
||||
|
||||
### Copyright Statements [3.iv]
|
||||
|
||||
The copyright holders each provide a statement of copyright in each source code file in `rclcpp_lifecycle`.
|
||||
|
||||
There is an automated test which runs a linter that ensures each file has at least one copyright statement. Latest linter result report can be seen [here](http://build.ros2.org/view/Epr/job/Epr__rclcpp_lifecycle__ubuntu_bionic_amd64/lastBuild/testReport/rclcpp_lifecycle/copyright/).
|
||||
There is an automated test which runs a linter that ensures each file has at least one copyright statement. Latest linter result report can be seen [here](http://build.ros2.org/view/Fpr/job/Fpr__rclcpp__ubuntu_focal_amd64/lastSuccessfulBuild/testReport/rclcpp_lifecycle/copyright/).
|
||||
|
||||
## Testing [4]
|
||||
|
||||
@@ -119,6 +119,8 @@ This includes:
|
||||
|
||||
Changes are required to make a best effort to keep or increase coverage before being accepted, but decreases are allowed if properly justified and accepted by reviewers.
|
||||
|
||||
Current coverage statistics can be viewed [here](https://ci.ros2.org/job/nightly_linux_coverage/lastSuccessfulBuild/cobertura/src_ros2_rclcpp_rclcpp_lifecycle_src/). A description of how coverage statistics are calculated is summarized in this page ["ROS 2 Onboarding Guide"](https://index.ros.org/doc/ros2/Contributing/ROS-2-On-boarding-Guide/#note-on-coverage-runs).
|
||||
|
||||
### Performance [4.iv]
|
||||
|
||||
It is not yet defined if this package requires performance testing and how addresses this topic.
|
||||
@@ -149,25 +151,31 @@ It also has several test dependencies, which do not affect the resulting quality
|
||||
|
||||
The `lifecycle_msgs` package contains message and service definitions for managing lifecycle nodes.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rcl_interfaces/blob/master/lifecycle_msgs/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ros2/rcl_interfaces/blob/master/lifecycle_msgs/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rclcpp`
|
||||
|
||||
The `rclcpp` package provides the ROS client library in C++.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rclcpp/blob/master/rclcpp/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ros2/rclcpp/blob/master/rclcpp/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rcl_lifecycle`
|
||||
|
||||
The `rcl_lifecycle` package provides functionality for ROS 2 lifecycle nodes in C.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rcl/blob/master/rcl_lifecycle/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ros2/rcl/blob/master/rcl_lifecycle/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rosidl_typesupport_cpp`
|
||||
|
||||
The `rosidl_typesupport_cpp` package generates the type support for C++ messages.
|
||||
|
||||
It is **Quality Level 4**, see its [Quality Declaration document](https://github.com/ros2/rosidl_typesupport/blob/master/rosidl_typesupport_cpp/QUALITY_DECLARATION.md).
|
||||
It is **Quality Level 3**, see its [Quality Declaration document](https://github.com/ros2/rosidl_typesupport/blob/master/rosidl_typesupport_cpp/QUALITY_DECLARATION.md).
|
||||
|
||||
#### `rmw`
|
||||
|
||||
`rmw` is the ROS 2 middleware library.
|
||||
|
||||
It is **Quality Level 2**, see its [Quality Declaration document](https://github.com/ros2/rmw/blob/master/rmw/QUALITY_DECLARATION.md).
|
||||
|
||||
### Direct Runtime non-ROS Dependency [5.iii]
|
||||
|
||||
|
||||
@@ -6,4 +6,4 @@ Visit the [rclcpp_lifecycle API documentation](http://docs.ros2.org/latest/api/r
|
||||
|
||||
## Quality Declaration
|
||||
|
||||
This package claims to be in the **Quality Level 4** category, see the [Quality Declaration](QUALITY_DECLARATION.md) for more details.
|
||||
This package claims to be in the **Quality Level 3** category, see the [Quality Declaration](QUALITY_DECLARATION.md) for more details.
|
||||
|
||||
@@ -469,17 +469,6 @@ public:
|
||||
remove_on_set_parameters_callback(
|
||||
const rclcpp_lifecycle::LifecycleNode::OnSetParametersCallbackHandle * const handler);
|
||||
|
||||
/// Register a callback to be called anytime a parameter is about to be changed.
|
||||
/**
|
||||
* \deprecated Use add_on_set_parameters_callback instead.
|
||||
* \sa rclcpp::Node::set_on_parameters_set_callback
|
||||
*/
|
||||
[[deprecated("use add_on_set_parameters_callback(OnParametersSetCallbackType callback) instead")]]
|
||||
RCLCPP_LIFECYCLE_PUBLIC
|
||||
rclcpp_lifecycle::LifecycleNode::OnParametersSetCallbackType
|
||||
set_on_parameters_set_callback(
|
||||
rclcpp_lifecycle::LifecycleNode::OnParametersSetCallbackType callback);
|
||||
|
||||
/// Return a vector of existing node names (string).
|
||||
/**
|
||||
* \sa rclcpp::Node::get_node_names
|
||||
|
||||
@@ -268,28 +268,6 @@ LifecycleNode::remove_on_set_parameters_callback(
|
||||
node_parameters_->remove_on_set_parameters_callback(callback);
|
||||
}
|
||||
|
||||
// suppress deprecated function warning
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
rclcpp::Node::OnParametersSetCallbackType
|
||||
LifecycleNode::set_on_parameters_set_callback(rclcpp::Node::OnParametersSetCallbackType callback)
|
||||
{
|
||||
return node_parameters_->set_on_parameters_set_callback(callback);
|
||||
}
|
||||
|
||||
// remove warning suppression
|
||||
#if !defined(_WIN32)
|
||||
# pragma GCC diagnostic pop
|
||||
#else // !defined(_WIN32)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
std::vector<std::string>
|
||||
LifecycleNode::get_node_names() const
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
@@ -217,21 +218,31 @@ private:
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
rclcpp::shutdown();
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(shutdown_mutex_);
|
||||
rclcpp::shutdown();
|
||||
}
|
||||
spinner_.join();
|
||||
}
|
||||
|
||||
void spin()
|
||||
{
|
||||
while (rclcpp::ok()) {
|
||||
rclcpp::spin_some(lifecycle_node_->get_node_base_interface());
|
||||
rclcpp::spin_some(lifecycle_client_);
|
||||
while (true) {
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(shutdown_mutex_);
|
||||
if (!rclcpp::ok()) {
|
||||
break;
|
||||
}
|
||||
rclcpp::spin_some(lifecycle_node_->get_node_base_interface());
|
||||
rclcpp::spin_some(lifecycle_client_);
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<EmptyLifecycleNode> lifecycle_node_;
|
||||
std::shared_ptr<LifecycleServiceClient> lifecycle_client_;
|
||||
std::mutex shutdown_mutex_;
|
||||
std::thread spinner_;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user