diff --git a/rcl/CMakeLists.txt b/rcl/CMakeLists.txt index 6edfea269..c9779c41b 100644 --- a/rcl/CMakeLists.txt +++ b/rcl/CMakeLists.txt @@ -35,6 +35,7 @@ set(${PROJECT_NAME}_sources src/rcl/client.c src/rcl/common.c src/rcl/context.c + src/rcl/event.c src/rcl/expand_topic_name.c src/rcl/graph.c src/rcl/guard_condition.c diff --git a/rcl/include/rcl/event.h b/rcl/include/rcl/event.h new file mode 100644 index 000000000..51b30559b --- /dev/null +++ b/rcl/include/rcl/event.h @@ -0,0 +1,169 @@ +// Copyright 2019 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. + +#ifndef RCL__EVENT_H_ +#define RCL__EVENT_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "rcl/client.h" +#include "rcl/macros.h" +#include "rcl/publisher.h" +#include "rcl/service.h" +#include "rcl/subscription.h" +#include "rcl/visibility_control.h" + +typedef enum rcl_publisher_event_type_t +{ + RCL_PUBLISHER_OFFERED_DEADLINE_MISSED, + RCL_PUBLISHER_LIVELINESS_LOST +} rcl_publisher_event_type_t; + +typedef enum rcl_subscription_event_type_t +{ + RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED, + RCL_SUBSCRIPTION_LIVELINESS_CHANGED +} rcl_subscription_event_type_t; + +/// rmw struct. +typedef struct rmw_event_t rmw_event_t; + +/// Internal rcl implementation struct. +struct rcl_event_impl_t; + +/// Structure which encapsulates a ROS QoS event handle. +typedef struct rcl_event_t +{ + struct rcl_event_impl_t * impl; +} rcl_event_t; + +/// Return a rcl_event_t struct with members set to `NULL`. +/** + * Should be called to get a null rcl_event_t before passing to + * rcl_event_init(). + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_event_t +rcl_get_zero_initialized_event(void); + +/// Initialize an rcl_event_t with a publisher. +/** + * Fill the rcl_event_t with the publisher and desired event_type. + * + * \param[in,out] event pointer to fill + * \param[in] publisher to get events from + * \param[in] event_type to listen for + * \return `RCL_RET_OK` if the rcl_event_t is filled, or + * \return `RCL_RET_INVALID_ARGUMENT` if any arguments are invalid, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_publisher_event_init( + rcl_event_t * event, + const rcl_publisher_t * publisher, + const rcl_publisher_event_type_t event_type); + +/// Initialize an rcl_event_t with a subscription. +/** + * Fill the rcl_event_t with the subscription and desired event_type. + * + * \param[in,out] event pointer to fill + * \param[in] subscription to get events from + * \param[in] event_type to listen for + * \return `RCL_RET_OK` if the rcl_event_t is filled, or + * \return `RCL_RET_INVALID_ARGUMENT` if any arguments are invalid, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_subscription_event_init( + rcl_event_t * event, + const rcl_subscription_t * subscription, + const rcl_subscription_event_type_t event_type); + +// Take event using the event handle. +/** + * Take an event from the event handle. + * + * \param[in] event_handle event object to take from + * \param[in, out] event_info event info object to write taken data into + * \param[in, out] taken boolean flag indicating if an event was taken or not + * \return `RCL_RET_OK` if successful, or + * \return `RCL_RET_BAD_ALLOC` if memory allocation failed, or + * \return `RCL_RET_ERROR` if an unexpected error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_take_event( + const rcl_event_t * event, + void * event_info); + +// Finalize an event. +/** + * Finalize an event. + * + * \param[in] event to finalize + * \return `RCL_RET_OK` if successful, or + * \return `RCL_RET_EVENT_INVALID` if event is null, or + * \return `RCL_RET_ERROR` if an unexpected error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_event_fini(rcl_event_t * event); + +/// Return the rmw event handle. +/** + * The handle returned is a pointer to the internally held rmw handle. + * This function can fail, and therefore return `NULL`, if the: + * - event is `NULL` + * - event is invalid (never called init, called fini, or invalid node) + * + * The returned handle is made invalid if the event is finalized or if + * rcl_shutdown() is called. + * The returned handle is not guaranteed to be valid for the life time of the + * event as it may be finalized and recreated itself. + * Therefore it is recommended to get the handle from the event using + * this function each time it is needed and avoid use of the handle + * concurrently with functions that might change it. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] event pointer to the rcl event + * \return rmw event handle if successful, otherwise `NULL` + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rmw_event_t * +rcl_event_get_rmw_handle(const rcl_event_t * event); + +#ifdef __cplusplus +} +#endif + +#endif // RCL__EVENT_H_ diff --git a/rcl/include/rcl/node.h b/rcl/include/rcl/node.h index 6b442ed4d..07c0cd42b 100644 --- a/rcl/include/rcl/node.h +++ b/rcl/include/rcl/node.h @@ -361,6 +361,31 @@ RCL_WARN_UNUSED rcl_ret_t rcl_node_get_domain_id(const rcl_node_t * node, size_t * domain_id); +/// Manually assert that this node is alive (for RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_NODE) +/** + * If the rmw Liveliness policy is set to RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_NODE, the creator of + * this node may manually call `assert_liveliness` at some point in time to signal to the rest + * of the system that this Node is still alive. + * This function must be called at least as often as the qos_profile's liveliness_lease_duration + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] node handle to the node that needs liveliness to be asserted + * \return `RCL_RET_OK` if the liveliness assertion was completed successfully, or + * \return `RCL_RET_NODE_INVALID` if the node is invalid, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_node_assert_liveliness(const rcl_node_t * node); + /// Return the rmw node handle. /** * The handle returned is a pointer to the internally held rmw handle. diff --git a/rcl/include/rcl/publisher.h b/rcl/include/rcl/publisher.h index 8f036582a..5f4834e5a 100644 --- a/rcl/include/rcl/publisher.h +++ b/rcl/include/rcl/publisher.h @@ -300,6 +300,31 @@ rcl_publish_serialized_message( rmw_publisher_allocation_t * allocation ); +/// Manually assert that this Publisher is alive (for RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC) +/** + * If the rmw Liveliness policy is set to RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC, the creator of + * this publisher may manually call `assert_liveliness` at some point in time to signal to the rest + * of the system that this Node is still alive. + * This function must be called at least as often as the qos_profile's liveliness_lease_duration + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] publisher handle to the publisher that needs liveliness to be asserted + * \return `RCL_RET_OK` if the liveliness assertion was completed successfully, or + * \return `RCL_RET_PUBLISHER_INVALID` if the publisher is invalid, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_publisher_assert_liveliness(const rcl_publisher_t * publisher); + /// Get the topic name for the publisher. /** * This function returns the publisher's internal topic name string. diff --git a/rcl/include/rcl/types.h b/rcl/include/rcl/types.h index cba805452..f60eefb5e 100644 --- a/rcl/include/rcl/types.h +++ b/rcl/include/rcl/types.h @@ -99,6 +99,12 @@ typedef rmw_ret_t rcl_ret_t; /// Argument is not a valid log level rule #define RCL_RET_INVALID_LOG_LEVEL_RULE 1020 +// rcl event specific ret codes in 20XX +/// Invalid rcl_event_t given return code. +#define RCL_RET_EVENT_INVALID 2000 +/// Failed to take an event from the event handle +#define RCL_RET_EVENT_TAKE_FAILED 2001 + /// typedef for rmw_serialized_message_t; typedef rmw_serialized_message_t rcl_serialized_message_t; diff --git a/rcl/include/rcl/wait.h b/rcl/include/rcl/wait.h index 53dd0273e..fd6278862 100644 --- a/rcl/include/rcl/wait.h +++ b/rcl/include/rcl/wait.h @@ -29,6 +29,7 @@ extern "C" #include "rcl/service.h" #include "rcl/subscription.h" #include "rcl/timer.h" +#include "rcl/event.h" #include "rcl/types.h" #include "rcl/visibility_control.h" @@ -52,6 +53,9 @@ typedef struct rcl_wait_set_t /// Storage for service pointers. const rcl_service_t ** services; size_t size_of_services; + /// Storage for event pointers. + const rcl_event_t ** events; + size_t size_of_events; /// Implementation specific storage. struct rcl_wait_set_impl_t * impl; } rcl_wait_set_t; @@ -124,6 +128,7 @@ rcl_wait_set_init( size_t number_of_timers, size_t number_of_clients, size_t number_of_services, + size_t number_of_events, rcl_context_t * context, rcl_allocator_t allocator); @@ -289,7 +294,8 @@ rcl_wait_set_resize( size_t guard_conditions_size, size_t timers_size, size_t clients_size, - size_t services_size); + size_t services_size, + size_t events_size); /// Store a pointer to the guard condition in the next empty spot in the set. /** @@ -343,6 +349,19 @@ rcl_wait_set_add_service( const rcl_service_t * service, size_t * index); +/// Store a pointer to the event in the next empty spot in the set. +/** + * This function behaves exactly the same as for subscriptions. + * \see rcl_wait_set_add_subscription + */ +RCL_PUBLIC +RCL_WARN_UNUSED +rcl_ret_t +rcl_wait_set_add_event( + rcl_wait_set_t * wait_set, + const rcl_event_t * event, + size_t * index); + /// Block until the wait set is ready or until the timeout has been exceeded. /** * This function will collect the items in the rcl_wait_set_t and pass them diff --git a/rcl/src/rcl/event.c b/rcl/src/rcl/event.c new file mode 100644 index 000000000..ce1eb326f --- /dev/null +++ b/rcl/src/rcl/event.c @@ -0,0 +1,186 @@ +// Copyright 2019 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. + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "rcl/event.h" + +#include + +#include "rcl/error_handling.h" +#include "rcl/expand_topic_name.h" +#include "rcl/remap.h" +#include "rcutils/logging_macros.h" +#include "rmw/error_handling.h" +#include "rmw/validate_full_topic_name.h" +#include "rmw/event.h" + +#include "./common.h" +#include "./publisher_impl.h" +#include "./subscription_impl.h" + +typedef struct rcl_event_impl_t +{ + rmw_event_t rmw_handle; + rcl_allocator_t allocator; +} rcl_event_impl_t; + +rcl_event_t +rcl_get_zero_initialized_event() +{ + static rcl_event_t null_event = {0}; + return null_event; +} + +rcl_ret_t +rcl_publisher_event_init( + rcl_event_t * event, + const rcl_publisher_t * publisher, + const rcl_publisher_event_type_t event_type) +{ + rcl_ret_t ret = RCL_RET_OK; + RCL_CHECK_ARGUMENT_FOR_NULL(event, RCL_RET_EVENT_INVALID); + // Check publisher and allocator first, so allocator can be used with errors. + RCL_CHECK_ARGUMENT_FOR_NULL(publisher, RCL_RET_INVALID_ARGUMENT); + rcl_allocator_t * allocator = &publisher->impl->options.allocator; + RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, "invalid allocator", return RCL_RET_INVALID_ARGUMENT); + + // Allocate space for the implementation struct. + event->impl = (rcl_event_impl_t *) allocator->allocate( + sizeof(rcl_event_impl_t), allocator->state); + RCL_CHECK_FOR_NULL_WITH_MSG( + event->impl, "allocating memory failed", ret = RCL_RET_BAD_ALLOC; return ret); + + event->impl->rmw_handle = rmw_get_zero_initialized_event(); + event->impl->allocator = *allocator; + + rmw_event_type_t rmw_event_type = RMW_EVENT_INVALID; + switch (event_type) { + case RCL_PUBLISHER_OFFERED_DEADLINE_MISSED: + rmw_event_type = RMW_EVENT_OFFERED_DEADLINE_MISSED; + break; + case RCL_PUBLISHER_LIVELINESS_LOST: + rmw_event_type = RMW_EVENT_LIVELINESS_LOST; + break; + default: + RCL_SET_ERROR_MSG("Event type for publisher not supported"); + return RCL_RET_INVALID_ARGUMENT; + } + return rmw_publisher_event_init( + &event->impl->rmw_handle, + publisher->impl->rmw_handle, + rmw_event_type); +} + +rcl_ret_t +rcl_subscription_event_init( + rcl_event_t * event, + const rcl_subscription_t * subscription, + const rcl_subscription_event_type_t event_type) +{ + rcl_ret_t ret = RCL_RET_OK; + RCL_CHECK_ARGUMENT_FOR_NULL(event, RCL_RET_EVENT_INVALID); + // Check subscription and allocator first, so allocator can be used with errors. + RCL_CHECK_ARGUMENT_FOR_NULL(subscription, RCL_RET_INVALID_ARGUMENT); + rcl_allocator_t * allocator = &subscription->impl->options.allocator; + RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, "invalid allocator", return RCL_RET_INVALID_ARGUMENT); + + // Allocate space for the implementation struct. + event->impl = (rcl_event_impl_t *) allocator->allocate( + sizeof(rcl_event_impl_t), allocator->state); + RCL_CHECK_FOR_NULL_WITH_MSG( + event->impl, "allocating memory failed", ret = RCL_RET_BAD_ALLOC; return ret); + + event->impl->rmw_handle = rmw_get_zero_initialized_event(); + event->impl->allocator = *allocator; + + rmw_event_type_t rmw_event_type = RMW_EVENT_INVALID; + switch (event_type) { + case RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED: + rmw_event_type = RMW_EVENT_REQUESTED_DEADLINE_MISSED; + break; + case RCL_SUBSCRIPTION_LIVELINESS_CHANGED: + rmw_event_type = RMW_EVENT_LIVELINESS_CHANGED; + break; + default: + RCL_SET_ERROR_MSG("Event type for subscription not supported"); + return RCL_RET_INVALID_ARGUMENT; + } + return rmw_subscription_event_init( + &event->impl->rmw_handle, + subscription->impl->rmw_handle, + rmw_event_type); +} + +rcl_ret_t +rcl_take_event( + const rcl_event_t * event, + void * event_info) +{ + bool taken = false; + RCL_CHECK_ARGUMENT_FOR_NULL(event, RCL_RET_EVENT_INVALID); + RCL_CHECK_ARGUMENT_FOR_NULL(event_info, RCL_RET_INVALID_ARGUMENT); + rmw_ret_t ret = rmw_take_event(&event->impl->rmw_handle, event_info, &taken); + if (RMW_RET_OK != ret) { + RCL_SET_ERROR_MSG(rmw_get_error_string().str); + return rcl_convert_rmw_ret_to_rcl_ret(ret); + } + if (!taken) { + RCUTILS_LOG_DEBUG_NAMED( + ROS_PACKAGE_NAME, "take_event request complete, unable to take event"); + return RCL_RET_EVENT_TAKE_FAILED; + } + RCUTILS_LOG_DEBUG_NAMED( + ROS_PACKAGE_NAME, "take_event request success"); + return rcl_convert_rmw_ret_to_rcl_ret(ret); +} + +rcl_ret_t +rcl_event_fini(rcl_event_t * event) +{ + rcl_ret_t result = RCL_RET_OK; + RCL_CHECK_ARGUMENT_FOR_NULL(event, RCL_RET_EVENT_INVALID); + + RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Finalizing event"); + if (NULL != event->impl) { + rcl_allocator_t allocator = event->impl->allocator; + rmw_ret_t ret = rmw_event_fini(&event->impl->rmw_handle); + if (ret != RMW_RET_OK) { + RCL_SET_ERROR_MSG(rmw_get_error_string().str); + result = rcl_convert_rmw_ret_to_rcl_ret(ret); + } + allocator.deallocate(event->impl, allocator.state); + event->impl = NULL; + } + RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Event finalized"); + + return result; +} + +rmw_event_t * +rcl_event_get_rmw_handle(const rcl_event_t * event) +{ + if (NULL == event) { + return NULL; // error already set + } else { + return &event->impl->rmw_handle; + } +} + +#ifdef __cplusplus +} +#endif diff --git a/rcl/src/rcl/node.c b/rcl/src/rcl/node.c index 4c57153e8..19cdf5dc1 100644 --- a/rcl/src/rcl/node.c +++ b/rcl/src/rcl/node.c @@ -525,6 +525,19 @@ rcl_node_get_domain_id(const rcl_node_t * node, size_t * domain_id) return RCL_RET_OK; } +rcl_ret_t +rcl_node_assert_liveliness(const rcl_node_t * node) +{ + if (!rcl_node_is_valid(node)) { + return RCL_RET_NODE_INVALID; // error already set + } + if (rmw_node_assert_liveliness(node->impl->rmw_node_handle) != RMW_RET_OK) { + RCL_SET_ERROR_MSG(rmw_get_error_string().str); + return RCL_RET_ERROR; + } + return RCL_RET_OK; +} + rmw_node_t * rcl_node_get_rmw_handle(const rcl_node_t * node) { diff --git a/rcl/src/rcl/publisher.c b/rcl/src/rcl/publisher.c index 4eec91903..bde157342 100644 --- a/rcl/src/rcl/publisher.c +++ b/rcl/src/rcl/publisher.c @@ -22,23 +22,16 @@ extern "C" #include #include -#include "./common.h" #include "rcl/allocator.h" #include "rcl/error_handling.h" #include "rcl/expand_topic_name.h" #include "rcl/remap.h" #include "rcutils/logging_macros.h" #include "rmw/error_handling.h" -#include "rmw/rmw.h" #include "rmw/validate_full_topic_name.h" -typedef struct rcl_publisher_impl_t -{ - rcl_publisher_options_t options; - rmw_qos_profile_t actual_qos; - rcl_context_t * context; - rmw_publisher_t * rmw_handle; -} rcl_publisher_impl_t; +#include "./common.h" +#include "./publisher_impl.h" rcl_publisher_t rcl_get_zero_initialized_publisher() @@ -289,6 +282,19 @@ rcl_publish_serialized_message( return RCL_RET_OK; } +rcl_ret_t +rcl_publisher_assert_liveliness(const rcl_publisher_t * publisher) +{ + if (!rcl_publisher_is_valid(publisher)) { + return RCL_RET_PUBLISHER_INVALID; // error already set + } + if (rmw_publisher_assert_liveliness(publisher->impl->rmw_handle) != RMW_RET_OK) { + RCL_SET_ERROR_MSG(rmw_get_error_string().str); + return RCL_RET_ERROR; + } + return RCL_RET_OK; +} + const char * rcl_publisher_get_topic_name(const rcl_publisher_t * publisher) { diff --git a/rcl/src/rcl/publisher_impl.h b/rcl/src/rcl/publisher_impl.h new file mode 100644 index 000000000..485a7c5ec --- /dev/null +++ b/rcl/src/rcl/publisher_impl.h @@ -0,0 +1,30 @@ +// Copyright 2015 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. + +#ifndef RCL__PUBLISHER_IMPL_H_ +#define RCL__PUBLISHER_IMPL_H_ + +#include "rmw/rmw.h" + +#include "rcl/publisher.h" + +typedef struct rcl_publisher_impl_t +{ + rcl_publisher_options_t options; + rmw_qos_profile_t actual_qos; + rcl_context_t * context; + rmw_publisher_t * rmw_handle; +} rcl_publisher_impl_t; + +#endif // RCL__PUBLISHER_IMPL_H_ diff --git a/rcl/src/rcl/subscription.c b/rcl/src/rcl/subscription.c index 43e2d770e..1cda902ff 100644 --- a/rcl/src/rcl/subscription.c +++ b/rcl/src/rcl/subscription.c @@ -21,20 +21,16 @@ extern "C" #include -#include "./common.h" #include "rcl/error_handling.h" #include "rcl/expand_topic_name.h" #include "rcl/remap.h" #include "rcutils/logging_macros.h" #include "rmw/error_handling.h" -#include "rmw/rmw.h" #include "rmw/validate_full_topic_name.h" -typedef struct rcl_subscription_impl_t -{ - rcl_subscription_options_t options; - rmw_subscription_t * rmw_handle; -} rcl_subscription_impl_t; +#include "./common.h" +#include "./subscription_impl.h" + rcl_subscription_t rcl_get_zero_initialized_subscription() diff --git a/rcl/src/rcl/subscription_impl.h b/rcl/src/rcl/subscription_impl.h new file mode 100644 index 000000000..7ad0fd8bc --- /dev/null +++ b/rcl/src/rcl/subscription_impl.h @@ -0,0 +1,28 @@ +// Copyright 2015 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. + +#ifndef RCL__SUBSCRIPTION_IMPL_H_ +#define RCL__SUBSCRIPTION_IMPL_H_ + +#include "rmw/rmw.h" + +#include "rcl/subscription.h" + +typedef struct rcl_subscription_impl_t +{ + rcl_subscription_options_t options; + rmw_subscription_t * rmw_handle; +} rcl_subscription_impl_t; + +#endif // RCL__SUBSCRIPTION_IMPL_H_ diff --git a/rcl/src/rcl/wait.c b/rcl/src/rcl/wait.c index 20117a135..a4694365f 100644 --- a/rcl/src/rcl/wait.c +++ b/rcl/src/rcl/wait.c @@ -29,6 +29,7 @@ extern "C" #include "rcutils/logging_macros.h" #include "rmw/error_handling.h" #include "rmw/rmw.h" +#include "rmw/event.h" #include "./context_impl.h" @@ -46,6 +47,10 @@ typedef struct rcl_wait_set_impl_t // number of services that have been added to the wait set size_t service_index; rmw_services_t rmw_services; + // number of events that have been added to the wait set + size_t event_index; + rmw_events_t rmw_events; + rmw_wait_set_t * rmw_wait_set; // number of timers that have been added to the wait set size_t timer_index; @@ -83,7 +88,7 @@ __wait_set_is_valid(const rcl_wait_set_t * wait_set) static void __wait_set_clean_up(rcl_wait_set_t * wait_set, rcl_allocator_t allocator) { - rcl_ret_t ret = rcl_wait_set_resize(wait_set, 0, 0, 0, 0, 0); + rcl_ret_t ret = rcl_wait_set_resize(wait_set, 0, 0, 0, 0, 0, 0); (void)ret; // NO LINT assert(RCL_RET_OK == ret); // Defensive, shouldn't fail with size 0. if (wait_set->impl) { @@ -100,6 +105,7 @@ rcl_wait_set_init( size_t number_of_timers, size_t number_of_clients, size_t number_of_services, + size_t number_of_events, rcl_context_t * context, rcl_allocator_t allocator) { @@ -138,12 +144,15 @@ rcl_wait_set_init( wait_set->impl->rmw_clients.client_count = 0; wait_set->impl->rmw_services.services = NULL; wait_set->impl->rmw_services.service_count = 0; + wait_set->impl->rmw_events.events = NULL; + wait_set->impl->rmw_events.event_count = 0; size_t num_conditions = (2 * number_of_subscriptions) + number_of_guard_conditions + number_of_clients + - number_of_services; + number_of_services + + number_of_events; wait_set->impl->rmw_wait_set = rmw_create_wait_set(&(context->impl->rmw_context), num_conditions); if (!wait_set->impl->rmw_wait_set) { @@ -157,7 +166,7 @@ rcl_wait_set_init( // Initialize subscription space. rcl_ret_t ret = rcl_wait_set_resize( wait_set, number_of_subscriptions, number_of_guard_conditions, number_of_timers, - number_of_clients, number_of_services); + number_of_clients, number_of_services, number_of_events); if (RCL_RET_OK != ret) { fail_ret = ret; goto fail; @@ -328,6 +337,7 @@ rcl_wait_set_clear(rcl_wait_set_t * wait_set) SET_CLEAR(guard_condition); SET_CLEAR(client); SET_CLEAR(service); + SET_CLEAR(event); SET_CLEAR(timer); SET_CLEAR_RMW( @@ -346,6 +356,10 @@ rcl_wait_set_clear(rcl_wait_set_t * wait_set) services, rmw_services.services, rmw_services.service_count); + SET_CLEAR_RMW( + events, + rmw_events.events, + rmw_events.event_count); return RCL_RET_OK; } @@ -362,7 +376,8 @@ rcl_wait_set_resize( size_t guard_conditions_size, size_t timers_size, size_t clients_size, - size_t services_size) + size_t services_size, + size_t events_size) { RCL_CHECK_ARGUMENT_FOR_NULL(wait_set, RCL_RET_INVALID_ARGUMENT); RCL_CHECK_ARGUMENT_FOR_NULL(wait_set->impl, RCL_RET_WAIT_SET_INVALID); @@ -419,6 +434,13 @@ rcl_wait_set_resize( SET_RESIZE_RMW_REALLOC( service, rmw_services.services, rmw_services.service_count) ); + SET_RESIZE(event, + SET_RESIZE_RMW_DEALLOC( + rmw_events.events, rmw_events.event_count), + SET_RESIZE_RMW_REALLOC( + event, rmw_events.events, rmw_events.event_count) + ); + return RCL_RET_OK; } @@ -477,6 +499,18 @@ rcl_wait_set_add_service( return RCL_RET_OK; } +rcl_ret_t +rcl_wait_set_add_event( + rcl_wait_set_t * wait_set, + const rcl_event_t * event, + size_t * index) +{ + SET_ADD(event) + SET_ADD_RMW(event, rmw_events.events, rmw_events.event_count) + wait_set->impl->rmw_events.events[current_index] = rmw_handle; + return RCL_RET_OK; +} + rcl_ret_t rcl_wait(rcl_wait_set_t * wait_set, int64_t timeout) { @@ -490,7 +524,8 @@ rcl_wait(rcl_wait_set_t * wait_set, int64_t timeout) wait_set->size_of_guard_conditions == 0 && wait_set->size_of_timers == 0 && wait_set->size_of_clients == 0 && - wait_set->size_of_services == 0) + wait_set->size_of_services == 0 && + wait_set->size_of_events == 0) { RCL_SET_ERROR_MSG("wait set is empty"); return RCL_RET_WAIT_SET_EMPTY; @@ -569,6 +604,7 @@ rcl_wait(rcl_wait_set_t * wait_set, int64_t timeout) &wait_set->impl->rmw_guard_conditions, &wait_set->impl->rmw_services, &wait_set->impl->rmw_clients, + &wait_set->impl->rmw_events, wait_set->impl->rmw_wait_set, timeout_argument); @@ -631,6 +667,14 @@ rcl_wait(rcl_wait_set_t * wait_set, int64_t timeout) wait_set->services[i] = NULL; } } + // Set corresponding rcl event handles NULL. + for (i = 0; i < wait_set->size_of_events; ++i) { + bool is_ready = wait_set->impl->rmw_events.events[i] != NULL; + RCUTILS_LOG_DEBUG_EXPRESSION_NAMED(is_ready, ROS_PACKAGE_NAME, "Event in wait set is ready"); + if (!is_ready) { + wait_set->events[i] = NULL; + } + } if (RMW_RET_TIMEOUT == ret && !is_timer_timeout) { return RCL_RET_TIMEOUT; diff --git a/rcl/test/CMakeLists.txt b/rcl/test/CMakeLists.txt index a66c95e3f..5ffae7cba 100644 --- a/rcl/test/CMakeLists.txt +++ b/rcl/test/CMakeLists.txt @@ -199,6 +199,21 @@ function(test_target_function) AMENT_DEPENDENCIES ${rmw_implementation} "osrf_testing_tools_cpp" "test_msgs" ) + # TODO(mm318): test_events seem to be failing on the macOS build farm. + # we will try to re-enable this test asap. + set(AMENT_GTEST_ARGS "") + if(APPLE) + set(AMENT_GTEST_ARGS "SKIP_TEST") + endif() + rcl_add_custom_gtest(test_events${target_suffix} + SRCS rcl/test_events.cpp + ENV ${rmw_implementation_env_var} + APPEND_LIBRARY_DIRS ${extra_lib_dirs} + LIBRARIES ${PROJECT_NAME} + AMENT_DEPENDENCIES ${rmw_implementation} "osrf_testing_tools_cpp" "test_msgs" + ${AMENT_GTEST_ARGS} + ) + rcl_add_custom_gtest(test_wait${target_suffix} SRCS rcl/test_wait.cpp ENV ${rmw_implementation_env_var} diff --git a/rcl/test/rcl/client_fixture.cpp b/rcl/test/rcl/client_fixture.cpp index 6ccdabe6c..75758c542 100644 --- a/rcl/test/rcl/client_fixture.cpp +++ b/rcl/test/rcl/client_fixture.cpp @@ -63,7 +63,8 @@ wait_for_client_to_be_ready( int64_t period_ms) { rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); - rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 0, 0, 1, 0, context, rcl_get_default_allocator()); + rcl_ret_t ret = + rcl_wait_set_init(&wait_set, 0, 0, 0, 1, 0, 0, context, rcl_get_default_allocator()); if (ret != RCL_RET_OK) { RCUTILS_LOG_ERROR_NAMED( ROS_PACKAGE_NAME, "Error in wait set init: %s", rcl_get_error_string().str); diff --git a/rcl/test/rcl/service_fixture.cpp b/rcl/test/rcl/service_fixture.cpp index 6f38c0a75..20aca9c5f 100644 --- a/rcl/test/rcl/service_fixture.cpp +++ b/rcl/test/rcl/service_fixture.cpp @@ -36,7 +36,8 @@ wait_for_service_to_be_ready( int64_t period_ms) { rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); - rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 0, 0, 0, 1, context, rcl_get_default_allocator()); + rcl_ret_t ret = + rcl_wait_set_init(&wait_set, 0, 0, 0, 0, 1, 0, context, rcl_get_default_allocator()); if (ret != RCL_RET_OK) { RCUTILS_LOG_ERROR_NAMED( ROS_PACKAGE_NAME, "Error in wait set init: %s", rcl_get_error_string().str); diff --git a/rcl/test/rcl/test_count_matched.cpp b/rcl/test/rcl/test_count_matched.cpp index c0eae560b..afa3dca0e 100644 --- a/rcl/test/rcl/test_count_matched.cpp +++ b/rcl/test/rcl/test_count_matched.cpp @@ -122,7 +122,7 @@ class CLASSNAME (TestCountFixture, RMW_IMPLEMENTATION) : public ::testing::Test this->wait_set_ptr = new rcl_wait_set_t; *this->wait_set_ptr = rcl_get_zero_initialized_wait_set(); ret = rcl_wait_set_init( - this->wait_set_ptr, 0, 1, 0, 0, 0, this->context_ptr, rcl_get_default_allocator()); + this->wait_set_ptr, 0, 1, 0, 0, 0, 0, this->context_ptr, rcl_get_default_allocator()); } void TearDown() @@ -194,7 +194,7 @@ TEST_F(CLASSNAME(TestCountFixture, RMW_IMPLEMENTATION), rcl_publisher_t pub = rcl_get_zero_initialized_publisher(); - rcl_publisher_options_t pub_ops; + rcl_publisher_options_t pub_ops = rcl_publisher_get_default_options(); pub_ops.qos.history = RMW_QOS_POLICY_HISTORY_KEEP_LAST; pub_ops.qos.depth = 10; pub_ops.qos.reliability = RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT; @@ -214,7 +214,7 @@ TEST_F(CLASSNAME(TestCountFixture, RMW_IMPLEMENTATION), rcl_subscription_t sub = rcl_get_zero_initialized_subscription(); - rcl_subscription_options_t sub_ops; + rcl_subscription_options_t sub_ops = rcl_subscription_get_default_options(); sub_ops.qos.history = RMW_QOS_POLICY_HISTORY_KEEP_LAST; sub_ops.qos.depth = 10; sub_ops.qos.reliability = RMW_QOS_POLICY_RELIABILITY_RELIABLE; diff --git a/rcl/test/rcl/test_events.cpp b/rcl/test/rcl/test_events.cpp new file mode 100644 index 000000000..c33a702c3 --- /dev/null +++ b/rcl/test/rcl/test_events.cpp @@ -0,0 +1,639 @@ +// Copyright 2019 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 + +#include +#include +#include + +#include "rcl/rcl.h" +#include "rcl/subscription.h" +#include "rcl/error_handling.h" + +#include "test_msgs/msg/strings.h" +#include "rosidl_generator_c/string_functions.h" + +#include "osrf_testing_tools_cpp/scope_exit.hpp" + +using std::chrono::milliseconds; +using std::chrono::seconds; + +constexpr seconds LIVELINESS_LEASE_DURATION_IN_S(1); +constexpr seconds DEADLINE_PERIOD_IN_S(1); + +#ifdef RMW_IMPLEMENTATION +# define CLASSNAME_(NAME, SUFFIX) NAME ## __ ## SUFFIX +# define CLASSNAME(NAME, SUFFIX) CLASSNAME_(NAME, SUFFIX) +#else +# define CLASSNAME(NAME, SUFFIX) NAME +#endif + +class CLASSNAME (TestEventFixture, RMW_IMPLEMENTATION) : public ::testing::Test +{ +public: + void SetUp() + { + is_opensplice = (std::string(rmw_get_implementation_identifier()).find("rmw_opensplice") == 0); + is_fastrtps = (std::string(rmw_get_implementation_identifier()).find("rmw_fastrtps") == 0); + + // TODO(mm318): Revisit once FastRTPS supports these QoS policies + is_unsupported = is_fastrtps; + + rcl_ret_t ret; + { + rcl_init_options_t init_options = rcl_get_zero_initialized_init_options(); + ret = rcl_init_options_init(&init_options, rcl_get_default_allocator()); + ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({ + EXPECT_EQ(RCL_RET_OK, rcl_init_options_fini(&init_options)) << rcl_get_error_string().str; + }); + this->context_ptr = new rcl_context_t; + *this->context_ptr = rcl_get_zero_initialized_context(); + ret = rcl_init(0, nullptr, &init_options, this->context_ptr); + ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + } + this->node_ptr = new rcl_node_t; + *this->node_ptr = rcl_get_zero_initialized_node(); + const char * name = "test_event_node"; + rcl_node_options_t node_options = rcl_node_get_default_options(); + ret = rcl_node_init(this->node_ptr, name, "", this->context_ptr, &node_options); + ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + ts = ROSIDL_GET_MSG_TYPE_SUPPORT(test_msgs, msg, Strings); + } + + rcl_ret_t setup_publisher( + const rmw_time_t & deadline, + const rmw_time_t & lifespan, + const rmw_time_t & liveliness_lease_duration, + const rmw_qos_liveliness_policy_t liveliness_policy) + { + // init publisher + publisher = rcl_get_zero_initialized_publisher(); + rcl_publisher_options_t publisher_options = rcl_publisher_get_default_options(); + publisher_options.qos.deadline = deadline; + publisher_options.qos.lifespan = lifespan; + publisher_options.qos.liveliness = liveliness_policy; + publisher_options.qos.liveliness_lease_duration = liveliness_lease_duration; + return rcl_publisher_init( + &publisher, + this->node_ptr, + this->ts, + this->topic, + &publisher_options); + } + + rcl_ret_t setup_subscriber( + const rmw_time_t & deadline, + const rmw_time_t & lifespan, + const rmw_time_t & liveliness_lease_duration, + const rmw_qos_liveliness_policy_t liveliness_policy) + { + // init publisher + subscription = rcl_get_zero_initialized_subscription(); + rcl_subscription_options_t subscription_options = rcl_subscription_get_default_options(); + subscription_options.qos.deadline = deadline; + subscription_options.qos.lifespan = lifespan; + subscription_options.qos.liveliness = liveliness_policy; + subscription_options.qos.liveliness_lease_duration = liveliness_lease_duration; + + return rcl_subscription_init( + &subscription, + this->node_ptr, + this->ts, + this->topic, + &subscription_options); + } + + void setup_publisher_and_subscriber( + const rcl_publisher_event_type_t & pub_event_type, + const rcl_subscription_event_type_t & sub_event_type) + { + rcl_ret_t ret; + + rmw_time_t lifespan {0, 0}; + rmw_time_t deadline {DEADLINE_PERIOD_IN_S.count(), 0}; + rmw_time_t lease_duration {LIVELINESS_LEASE_DURATION_IN_S.count(), 0}; + rmw_qos_liveliness_policy_t liveliness_policy = RMW_QOS_POLICY_LIVELINESS_AUTOMATIC; + + // init publisher + ret = setup_publisher(deadline, lifespan, lease_duration, liveliness_policy); + ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + + // init publisher events + publisher_event = rcl_get_zero_initialized_event(); + ret = rcl_publisher_event_init(&publisher_event, &publisher, pub_event_type); + ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + + // init subscription + ret = setup_subscriber(deadline, lifespan, lease_duration, liveliness_policy); + ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + + // init subscription event + subscription_event = rcl_get_zero_initialized_event(); + ret = rcl_subscription_event_init(&subscription_event, &subscription, sub_event_type); + ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + + // wait for discovery + // total wait time of 10 seconds, if never ready + size_t max_iterations = 1000; + milliseconds wait_period(10); + size_t iteration = 0; + do { + iteration++; + size_t count = 0; + rcl_ret_t ret = rcl_subscription_get_publisher_count(&subscription, &count); + ASSERT_EQ(ret, RCL_RET_OK); + if (count > 0) { + break; + } + std::this_thread::sleep_for(wait_period); + } while (iteration < max_iterations); + } + + void tear_down_publisher_subscriber() + { + rcl_ret_t ret; + + ret = rcl_event_fini(&subscription_event); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + + ret = rcl_subscription_fini(&subscription, this->node_ptr); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + + ret = rcl_event_fini(&publisher_event); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + + ret = rcl_publisher_fini(&publisher, this->node_ptr); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + } + + void TearDown() + { + rcl_ret_t ret; + + ret = rcl_node_fini(this->node_ptr); + delete this->node_ptr; + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + + ret = rcl_shutdown(this->context_ptr); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + + ret = rcl_context_fini(this->context_ptr); + delete this->context_ptr; + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + } + +protected: + rcl_context_t * context_ptr; + rcl_node_t * node_ptr; + + rcl_publisher_t publisher; + rcl_event_t publisher_event; + rcl_subscription_t subscription; + rcl_event_t subscription_event; + bool is_fastrtps; + bool is_opensplice; + bool is_unsupported; + const char * topic = "rcl_test_publisher_subscription_events"; + const rosidl_message_type_support_t * ts; +}; + +rcl_ret_t +wait_for_msgs_and_events( + rcl_subscription_t * subscription, + rcl_event_t * subscription_event, + rcl_event_t * publisher_event, + rcl_context_t * context, + int64_t period_ms, + bool * msg_ready, + bool * subscription_event_ready, + bool * publisher_event_ready) +{ + *msg_ready = false; + *subscription_event_ready = false; + *publisher_event_ready = false; + + int num_subscriptions = (nullptr == subscription ? 0 : 1); + int num_events = (nullptr == subscription_event ? 0 : 1) + (nullptr == publisher_event ? 0 : 1); + + rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); + rcl_ret_t ret = rcl_wait_set_init( + &wait_set, + num_subscriptions, 0, 0, 0, 0, num_events, + context, + rcl_get_default_allocator()); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({ + rcl_ret_t ret = rcl_wait_set_fini(&wait_set); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + }); + + ret = rcl_wait_set_clear(&wait_set); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + + if (nullptr != subscription) { + ret = rcl_wait_set_add_subscription(&wait_set, subscription, NULL); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + } + if (nullptr != subscription_event) { + ret = rcl_wait_set_add_event(&wait_set, subscription_event, NULL); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + } + if (nullptr != publisher_event) { + ret = rcl_wait_set_add_event(&wait_set, publisher_event, NULL); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + } + + ret = rcl_wait(&wait_set, RCL_MS_TO_NS(period_ms)); + if (ret == RCL_RET_TIMEOUT) { + return ret; + } + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + + for (size_t i = 0; i < wait_set.size_of_subscriptions; ++i) { + if (wait_set.subscriptions[i] && wait_set.subscriptions[i] == subscription) { + *msg_ready = true; + } + } + for (size_t i = 0; i < wait_set.size_of_events; ++i) { + if (nullptr != wait_set.events[i]) { + if (wait_set.events[i] == subscription_event) { + *subscription_event_ready = true; + } else if (wait_set.events[i] == publisher_event) { + *publisher_event_ready = true; + } + } + } + + return RCL_RET_OK; +} + +/// Conditional function for determining when the wait_for_msgs_and_events loop is complete. +/** + * Conditional function for determining when the wait_for_msgs_and_events loop is complete. + * + * \param msg_persist_ready true if a msg has ever been received + * \param subscription_persist_readytrue if a subscription has been received + * \param publisher_persist_ready true if a pulbisher event has been received + * \return true when the desired conditions are met + */ +using WaitConditionPredicate = std::function< + bool ( + const bool & msg_persist_ready, + const bool & subscription_persist_ready, + const bool & publisher_persist_ready + )>; + +// Wait for msgs and events until all conditions are met or a timeout has occured. +template +rcl_ret_t +conditional_wait_for_msgs_and_events( + const WaitConditionPredicate & events_ready, + rcl_subscription_t * subscription, + rcl_event_t * subscription_event, + rcl_event_t * publisher_event, + rcl_context_t * context, + int64_t period_ms, + bool * msg_persist_ready, + bool * subscription_persist_ready, + bool * publisher_persist_ready, + test_msgs__msg__Strings * msg, + S * subscription_discrete_event, + P * publisher_discrete_event) +{ + *msg_persist_ready = false; + *subscription_persist_ready = false; + *publisher_persist_ready = false; + auto timeout = milliseconds(2000); + auto start_time = std::chrono::system_clock::now(); + bool msg_ready, subscription_event_ready, publisher_event_ready; + do { + // wait for msg and events + wait_for_msgs_and_events(subscription, subscription_event, publisher_event, + context, period_ms, &msg_ready, &subscription_event_ready, &publisher_event_ready); + // test that the message published to topic is as expected + if (msg_ready) { + EXPECT_EQ(rcl_take(subscription, msg, nullptr, nullptr), RCL_RET_OK); + } + if (subscription_event_ready && subscription_discrete_event) { + EXPECT_EQ(rcl_take_event(subscription_event, subscription_discrete_event), RCL_RET_OK); + } + if (publisher_event_ready && publisher_discrete_event) { + EXPECT_EQ(rcl_take_event(publisher_event, publisher_discrete_event), RCL_RET_OK); + } + *msg_persist_ready |= msg_ready; + *subscription_persist_ready |= subscription_event_ready; + *publisher_persist_ready |= publisher_event_ready; + if (std::chrono::system_clock::now() - start_time > timeout) { + return RCL_RET_TIMEOUT; + } + } while (!(events_ready(*msg_persist_ready, + *subscription_persist_ready, + *publisher_persist_ready))); + return RCL_RET_OK; +} + +TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_unsupported_lifespan) { + if (is_unsupported) { + rmw_time_t deadline {0, 0}; + rmw_time_t lifespan {1, 0}; + rmw_time_t lease_duration {1, 0}; + rmw_qos_liveliness_policy_t liveliness_policy = RMW_QOS_POLICY_LIVELINESS_AUTOMATIC; + EXPECT_EQ(RCL_RET_ERROR, + setup_subscriber(deadline, lifespan, lease_duration, + liveliness_policy)) << "Initialized subscriber lifespan when unsupported"; + EXPECT_EQ(RCL_RET_ERROR, + setup_publisher(deadline, lifespan, lease_duration, + liveliness_policy)) << "Initialized publisher lifespan when unsupported"; + + lifespan = {0, 1}; + EXPECT_EQ(RCL_RET_ERROR, + setup_subscriber(deadline, lifespan, lease_duration, + liveliness_policy)) << "Initialized subscriber lifespan when unsupported"; + EXPECT_EQ(RCL_RET_ERROR, + setup_publisher(deadline, lifespan, lease_duration, + liveliness_policy)) << "Initialized publisher lifespan when unsupported"; + } +} + +TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_unsupported_liveliness) { + if (is_unsupported) { + rmw_time_t deadline {0, 0}; + rmw_time_t lifespan {0, 0}; + rmw_time_t lease_duration {0, 0}; + rmw_qos_liveliness_policy_t liveliness_policy = RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_NODE; + EXPECT_EQ(RCL_RET_ERROR, + setup_subscriber(deadline, lifespan, lease_duration, + liveliness_policy)) << + "Initialized subscriber RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_NODE when unsupported"; + EXPECT_EQ(RCL_RET_ERROR, + setup_publisher(deadline, lifespan, lease_duration, + liveliness_policy)) << + "Initialized publisher RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_NODE when unsupported"; + + liveliness_policy = RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC; + EXPECT_EQ(RCL_RET_ERROR, + setup_subscriber(deadline, lifespan, lease_duration, + liveliness_policy)) << + "Initialized subscriber RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC when unsupported"; + EXPECT_EQ(RCL_RET_ERROR, + setup_publisher(deadline, lifespan, lease_duration, + liveliness_policy)) << + "Initialized publisher RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC when unsupported"; + } +} + +TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_unsupported_unsupported_deadline) { + if (is_unsupported) { + rmw_time_t deadline {1, 0}; + rmw_time_t lifespan {0, 0}; + rmw_time_t lease_duration {0, 0}; + rmw_qos_liveliness_policy_t liveliness_policy = RMW_QOS_POLICY_LIVELINESS_AUTOMATIC; + EXPECT_EQ(RCL_RET_ERROR, + setup_subscriber(deadline, lifespan, lease_duration, + liveliness_policy)) << "Initialized subscriber deadline when unsupported"; + EXPECT_EQ(RCL_RET_ERROR, + setup_publisher(deadline, lifespan, lease_duration, + liveliness_policy)) << "Initialized publisher deadline when unsupported"; + + deadline = {0, 1}; + EXPECT_EQ(RCL_RET_ERROR, + setup_subscriber(deadline, lifespan, lease_duration, + liveliness_policy)) << "Initialized subscriber deadline when unsupported"; + EXPECT_EQ(RCL_RET_ERROR, + setup_publisher(deadline, lifespan, lease_duration, + liveliness_policy)) << "Initialized publisher deadline when unsupported"; + } +} + +/* + * Basic test of publisher and subscriber liveliness events, with publisher killed + */ +TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_pubsub_liveliness_kill_pub) +{ + if (is_unsupported) { + return; + } + setup_publisher_and_subscriber(RCL_PUBLISHER_LIVELINESS_LOST, + RCL_SUBSCRIPTION_LIVELINESS_CHANGED); + rcl_ret_t ret; + + // publish message to topic + const char * test_string = "testing"; + { + test_msgs__msg__Strings msg; + test_msgs__msg__Strings__init(&msg); + ASSERT_TRUE(rosidl_generator_c__String__assign(&msg.string_value, test_string)); + ret = rcl_publish(&publisher, &msg, nullptr); + test_msgs__msg__Strings__fini(&msg); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + } + + // kill the publisher + ret = rcl_event_fini(&publisher_event); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + ret = rcl_publisher_fini(&publisher, this->node_ptr); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + + WaitConditionPredicate msg_and_subevent_ready = []( + const bool & msg_persist_ready, + const bool & subscription_persist_ready, + const bool &) { + return msg_persist_ready && subscription_persist_ready; + }; + test_msgs__msg__Strings msg; + test_msgs__msg__Strings__init(&msg); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({ + test_msgs__msg__Strings__fini(&msg); + }); + rmw_liveliness_changed_status_t liveliness_status; + bool msg_persist_ready, subscription_persist_ready, publisher_persist_ready; + rcl_ret_t wait_res = conditional_wait_for_msgs_and_events( + msg_and_subevent_ready, &subscription, &subscription_event, nullptr, context_ptr, 1000, + &msg_persist_ready, &subscription_persist_ready, &publisher_persist_ready, + &msg, &liveliness_status, nullptr); + EXPECT_EQ(wait_res, RCL_RET_OK); + + // test that the message published to topic is as expected + EXPECT_TRUE(msg_persist_ready); + // test subscriber/datareader liveliness changed status + EXPECT_TRUE(subscription_persist_ready); + // test that the killed publisher/datawriter has no active events + EXPECT_FALSE(publisher_persist_ready); + + if (msg_persist_ready) { + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + EXPECT_EQ(std::string(msg.string_value.data, msg.string_value.size), + std::string(test_string)); + } + if (subscription_persist_ready) { + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + EXPECT_EQ(liveliness_status.alive_count, 0); + // TODO(mm3188): Connext and OpenSplice seem to be tracking alive_count_change differently. + // Issue has been raised at https://github.com/ADLINK-IST/opensplice/issues/88 + if (is_opensplice) { + EXPECT_EQ(liveliness_status.alive_count_change, 2); + } else { + EXPECT_EQ(liveliness_status.alive_count_change, 0); + } + EXPECT_EQ(liveliness_status.not_alive_count, 0); + EXPECT_EQ(liveliness_status.not_alive_count_change, 0); + } + + // clean up + ret = rcl_event_fini(&subscription_event); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + ret = rcl_subscription_fini(&subscription, this->node_ptr); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; +} + +/* + * Basic test of publisher and subscriber deadline events, with first message sent after deadline + */ +TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_pubsub_deadline_missed) +{ + if (is_unsupported) { + return; + } + setup_publisher_and_subscriber(RCL_PUBLISHER_OFFERED_DEADLINE_MISSED, + RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED); + rcl_ret_t ret; + + // publish message to topic + const char * test_string = "testing"; + { + test_msgs__msg__Strings msg; + test_msgs__msg__Strings__init(&msg); + ASSERT_TRUE(rosidl_generator_c__String__assign(&msg.string_value, test_string)); + ret = rcl_publish(&publisher, &msg, nullptr); + test_msgs__msg__Strings__fini(&msg); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + } + + WaitConditionPredicate all_ready = []( + const bool & msg_persist_ready, + const bool & subscription_persist_ready, + const bool & publisher_persist_ready) { + return msg_persist_ready && subscription_persist_ready && publisher_persist_ready; + }; + test_msgs__msg__Strings msg; + test_msgs__msg__Strings__init(&msg); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({ + test_msgs__msg__Strings__fini(&msg); + }); + rmw_offered_deadline_missed_status_t offered_deadline_status; + rmw_requested_deadline_missed_status_t requested_deadline_status; + bool msg_persist_ready, subscription_persist_ready, publisher_persist_ready; + rcl_ret_t wait_res = conditional_wait_for_msgs_and_events( + all_ready, &subscription, &subscription_event, &publisher_event, context_ptr, 1000, + &msg_persist_ready, &subscription_persist_ready, &publisher_persist_ready, + &msg, &requested_deadline_status, &offered_deadline_status); + EXPECT_EQ(wait_res, RCL_RET_OK); + + // test that the message published to topic is as expected + if (msg_persist_ready) { + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + EXPECT_EQ(std::string(msg.string_value.data, msg.string_value.size), + std::string(test_string)); + } + + if (subscription_persist_ready) { + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + EXPECT_EQ(requested_deadline_status.total_count, 1); + EXPECT_EQ(requested_deadline_status.total_count_change, 1); + } + + if (publisher_persist_ready) { + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + EXPECT_EQ(offered_deadline_status.total_count, 1); + EXPECT_EQ(offered_deadline_status.total_count_change, 1); + } + // test that the message published to topic is as expected + EXPECT_TRUE(msg_persist_ready); + + // test subscriber/datareader deadline missed status + EXPECT_TRUE(subscription_persist_ready); + + // test publisher/datawriter deadline missed status + EXPECT_TRUE(publisher_persist_ready); + + // clean up + tear_down_publisher_subscriber(); +} + +/* + * Basic test of publisher and subscriber deadline events, with first message sent before deadline + */ +TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_pubsub_no_deadline_missed) +{ + if (is_unsupported) { + return; + } + setup_publisher_and_subscriber(RCL_PUBLISHER_OFFERED_DEADLINE_MISSED, + RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED); + rcl_ret_t ret; + + // publish message to topic + const char * test_string = "testing"; + { + test_msgs__msg__Strings msg; + test_msgs__msg__Strings__init(&msg); + ASSERT_TRUE(rosidl_generator_c__String__assign(&msg.string_value, test_string)); + ret = rcl_publish(&publisher, &msg, nullptr); + test_msgs__msg__Strings__fini(&msg); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + } + + // wait for msg and events + bool msg_ready, subscription_event_ready, publisher_event_ready; + EXPECT_EQ(wait_for_msgs_and_events(&subscription, &subscription_event, &publisher_event, + context_ptr, 1000, &msg_ready, &subscription_event_ready, &publisher_event_ready), RCL_RET_OK); + + // test that the message published to topic is as expected + EXPECT_TRUE(msg_ready); + { + test_msgs__msg__Strings msg; + test_msgs__msg__Strings__init(&msg); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({ + test_msgs__msg__Strings__fini(&msg); + }); + ret = rcl_take(&subscription, &msg, nullptr, nullptr); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + EXPECT_EQ(std::string(msg.string_value.data, msg.string_value.size), std::string(test_string)); + } + + // test subscriber/datareader deadline missed status + EXPECT_FALSE(subscription_event_ready); + { + rmw_requested_deadline_missed_status_t deadline_status; + ret = rcl_take_event(&subscription_event, &deadline_status); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + EXPECT_EQ(deadline_status.total_count, 0); + EXPECT_EQ(deadline_status.total_count_change, 0); + } + + // test publisher/datawriter deadline missed status + EXPECT_FALSE(publisher_event_ready); + { + rmw_offered_deadline_missed_status_t deadline_status; + ret = rcl_take_event(&publisher_event, &deadline_status); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + EXPECT_EQ(deadline_status.total_count, 0); + EXPECT_EQ(deadline_status.total_count_change, 0); + } + + // clean up + tear_down_publisher_subscriber(); +} diff --git a/rcl/test/rcl/test_get_actual_qos.cpp b/rcl/test/rcl/test_get_actual_qos.cpp index 1ad4a6f2d..f31d94c8e 100644 --- a/rcl/test/rcl/test_get_actual_qos.cpp +++ b/rcl/test/rcl/test_get_actual_qos.cpp @@ -70,9 +70,7 @@ class TEST_FIXTURE_P_RMW (TestGetActualQoS) : public ::testing::TestWithParam { public: - rcl_node_t * node_ptr; - rcl_context_t * context_ptr; - void SetUp() + void SetUp() override { rcl_ret_t ret; rcl_node_options_t node_options = rcl_node_get_default_options(); @@ -91,7 +89,7 @@ class TEST_FIXTURE_P_RMW (TestGetActualQoS) ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; } - void TearDown() + void TearDown() override { rcl_ret_t ret; @@ -106,6 +104,10 @@ class TEST_FIXTURE_P_RMW (TestGetActualQoS) delete this->context_ptr; EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; } + +protected: + rcl_node_t * node_ptr; + rcl_context_t * context_ptr; }; TEST_P_RMW(TestGetActualQoS, test_publisher_get_qos_settings) { @@ -199,8 +201,8 @@ get_parameters() #ifdef RMW_IMPLEMENTATION_STR std::string rmw_implementation_str = RMW_IMPLEMENTATION_STR; - if (!rmw_implementation_str.compare("rmw_fastrtps_cpp") || - !rmw_implementation_str.compare("rmw_fastrtps_dynamic_cpp")) + if (rmw_implementation_str == "rmw_fastrtps_cpp" || + rmw_implementation_str == "rmw_fastrtps_dynamic_cpp") { rmw_qos_profile_t expected_system_default_qos = expected_fastrtps_default_qos_profile(); parameters.push_back({ @@ -208,9 +210,9 @@ get_parameters() expected_system_default_qos, "publisher_system_default_qos"}); } else { - if (!rmw_implementation_str.compare("rmw_opensplice_cpp") || - !rmw_implementation_str.compare("rmw_connext_cpp") || - !rmw_implementation_str.compare("rmw_connext_dynamic_cpp")) + if (rmw_implementation_str == "rmw_connext_cpp" || + rmw_implementation_str == "rmw_connext_dynamic_cpp" || + rmw_implementation_str == "rmw_opensplice_cpp") { rmw_qos_profile_t expected_system_default_qos = expected_system_default_qos_profile(); parameters.push_back({ diff --git a/rcl/test/rcl/test_graph.cpp b/rcl/test/rcl/test_graph.cpp index e545039b0..508a07852 100644 --- a/rcl/test/rcl/test_graph.cpp +++ b/rcl/test/rcl/test_graph.cpp @@ -99,7 +99,7 @@ class CLASSNAME (TestGraphFixture, RMW_IMPLEMENTATION) : public ::testing::Test this->wait_set_ptr = new rcl_wait_set_t; *this->wait_set_ptr = rcl_get_zero_initialized_wait_set(); ret = rcl_wait_set_init( - this->wait_set_ptr, 0, 1, 0, 0, 0, this->context_ptr, rcl_get_default_allocator()); + this->wait_set_ptr, 0, 1, 0, 0, 0, 0, this->context_ptr, rcl_get_default_allocator()); ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; } diff --git a/rcl/test/rcl/test_service.cpp b/rcl/test/rcl/test_service.cpp index 9a32c811c..de4001ae1 100644 --- a/rcl/test/rcl/test_service.cpp +++ b/rcl/test/rcl/test_service.cpp @@ -84,7 +84,8 @@ wait_for_service_to_be_ready( bool & success) { rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); - rcl_ret_t ret = rcl_wait_set_init(&wait_set, 0, 0, 0, 0, 1, context, rcl_get_default_allocator()); + rcl_ret_t ret = + rcl_wait_set_init(&wait_set, 0, 0, 0, 0, 1, 0, context, rcl_get_default_allocator()); ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({ rcl_ret_t ret = rcl_wait_set_fini(&wait_set); diff --git a/rcl/test/rcl/test_subscription.cpp b/rcl/test/rcl/test_subscription.cpp index 03cd5de87..2463f95a7 100644 --- a/rcl/test/rcl/test_subscription.cpp +++ b/rcl/test/rcl/test_subscription.cpp @@ -85,7 +85,8 @@ wait_for_subscription_to_be_ready( bool & success) { rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); - rcl_ret_t ret = rcl_wait_set_init(&wait_set, 1, 0, 0, 0, 0, context, rcl_get_default_allocator()); + rcl_ret_t ret = + rcl_wait_set_init(&wait_set, 1, 0, 0, 0, 0, 0, context, rcl_get_default_allocator()); ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({ rcl_ret_t ret = rcl_wait_set_fini(&wait_set); diff --git a/rcl/test/rcl/test_timer.cpp b/rcl/test/rcl/test_timer.cpp index 3a3b1e2e9..87ed1cc1d 100644 --- a/rcl/test/rcl/test_timer.cpp +++ b/rcl/test/rcl/test_timer.cpp @@ -84,7 +84,7 @@ TEST_F(TestTimerFixture, test_two_timers) { ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); - ret = rcl_wait_set_init(&wait_set, 0, 0, 2, 0, 0, context_ptr, rcl_get_default_allocator()); + ret = rcl_wait_set_init(&wait_set, 0, 0, 2, 0, 0, 0, context_ptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; ret = rcl_wait_set_add_timer(&wait_set, &timer, NULL); @@ -140,7 +140,7 @@ TEST_F(TestTimerFixture, test_two_timers_ready_before_timeout) { ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); - ret = rcl_wait_set_init(&wait_set, 0, 0, 2, 0, 0, context_ptr, rcl_get_default_allocator()); + ret = rcl_wait_set_init(&wait_set, 0, 0, 2, 0, 0, 0, context_ptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; ret = rcl_wait_set_add_timer(&wait_set, &timer, NULL); @@ -191,7 +191,7 @@ TEST_F(TestTimerFixture, test_timer_not_ready) { ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); - ret = rcl_wait_set_init(&wait_set, 0, 0, 1, 0, 0, context_ptr, rcl_get_default_allocator()); + ret = rcl_wait_set_init(&wait_set, 0, 0, 1, 0, 0, 0, context_ptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; ret = rcl_wait_set_add_timer(&wait_set, &timer, NULL); @@ -239,7 +239,7 @@ TEST_F(TestTimerFixture, test_canceled_timer) { ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); - ret = rcl_wait_set_init(&wait_set, 0, 0, 1, 0, 0, context_ptr, rcl_get_default_allocator()); + ret = rcl_wait_set_init(&wait_set, 0, 0, 1, 0, 0, 0, context_ptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; ret = rcl_wait_set_add_timer(&wait_set, &timer, NULL); @@ -459,7 +459,11 @@ TEST_F(TestTimerFixture, test_ros_time_wakes_wait) { std::thread wait_thr([&](void) { rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); - ret = rcl_wait_set_init(&wait_set, 0, 0, 1, 0, 0, context_ptr, rcl_get_default_allocator()); + ret = rcl_wait_set_init( + &wait_set, + 0, 0, 1, 0, 0, 0, + context_ptr, + rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; ASSERT_EQ(RCL_RET_OK, rcl_wait_set_add_timer(&wait_set, &timer, NULL)) << diff --git a/rcl/test/rcl/test_wait.cpp b/rcl/test/rcl/test_wait.cpp index 58a7f8158..d61c02cd4 100644 --- a/rcl/test/rcl/test_wait.cpp +++ b/rcl/test/rcl/test_wait.cpp @@ -69,10 +69,10 @@ TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), test_resize_to_zero) { // Initialize a wait set with a subscription and then resize it to zero. rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); rcl_ret_t ret = - rcl_wait_set_init(&wait_set, 1, 1, 1, 1, 1, context_ptr, rcl_get_default_allocator()); + rcl_wait_set_init(&wait_set, 1, 1, 1, 1, 1, 0, context_ptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; - ret = rcl_wait_set_resize(&wait_set, 0u, 0u, 0u, 0u, 0u); + ret = rcl_wait_set_resize(&wait_set, 0u, 0u, 0u, 0u, 0u, 0u); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; EXPECT_EQ(wait_set.size_of_subscriptions, 0ull); @@ -89,7 +89,7 @@ TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), test_resize_to_zero) { TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), finite_timeout) { rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); rcl_ret_t ret = - rcl_wait_set_init(&wait_set, 0, 0, 1, 0, 0, context_ptr, rcl_get_default_allocator()); + rcl_wait_set_init(&wait_set, 0, 0, 1, 0, 0, 0, context_ptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; int64_t timeout = RCL_MS_TO_NS(10); // nanoseconds @@ -109,7 +109,7 @@ TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), finite_timeout) { TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), negative_timeout) { rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); rcl_ret_t ret = - rcl_wait_set_init(&wait_set, 0, 1, 1, 0, 0, context_ptr, rcl_get_default_allocator()); + rcl_wait_set_init(&wait_set, 0, 1, 1, 0, 0, 0, context_ptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; // Add a dummy guard condition to avoid an error @@ -156,7 +156,7 @@ TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), negative_timeout) { TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), zero_timeout) { rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); rcl_ret_t ret = - rcl_wait_set_init(&wait_set, 0, 1, 1, 0, 0, context_ptr, rcl_get_default_allocator()); + rcl_wait_set_init(&wait_set, 0, 1, 1, 0, 0, 0, context_ptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; // Add a dummy guard condition to avoid an error @@ -189,7 +189,7 @@ TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), zero_timeout) { TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), zero_timeout_triggered_guard_condition) { rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); rcl_ret_t ret = - rcl_wait_set_init(&wait_set, 0, 1, 0, 0, 0, context_ptr, rcl_get_default_allocator()); + rcl_wait_set_init(&wait_set, 0, 1, 0, 0, 0, 0, context_ptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; rcl_guard_condition_t guard_cond = rcl_get_zero_initialized_guard_condition(); @@ -223,7 +223,7 @@ TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), zero_timeout_triggered TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), canceled_timer) { rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); rcl_ret_t ret = - rcl_wait_set_init(&wait_set, 0, 1, 1, 0, 0, context_ptr, rcl_get_default_allocator()); + rcl_wait_set_init(&wait_set, 0, 1, 1, 0, 0, 0, context_ptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; // Add a dummy guard condition to avoid an error @@ -276,7 +276,7 @@ TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), canceled_timer) { TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), excess_capacity) { rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); rcl_ret_t ret = - rcl_wait_set_init(&wait_set, 42, 42, 42, 42, 42, context_ptr, rcl_get_default_allocator()); + rcl_wait_set_init(&wait_set, 42, 42, 42, 42, 42, 0, context_ptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; int64_t timeout = 1; @@ -361,7 +361,7 @@ TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), multi_wait_set_threade // setup the wait set test_set.wait_set = rcl_get_zero_initialized_wait_set(); ret = rcl_wait_set_init( - &test_set.wait_set, 0, 1, 0, 0, 0, context_ptr, rcl_get_default_allocator()); + &test_set.wait_set, 0, 1, 0, 0, 0, 0, context_ptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; ret = rcl_wait_set_add_guard_condition(&test_set.wait_set, &test_set.guard_condition, NULL); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; @@ -419,7 +419,7 @@ TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), multi_wait_set_threade TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), guard_condition) { rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); rcl_ret_t ret = - rcl_wait_set_init(&wait_set, 0, 1, 0, 0, 0, context_ptr, rcl_get_default_allocator()); + rcl_wait_set_init(&wait_set, 0, 1, 0, 0, 0, 0, context_ptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; rcl_guard_condition_t guard_cond = rcl_get_zero_initialized_guard_condition(); ret = rcl_guard_condition_init( @@ -467,7 +467,7 @@ TEST_F(CLASSNAME(WaitSetTestFixture, RMW_IMPLEMENTATION), add_with_index) { const size_t kNumEntities = 3u; rcl_wait_set_t wait_set = rcl_get_zero_initialized_wait_set(); rcl_ret_t ret = rcl_wait_set_init( - &wait_set, 0, kNumEntities, 0, 0, 0, context_ptr, rcl_get_default_allocator()); + &wait_set, 0, kNumEntities, 0, 0, 0, 0, context_ptr, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; // Initialize to invalid value diff --git a/rcl_action/test/rcl_action/test_action_communication.cpp b/rcl_action/test/rcl_action/test_action_communication.cpp index 07af43f43..07ab08a63 100644 --- a/rcl_action/test/rcl_action/test_action_communication.cpp +++ b/rcl_action/test/rcl_action/test_action_communication.cpp @@ -98,6 +98,7 @@ class CLASSNAME (TestActionCommunication, RMW_IMPLEMENTATION) : public ::testing num_timers_server + num_timers_client, num_clients_server + num_clients_client, num_services_server + num_services_client, + 0 /* num_events_server + num_events_client */, &context, rcl_get_default_allocator()); ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; diff --git a/rcl_action/test/rcl_action/test_action_interaction.cpp b/rcl_action/test/rcl_action/test_action_interaction.cpp index 60c0d694b..49dc35178 100644 --- a/rcl_action/test/rcl_action/test_action_interaction.cpp +++ b/rcl_action/test/rcl_action/test_action_interaction.cpp @@ -110,6 +110,7 @@ class CLASSNAME (TestActionClientServerInteraction, RMW_IMPLEMENTATION) : public num_timers_server + num_timers_client, num_clients_server + num_clients_client, num_services_server + num_services_client, + 0 /* num_events_server + num_events_client */, &context, rcl_get_default_allocator()); ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str;