From ec19f99ab2e4af8e7e9f079afe47d3e92943acc9 Mon Sep 17 00:00:00 2001 From: Ivan Santiago Paunovic Date: Fri, 5 Jun 2020 17:40:42 -0300 Subject: [PATCH 1/3] Add message lost subscription event Signed-off-by: Ivan Santiago Paunovic --- rcl/include/rcl/event.h | 1 + rcl/src/rcl/event.c | 3 + rcl/test/rcl/test_events.cpp | 148 +++++++++++++++++++++++++++++++---- 3 files changed, 137 insertions(+), 15 deletions(-) diff --git a/rcl/include/rcl/event.h b/rcl/include/rcl/event.h index 01def23d0..daea4729c 100644 --- a/rcl/include/rcl/event.h +++ b/rcl/include/rcl/event.h @@ -39,6 +39,7 @@ typedef enum rcl_subscription_event_type_t RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED, RCL_SUBSCRIPTION_LIVELINESS_CHANGED, RCL_SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS, + RCL_SUBSCRIPTION_MESSAGE_LOST, } rcl_subscription_event_type_t; /// rmw struct. diff --git a/rcl/src/rcl/event.c b/rcl/src/rcl/event.c index 81ccf7c50..8cc719470 100644 --- a/rcl/src/rcl/event.c +++ b/rcl/src/rcl/event.c @@ -122,6 +122,9 @@ rcl_subscription_event_init( case RCL_SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS: rmw_event_type = RMW_EVENT_REQUESTED_QOS_INCOMPATIBLE; break; + case RCL_SUBSCRIPTION_MESSAGE_LOST: + rmw_event_type = RMW_EVENT_MESSAGE_LOST; + break; default: RCL_SET_ERROR_MSG("Event type for subscription not supported"); return RCL_RET_INVALID_ARGUMENT; diff --git a/rcl/test/rcl/test_events.cpp b/rcl/test/rcl/test_events.cpp index c5184ac32..2aabeb3bd 100644 --- a/rcl/test/rcl/test_events.cpp +++ b/rcl/test/rcl/test_events.cpp @@ -31,6 +31,8 @@ #include "osrf_testing_tools_cpp/scope_exit.hpp" +#include "./wait_for_entity_helpers.hpp" + using namespace std::chrono_literals; using std::chrono::seconds; using std::chrono::duration_cast; @@ -88,7 +90,7 @@ class CLASSNAME (TestEventFixture, RMW_IMPLEMENTATION) ts = ROSIDL_GET_MSG_TYPE_SUPPORT(test_msgs, msg, Strings); } - rcl_ret_t setup_publisher(const rmw_qos_profile_t qos_profile) + rcl_ret_t setup_publisher(const rmw_qos_profile_t qos_profile = default_qos_profile) { // init publisher publisher = rcl_get_zero_initialized_publisher(); @@ -102,7 +104,7 @@ class CLASSNAME (TestEventFixture, RMW_IMPLEMENTATION) &publisher_options); } - rcl_ret_t setup_subscriber(const rmw_qos_profile_t qos_profile) + rcl_ret_t setup_subscriber(const rmw_qos_profile_t qos_profile = default_qos_profile) { // init publisher subscription = rcl_get_zero_initialized_subscription(); @@ -117,8 +119,8 @@ class CLASSNAME (TestEventFixture, RMW_IMPLEMENTATION) } void setup_publisher_subscriber( - const rmw_qos_profile_t pub_qos_profile, - const rmw_qos_profile_t sub_qos_profile) + const rmw_qos_profile_t pub_qos_profile = default_qos_profile, + const rmw_qos_profile_t sub_qos_profile = default_qos_profile) { rcl_ret_t ret; @@ -131,30 +133,31 @@ class CLASSNAME (TestEventFixture, RMW_IMPLEMENTATION) ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; } - void setup_publisher_subscriber_events( - const rcl_publisher_event_type_t & pub_event_type, - const rcl_subscription_event_type_t & sub_event_type) + void setup_publisher_event(const rcl_publisher_event_type_t & pub_event_type) { - rcl_ret_t ret; - // init publisher events publisher_event = rcl_get_zero_initialized_event(); - ret = rcl_publisher_event_init(&publisher_event, &publisher, pub_event_type); + rcl_ret_t ret = rcl_publisher_event_init(&publisher_event, &publisher, pub_event_type); ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + } + void setup_subscriber_event(const rcl_subscription_event_type_t & sub_event_type) + { // init subscription event subscription_event = rcl_get_zero_initialized_event(); - ret = rcl_subscription_event_init(&subscription_event, &subscription, sub_event_type); + rcl_ret_t ret = rcl_subscription_event_init(&subscription_event, &subscription, sub_event_type); ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; } - void setup_publisher_subscriber_and_events_and_assert_discovery( + void setup_publisher_subscriber_events( const rcl_publisher_event_type_t & pub_event_type, const rcl_subscription_event_type_t & sub_event_type) { - setup_publisher_subscriber(default_qos_profile, default_qos_profile); - setup_publisher_subscriber_events(pub_event_type, sub_event_type); + setup_publisher_event(pub_event_type); + setup_subscriber_event(sub_event_type); + } + void assert_discovery() { rcl_ret_t ret; // wait for discovery, time out after 10s static const size_t max_iterations = 1000; @@ -176,6 +179,15 @@ class CLASSNAME (TestEventFixture, RMW_IMPLEMENTATION) ASSERT_TRUE(subscribe_success) << "Publisher/Subscription discovery timed out"; } + void setup_publisher_subscriber_and_events_and_assert_discovery( + const rcl_publisher_event_type_t & pub_event_type, + const rcl_subscription_event_type_t & sub_event_type) + { + setup_publisher_subscriber(); + setup_publisher_subscriber_events(pub_event_type, sub_event_type); + assert_discovery(); + } + void tear_down_publisher_subscriber() { rcl_ret_t ret; @@ -305,7 +317,6 @@ wait_for_msgs_and_events( 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; @@ -346,6 +357,7 @@ rcl_ret_t conditional_wait_for_msgs_and_events( rcl_context_t * context, seconds timeout, + seconds timeout, const WaitConditionPredicate & events_ready, rcl_subscription_t * subscription, rcl_event_t * subscription_event, @@ -601,6 +613,112 @@ TEST_F(TestEventFixture, test_pubsub_liveliness_kill_pub) tear_down_publisher_subscriber(); } +/* + * Basic test of subscription message lost event + */ +TEST_F(TestEventFixture, test_sub_message_lost_event) +{ + if (0 != strcmp(rmw_get_implementation_identifier(), "rmw_connext_cpp")) { + GTEST_SKIP(); + } + + rmw_qos_profile_t qos_profile = rmw_qos_profile_default; + qos_profile.depth = 1; + qos_profile.reliability = RMW_QOS_POLICY_RELIABILITY_RELIABLE; + setup_publisher_subscriber(qos_profile, qos_profile); + setup_subscriber_event(RCL_SUBSCRIPTION_MESSAGE_LOST); + assert_discovery(); + + sleep(3); + + // test subscriber message lost status + { + rmw_message_lost_status_t message_lost_status; + rcl_ret_t ret = rcl_take_event(&subscription_event, &message_lost_status); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + EXPECT_EQ(message_lost_status.total_count, 0u); + EXPECT_EQ(message_lost_status.total_count_change, 0u); + } + + const char * test_string = "testing"; + { + test_msgs__msg__Strings msg; + test_msgs__msg__Strings__init(&msg); + ASSERT_TRUE(rosidl_runtime_c__String__assign(&msg.string_value, "test1")); + rcl_ret_t ret = rcl_publish(&publisher, &msg, nullptr); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + test_msgs__msg__Strings__fini(&msg); + } + + WaitConditionPredicate msg_ready_predicate = []( + const bool & msg_persist_ready, + const bool & subscription_persist_ready, + const bool & publisher_persist_ready) { + (void)subscription_persist_ready; + (void)publisher_persist_ready; + return msg_persist_ready; + }; + bool msg_persist_ready, subscription_persist_ready, publisher_persist_ready; + rcl_ret_t ret = conditional_wait_for_msgs_and_events( + context_ptr, MAX_WAIT_PER_TESTCASE, msg_ready_predicate, + &subscription, &subscription_event, nullptr, + &msg_persist_ready, &subscription_persist_ready, &publisher_persist_ready); + EXPECT_EQ(ret, RCL_RET_OK); + + // Publish a second message without reading the first. + // As the history depth is one, one will be lost. + { + test_msgs__msg__Strings msg; + test_msgs__msg__Strings__init(&msg); + ASSERT_TRUE(rosidl_runtime_c__String__assign(&msg.string_value, test_string)); + rcl_ret_t ret = rcl_publish(&publisher, &msg, nullptr); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + test_msgs__msg__Strings__fini(&msg); + } + + WaitConditionPredicate ready_predicate = []( + const bool & msg_persist_ready, + const bool & subscription_persist_ready, + const bool & publisher_persist_ready) { + (void)publisher_persist_ready; + return msg_persist_ready && subscription_persist_ready; + }; + ret = conditional_wait_for_msgs_and_events( + context_ptr, MAX_WAIT_PER_TESTCASE, ready_predicate, + &subscription, &subscription_event, nullptr, + &msg_persist_ready, &subscription_persist_ready, &publisher_persist_ready); + EXPECT_EQ(ret, RCL_RET_OK); + + // test that the message published to topic is as expected + ASSERT_TRUE(msg_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); + }); + 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 message lost status + { + EXPECT_TRUE(subscription_persist_ready); + rmw_message_lost_status_t message_lost_status; + rcl_ret_t ret = rcl_take_event(&subscription_event, &message_lost_status); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + EXPECT_EQ(message_lost_status.total_count, 1u); + EXPECT_EQ(message_lost_status.total_count_change, 1u); + } + + // clean up + ret = rcl_event_fini(&subscription_event); + EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; + tear_down_publisher_subscriber(); +} + /* * Basic test of publisher and subscriber incompatible qos callback events. * Only implemented in opensplice at the moment. From 555c475264ff2f2c641f3767944aeac04273ea0b Mon Sep 17 00:00:00 2001 From: Ivan Santiago Paunovic Date: Fri, 5 Jun 2020 18:24:43 -0300 Subject: [PATCH 2/3] cleanup tests Signed-off-by: Ivan Santiago Paunovic --- rcl/test/rcl/test_events.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/rcl/test/rcl/test_events.cpp b/rcl/test/rcl/test_events.cpp index 2aabeb3bd..9f0f6742d 100644 --- a/rcl/test/rcl/test_events.cpp +++ b/rcl/test/rcl/test_events.cpp @@ -31,8 +31,6 @@ #include "osrf_testing_tools_cpp/scope_exit.hpp" -#include "./wait_for_entity_helpers.hpp" - using namespace std::chrono_literals; using std::chrono::seconds; using std::chrono::duration_cast; @@ -357,7 +355,6 @@ rcl_ret_t conditional_wait_for_msgs_and_events( rcl_context_t * context, seconds timeout, - seconds timeout, const WaitConditionPredicate & events_ready, rcl_subscription_t * subscription, rcl_event_t * subscription_event, @@ -618,7 +615,10 @@ TEST_F(TestEventFixture, test_pubsub_liveliness_kill_pub) */ TEST_F(TestEventFixture, test_sub_message_lost_event) { - if (0 != strcmp(rmw_get_implementation_identifier(), "rmw_connext_cpp")) { + if ( + 0 != strcmp(rmw_get_implementation_identifier(), "rmw_connext_cpp") && + 0 != strcmp(rmw_get_implementation_identifier(), "rmw_cyclonedds_cpp")) + { GTEST_SKIP(); } @@ -629,8 +629,6 @@ TEST_F(TestEventFixture, test_sub_message_lost_event) setup_subscriber_event(RCL_SUBSCRIPTION_MESSAGE_LOST); assert_discovery(); - sleep(3); - // test subscriber message lost status { rmw_message_lost_status_t message_lost_status; @@ -691,6 +689,7 @@ TEST_F(TestEventFixture, test_sub_message_lost_event) // test that the message published to topic is as expected ASSERT_TRUE(msg_persist_ready); + EXPECT_TRUE(subscription_persist_ready); test_msgs__msg__Strings msg; test_msgs__msg__Strings__init(&msg); OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( From d9fce8b15356c4360147df494878c94a1e9b03fc Mon Sep 17 00:00:00 2001 From: Ivan Santiago Paunovic Date: Wed, 10 Jun 2020 16:53:22 -0300 Subject: [PATCH 3/3] Undo changes in test_events.cpp Signed-off-by: Ivan Santiago Paunovic --- rcl/test/rcl/test_events.cpp | 147 ++++------------------------------- 1 file changed, 15 insertions(+), 132 deletions(-) diff --git a/rcl/test/rcl/test_events.cpp b/rcl/test/rcl/test_events.cpp index 9f0f6742d..c5184ac32 100644 --- a/rcl/test/rcl/test_events.cpp +++ b/rcl/test/rcl/test_events.cpp @@ -88,7 +88,7 @@ class CLASSNAME (TestEventFixture, RMW_IMPLEMENTATION) ts = ROSIDL_GET_MSG_TYPE_SUPPORT(test_msgs, msg, Strings); } - rcl_ret_t setup_publisher(const rmw_qos_profile_t qos_profile = default_qos_profile) + rcl_ret_t setup_publisher(const rmw_qos_profile_t qos_profile) { // init publisher publisher = rcl_get_zero_initialized_publisher(); @@ -102,7 +102,7 @@ class CLASSNAME (TestEventFixture, RMW_IMPLEMENTATION) &publisher_options); } - rcl_ret_t setup_subscriber(const rmw_qos_profile_t qos_profile = default_qos_profile) + rcl_ret_t setup_subscriber(const rmw_qos_profile_t qos_profile) { // init publisher subscription = rcl_get_zero_initialized_subscription(); @@ -117,8 +117,8 @@ class CLASSNAME (TestEventFixture, RMW_IMPLEMENTATION) } void setup_publisher_subscriber( - const rmw_qos_profile_t pub_qos_profile = default_qos_profile, - const rmw_qos_profile_t sub_qos_profile = default_qos_profile) + const rmw_qos_profile_t pub_qos_profile, + const rmw_qos_profile_t sub_qos_profile) { rcl_ret_t ret; @@ -131,31 +131,30 @@ class CLASSNAME (TestEventFixture, RMW_IMPLEMENTATION) ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; } - void setup_publisher_event(const rcl_publisher_event_type_t & pub_event_type) + void setup_publisher_subscriber_events( + const rcl_publisher_event_type_t & pub_event_type, + const rcl_subscription_event_type_t & sub_event_type) { + rcl_ret_t ret; + // init publisher events publisher_event = rcl_get_zero_initialized_event(); - rcl_ret_t ret = rcl_publisher_event_init(&publisher_event, &publisher, pub_event_type); + ret = rcl_publisher_event_init(&publisher_event, &publisher, pub_event_type); ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; - } - void setup_subscriber_event(const rcl_subscription_event_type_t & sub_event_type) - { // init subscription event subscription_event = rcl_get_zero_initialized_event(); - rcl_ret_t ret = rcl_subscription_event_init(&subscription_event, &subscription, sub_event_type); + ret = rcl_subscription_event_init(&subscription_event, &subscription, sub_event_type); ASSERT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; } - void setup_publisher_subscriber_events( + void setup_publisher_subscriber_and_events_and_assert_discovery( const rcl_publisher_event_type_t & pub_event_type, const rcl_subscription_event_type_t & sub_event_type) { - setup_publisher_event(pub_event_type); - setup_subscriber_event(sub_event_type); - } + setup_publisher_subscriber(default_qos_profile, default_qos_profile); + setup_publisher_subscriber_events(pub_event_type, sub_event_type); - void assert_discovery() { rcl_ret_t ret; // wait for discovery, time out after 10s static const size_t max_iterations = 1000; @@ -177,15 +176,6 @@ class CLASSNAME (TestEventFixture, RMW_IMPLEMENTATION) ASSERT_TRUE(subscribe_success) << "Publisher/Subscription discovery timed out"; } - void setup_publisher_subscriber_and_events_and_assert_discovery( - const rcl_publisher_event_type_t & pub_event_type, - const rcl_subscription_event_type_t & sub_event_type) - { - setup_publisher_subscriber(); - setup_publisher_subscriber_events(pub_event_type, sub_event_type); - assert_discovery(); - } - void tear_down_publisher_subscriber() { rcl_ret_t ret; @@ -315,6 +305,7 @@ wait_for_msgs_and_events( 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; @@ -610,114 +601,6 @@ TEST_F(TestEventFixture, test_pubsub_liveliness_kill_pub) tear_down_publisher_subscriber(); } -/* - * Basic test of subscription message lost event - */ -TEST_F(TestEventFixture, test_sub_message_lost_event) -{ - if ( - 0 != strcmp(rmw_get_implementation_identifier(), "rmw_connext_cpp") && - 0 != strcmp(rmw_get_implementation_identifier(), "rmw_cyclonedds_cpp")) - { - GTEST_SKIP(); - } - - rmw_qos_profile_t qos_profile = rmw_qos_profile_default; - qos_profile.depth = 1; - qos_profile.reliability = RMW_QOS_POLICY_RELIABILITY_RELIABLE; - setup_publisher_subscriber(qos_profile, qos_profile); - setup_subscriber_event(RCL_SUBSCRIPTION_MESSAGE_LOST); - assert_discovery(); - - // test subscriber message lost status - { - rmw_message_lost_status_t message_lost_status; - rcl_ret_t ret = rcl_take_event(&subscription_event, &message_lost_status); - EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; - EXPECT_EQ(message_lost_status.total_count, 0u); - EXPECT_EQ(message_lost_status.total_count_change, 0u); - } - - const char * test_string = "testing"; - { - test_msgs__msg__Strings msg; - test_msgs__msg__Strings__init(&msg); - ASSERT_TRUE(rosidl_runtime_c__String__assign(&msg.string_value, "test1")); - rcl_ret_t ret = rcl_publish(&publisher, &msg, nullptr); - EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; - test_msgs__msg__Strings__fini(&msg); - } - - WaitConditionPredicate msg_ready_predicate = []( - const bool & msg_persist_ready, - const bool & subscription_persist_ready, - const bool & publisher_persist_ready) { - (void)subscription_persist_ready; - (void)publisher_persist_ready; - return msg_persist_ready; - }; - bool msg_persist_ready, subscription_persist_ready, publisher_persist_ready; - rcl_ret_t ret = conditional_wait_for_msgs_and_events( - context_ptr, MAX_WAIT_PER_TESTCASE, msg_ready_predicate, - &subscription, &subscription_event, nullptr, - &msg_persist_ready, &subscription_persist_ready, &publisher_persist_ready); - EXPECT_EQ(ret, RCL_RET_OK); - - // Publish a second message without reading the first. - // As the history depth is one, one will be lost. - { - test_msgs__msg__Strings msg; - test_msgs__msg__Strings__init(&msg); - ASSERT_TRUE(rosidl_runtime_c__String__assign(&msg.string_value, test_string)); - rcl_ret_t ret = rcl_publish(&publisher, &msg, nullptr); - EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; - test_msgs__msg__Strings__fini(&msg); - } - - WaitConditionPredicate ready_predicate = []( - const bool & msg_persist_ready, - const bool & subscription_persist_ready, - const bool & publisher_persist_ready) { - (void)publisher_persist_ready; - return msg_persist_ready && subscription_persist_ready; - }; - ret = conditional_wait_for_msgs_and_events( - context_ptr, MAX_WAIT_PER_TESTCASE, ready_predicate, - &subscription, &subscription_event, nullptr, - &msg_persist_ready, &subscription_persist_ready, &publisher_persist_ready); - EXPECT_EQ(ret, RCL_RET_OK); - - // test that the message published to topic is as expected - ASSERT_TRUE(msg_persist_ready); - EXPECT_TRUE(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); - }); - 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 message lost status - { - EXPECT_TRUE(subscription_persist_ready); - rmw_message_lost_status_t message_lost_status; - rcl_ret_t ret = rcl_take_event(&subscription_event, &message_lost_status); - EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; - EXPECT_EQ(message_lost_status.total_count, 1u); - EXPECT_EQ(message_lost_status.total_count_change, 1u); - } - - // clean up - ret = rcl_event_fini(&subscription_event); - EXPECT_EQ(ret, RCL_RET_OK) << rcl_get_error_string().str; - tear_down_publisher_subscriber(); -} - /* * Basic test of publisher and subscriber incompatible qos callback events. * Only implemented in opensplice at the moment.