From 9965d860968644326fd7db155ab9d8c93fb8502e Mon Sep 17 00:00:00 2001 From: Marika Lehmann Date: Tue, 22 Feb 2022 18:36:19 +0100 Subject: [PATCH] iox-#1142 Add find service function that stores result Signed-off-by: Marika Lehmann --- .../iceoryx_binding_c/service_discovery.h | 42 +++++++--- .../source/c_service_discovery.cpp | 64 +++++++++++++-- .../moduletests/test_service_discovery.cpp | 81 ++++++++++++++++--- 3 files changed, 157 insertions(+), 30 deletions(-) diff --git a/iceoryx_binding_c/include/iceoryx_binding_c/service_discovery.h b/iceoryx_binding_c/include/iceoryx_binding_c/service_discovery.h index c585db0b870..f4fd8bca0a9 100644 --- a/iceoryx_binding_c/include/iceoryx_binding_c/service_discovery.h +++ b/iceoryx_binding_c/include/iceoryx_binding_c/service_discovery.h @@ -21,29 +21,47 @@ #include "iceoryx_binding_c/types.h" #include "service_description.h" -/////// @brief service discovery handle -////// typedef struct cpp2c_ServiceDiscovery* iox_service_discovery_t; +/// @brief service discovery handle typedef CLASS ServiceDiscovery* iox_service_discovery_t; -///// @brief initializes a listener struct from a storage struct pointer -///// @param[in] self pointer to raw memory which can hold a listener -///// @return an initialized iox_listener_t +/// @brief initializes a service discovery from a storage struct pointer +/// @param[in] self pointer to raw memory which can hold a service discovery +/// @return an initialized iox_service_discovery_t iox_service_discovery_t iox_service_discovery_init(iox_service_discovery_storage_t* self); -///// @brief after using an iox_listener_t it must be cleaned up with this function -///// @param[in] self the listener which should be deinitialized +/// @brief after using an iox_service_discovery_t it must be cleaned up with this function +/// @param[in] self the service discovery which should be deinitialized void iox_service_discovery_deinit(iox_service_discovery_t const self); +/// @brief Searches all services that match the provided service description +/// @param[in] self handle of the service discovery +/// @param[in] service service string to search for, a nullptr corresponds to a wildcard +/// @param[in] instance instance string to search for, a nullptr corresponds to a wildcard +/// @param[in] event event string to search for, a nullptr corresponds to a wildcard +/// @param[in] serviceContainer preallocated memory to an array of ***** in which the matching services can be written +/// @param[in] serviceContainerCapacity the capacity of the preallocated serviceContainer +/// @param[in] missedServices if the serviceContainer has insufficient size the number of missed services which could +/// not be written into the serviceContainer are stored here +/// @return the number of services which were written into the serviceContainer +uint64_t iox_service_discovery_find_service(iox_service_discovery_t const self, + const char* const service, + const char* const instance, + const char* const event, + iox_service_description_t* const serviceContainer, + const uint64_t serviceContainerCapacity, + uint64_t* missedServices); + /// @brief Searches all services that match the provided service description and applies a function to each of them /// @param[in] self handle of the service discovery /// @param[in] service service string to search for, a nullptr corresponds to a wildcard /// @param[in] instance instance string to search for, a nullptr corresponds to a wildcard /// @param[in] event event string to search for, a nullptr corresponds to a wildcard /// @param[in] callable to apply to all matching services -void iox_service_discovery_find_service(iox_service_discovery_t const self, - const char* const service, - const char* const instance, - const char* const event, - void (*callable)(const iox_service_description_t)); +void iox_service_discovery_find_service_with_context_data(iox_service_discovery_t const self, + const char* const service, + const char* const instance, + const char* const event, + void (*callable)(const iox_service_description_t, void*), + void* const contextData); #endif diff --git a/iceoryx_binding_c/source/c_service_discovery.cpp b/iceoryx_binding_c/source/c_service_discovery.cpp index 02a3f6ab3ba..d05ef7fadf3 100644 --- a/iceoryx_binding_c/source/c_service_discovery.cpp +++ b/iceoryx_binding_c/source/c_service_discovery.cpp @@ -41,11 +41,63 @@ void iox_service_discovery_deinit(iox_service_discovery_t const self) self->~ServiceDiscovery(); } -void iox_service_discovery_find_service(iox_service_discovery_t const self, - const char* const service, - const char* const instance, - const char* const event, - void (*callable)(const iox_service_description_t)) +uint64_t iox_service_discovery_find_service(iox_service_discovery_t const self, + const char* const service, + const char* const instance, + const char* const event, + iox_service_description_t* const serviceContainer, + const uint64_t serviceContainerCapacity, + uint64_t* missedServices) +{ + iox::cxx::Expects(self != nullptr); + iox::cxx::Expects(serviceContainer != nullptr); + + cxx::optional maybeService; + if (service != nullptr) + { + maybeService.emplace(cxx::TruncateToCapacity, service); + } + cxx::optional maybeInstance; + if (instance != nullptr) + { + maybeInstance.emplace(cxx::TruncateToCapacity, instance); + } + cxx::optional maybeEvent; + if (event != nullptr) + { + maybeEvent.emplace(cxx::TruncateToCapacity, event); + } + + ServiceContainer temp; + auto filter = [&](const capro::ServiceDescription& s) { temp.emplace_back(s); }; + self->findService(maybeService, maybeInstance, maybeEvent, filter); + + uint64_t serviceContainerSize = 0U; + uint64_t tempSize = temp.size(); + if (tempSize > serviceContainerCapacity) + { + *missedServices = tempSize - serviceContainerCapacity; + serviceContainerSize = serviceContainerCapacity; + } + else + { + *missedServices = 0U; + serviceContainerSize = tempSize; + } + + for (uint64_t i = 0U; i < serviceContainerSize; ++i) + { + serviceContainer[i] = TranslateServiceDescription(temp[i]); + } + return serviceContainerSize; +} + +void iox_service_discovery_find_service_with_context_data(iox_service_discovery_t const self, + const char* const service, + const char* const instance, + const char* const event, + void (*callable)(const iox_service_description_t, void*), + void* const contextData) { iox::cxx::Expects(self != nullptr); iox::cxx::Expects(callable != nullptr); @@ -66,6 +118,6 @@ void iox_service_discovery_find_service(iox_service_discovery_t const self, maybeEvent.emplace(cxx::TruncateToCapacity, event); } - auto filter = [&](const capro::ServiceDescription& s) { callable(TranslateServiceDescription(s)); }; + auto filter = [&](const capro::ServiceDescription& s) { callable(TranslateServiceDescription(s), contextData); }; self->findService(maybeService, maybeInstance, maybeEvent, filter); } diff --git a/iceoryx_binding_c/test/moduletests/test_service_discovery.cpp b/iceoryx_binding_c/test/moduletests/test_service_discovery.cpp index 9abaa8d7e3a..1c65834e2b6 100644 --- a/iceoryx_binding_c/test/moduletests/test_service_discovery.cpp +++ b/iceoryx_binding_c/test/moduletests/test_service_discovery.cpp @@ -29,6 +29,7 @@ extern "C" { namespace { using namespace ::testing; +using description_vector = cxx::vector; class iox_service_discovery_test : public RouDi_GTest { @@ -48,14 +49,14 @@ class iox_service_discovery_test : public RouDi_GTest iox_service_discovery_storage_t sutStorage; iox_service_discovery_t sut; - static cxx::vector searchResult; - static void findHandler(const iox_service_description_t s) + static description_vector searchResult; + static void findHandler(const iox_service_description_t s, void* contextData) { - searchResult.emplace_back(s); + static_cast(contextData)->emplace_back(s); } }; -cxx::vector iox_service_discovery_test::searchResult; +description_vector iox_service_discovery_test::searchResult; TEST(iox_service_discovery_DeathTest, InitServiceDiscoveryWithNullptrForStorageTerminates) { @@ -65,17 +66,17 @@ TEST(iox_service_discovery_DeathTest, InitServiceDiscoveryWithNullptrForStorageT /// @note We test only if the arguments of iox_service_discovery_find_service are correctly passed to /// ServiceDiscovery::findService. -TEST_F(iox_service_discovery_test, FindServiceWithNullptrsForServiceInstanceEventsReturnsAllServices) +TEST_F(iox_service_discovery_test, FindServiceWithContextDataWithNullptrsForServiceInstanceEventReturnsAllServices) { ::testing::Test::RecordProperty("TEST_ID", "09a2cd6c-fba9-4b9d-af96-c5a6cc168d98"); - iox_service_discovery_find_service(sut, nullptr, nullptr, nullptr, findHandler); + iox_service_discovery_find_service_with_context_data(sut, nullptr, nullptr, nullptr, findHandler, &searchResult); for (const auto& service : searchResult) { EXPECT_THAT(service.instanceString, StrEq("RouDi_ID")); } } -TEST_F(iox_service_discovery_test, FindServiceReturnsOfferedService) +TEST_F(iox_service_discovery_test, FindServiceWithContextDataReturnsOfferedService) { ::testing::Test::RecordProperty("TEST_ID", "bb12e514-e7af-4946-b098-98b3cd0f43a5"); iox_pub_options_t options; @@ -85,15 +86,71 @@ TEST_F(iox_service_discovery_test, FindServiceReturnsOfferedService) ASSERT_NE(publisher, nullptr); const iox_service_description_t SERVICE_DESCRIPTION = iox_pub_get_service_description(publisher); - iox_service_discovery_find_service(sut, - SERVICE_DESCRIPTION.serviceString, - SERVICE_DESCRIPTION.instanceString, - SERVICE_DESCRIPTION.eventString, - findHandler); + iox_service_discovery_find_service_with_context_data(sut, + SERVICE_DESCRIPTION.serviceString, + SERVICE_DESCRIPTION.instanceString, + SERVICE_DESCRIPTION.eventString, + findHandler, + &searchResult); ASSERT_THAT(searchResult.size(), Eq(1U)); EXPECT_THAT(*searchResult.begin()->serviceString, Eq(*SERVICE_DESCRIPTION.serviceString)); EXPECT_THAT(*searchResult.begin()->instanceString, Eq(*SERVICE_DESCRIPTION.instanceString)); EXPECT_THAT(*searchResult.begin()->eventString, Eq(*SERVICE_DESCRIPTION.eventString)); } +TEST_F(iox_service_discovery_test, FindServiceWithNullptrsForServiceInstanceEventReturnsAllServices) +{ + const uint64_t SERVICE_CONTAINER_CAPACITY = 10; + iox_service_description_t serviceContainer[SERVICE_CONTAINER_CAPACITY]; + uint64_t missedServices = 0U; + const auto numberFoundServices = iox_service_discovery_find_service( + sut, nullptr, nullptr, nullptr, serviceContainer, SERVICE_CONTAINER_CAPACITY, &missedServices); + + EXPECT_THAT(numberFoundServices, Eq(6U)); + EXPECT_THAT(missedServices, Eq(0U)); + for (uint64_t i = 0U; i < numberFoundServices; ++i) + { + EXPECT_THAT(serviceContainer[i].instanceString, StrEq("RouDi_ID")); + } +} + +TEST_F(iox_service_discovery_test, FindServiceReturnsOfferedService) +{ + iox_pub_options_t options; + iox_pub_options_init(&options); + iox_pub_storage_t storage; + auto* publisher = iox_pub_init(&storage, "service", "instance", "event", &options); + ASSERT_NE(publisher, nullptr); + const iox_service_description_t SERVICE_DESCRIPTION = iox_pub_get_service_description(publisher); + + const uint64_t SERVICE_CONTAINER_CAPACITY = 10; + iox_service_description_t serviceContainer[SERVICE_CONTAINER_CAPACITY]; + uint64_t missedServices = 0U; + const auto numberFoundServices = iox_service_discovery_find_service(sut, + SERVICE_DESCRIPTION.serviceString, + SERVICE_DESCRIPTION.instanceString, + SERVICE_DESCRIPTION.eventString, + serviceContainer, + SERVICE_CONTAINER_CAPACITY, + &missedServices); + + EXPECT_THAT(numberFoundServices, Eq(1U)); + EXPECT_THAT(missedServices, Eq(0U)); + EXPECT_THAT(serviceContainer[0U].serviceString, StrEq(SERVICE_DESCRIPTION.serviceString)); + EXPECT_THAT(serviceContainer[0U].instanceString, StrEq(SERVICE_DESCRIPTION.instanceString)); + EXPECT_THAT(serviceContainer[0U].eventString, StrEq(SERVICE_DESCRIPTION.eventString)); +} + +TEST_F(iox_service_discovery_test, FindServiceReturnsCorrectNumberOfServicesWhenServiceContainerTooSmall) +{ + const uint64_t SERVICE_CONTAINER_CAPACITY = 3; + iox_service_description_t serviceContainer[SERVICE_CONTAINER_CAPACITY]; + uint64_t missedServices = 0U; + const auto numberFoundServices = iox_service_discovery_find_service( + sut, nullptr, nullptr, nullptr, serviceContainer, SERVICE_CONTAINER_CAPACITY, &missedServices); + + EXPECT_THAT(numberFoundServices, Eq(SERVICE_CONTAINER_CAPACITY)); + EXPECT_THAT(missedServices, Eq(6U - SERVICE_CONTAINER_CAPACITY)); +} + } // namespace