|
24 | 24 | #include "rcl_interfaces/srv/list_parameters.hpp" |
25 | 25 |
|
26 | 26 | #include "../mocking_utils/patch.hpp" |
| 27 | +#include "../utils/rclcpp_gtest_macros.hpp" |
27 | 28 |
|
28 | 29 | #include "test_msgs/srv/empty.hpp" |
29 | 30 |
|
@@ -431,3 +432,105 @@ TEST_F(TestClient, on_new_response_callback) { |
431 | 432 | std::function<void(size_t)> invalid_cb = nullptr; |
432 | 433 | EXPECT_THROW(client->set_on_new_response_callback(invalid_cb), std::invalid_argument); |
433 | 434 | } |
| 435 | + |
| 436 | +TEST_F(TestClient, rcl_client_request_publisher_get_actual_qos_error) { |
| 437 | + auto mock = mocking_utils::patch_and_return( |
| 438 | + "lib:rclcpp", rcl_client_request_publisher_get_actual_qos, nullptr); |
| 439 | + auto client = node->create_client<test_msgs::srv::Empty>("service"); |
| 440 | + RCLCPP_EXPECT_THROW_EQ( |
| 441 | + client->get_request_publisher_actual_qos(), |
| 442 | + std::runtime_error("failed to get client's request publisher qos settings: error not set")); |
| 443 | +} |
| 444 | + |
| 445 | +TEST_F(TestClient, rcl_client_response_subscription_get_actual_qos_error) { |
| 446 | + auto mock = mocking_utils::patch_and_return( |
| 447 | + "lib:rclcpp", rcl_client_response_subscription_get_actual_qos, nullptr); |
| 448 | + auto client = node->create_client<test_msgs::srv::Empty>("service"); |
| 449 | + RCLCPP_EXPECT_THROW_EQ( |
| 450 | + client->get_response_subscription_actual_qos(), |
| 451 | + std::runtime_error("failed to get client's response subscription qos settings: error not set")); |
| 452 | +} |
| 453 | + |
| 454 | +TEST_F(TestClient, client_qos) { |
| 455 | + rmw_qos_profile_t qos_profile = rmw_qos_profile_services_default; |
| 456 | + qos_profile.liveliness = RMW_QOS_POLICY_LIVELINESS_AUTOMATIC; |
| 457 | + uint64_t duration = 1; |
| 458 | + qos_profile.deadline = {duration, duration}; |
| 459 | + qos_profile.lifespan = {duration, duration}; |
| 460 | + qos_profile.liveliness_lease_duration = {duration, duration}; |
| 461 | + |
| 462 | + auto client = |
| 463 | + node->create_client<test_msgs::srv::Empty>("client", qos_profile); |
| 464 | + |
| 465 | + auto init_qos = |
| 466 | + rclcpp::QoS(rclcpp::QoSInitialization::from_rmw(qos_profile), qos_profile); |
| 467 | + auto rp_qos = client->get_request_publisher_actual_qos(); |
| 468 | + auto rs_qos = client->get_response_subscription_actual_qos(); |
| 469 | + |
| 470 | + EXPECT_EQ(init_qos, rp_qos); |
| 471 | + // Lifespan has no meaning for subscription/readers |
| 472 | + rs_qos.lifespan(qos_profile.lifespan); |
| 473 | + EXPECT_EQ(init_qos, rs_qos); |
| 474 | +} |
| 475 | + |
| 476 | +TEST_F(TestClient, client_qos_depth) { |
| 477 | + using namespace std::literals::chrono_literals; |
| 478 | + |
| 479 | + rmw_qos_profile_t client_qos_profile = rmw_qos_profile_default; |
| 480 | + client_qos_profile.depth = 2; |
| 481 | + |
| 482 | + auto client = node->create_client<test_msgs::srv::Empty>("test_qos_depth", client_qos_profile); |
| 483 | + |
| 484 | + uint64_t server_cb_count_ = 0; |
| 485 | + auto server_callback = [&]( |
| 486 | + const test_msgs::srv::Empty::Request::SharedPtr, |
| 487 | + test_msgs::srv::Empty::Response::SharedPtr) {server_cb_count_++;}; |
| 488 | + |
| 489 | + auto server_node = std::make_shared<rclcpp::Node>("server_node", "/ns"); |
| 490 | + |
| 491 | + rmw_qos_profile_t server_qos_profile = rmw_qos_profile_default; |
| 492 | + |
| 493 | + auto server = server_node->create_service<test_msgs::srv::Empty>( |
| 494 | + "test_qos_depth", std::move(server_callback), server_qos_profile); |
| 495 | + |
| 496 | + auto request = std::make_shared<test_msgs::srv::Empty::Request>(); |
| 497 | + ::testing::AssertionResult request_result = ::testing::AssertionSuccess(); |
| 498 | + |
| 499 | + using SharedFuture = rclcpp::Client<test_msgs::srv::Empty>::SharedFuture; |
| 500 | + uint64_t client_cb_count_ = 0; |
| 501 | + auto client_callback = [&client_cb_count_, &request_result](SharedFuture future_response) { |
| 502 | + if (nullptr == future_response.get()) { |
| 503 | + request_result = ::testing::AssertionFailure() << "Future response was null"; |
| 504 | + } |
| 505 | + client_cb_count_++; |
| 506 | + }; |
| 507 | + |
| 508 | + uint64_t client_requests = 5; |
| 509 | + for (uint64_t i = 0; i < client_requests; i++) { |
| 510 | + client->async_send_request(request, client_callback); |
| 511 | + std::this_thread::sleep_for(10ms); |
| 512 | + } |
| 513 | + |
| 514 | + auto start = std::chrono::steady_clock::now(); |
| 515 | + while ((server_cb_count_ < client_requests) && |
| 516 | + (std::chrono::steady_clock::now() - start) < 2s) |
| 517 | + { |
| 518 | + rclcpp::spin_some(server_node); |
| 519 | + std::this_thread::sleep_for(2ms); |
| 520 | + } |
| 521 | + |
| 522 | + EXPECT_GT(server_cb_count_, client_qos_profile.depth); |
| 523 | + |
| 524 | + start = std::chrono::steady_clock::now(); |
| 525 | + while ((client_cb_count_ < client_qos_profile.depth) && |
| 526 | + (std::chrono::steady_clock::now() - start) < 1s) |
| 527 | + { |
| 528 | + rclcpp::spin_some(node); |
| 529 | + } |
| 530 | + |
| 531 | + // Spin an extra time to check if client QoS depth has been ignored, |
| 532 | + // so more client callbacks might be called than expected. |
| 533 | + rclcpp::spin_some(node); |
| 534 | + |
| 535 | + EXPECT_EQ(client_cb_count_, client_qos_profile.depth); |
| 536 | +} |
0 commit comments