diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c4008c2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# Workspace folders +build/ +install/ +log/ + +# VS Code +.vscode/ diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 7aed7f9..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "files.associations": { - "*.tcc": "cpp", - "string": "cpp", - "unordered_map": "cpp", - "unordered_set": "cpp", - "string_view": "cpp" - } -} \ No newline at end of file diff --git a/rmw_implementation/CHANGELOG.rst b/rmw_implementation/CHANGELOG.rst index 6ca13f1..e3fac0e 100644 --- a/rmw_implementation/CHANGELOG.rst +++ b/rmw_implementation/CHANGELOG.rst @@ -2,6 +2,18 @@ Changelog for package rmw_implementation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +3.1.4 (2025-12-23) +------------------ +* Updated deprecated ament_index_cpp API (`#272 `_) +* Contributors: Alejandro Hernández Cordero + +3.1.3 (2025-11-18) +------------------ +* Add rmw_get_clients_info_by_service , rmw_servers_clients_info_by_service (`#238 `_) +* fix cmake deprecation (`#267 `_) +* Explain rosidl_typesupport\_{c,cpp} in rmw impl typesupport list (`#265 `_) +* Contributors: Christophe Bedard, Minju, Lee, mosfet80 + 3.1.2 (2025-07-29) ------------------ diff --git a/rmw_implementation/CMakeLists.txt b/rmw_implementation/CMakeLists.txt index 2128c5d..78e6403 100644 --- a/rmw_implementation/CMakeLists.txt +++ b/rmw_implementation/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.20) project(rmw_implementation) diff --git a/rmw_implementation/package.xml b/rmw_implementation/package.xml index 190cae5..8fa6ee0 100644 --- a/rmw_implementation/package.xml +++ b/rmw_implementation/package.xml @@ -2,7 +2,7 @@ rmw_implementation - 3.1.2 + 3.1.4 Proxy implementation of the ROS 2 Middleware Interface. William Woodall @@ -27,6 +27,7 @@ rmw_cyclonedds_cpp rmw_fastrtps_cpp rmw_fastrtps_dynamic_cpp + rmw_zenoh_cpp rmw_implementation_cmake diff --git a/rmw_implementation/src/functions.cpp b/rmw_implementation/src/functions.cpp index 884954a..8d380ab 100644 --- a/rmw_implementation/src/functions.cpp +++ b/rmw_implementation/src/functions.cpp @@ -15,6 +15,7 @@ #include "functions.hpp" #include +#include #include #include #include @@ -34,6 +35,7 @@ #include "rmw/features.h" #include "rmw/get_network_flow_endpoints.h" #include "rmw/get_node_info_and_types.h" +#include "rmw/get_service_endpoint_info.h" #include "rmw/get_service_names_and_types.h" #include "rmw/get_topic_endpoint_info.h" #include "rmw/get_topic_names_and_types.h" @@ -108,8 +110,8 @@ load_library() // OK, we failed to load the default RMW. Fetch all of the ones we can // find and attempt to load them one-by-one. rmw_reset_error(); - const std::map packages_with_prefixes = ament_index_cpp::get_resources( - "rmw_typesupport"); + const std::map packages_with_prefixes = + ament_index_cpp::get_resources_by_name("rmw_typesupport"); for (const auto & package_prefix_pair : packages_with_prefixes) { if (package_prefix_pair.first != "rmw_implementation") { ret = attempt_to_load_one_rmw(package_prefix_pair.first); @@ -770,6 +772,26 @@ RMW_INTERFACE_FN( bool, rmw_topic_endpoint_info_array_t *)) +RMW_INTERFACE_FN( + rmw_get_clients_info_by_service, + rmw_ret_t, RMW_RET_ERROR, + 5, ARG_TYPES( + const rmw_node_t *, + rcutils_allocator_t *, + const char *, + bool, + rmw_service_endpoint_info_array_t *)) + +RMW_INTERFACE_FN( + rmw_get_servers_info_by_service, + rmw_ret_t, RMW_RET_ERROR, + 5, ARG_TYPES( + const rmw_node_t *, + rcutils_allocator_t *, + const char *, + bool, + rmw_service_endpoint_info_array_t *)) + RMW_INTERFACE_FN( rmw_qos_profile_check_compatible, rmw_ret_t, RMW_RET_ERROR, @@ -946,6 +968,8 @@ void prefetch_symbols(void) GET_SYMBOL(rmw_set_log_severity) GET_SYMBOL(rmw_get_publishers_info_by_topic) GET_SYMBOL(rmw_get_subscriptions_info_by_topic) + GET_SYMBOL(rmw_get_clients_info_by_service) + GET_SYMBOL(rmw_get_servers_info_by_service) GET_SYMBOL(rmw_qos_profile_check_compatible) GET_SYMBOL(rmw_publisher_get_network_flow_endpoints) GET_SYMBOL(rmw_subscription_get_network_flow_endpoints) @@ -1078,6 +1102,8 @@ unload_library() symbol_rmw_set_log_severity = nullptr; symbol_rmw_get_publishers_info_by_topic = nullptr; symbol_rmw_get_subscriptions_info_by_topic = nullptr; + symbol_rmw_get_clients_info_by_service = nullptr; + symbol_rmw_get_servers_info_by_service = nullptr; symbol_rmw_qos_profile_check_compatible = nullptr; symbol_rmw_publisher_get_network_flow_endpoints = nullptr; symbol_rmw_subscription_get_network_flow_endpoints = nullptr; diff --git a/test_rmw_implementation/CHANGELOG.rst b/test_rmw_implementation/CHANGELOG.rst index 4d15ac0..2471dbf 100644 --- a/test_rmw_implementation/CHANGELOG.rst +++ b/test_rmw_implementation/CHANGELOG.rst @@ -2,6 +2,15 @@ Changelog for package test_rmw_implementation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +3.1.4 (2025-12-23) +------------------ + +3.1.3 (2025-11-18) +------------------ +* Add rmw_get_clients_info_by_service , rmw_servers_clients_info_by_service (`#238 `_) +* fix cmake deprecation (`#267 `_) +* Contributors: Minju, Lee, mosfet80 + 3.1.2 (2025-07-29) ------------------ * Test failing deserialization of invalid sequence length (`#261 `_) diff --git a/test_rmw_implementation/CMakeLists.txt b/test_rmw_implementation/CMakeLists.txt index 3fde428..9c2cacd 100644 --- a/test_rmw_implementation/CMakeLists.txt +++ b/test_rmw_implementation/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.20) project(test_rmw_implementation) @@ -15,6 +15,7 @@ endif() find_package(ament_cmake REQUIRED) if(BUILD_TESTING) + find_package(ament_cmake_ros REQUIRED) find_package(ament_cmake_gtest REQUIRED) find_package(osrf_testing_tools_cpp REQUIRED) @@ -199,100 +200,100 @@ if(BUILD_TESTING) message(STATUS "Creating API tests for '${rmw_implementation}'") set(rmw_implementation_env_var RMW_IMPLEMENTATION=${rmw_implementation}) - ament_add_gtest_test(test_init_shutdown + ament_add_ros_isolated_gtest_test(test_init_shutdown TEST_NAME test_init_shutdown${target_suffix} ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_init_options + ament_add_ros_isolated_gtest_test(test_init_options TEST_NAME test_init_options${target_suffix} ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_create_destroy_node + ament_add_ros_isolated_gtest_test(test_create_destroy_node TEST_NAME test_create_destroy_node${target_suffix} ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_publisher + ament_add_ros_isolated_gtest_test(test_publisher TEST_NAME test_publisher${target_suffix} ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_subscription + ament_add_ros_isolated_gtest_test(test_subscription TEST_NAME test_subscription${target_suffix} TIMEOUT 120 ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_serialize_deserialize + ament_add_ros_isolated_gtest_test(test_serialize_deserialize TEST_NAME test_serialize_deserialize${target_suffix} ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_publisher_allocator + ament_add_ros_isolated_gtest_test(test_publisher_allocator TEST_NAME test_publisher_allocator${target_suffix} ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_subscription_allocator + ament_add_ros_isolated_gtest_test(test_subscription_allocator TEST_NAME test_subscription_allocator${target_suffix} ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_wait_set + ament_add_ros_isolated_gtest_test(test_wait_set TEST_NAME test_wait_set${target_suffix} ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_graph_api + ament_add_ros_isolated_gtest_test(test_graph_api TEST_NAME test_graph_api${target_suffix} TIMEOUT 120 ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_unique_identifiers + ament_add_ros_isolated_gtest_test(test_unique_identifiers TEST_NAME test_unique_identifiers${target_suffix} ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_service + ament_add_ros_isolated_gtest_test(test_service TEST_NAME test_service${target_suffix} ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_client + ament_add_ros_isolated_gtest_test(test_client TEST_NAME test_client${target_suffix} TIMEOUT 120 ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_qos_profile_check_compatible + ament_add_ros_isolated_gtest_test(test_qos_profile_check_compatible TEST_NAME test_qos_profile_check_compatible${target_suffix} ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_duration_infinite + ament_add_ros_isolated_gtest_test(test_duration_infinite TEST_NAME test_duration_infinite${target_suffix} ENV ${rmw_implementation_env_var} ) - ament_add_gtest_test(test_event + ament_add_ros_isolated_gtest_test(test_event TEST_NAME test_event${target_suffix} ENV ${rmw_implementation_env_var} diff --git a/test_rmw_implementation/package.xml b/test_rmw_implementation/package.xml index 7c0670c..5d206cd 100644 --- a/test_rmw_implementation/package.xml +++ b/test_rmw_implementation/package.xml @@ -2,7 +2,7 @@ test_rmw_implementation - 3.1.2 + 3.1.4 Test suite for ROS middleware API. William Woodall @@ -14,7 +14,7 @@ ament_cmake - ament_cmake_gtest + ament_cmake_ros ament_lint_auto ament_lint_common osrf_testing_tools_cpp diff --git a/test_rmw_implementation/test/test_graph_api.cpp b/test_rmw_implementation/test/test_graph_api.cpp index 0468158..724c9b7 100644 --- a/test_rmw_implementation/test/test_graph_api.cpp +++ b/test_rmw_implementation/test/test_graph_api.cpp @@ -21,6 +21,7 @@ #include "rmw/error_handling.h" #include "rmw/get_node_info_and_types.h" +#include "rmw/get_service_endpoint_info.h" #include "rmw/get_service_names_and_types.h" #include "rmw/get_topic_endpoint_info.h" #include "rmw/get_topic_names_and_types.h" @@ -835,6 +836,132 @@ TEST_F(TestGraphAPI, get_subscriptions_info_by_topic_with_bad_arguments) { EXPECT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; } +TEST_F(TestGraphAPI, get_clients_info_by_service_with_bad_arguments) { + rcutils_allocator_t allocator = rcutils_get_default_allocator(); + constexpr char service_name[] = "/test_service"; + bool no_mangle = false; + rmw_service_endpoint_info_array_t clients_info = + rmw_get_zero_initialized_service_endpoint_info_array(); + + // A null node is an invalid argument. + rmw_ret_t ret = rmw_get_clients_info_by_service( + nullptr, &allocator, service_name, no_mangle, &clients_info); + EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, ret); + rmw_reset_error(); + EXPECT_EQ(RMW_RET_OK, rmw_service_endpoint_info_array_check_zero(&clients_info)); + + // A node from a different implementation is an invalid argument. + const char * implementation_identifier = node->implementation_identifier; + node->implementation_identifier = "not-an-rmw-implementation-identifier"; + ret = rmw_get_clients_info_by_service( + node, &allocator, service_name, no_mangle, &clients_info); + EXPECT_EQ(RMW_RET_INCORRECT_RMW_IMPLEMENTATION, ret); + node->implementation_identifier = implementation_identifier; + rmw_reset_error(); + EXPECT_EQ(RMW_RET_OK, rmw_service_endpoint_info_array_check_zero(&clients_info)); + + // A null allocator is an invalid argument. + ret = rmw_get_clients_info_by_service( + node, nullptr, service_name, no_mangle, &clients_info); + EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, ret); + rmw_reset_error(); + EXPECT_EQ(RMW_RET_OK, rmw_service_endpoint_info_array_check_zero(&clients_info)); + + // An invalid (zero initialized) allocator is an invalid argument. + rcutils_allocator_t invalid_allocator = rcutils_get_zero_initialized_allocator(); + ret = rmw_get_clients_info_by_service( + node, &invalid_allocator, service_name, no_mangle, &clients_info); + EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, ret); + rmw_reset_error(); + EXPECT_EQ(RMW_RET_OK, rmw_service_endpoint_info_array_check_zero(&clients_info)); + + // A null service name is an invalid argument. + ret = rmw_get_clients_info_by_service( + node, &allocator, nullptr, no_mangle, &clients_info); + EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, ret); + rmw_reset_error(); + EXPECT_EQ(RMW_RET_OK, rmw_service_endpoint_info_array_check_zero(&clients_info)); + + // A null array of service endpoint info is an invalid argument. + ret = rmw_get_clients_info_by_service(node, &allocator, service_name, no_mangle, nullptr); + EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, ret); + rmw_reset_error(); + EXPECT_EQ(RMW_RET_OK, rmw_service_endpoint_info_array_check_zero(&clients_info)); + + // A non zero initialized array of service endpoint info is an invalid argument. + ret = rmw_service_endpoint_info_array_init_with_size(&clients_info, 1u, &allocator); + ASSERT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; + ret = rmw_get_clients_info_by_service( + node, &allocator, service_name, no_mangle, &clients_info); + EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, ret); + rmw_reset_error(); + ret = rmw_service_endpoint_info_array_fini(&clients_info, &allocator); + EXPECT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; +} + +TEST_F(TestGraphAPI, get_servers_info_by_service_with_bad_arguments) { + rcutils_allocator_t allocator = rcutils_get_default_allocator(); + constexpr char service_name[] = "/test_service"; + bool no_mangle = false; + rmw_service_endpoint_info_array_t servers_info = + rmw_get_zero_initialized_service_endpoint_info_array(); + + // A null node is an invalid argument. + rmw_ret_t ret = rmw_get_servers_info_by_service( + nullptr, &allocator, service_name, no_mangle, &servers_info); + EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, ret); + rmw_reset_error(); + EXPECT_EQ(RMW_RET_OK, rmw_service_endpoint_info_array_check_zero(&servers_info)); + + // A node from a different implementation is an invalid argument. + const char * implementation_identifier = node->implementation_identifier; + node->implementation_identifier = "not-an-rmw-implementation-identifier"; + ret = rmw_get_servers_info_by_service( + node, &allocator, service_name, no_mangle, &servers_info); + EXPECT_EQ(RMW_RET_INCORRECT_RMW_IMPLEMENTATION, ret); + node->implementation_identifier = implementation_identifier; + rmw_reset_error(); + EXPECT_EQ(RMW_RET_OK, rmw_service_endpoint_info_array_check_zero(&servers_info)); + + // A null allocator is an invalid argument. + ret = rmw_get_servers_info_by_service( + node, nullptr, service_name, no_mangle, &servers_info); + EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, ret); + rmw_reset_error(); + EXPECT_EQ(RMW_RET_OK, rmw_service_endpoint_info_array_check_zero(&servers_info)); + + // An invalid (zero initialized) allocator is an invalid argument. + rcutils_allocator_t invalid_allocator = rcutils_get_zero_initialized_allocator(); + ret = rmw_get_servers_info_by_service( + node, &invalid_allocator, service_name, no_mangle, &servers_info); + EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, ret); + rmw_reset_error(); + EXPECT_EQ(RMW_RET_OK, rmw_service_endpoint_info_array_check_zero(&servers_info)); + + // A null service name is an invalid argument. + ret = rmw_get_servers_info_by_service( + node, &allocator, nullptr, no_mangle, &servers_info); + EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, ret); + rmw_reset_error(); + EXPECT_EQ(RMW_RET_OK, rmw_service_endpoint_info_array_check_zero(&servers_info)); + + // A null array of service endpoint info is an invalid argument. + ret = rmw_get_servers_info_by_service(node, &allocator, service_name, no_mangle, nullptr); + EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, ret); + rmw_reset_error(); + EXPECT_EQ(RMW_RET_OK, rmw_service_endpoint_info_array_check_zero(&servers_info)); + + // A non zero initialized array of service endpoint info is an invalid argument. + ret = rmw_service_endpoint_info_array_init_with_size(&servers_info, 1u, &allocator); + ASSERT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; + ret = rmw_get_servers_info_by_service( + node, &allocator, service_name, no_mangle, &servers_info); + EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, ret); + rmw_reset_error(); + ret = rmw_service_endpoint_info_array_fini(&servers_info, &allocator); + EXPECT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; +} + TEST_F(TestGraphAPI, count_publishers_with_bad_arguments) { size_t count = 0u; constexpr char topic_name[] = "/test_topic";