Skip to content

Commit

Permalink
iox-eclipse-iceoryx#1142 Add find service function that stores result
Browse files Browse the repository at this point in the history
Signed-off-by: Marika Lehmann <[email protected]>
  • Loading branch information
FerdinandSpitzschnueffler committed Feb 22, 2022
1 parent ff7115a commit 9965d86
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 30 deletions.
42 changes: 30 additions & 12 deletions iceoryx_binding_c/include/iceoryx_binding_c/service_discovery.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
64 changes: 58 additions & 6 deletions iceoryx_binding_c/source/c_service_discovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<capro::IdString_t> maybeService;
if (service != nullptr)
{
maybeService.emplace(cxx::TruncateToCapacity, service);
}
cxx::optional<capro::IdString_t> maybeInstance;
if (instance != nullptr)
{
maybeInstance.emplace(cxx::TruncateToCapacity, instance);
}
cxx::optional<capro::IdString_t> 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);
Expand All @@ -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);
}
81 changes: 69 additions & 12 deletions iceoryx_binding_c/test/moduletests/test_service_discovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ extern "C" {
namespace
{
using namespace ::testing;
using description_vector = cxx::vector<iox_service_description_t, MAX_NUMBER_OF_SERVICES>;

class iox_service_discovery_test : public RouDi_GTest
{
Expand All @@ -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<iox_service_description_t, 100> 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<description_vector*>(contextData)->emplace_back(s);
}
};

cxx::vector<iox_service_description_t, MAX_NUMBER_OF_SERVICES> iox_service_discovery_test::searchResult;
description_vector iox_service_discovery_test::searchResult;

TEST(iox_service_discovery_DeathTest, InitServiceDiscoveryWithNullptrForStorageTerminates)
{
Expand All @@ -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;
Expand All @@ -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

0 comments on commit 9965d86

Please sign in to comment.