Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qos test #4

Merged
merged 19 commits into from
Apr 3, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 92 additions & 43 deletions rcl/test/rcl/test_events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@

#include "osrf_testing_tools_cpp/scope_exit.hpp"

constexpr int DISCOVERY_WAIT_TIME_IN_MS = 1000;
constexpr int LIVELINESS_LEASE_DURATION_IN_MS = 1000;
constexpr int DEADLINE_PERIOD_IN_MS = 1000;

#ifdef RMW_IMPLEMENTATION
# define CLASSNAME_(NAME, SUFFIX) NAME ## __ ## SUFFIX
Expand Down Expand Up @@ -74,7 +77,10 @@ class CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION) : public ::testing::Test
// init publisher
publisher = rcl_get_zero_initialized_publisher();
rcl_publisher_options_t publisher_options = rcl_publisher_get_default_options();
publisher_options.qos.deadline = rmw_time_t {1, 0};
publisher_options.qos.deadline = rmw_time_t {DEADLINE_PERIOD_IN_MS / 1000, 0};
publisher_options.qos.liveliness = RMW_QOS_POLICY_LIVELINESS_AUTOMATIC;
publisher_options.qos.liveliness_lease_duration =
rmw_time_t {LIVELINESS_LEASE_DURATION_IN_MS / 1000, 0};
ret = rcl_publisher_init(&publisher, this->node_ptr, ts, topic, &publisher_options);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;

Expand All @@ -86,7 +92,10 @@ class CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION) : public ::testing::Test
// init subscription
subscription = rcl_get_zero_initialized_subscription();
rcl_subscription_options_t subscription_options = rcl_subscription_get_default_options();
subscription_options.qos.deadline = rmw_time_t {1, 0};
subscription_options.qos.deadline = rmw_time_t {DEADLINE_PERIOD_IN_MS / 1000, 0};
subscription_options.qos.liveliness = RMW_QOS_POLICY_LIVELINESS_AUTOMATIC;
subscription_options.qos.liveliness_lease_duration =
rmw_time_t {LIVELINESS_LEASE_DURATION_IN_MS / 1000, 0};
ret = rcl_subscription_init(&subscription, this->node_ptr, ts, topic, &subscription_options);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;

Expand All @@ -96,7 +105,7 @@ class CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION) : public ::testing::Test
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
}

void TearDown()
void TearDownPubSub()
{
rcl_ret_t ret;

Expand All @@ -111,6 +120,11 @@ class CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION) : public ::testing::Test

ret = rcl_publisher_fini(&publisher, this->node_ptr);
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
}

void TearDown()
{
rcl_ret_t ret;

ret = rcl_node_fini(this->node_ptr);
delete this->node_ptr;
Expand Down Expand Up @@ -207,19 +221,22 @@ wait_for_msgs_and_events(
}

/*
* Basic test of publisher and subscriber liveliness events
* Basic test of publisher and subscriber liveliness events, with publisher killed
*/
TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_pubsub_liveliness)
TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_pubsub_liveliness_kill_pub)
{
// initialize publisher and subscriber
SetUpPubSub(RCL_PUBLISHER_LIVELINESS_LOST, RCL_SUBSCRIPTION_LIVELINESS_CHANGED);

// wait for discovery
// TODO(wjwwood): add logic to wait for the connection to be established
// probably using the count_subscriptions busy wait mechanism
// until then we will sleep for a short period of time
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::this_thread::sleep_for(std::chrono::milliseconds(DISCOVERY_WAIT_TIME_IN_MS));

rcl_ret_t ret;

// publish message to topic
const char * test_string = "testing";
{
test_msgs__msg__Primitives msg;
Expand All @@ -230,12 +247,23 @@ TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_pubsub_liveliness)
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
}

// kill the publisher
ret = rcl_event_fini(&publisher_event);
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
ret = rcl_publisher_fini(&publisher, this->node_ptr);
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;

// wait for lease duration to expire
std::this_thread::sleep_for(std::chrono::milliseconds(LIVELINESS_LEASE_DURATION_IN_MS + 500));

// wait for events
bool msg_ready, subscription_event_ready, publisher_event_ready;
ASSERT_TRUE(wait_for_msgs_and_events(&subscription, &subscription_event,
&publisher_event, context_ptr, 1, 1000, msg_ready, subscription_event_ready,
publisher_event_ready));
ASSERT_TRUE(wait_for_msgs_and_events(&subscription, &subscription_event, nullptr,
context_ptr, 1, 1000, msg_ready, subscription_event_ready, publisher_event_ready));

if (msg_ready) {
// test that the message published to topic is as expected
EXPECT_TRUE(msg_ready);
{
test_msgs__msg__Primitives msg;
test_msgs__msg__Primitives__init(&msg);
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
Expand All @@ -246,41 +274,45 @@ TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_pubsub_liveliness)
EXPECT_EQ(std::string(test_string), std::string(msg.string_value.data, msg.string_value.size));
}

ASSERT_TRUE(subscription_event_ready);
if (subscription_event_ready) {
// test subscriber/datareader liveliness changed status
EXPECT_TRUE(subscription_event_ready);
{
rmw_liveliness_changed_status_t liveliness_status;
ret = rcl_take_event(&subscription_event, &liveliness_status);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
EXPECT_EQ(liveliness_status.alive_count, 1);
EXPECT_EQ(liveliness_status.alive_count_change, 1);
EXPECT_EQ(liveliness_status.alive_count, 0);
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);
}

ASSERT_TRUE(publisher_event_ready);
if (publisher_event_ready) {
rmw_liveliness_lost_status_t liveliness_status;
ret = rcl_take_event(&publisher_event, &liveliness_status);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
EXPECT_EQ(liveliness_status.total_count, 0);
EXPECT_EQ(liveliness_status.total_count_change, 0);
}
// test that the killed publisher/datawriter has no active events
EXPECT_FALSE(publisher_event_ready);

// clean up
ret = rcl_event_fini(&subscription_event);
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
ret = rcl_subscription_fini(&subscription, this->node_ptr);
EXPECT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
}

/*
* Basic test of publisher and subscriber deadline events
* Basic test of publisher and subscriber deadline events, with first message sent after deadline
*/
TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_pubsub_deadline)
TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_pubsub_deadline_missed)
{
// initialize publisher and subscriber
SetUpPubSub(RCL_PUBLISHER_OFFERED_DEADLINE_MISSED, RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED);

// wait for discovery. also adds delay to publishing of message
// TODO(wjwwood): add logic to wait for the connection to be established
// probably using the count_subscriptions busy wait mechanism
// until then we will sleep for a short period of time
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::this_thread::sleep_for(std::chrono::milliseconds(DEADLINE_PERIOD_IN_MS + 500));

rcl_ret_t ret;

// publish message to topic
const char * test_string = "testing";
{
test_msgs__msg__Primitives msg;
Expand All @@ -291,12 +323,14 @@ TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_pubsub_deadline)
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
}

// wait for events
bool msg_ready, subscription_event_ready, publisher_event_ready;
ASSERT_TRUE(wait_for_msgs_and_events(&subscription, &subscription_event,
&publisher_event, context_ptr, 1, 1000, msg_ready, subscription_event_ready,
publisher_event_ready));
ASSERT_TRUE(wait_for_msgs_and_events(&subscription, &subscription_event, &publisher_event,
context_ptr, 1, 1000, msg_ready, subscription_event_ready, publisher_event_ready));

if (msg_ready) {
// test that the message published to topic is as expected
EXPECT_TRUE(msg_ready);
{
test_msgs__msg__Primitives msg;
test_msgs__msg__Primitives__init(&msg);
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
Expand All @@ -307,39 +341,47 @@ TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_pubsub_deadline)
EXPECT_EQ(std::string(test_string), std::string(msg.string_value.data, msg.string_value.size));
}

ASSERT_TRUE(subscription_event_ready);
if (subscription_event_ready) {
// test subscriber/datareader deadline missed status
EXPECT_TRUE(subscription_event_ready);
{
rmw_requested_deadline_missed_status_t deadline_status;
ret = rcl_take_event(&subscription_event, &deadline_status);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
EXPECT_EQ(deadline_status.total_count, 1);
EXPECT_EQ(deadline_status.total_count_change, 1);
}

ASSERT_TRUE(publisher_event_ready);
if (publisher_event_ready) {
// test publisher/datawriter deadline missed status
EXPECT_TRUE(publisher_event_ready);
{
rmw_offered_deadline_missed_status_t deadline_status;
ret = rcl_take_event(&publisher_event, &deadline_status);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
EXPECT_EQ(deadline_status.total_count, 1);
EXPECT_EQ(deadline_status.total_count_change, 1);
}

// clean up
TearDownPubSub();
}

/*
* Test of publisher and subscriber, expecting no deadline events
* 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)
{
// initialize publisher and subscriber
SetUpPubSub(RCL_PUBLISHER_OFFERED_DEADLINE_MISSED, RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED);

// wait for discovery. also adds delay to publishing of message
// TODO(wjwwood): add logic to wait for the connection to be established
// probably using the count_subscriptions busy wait mechanism
// until then we will sleep for a short period of time
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::this_thread::sleep_for(std::chrono::milliseconds(DEADLINE_PERIOD_IN_MS - 500));

rcl_ret_t ret;

// publish message to topic
const char * test_string = "testing";
{
test_msgs__msg__Primitives msg;
Expand All @@ -350,12 +392,14 @@ TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_pubsub_no_deadline_
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
}

// wait for events
bool msg_ready, subscription_event_ready, publisher_event_ready;
ASSERT_TRUE(wait_for_msgs_and_events(&subscription, &subscription_event,
&publisher_event, context_ptr, 1, 1000, msg_ready, subscription_event_ready,
publisher_event_ready));
ASSERT_FALSE(wait_for_msgs_and_events(&subscription, &subscription_event, &publisher_event,
context_ptr, 1, 1000, msg_ready, subscription_event_ready, publisher_event_ready));

if (msg_ready) {
// test that the message published to topic is as expected
EXPECT_TRUE(msg_ready);
{
test_msgs__msg__Primitives msg;
test_msgs__msg__Primitives__init(&msg);
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT({
Expand All @@ -366,21 +410,26 @@ TEST_F(CLASSNAME(TestEventFixture, RMW_IMPLEMENTATION), test_pubsub_no_deadline_
EXPECT_EQ(std::string(test_string), std::string(msg.string_value.data, msg.string_value.size));
}

ASSERT_TRUE(subscription_event_ready);
if (subscription_event_ready) {
// 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);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
EXPECT_EQ(deadline_status.total_count, 0);
EXPECT_EQ(deadline_status.total_count_change, 0);
}

ASSERT_TRUE(publisher_event_ready);
if (publisher_event_ready) {
// 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);
ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str;
EXPECT_EQ(deadline_status.total_count, 0);
EXPECT_EQ(deadline_status.total_count_change, 0);
}

// clean up
TearDownPubSub();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't you be able to do auto teardown using the class fixture?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the liveliness test, I can only tear down the subscriber, so I couldn't make the auto TearDown() tear down absolutely everything.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I guess it's already doing a manual setup, so it's not out of pattern.

You could perhaps on the fixture set a this->doTearDownPublisher and check that on the TearDown method - might keep more logic contained on the fixture such that you can't accidentally forget to clean up

Not blocking approval on this, just picking through it

}