diff --git a/rclcpp/test/CMakeLists.txt b/rclcpp/test/CMakeLists.txt index d500f3e..46fe7c1 100644 --- a/rclcpp/test/CMakeLists.txt +++ b/rclcpp/test/CMakeLists.txt @@ -17,6 +17,20 @@ rosidl_generate_interfaces(${PROJECT_NAME}_test_msgs SKIP_INSTALL ) +ament_add_gtest(test_any_service_callback rclcpp/test_any_service_callback.cpp) +if(TARGET test_any_service_callback) + ament_target_dependencies(test_any_service_callback + "test_msgs" + ) + target_link_libraries(test_any_service_callback ${PROJECT_NAME}) +endif() +ament_add_gtest(test_any_subscription_callback rclcpp/test_any_subscription_callback.cpp) +if(TARGET test_any_subscription_callback) + ament_target_dependencies(test_any_subscription_callback + "test_msgs" + ) + target_link_libraries(test_any_subscription_callback ${PROJECT_NAME}) +endif() ament_add_gtest(test_client rclcpp/test_client.cpp) if(TARGET test_client) ament_target_dependencies(test_client @@ -39,6 +53,13 @@ if(TARGET test_create_timer) target_link_libraries(test_create_timer ${PROJECT_NAME}) target_include_directories(test_create_timer PRIVATE rclcpp/) endif() +ament_add_gtest(test_create_subscription rclcpp/test_create_subscription.cpp) +if(TARGET test_create_subscription) + target_link_libraries(test_create_subscription ${PROJECT_NAME}) + ament_target_dependencies(test_create_subscription + "test_msgs" + ) +endif() ament_add_gtest(test_expand_topic_or_service_name rclcpp/test_expand_topic_or_service_name.cpp) if(TARGET test_expand_topic_or_service_name) ament_target_dependencies(test_expand_topic_or_service_name diff --git a/rclcpp/test/rclcpp/test_any_service_callback.cpp b/rclcpp/test/rclcpp/test_any_service_callback.cpp new file mode 100644 index 0000000..d16c119 --- /dev/null +++ b/rclcpp/test/rclcpp/test_any_service_callback.cpp @@ -0,0 +1,78 @@ +// Copyright 2020 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This file includes basic API tests for the AnyServiceCallback class. +// It is also tested in test_externally_defined_services.cpp + +#include + +#include +#include +#include + +#include "rclcpp/any_service_callback.hpp" +#include "test_msgs/srv/empty.hpp" +#include "test_msgs/srv/empty.h" + +class TestAnyServiceCallback : public ::testing::Test +{ +public: + void SetUp() + { + request_header_ = std::make_shared(); + request_ = std::make_shared(); + response_ = std::make_shared(); + } + +protected: + rclcpp::AnyServiceCallback any_service_callback_; + std::shared_ptr request_header_; + std::shared_ptr request_; + std::shared_ptr response_; +}; + +TEST_F(TestAnyServiceCallback, no_set_and_dispatch_throw) { + EXPECT_THROW( + any_service_callback_.dispatch(request_header_, request_, response_), + std::runtime_error); +} + +TEST_F(TestAnyServiceCallback, set_and_dispatch_no_header) { + int callback_calls = 0; + auto callback = [&callback_calls](const std::shared_ptr, + std::shared_ptr) { + callback_calls++; + }; + + any_service_callback_.set(callback); + EXPECT_NO_THROW( + any_service_callback_.dispatch(request_header_, request_, response_)); + EXPECT_EQ(callback_calls, 1); +} + + +TEST_F(TestAnyServiceCallback, set_and_dispatch_header) { + int callback_with_header_calls = 0; + auto callback_with_header = + [&callback_with_header_calls](const std::shared_ptr, + const std::shared_ptr, + std::shared_ptr) { + callback_with_header_calls++; + }; + + any_service_callback_.set(callback_with_header); + EXPECT_NO_THROW( + any_service_callback_.dispatch(request_header_, request_, response_)); + EXPECT_EQ(callback_with_header_calls, 1); +} diff --git a/rclcpp/test/rclcpp/test_any_subscription_callback.cpp b/rclcpp/test/rclcpp/test_any_subscription_callback.cpp new file mode 100644 index 0000000..8131681 --- /dev/null +++ b/rclcpp/test/rclcpp/test_any_subscription_callback.cpp @@ -0,0 +1,205 @@ +// Copyright 2020 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include +#include +#include + +#include "rclcpp/any_subscription_callback.hpp" +#include "test_msgs/msg/empty.hpp" +#include "test_msgs/msg/empty.h" + +class TestAnySubscriptionCallback : public ::testing::Test +{ +public: + TestAnySubscriptionCallback() + : any_subscription_callback_(allocator_) {} + void SetUp() + { + msg_shared_ptr_ = std::make_shared(); + msg_const_shared_ptr_ = std::make_shared(); + msg_unique_ptr_ = std::make_unique(); + } + +protected: + std::shared_ptr> allocator_; + rclcpp::AnySubscriptionCallback> + any_subscription_callback_; + + std::shared_ptr msg_shared_ptr_; + std::shared_ptr msg_const_shared_ptr_; + std::unique_ptr msg_unique_ptr_; + rclcpp::MessageInfo message_info_; +}; + +TEST_F(TestAnySubscriptionCallback, construct_destruct) { +} + +TEST_F(TestAnySubscriptionCallback, unset_dispatch_throw) { + EXPECT_THROW( + any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_), + std::runtime_error); + EXPECT_THROW( + any_subscription_callback_.dispatch_intra_process(msg_const_shared_ptr_, message_info_), + std::runtime_error); + EXPECT_THROW( + any_subscription_callback_.dispatch_intra_process(std::move(msg_unique_ptr_), message_info_), + std::runtime_error); +} + +TEST_F(TestAnySubscriptionCallback, set_dispatch_shared_ptr) { + int callback_count = 0; + auto shared_ptr_callback = [&callback_count]( + const std::shared_ptr) { + callback_count++; + }; + + any_subscription_callback_.set(shared_ptr_callback); + EXPECT_NO_THROW(any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_)); + EXPECT_EQ(callback_count, 1); + + // Can't convert ConstSharedPtr to SharedPtr + EXPECT_THROW( + any_subscription_callback_.dispatch_intra_process(msg_const_shared_ptr_, message_info_), + std::runtime_error); + EXPECT_EQ(callback_count, 1); + + // Promotes Unique into SharedPtr + EXPECT_NO_THROW( + any_subscription_callback_.dispatch_intra_process(std::move(msg_unique_ptr_), message_info_)); + EXPECT_EQ(callback_count, 2); +} + +TEST_F(TestAnySubscriptionCallback, set_dispatch_shared_ptr_w_info) { + int callback_count = 0; + auto shared_ptr_w_info_callback = [&callback_count]( + const std::shared_ptr, const rclcpp::MessageInfo &) { + callback_count++; + }; + + any_subscription_callback_.set(shared_ptr_w_info_callback); + + EXPECT_NO_THROW(any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_)); + EXPECT_EQ(callback_count, 1); + + // Can't convert ConstSharedPtr to SharedPtr + EXPECT_THROW( + any_subscription_callback_.dispatch_intra_process(msg_const_shared_ptr_, message_info_), + std::runtime_error); + EXPECT_EQ(callback_count, 1); + + // Promotes Unique into SharedPtr + EXPECT_NO_THROW( + any_subscription_callback_.dispatch_intra_process(std::move(msg_unique_ptr_), message_info_)); + EXPECT_EQ(callback_count, 2); +} + +TEST_F(TestAnySubscriptionCallback, set_dispatch_const_shared_ptr) { + int callback_count = 0; + auto const_shared_ptr_callback = [&callback_count]( + std::shared_ptr) { + callback_count++; + }; + + any_subscription_callback_.set(const_shared_ptr_callback); + + // Ok to promote shared_ptr to ConstSharedPtr + EXPECT_NO_THROW(any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_)); + EXPECT_EQ(callback_count, 1); + + EXPECT_NO_THROW( + any_subscription_callback_.dispatch_intra_process(msg_const_shared_ptr_, message_info_)); + EXPECT_EQ(callback_count, 2); + + // Not allowed to convert unique_ptr to const shared_ptr + EXPECT_THROW( + any_subscription_callback_.dispatch_intra_process(std::move(msg_unique_ptr_), message_info_), + std::runtime_error); + EXPECT_EQ(callback_count, 2); +} + +TEST_F(TestAnySubscriptionCallback, set_dispatch_const_shared_ptr_w_info) { + int callback_count = 0; + auto const_shared_ptr_callback = [&callback_count]( + std::shared_ptr, const rclcpp::MessageInfo &) { + callback_count++; + }; + + any_subscription_callback_.set( + std::move(const_shared_ptr_callback)); + + // Ok to promote shared_ptr to ConstSharedPtr + EXPECT_NO_THROW(any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_)); + EXPECT_EQ(callback_count, 1); + + EXPECT_NO_THROW( + any_subscription_callback_.dispatch_intra_process(msg_const_shared_ptr_, message_info_)); + EXPECT_EQ(callback_count, 2); + + // Not allowed to convert unique_ptr to const shared_ptr + EXPECT_THROW( + any_subscription_callback_.dispatch_intra_process(std::move(msg_unique_ptr_), message_info_), + std::runtime_error); + EXPECT_EQ(callback_count, 2); +} + +TEST_F(TestAnySubscriptionCallback, set_dispatch_unique_ptr) { + int callback_count = 0; + auto unique_ptr_callback = [&callback_count]( + std::unique_ptr) { + callback_count++; + }; + + any_subscription_callback_.set(unique_ptr_callback); + + // Message is copied into unique_ptr + EXPECT_NO_THROW(any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_)); + EXPECT_EQ(callback_count, 1); + + EXPECT_THROW( + any_subscription_callback_.dispatch_intra_process(msg_const_shared_ptr_, message_info_), + std::runtime_error); + EXPECT_EQ(callback_count, 1); + + // Unique_ptr is_moved + EXPECT_NO_THROW( + any_subscription_callback_.dispatch_intra_process(std::move(msg_unique_ptr_), message_info_)); + EXPECT_EQ(callback_count, 2); +} + +TEST_F(TestAnySubscriptionCallback, set_dispatch_unique_ptr_w_info) { + int callback_count = 0; + auto unique_ptr_callback = [&callback_count]( + std::unique_ptr, const rclcpp::MessageInfo &) { + callback_count++; + }; + + any_subscription_callback_.set(unique_ptr_callback); + + // Message is copied into unique_ptr + EXPECT_NO_THROW(any_subscription_callback_.dispatch(msg_shared_ptr_, message_info_)); + EXPECT_EQ(callback_count, 1); + + EXPECT_THROW( + any_subscription_callback_.dispatch_intra_process(msg_const_shared_ptr_, message_info_), + std::runtime_error); + EXPECT_EQ(callback_count, 1); + + // Unique_ptr is_moved + EXPECT_NO_THROW( + any_subscription_callback_.dispatch_intra_process(std::move(msg_unique_ptr_), message_info_)); + EXPECT_EQ(callback_count, 2); +} diff --git a/rclcpp/test/rclcpp/test_create_subscription.cpp b/rclcpp/test/rclcpp/test_create_subscription.cpp new file mode 100644 index 0000000..184904b --- /dev/null +++ b/rclcpp/test/rclcpp/test_create_subscription.cpp @@ -0,0 +1,67 @@ +// Copyright 2020 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include +#include + +#include "rclcpp/create_subscription.hpp" +#include "rclcpp/node.hpp" +#include "test_msgs/msg/empty.hpp" +#include "test_msgs/msg/empty.h" + +using namespace std::chrono_literals; + +class TestCreateSubscription : public ::testing::Test +{ +public: + void SetUp() override + { + rclcpp::init(0, nullptr); + } + + void TearDown() override + { + rclcpp::shutdown(); + } +}; + +TEST_F(TestCreateSubscription, create) { + auto node = std::make_shared("my_node", "/ns"); + const rclcpp::QoS qos(10); + auto options = rclcpp::SubscriptionOptions(); + auto callback = [](const test_msgs::msg::Empty::SharedPtr) {}; + auto subscription = + rclcpp::create_subscription(node, "topic_name", qos, callback, options); + + ASSERT_NE(nullptr, subscription); + EXPECT_STREQ("/ns/topic_name", subscription->get_topic_name()); +} + +TEST_F(TestCreateSubscription, create_with_statistics) { + auto node = std::make_shared("my_node", "/ns"); + const rclcpp::QoS qos(10); + auto options = rclcpp::SubscriptionOptions(); + options.topic_stats_options.state = rclcpp::TopicStatisticsState::Enable; + options.topic_stats_options.publish_topic = "topic_statistics"; + options.topic_stats_options.publish_period = 5min; + + auto callback = [](const test_msgs::msg::Empty::SharedPtr) {}; + auto subscription = + rclcpp::create_subscription(node, "topic_name", qos, callback, options); + + ASSERT_NE(nullptr, subscription); + EXPECT_STREQ("/ns/topic_name", subscription->get_topic_name()); +}