From 0d4a26b4c6694a28ed0923b7b28bf894ff12e487 Mon Sep 17 00:00:00 2001 From: Brian Date: Thu, 2 Feb 2023 09:34:24 -0500 Subject: [PATCH] Service introspection (#127) * preliminary c ts impl for service introspection msg gen * preliminary cpp ts impl for service introspection msg gen Signed-off-by: Brian Chen Signed-off-by: Jacob Perron Signed-off-by: Ivan Santiago Paunovic Signed-off-by: Chris Lalancette --- .../resource/msg__type_support.cpp.em | 1 + .../resource/srv__type_support.cpp.em | 20 +- .../benchmark_type_support_dispatch.cpp | 2 +- .../test_service_type_support_dispatch.cpp | 2 +- rosidl_typesupport_c/test/test_type_support.c | 2 +- .../resource/srv__type_support.cpp.em | 14 +- .../benchmark_type_support_dispatch.cpp | 2 +- .../test_service_type_support_dispatch.cpp | 2 +- .../test/test_type_support.cpp | 4 +- rosidl_typesupport_tests/CMakeLists.txt | 43 ++++ rosidl_typesupport_tests/package.xml | 27 +++ .../test_service_typesupport.cpp | 182 +++++++++++++++++ .../test_service_typesupport.cpp | 186 ++++++++++++++++++ 13 files changed, 477 insertions(+), 10 deletions(-) create mode 100644 rosidl_typesupport_tests/CMakeLists.txt create mode 100644 rosidl_typesupport_tests/package.xml create mode 100644 rosidl_typesupport_tests/test/rosidl_typesupport_c/test_service_typesupport.cpp create mode 100644 rosidl_typesupport_tests/test/rosidl_typesupport_cpp/test_service_typesupport.cpp diff --git a/rosidl_typesupport_c/resource/msg__type_support.cpp.em b/rosidl_typesupport_c/resource/msg__type_support.cpp.em index 6e1e7844..5a982313 100644 --- a/rosidl_typesupport_c/resource/msg__type_support.cpp.em +++ b/rosidl_typesupport_c/resource/msg__type_support.cpp.em @@ -10,6 +10,7 @@ header_files = [ 'rosidl_runtime_c/message_type_support_struct.h', include_base + '__struct.h', include_base + '__type_support.h', + include_base + '__functions.h', ] if len(type_supports) != 1: header_files += [ diff --git a/rosidl_typesupport_c/resource/srv__type_support.cpp.em b/rosidl_typesupport_c/resource/srv__type_support.cpp.em index c0303ff4..e0de2141 100644 --- a/rosidl_typesupport_c/resource/srv__type_support.cpp.em +++ b/rosidl_typesupport_c/resource/srv__type_support.cpp.em @@ -15,6 +15,14 @@ TEMPLATE( type_supports=type_supports) }@ +@{ +TEMPLATE( + 'msg__type_support.cpp.em', + package_name=package_name, interface_path=interface_path, + message=service.event_message, include_directives=include_directives, + type_supports=type_supports) +}@ + @{ from rosidl_pycommon import convert_camel_case_to_lower_case_underscore include_parts = [package_name] + list(interface_path.parents[0].parts) + [ @@ -33,6 +41,8 @@ if len(type_supports) != 1: 'rosidl_typesupport_c/type_support_map.h', ] header_files.append('rosidl_typesupport_interface/macros.h') +header_files.append('service_msgs/msg/service_event_info.h') +header_files.append('builtin_interfaces/msg/time.h') }@ @[for header_file in header_files]@ @[ if header_file in include_directives]@ @@ -53,7 +63,6 @@ namespace @(ns) namespace rosidl_typesupport_c { - typedef struct _@(service.namespaced_type.name)_type_support_ids_t { const char * typesupport_identifier[@(len(type_supports))]; @@ -109,6 +118,15 @@ static const rosidl_service_type_support_t @(service.namespaced_type.name)_servi rosidl_typesupport_c__typesupport_identifier, reinterpret_cast(&_@(service.namespaced_type.name)_service_typesupport_map), rosidl_typesupport_c__get_service_typesupport_handle_function, + ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_CREATE_EVENT_MESSAGE_SYMBOL_NAME( + rosidl_typesupport_c, + @(',\n '.join(service.namespaced_type.namespaced_name())) + ), + ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_DESTROY_EVENT_MESSAGE_SYMBOL_NAME( + rosidl_typesupport_c, + @(',\n '.join(service.namespaced_type.namespaced_name())) + ), + &@(service.namespaced_type.name)_Event_message_type_support_handle }; } // namespace rosidl_typesupport_c diff --git a/rosidl_typesupport_c/test/benchmark/benchmark_type_support_dispatch.cpp b/rosidl_typesupport_c/test/benchmark/benchmark_type_support_dispatch.cpp index bc77f83f..a582d1b6 100644 --- a/rosidl_typesupport_c/test/benchmark/benchmark_type_support_dispatch.cpp +++ b/rosidl_typesupport_c/test/benchmark/benchmark_type_support_dispatch.cpp @@ -42,7 +42,7 @@ rosidl_message_type_support_t get_rosidl_message_type_support(const char * ident rosidl_service_type_support_t get_rosidl_service_type_support(const char * identifier) { - return {identifier, nullptr, nullptr}; + return {identifier, nullptr, nullptr, nullptr, nullptr, nullptr}; } type_support_map_t get_typesupport_map(void ** library_array) diff --git a/rosidl_typesupport_c/test/test_service_type_support_dispatch.cpp b/rosidl_typesupport_c/test/test_service_type_support_dispatch.cpp index d8e82537..e54a33c0 100644 --- a/rosidl_typesupport_c/test/test_service_type_support_dispatch.cpp +++ b/rosidl_typesupport_c/test/test_service_type_support_dispatch.cpp @@ -38,7 +38,7 @@ constexpr const char * symbols[map_size] = { rosidl_service_type_support_t get_rosidl_service_type_support(const char * identifier) { - return {identifier, nullptr, nullptr}; + return {identifier, nullptr, nullptr, nullptr, nullptr, nullptr}; } type_support_map_t get_typesupport_map(void ** library_array) diff --git a/rosidl_typesupport_c/test/test_type_support.c b/rosidl_typesupport_c/test/test_type_support.c index 37047082..2364d006 100644 --- a/rosidl_typesupport_c/test/test_type_support.c +++ b/rosidl_typesupport_c/test/test_type_support.c @@ -34,7 +34,7 @@ static const rosidl_message_type_support_t message_type_support = { }; static const rosidl_service_type_support_t service_type_support = { - 0, 0, 0 + 0, 0, 0, 0, 0, 0 }; const rosidl_message_type_support_t * test_message_type_support() {return &message_type_support;} diff --git a/rosidl_typesupport_cpp/resource/srv__type_support.cpp.em b/rosidl_typesupport_cpp/resource/srv__type_support.cpp.em index 26242ccd..8004b186 100644 --- a/rosidl_typesupport_cpp/resource/srv__type_support.cpp.em +++ b/rosidl_typesupport_cpp/resource/srv__type_support.cpp.em @@ -15,6 +15,14 @@ TEMPLATE( type_supports=type_supports) }@ +@{ +TEMPLATE( + 'msg__type_support.cpp.em', + package_name=package_name, interface_path=interface_path, + message=service.event_message, include_directives=include_directives, + type_supports=type_supports) +}@ + @{ from rosidl_pycommon import convert_camel_case_to_lower_case_underscore include_parts = [package_name] + list(interface_path.parents[0].parts) + [ @@ -24,11 +32,11 @@ include_base = '/'.join(include_parts) header_files = [ 'cstddef', 'rosidl_runtime_c/service_type_support_struct.h', + 'rosidl_typesupport_cpp/service_type_support.hpp', include_base + '__struct.hpp', ] if len(type_supports) != 1: header_files.append('rosidl_typesupport_cpp/identifier.hpp') -header_files.append('rosidl_typesupport_cpp/service_type_support.hpp') if len(type_supports) != 1: header_files += [ 'rosidl_typesupport_c/type_support_map.h', @@ -76,7 +84,6 @@ typedef struct _@(service.namespaced_type.name)_type_support_symbol_names_t { const char * symbol_name[@(len(type_supports))]; } _@(service.namespaced_type.name)_type_support_symbol_names_t; - #define STRINGIFY_(s) #s #define STRINGIFY(s) STRINGIFY_(s) @@ -113,6 +120,9 @@ static const rosidl_service_type_support_t @(service.namespaced_type.name)_servi ::rosidl_typesupport_cpp::typesupport_identifier, reinterpret_cast(&_@(service.namespaced_type.name)_service_typesupport_map), ::rosidl_typesupport_cpp::get_service_typesupport_handle_function, + &::rosidl_typesupport_cpp::service_create_event_message<@('::'.join([package_name, *interface_path.parents[0].parts, service.namespaced_type.name]))>, + &::rosidl_typesupport_cpp::service_destroy_event_message<@('::'.join([package_name, *interface_path.parents[0].parts, service.namespaced_type.name]))>, + ::rosidl_typesupport_cpp::get_message_type_support_handle<@('::'.join([package_name, *interface_path.parents[0].parts, service.namespaced_type.name]))_Event>(), }; } // namespace rosidl_typesupport_cpp diff --git a/rosidl_typesupport_cpp/test/benchmark/benchmark_type_support_dispatch.cpp b/rosidl_typesupport_cpp/test/benchmark/benchmark_type_support_dispatch.cpp index 8de0e2f3..187763b4 100644 --- a/rosidl_typesupport_cpp/test/benchmark/benchmark_type_support_dispatch.cpp +++ b/rosidl_typesupport_cpp/test/benchmark/benchmark_type_support_dispatch.cpp @@ -42,7 +42,7 @@ rosidl_message_type_support_t get_rosidl_message_type_support(const char * ident rosidl_service_type_support_t get_rosidl_service_type_support(const char * identifier) { - return {identifier, nullptr, nullptr}; + return {identifier, nullptr, nullptr, nullptr, nullptr, nullptr}; } type_support_map_t get_typesupport_map(void ** library_array) diff --git a/rosidl_typesupport_cpp/test/test_service_type_support_dispatch.cpp b/rosidl_typesupport_cpp/test/test_service_type_support_dispatch.cpp index aae3fc4c..ca9783f5 100644 --- a/rosidl_typesupport_cpp/test/test_service_type_support_dispatch.cpp +++ b/rosidl_typesupport_cpp/test/test_service_type_support_dispatch.cpp @@ -35,7 +35,7 @@ constexpr const char * symbols[map_size] = { rosidl_service_type_support_t get_rosidl_service_type_support(const char * identifier) { - return {identifier, nullptr, nullptr}; + return {identifier, nullptr, nullptr, nullptr, nullptr, nullptr}; } type_support_map_t get_typesupport_map(void ** library_array) diff --git a/rosidl_typesupport_cpp/test/test_type_support.cpp b/rosidl_typesupport_cpp/test/test_type_support.cpp index b0a27dce..243fae1e 100644 --- a/rosidl_typesupport_cpp/test/test_type_support.cpp +++ b/rosidl_typesupport_cpp/test/test_type_support.cpp @@ -35,11 +35,11 @@ const rosidl_service_type_support_t * test_service_type_support(); #endif static const rosidl_message_type_support_t message_type_support = { - 0, 0, 0 + nullptr, nullptr, nullptr }; static const rosidl_service_type_support_t service_type_support = { - 0, 0, 0 + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; const rosidl_message_type_support_t * test_message_type_support() {return &message_type_support;} diff --git a/rosidl_typesupport_tests/CMakeLists.txt b/rosidl_typesupport_tests/CMakeLists.txt new file mode 100644 index 00000000..a90ce66b --- /dev/null +++ b/rosidl_typesupport_tests/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 3.8) +project(rosidl_typesupport_tests) + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +find_package(ament_cmake REQUIRED) + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + ament_lint_auto_find_test_dependencies() + find_package(rosidl_cmake REQUIRED) + find_package(ament_cmake_gtest REQUIRED) + find_package(test_interface_files REQUIRED) + find_package(rcutils REQUIRED) + + rosidl_generate_interfaces(${PROJECT_NAME} + ${test_interface_files_MSG_FILES} + ${test_interface_files_SRV_FILES} + ${test_interface_files_ACTION_FILES} + SKIP_INSTALL + ) + + rosidl_get_typesupport_target(cpp_typesupport_target ${PROJECT_NAME} "rosidl_typesupport_cpp") + rosidl_get_typesupport_target(c_typesupport_target ${PROJECT_NAME} "rosidl_typesupport_c") + + ament_add_gtest(test_service_typesupport_cpp + test/rosidl_typesupport_cpp/test_service_typesupport.cpp + ) + target_link_libraries(test_service_typesupport_cpp + "${cpp_typesupport_target}" + ) + + ament_add_gtest(test_service_typesupport_c + test/rosidl_typesupport_c/test_service_typesupport.cpp + ) + target_link_libraries(test_service_typesupport_c + "${c_typesupport_target}" + ) +endif() + +ament_package() diff --git a/rosidl_typesupport_tests/package.xml b/rosidl_typesupport_tests/package.xml new file mode 100644 index 00000000..414eeab4 --- /dev/null +++ b/rosidl_typesupport_tests/package.xml @@ -0,0 +1,27 @@ + + + + rosidl_typesupport_tests + 2.2.0 + Test rosidl_typesupport_c and rosidl_typesupport_cpp packages + Jacob Perron + Apache License 2.0 + Brian Chen + + ament_cmake + + ament_lint_auto + ament_lint_common + ament_cmake_gtest + rcutils + rosidl_cmake + rosidl_typesupport_c + rosidl_typesupport_cpp + test_interface_files + service_msgs + action_msgs + + + ament_cmake + + diff --git a/rosidl_typesupport_tests/test/rosidl_typesupport_c/test_service_typesupport.cpp b/rosidl_typesupport_tests/test/rosidl_typesupport_c/test_service_typesupport.cpp new file mode 100644 index 00000000..ecc1df0a --- /dev/null +++ b/rosidl_typesupport_tests/test/rosidl_typesupport_c/test_service_typesupport.cpp @@ -0,0 +1,182 @@ +// Copyright 2022 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 "gtest/gtest.h" + +#include "rcutils/allocator.h" + +#include "rosidl_runtime_c/string_functions.h" + +#include "rosidl_typesupport_tests/action/fibonacci.h" +#include "rosidl_typesupport_tests/srv/basic_types.h" + +TEST(test_service_typesupport, event_message_create_and_destroy_invalid_arguments) +{ + rcutils_allocator_t allocator = rcutils_get_default_allocator(); + const rosidl_service_type_support_t * srv_ts = + rosidl_typesupport_c__get_service_type_support_handle__rosidl_typesupport_tests__srv__BasicTypes(); // NOLINT + + rosidl_service_introspection_info_t valid_info; + + // null info + EXPECT_EQ( + nullptr, + srv_ts->event_message_create_handle_function(nullptr, &allocator, nullptr, nullptr)); + // null allocator + EXPECT_EQ( + nullptr, + srv_ts->event_message_create_handle_function(&valid_info, nullptr, nullptr, nullptr)); +} + +TEST(test_service_typesupport, basic_types_event_message_create) +{ + rcutils_allocator_t allocator = rcutils_get_default_allocator(); + const rosidl_service_type_support_t * srv_ts = + rosidl_typesupport_c__get_service_type_support_handle__rosidl_typesupport_tests__srv__BasicTypes(); // NOLINT + + const rosidl_message_type_support_t * msg_ts = + rosidl_typesupport_c__get_message_type_support_handle__rosidl_typesupport_tests__srv__BasicTypes_Event(); // NOLINT + + EXPECT_STREQ(srv_ts->typesupport_identifier, "rosidl_typesupport_c"); + EXPECT_STREQ(msg_ts->typesupport_identifier, "rosidl_typesupport_c"); + + EXPECT_EQ(srv_ts->event_typesupport, msg_ts); + + rosidl_service_introspection_info_t expected_info; + expected_info.sequence_number = 2; + expected_info.event_type = 2; + expected_info.stamp_nanosec = 123; + expected_info.stamp_sec = 123; + auto gid = std::array{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + std::copy(gid.begin(), gid.end(), expected_info.client_gid); + + rosidl_typesupport_tests__srv__BasicTypes_Request expected_request; + rosidl_typesupport_tests__srv__BasicTypes_Request__init(&expected_request); + expected_request.int16_value = -1; + expected_request.uint16_value = 123; + rosidl_typesupport_tests__srv__BasicTypes_Response expected_response; + rosidl_typesupport_tests__srv__BasicTypes_Response__init(&expected_response); + expected_response.bool_value = true; + rosidl_runtime_c__String__assign(&expected_response.string_value, "hello world"); + + // null request and response arguments + { + auto * event = static_cast( + srv_ts->event_message_create_handle_function(&expected_info, &allocator, nullptr, nullptr)); // NOLINT + ASSERT_NE(event, nullptr); + EXPECT_EQ(event->info.sequence_number, expected_info.sequence_number); + EXPECT_EQ(event->info.event_type, expected_info.event_type); + EXPECT_EQ(event->info.stamp.nanosec, expected_info.stamp_nanosec); + EXPECT_EQ(event->info.stamp.sec, expected_info.stamp_sec); + for (int i = 0; i < 16; ++i) { + EXPECT_EQ(event->info.client_gid[i], expected_info.client_gid[i]); + } + EXPECT_EQ(event->request.size, 0U); + EXPECT_EQ(event->response.size, 0U); + + ASSERT_TRUE(srv_ts->event_message_destroy_handle_function(event, &allocator)); + } + + // request argument set, null response argument + { + auto * event = static_cast( + srv_ts->event_message_create_handle_function( + &expected_info, + &allocator, + static_cast(&expected_request), + nullptr)); + ASSERT_NE(event, nullptr); + EXPECT_EQ(event->info.sequence_number, expected_info.sequence_number); + EXPECT_EQ(event->info.event_type, expected_info.event_type); + EXPECT_EQ(event->info.stamp.nanosec, expected_info.stamp_nanosec); + EXPECT_EQ(event->info.stamp.sec, expected_info.stamp_sec); + for (int i = 0; i < 16; ++i) { + EXPECT_EQ(event->info.client_gid[i], expected_info.client_gid[i]); + } + ASSERT_EQ(event->request.size, 1U); + EXPECT_EQ(event->response.size, 0U); + EXPECT_EQ(event->request.data[0].int16_value, expected_request.int16_value); + EXPECT_EQ(event->request.data[0].uint16_value, expected_request.uint16_value); + ASSERT_TRUE(srv_ts->event_message_destroy_handle_function(event, &allocator)); + } + + // response argument set, null request argument + { + auto * event = static_cast( + srv_ts->event_message_create_handle_function( + &expected_info, + &allocator, + nullptr, + static_cast(&expected_response))); + + ASSERT_NE(event, nullptr); + EXPECT_EQ(event->info.sequence_number, expected_info.sequence_number); + EXPECT_EQ(event->info.event_type, expected_info.event_type); + EXPECT_EQ(event->info.stamp.nanosec, expected_info.stamp_nanosec); + EXPECT_EQ(event->info.stamp.sec, expected_info.stamp_sec); + for (int i = 0; i < 16; ++i) { + EXPECT_EQ(event->info.client_gid[i], expected_info.client_gid[i]); + } + EXPECT_EQ(event->request.size, 0U); + ASSERT_EQ(event->response.size, 1U); + EXPECT_EQ(event->response.data[0].bool_value, expected_response.bool_value); + EXPECT_TRUE( + rosidl_runtime_c__String__are_equal( + &event->response.data[0].string_value, &expected_response.string_value)); + ASSERT_TRUE(srv_ts->event_message_destroy_handle_function(event, &allocator)); + } + + // both request and response arguments set + { + auto * event = static_cast( + srv_ts->event_message_create_handle_function( + &expected_info, + &allocator, + static_cast(&expected_request), + static_cast(&expected_response))); + + ASSERT_NE(event, nullptr); + EXPECT_EQ(event->info.sequence_number, expected_info.sequence_number); + EXPECT_EQ(event->info.event_type, expected_info.event_type); + EXPECT_EQ(event->info.stamp.nanosec, expected_info.stamp_nanosec); + EXPECT_EQ(event->info.stamp.sec, expected_info.stamp_sec); + for (int i = 0; i < 16; ++i) { + EXPECT_EQ(event->info.client_gid[i], expected_info.client_gid[i]); + } + ASSERT_EQ(event->request.size, 1U); + EXPECT_EQ(event->request.data[0].int16_value, expected_request.int16_value); + EXPECT_EQ(event->request.data[0].uint16_value, expected_request.uint16_value); + ASSERT_EQ(event->response.size, 1U); + EXPECT_EQ(event->response.data[0].bool_value, expected_response.bool_value); + EXPECT_TRUE( + rosidl_runtime_c__String__are_equal( + &event->response.data[0].string_value, &expected_response.string_value)); + ASSERT_TRUE(srv_ts->event_message_destroy_handle_function(event, &allocator)); + } +} + +TEST(test_service_typesupport, fibonacci_action_services_event) +{ + const rosidl_message_type_support_t * send_goal_event_msg_ts = + rosidl_typesupport_c__get_message_type_support_handle__rosidl_typesupport_tests__action__Fibonacci_SendGoal_Event(); // NOLINT + const rosidl_message_type_support_t * get_result_event_msg_ts = + rosidl_typesupport_c__get_message_type_support_handle__rosidl_typesupport_tests__action__Fibonacci_GetResult_Event(); // NOLINT + ASSERT_NE(nullptr, send_goal_event_msg_ts); + ASSERT_NE(nullptr, get_result_event_msg_ts); + EXPECT_STREQ(send_goal_event_msg_ts->typesupport_identifier, "rosidl_typesupport_c"); + EXPECT_STREQ(get_result_event_msg_ts->typesupport_identifier, "rosidl_typesupport_c"); +} diff --git a/rosidl_typesupport_tests/test/rosidl_typesupport_cpp/test_service_typesupport.cpp b/rosidl_typesupport_tests/test/rosidl_typesupport_cpp/test_service_typesupport.cpp new file mode 100644 index 00000000..d711422e --- /dev/null +++ b/rosidl_typesupport_tests/test/rosidl_typesupport_cpp/test_service_typesupport.cpp @@ -0,0 +1,186 @@ +// Copyright 2022 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 "gtest/gtest.h" + +#include "rcutils/allocator.h" + +#include "rosidl_typesupport_cpp/message_type_support.hpp" +#include "rosidl_typesupport_cpp/service_type_support.hpp" + +#include "rosidl_typesupport_tests/action/fibonacci.hpp" +#include "rosidl_typesupport_tests/srv/basic_types.hpp" + +TEST(test_service_typesupport, event_message_create_and_destroy_invalid_arguments) +{ + rcutils_allocator_t allocator = rcutils_get_default_allocator(); + const rosidl_service_type_support_t * srv_ts = + rosidl_typesupport_cpp::get_service_type_support_handle(); // NOLINT + + rosidl_service_introspection_info_t valid_info; + + // null info + { + EXPECT_THROW( + srv_ts->event_message_create_handle_function(nullptr, &allocator, nullptr, nullptr), + std::invalid_argument); + } + // null allocator + { + EXPECT_THROW( + srv_ts->event_message_create_handle_function(&valid_info, nullptr, nullptr, nullptr), + std::invalid_argument); + } +} + +TEST(test_service_typesupport, basic_types_event_message_create) +{ + rcutils_allocator_t allocator = rcutils_get_default_allocator(); + const rosidl_service_type_support_t * srv_ts = + rosidl_typesupport_cpp::get_service_type_support_handle(); // NOLINT + + const rosidl_message_type_support_t * msg_ts = + rosidl_typesupport_cpp::get_message_type_support_handle(); // NOLINT + + EXPECT_STREQ(srv_ts->typesupport_identifier, "rosidl_typesupport_cpp"); + EXPECT_STREQ(msg_ts->typesupport_identifier, "rosidl_typesupport_cpp"); + + // typesupports are static so this comparison *should* be valid? + EXPECT_EQ(srv_ts->event_typesupport, msg_ts); + + rosidl_service_introspection_info_t expected_info; + expected_info.sequence_number = 2; + expected_info.event_type = 2; + expected_info.stamp_nanosec = 123; + expected_info.stamp_sec = 123; + auto gid = std::array{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + std::copy(gid.begin(), gid.end(), expected_info.client_gid); + + auto expected_request = rosidl_typesupport_tests::srv::BasicTypes_Request(); + expected_request.int16_value = -1; + expected_request.uint16_value = 123; + auto expected_response = rosidl_typesupport_tests::srv::BasicTypes_Response(); + expected_response.bool_value = true; + expected_response.string_value = "hello world"; + + // null request and response arguments + { + auto * event = static_cast( + srv_ts->event_message_create_handle_function(&expected_info, &allocator, nullptr, nullptr)); + ASSERT_NE(event, nullptr); + EXPECT_EQ(event->info.sequence_number, expected_info.sequence_number); + EXPECT_EQ(event->info.event_type, expected_info.event_type); + EXPECT_EQ(event->info.stamp.nanosec, expected_info.stamp_nanosec); + EXPECT_EQ(event->info.stamp.sec, expected_info.stamp_sec); + for (int i = 0; i < 16; ++i) { + EXPECT_EQ(event->info.client_gid[i], expected_info.client_gid[i]); + } + EXPECT_EQ(event->request.size(), 0U); + EXPECT_EQ(event->response.size(), 0U); + + ASSERT_TRUE(srv_ts->event_message_destroy_handle_function(event, &allocator)); + } + + // request argument set, null response argument + { + auto * event = static_cast( + srv_ts->event_message_create_handle_function( + &expected_info, + &allocator, + static_cast(&expected_request), + nullptr)); + + ASSERT_NE(event, nullptr); + EXPECT_EQ(event->info.sequence_number, expected_info.sequence_number); + EXPECT_EQ(event->info.event_type, expected_info.event_type); + EXPECT_EQ(event->info.stamp.nanosec, expected_info.stamp_nanosec); + EXPECT_EQ(event->info.stamp.sec, expected_info.stamp_sec); + for (int i = 0; i < 16; ++i) { + EXPECT_EQ(event->info.client_gid[i], expected_info.client_gid[i]); + } + ASSERT_EQ(event->request.size(), 1U); + EXPECT_EQ(event->response.size(), 0U); + EXPECT_EQ(event->request[0].int16_value, expected_request.int16_value); + EXPECT_EQ(event->request[0].uint16_value, expected_request.uint16_value); + ASSERT_TRUE(srv_ts->event_message_destroy_handle_function(event, &allocator)); + } + + // response argument set, null request argument + { + auto * event = static_cast( + srv_ts->event_message_create_handle_function( + &expected_info, + &allocator, + nullptr, + static_cast(&expected_response))); + + ASSERT_NE(event, nullptr); + EXPECT_EQ(event->info.sequence_number, expected_info.sequence_number); + EXPECT_EQ(event->info.event_type, expected_info.event_type); + EXPECT_EQ(event->info.stamp.nanosec, expected_info.stamp_nanosec); + EXPECT_EQ(event->info.stamp.sec, expected_info.stamp_sec); + for (int i = 0; i < 16; ++i) { + EXPECT_EQ(event->info.client_gid[i], expected_info.client_gid[i]); + } + EXPECT_EQ(event->request.size(), 0U); + ASSERT_EQ(event->response.size(), 1U); + EXPECT_EQ(event->response[0].bool_value, expected_response.bool_value); + EXPECT_EQ(event->response[0].string_value, expected_response.string_value); + ASSERT_TRUE(srv_ts->event_message_destroy_handle_function(event, &allocator)); + } + + // both request and response arguments set + { + auto * event = static_cast( + srv_ts->event_message_create_handle_function( + &expected_info, + &allocator, + static_cast(&expected_request), + static_cast(&expected_response))); + + ASSERT_NE(event, nullptr); + EXPECT_EQ(event->info.sequence_number, expected_info.sequence_number); + EXPECT_EQ(event->info.event_type, expected_info.event_type); + EXPECT_EQ(event->info.stamp.nanosec, expected_info.stamp_nanosec); + EXPECT_EQ(event->info.stamp.sec, expected_info.stamp_sec); + for (int i = 0; i < 16; ++i) { + EXPECT_EQ(event->info.client_gid[i], expected_info.client_gid[i]); + } + ASSERT_EQ(event->request.size(), 1U); + EXPECT_EQ(event->request[0].int16_value, expected_request.int16_value); + EXPECT_EQ(event->request[0].uint16_value, expected_request.uint16_value); + ASSERT_EQ(event->response.size(), 1U); + EXPECT_EQ(event->response[0].bool_value, expected_response.bool_value); + EXPECT_EQ(event->response[0].string_value, expected_response.string_value); + ASSERT_TRUE(srv_ts->event_message_destroy_handle_function(event, &allocator)); + } +} + +TEST(test_service_typesupport, fibonacci_action_services_event) +{ + const rosidl_message_type_support_t * send_goal_event_msg_ts = + rosidl_typesupport_cpp::get_message_type_support_handle< + rosidl_typesupport_tests::action::Fibonacci_SendGoal::Event>(); + const rosidl_message_type_support_t * get_result_event_msg_ts = + rosidl_typesupport_cpp::get_message_type_support_handle< + rosidl_typesupport_tests::action::Fibonacci_GetResult::Event>(); + ASSERT_NE(nullptr, send_goal_event_msg_ts); + ASSERT_NE(nullptr, get_result_event_msg_ts); + EXPECT_STREQ(send_goal_event_msg_ts->typesupport_identifier, "rosidl_typesupport_cpp"); + EXPECT_STREQ(get_result_event_msg_ts->typesupport_identifier, "rosidl_typesupport_cpp"); +}