Skip to content

Commit

Permalink
Add rmw_discovery_options_init and tests
Browse files Browse the repository at this point in the history
Signed-off-by: Shane Loretz <sloretz@google.com>
  • Loading branch information
sloretz committed Mar 27, 2023
1 parent 5fc6ce9 commit 2cf62e3
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 19 deletions.
34 changes: 31 additions & 3 deletions rmw/include/rmw/discovery_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ typedef struct RMW_PUBLIC_TYPE rmw_discovery_options_s

/// The number of manually-specified peers
size_t static_peers_count;

/// The allocator used to allocate static_peers
rcutils_allocator_t allocator;
} rmw_discovery_options_t;

/// Return a zero-initialized discovery options structure.
Expand All @@ -71,6 +74,32 @@ RMW_WARN_UNUSED
rmw_discovery_options_t
rmw_get_zero_initialized_discovery_options(void);

/// Initialize a discovery options structure with a set number of static peers.
/**
* This function initializes rmw_discovery_options_t with space for a set number of static peers.
*
* \param[in] discovery_options Pointer to a zero initialized option structure to be initialized on
* success, but left unchanged on failure.
* \param[in] size Number of static peers to allocate space for.
* \param[in] allocator Allocator to be used to allocate memory.
* \returns `RMW_RET_OK` if successful, or
* \returns `RMW_RET_INVALID_ARGUMENT` if `discovery_options` is NULL, or
* \returns `RMW_RET_INVALID_ARGUMENT` if `discovery_options` is not
* zero initialized, or
* \returns `RMW_RET_INVALID_ARGUMENT` if `allocator` is invalid,
* by rcutils_allocator_is_valid() definition, or
* \returns `RMW_BAD_ALLOC` if memory allocation fails, or
* \returns `RMW_RET_ERROR` when an unspecified error occurs.
* \remark This function sets the RMW error state on failure.
*/
RMW_PUBLIC
RMW_WARN_UNUSED
rmw_ret_t
rmw_discovery_options_init(
rmw_discovery_options_t * discovery_options,
size_t size,
rcutils_allocator_t * allocator);

/// Compare two discovery parameter instances for equality.
/**
* Equality means the automatic_discovery_range values are equal, they have the same
Expand Down Expand Up @@ -117,7 +146,7 @@ RMW_WARN_UNUSED
rmw_ret_t
rmw_discovery_options_copy(
const rmw_discovery_options_t * src,
rcutils_allocator_t allocator,
rcutils_allocator_t * allocator,
rmw_discovery_options_t * dst);

/// Destructor for rmw_discovery_options_t
Expand All @@ -132,8 +161,7 @@ RMW_PUBLIC
RMW_WARN_UNUSED
rmw_ret_t
rmw_discovery_options_fini(
rmw_discovery_options_t * discovery_options,
rcutils_allocator_t allocator);
rmw_discovery_options_t * discovery_options);
#ifdef __cplusplus
}
#endif
Expand Down
73 changes: 57 additions & 16 deletions rmw/src/discovery_options.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,47 @@ rmw_get_zero_initialized_discovery_options(void)
return result;
}

RMW_PUBLIC
RMW_WARN_UNUSED
rmw_ret_t
rmw_discovery_options_init(
rmw_discovery_options_t * discovery_options,
size_t size,
rcutils_allocator_t * allocator)
{
RCUTILS_CAN_RETURN_WITH_ERROR_OF(RMW_RET_INVALID_ARGUMENT);
RCUTILS_CAN_RETURN_WITH_ERROR_OF(RMW_RET_BAD_ALLOC);

RMW_CHECK_ARGUMENT_FOR_NULL(discovery_options, RMW_RET_INVALID_ARGUMENT);
RCUTILS_CHECK_ALLOCATOR(allocator, return RMW_RET_INVALID_ARGUMENT);

if (0 != discovery_options->static_peers_count || NULL != discovery_options->static_peers) {
RMW_SET_ERROR_MSG("discovery_options must be zero intialized");
return RMW_RET_INVALID_ARGUMENT;
}

if (0u == size) {
// Nothing to do
return RMW_RET_OK;
}

discovery_options->static_peers =
allocator->zero_allocate(
size,
sizeof(rmw_peer_address_t),
allocator->state);

if (NULL == discovery_options->static_peers) {
RMW_SET_ERROR_MSG("failed to allocate memory for static_peers");
return RMW_RET_BAD_ALLOC;
}

discovery_options->static_peers_count = size;
discovery_options->allocator = *allocator;

return RMW_RET_OK;
}

rmw_ret_t
rmw_discovery_options_equal(
const rmw_discovery_options_t * const left,
Expand Down Expand Up @@ -76,24 +117,24 @@ rmw_discovery_options_equal(
rmw_ret_t
rmw_discovery_options_copy(
const rmw_discovery_options_t * src,
rcutils_allocator_t allocator,
rcutils_allocator_t * allocator,
rmw_discovery_options_t * dst)
{
RMW_CHECK_ARGUMENT_FOR_NULL(src, RMW_RET_INVALID_ARGUMENT);
RCUTILS_CHECK_ALLOCATOR(&allocator, return RMW_RET_INVALID_ARGUMENT);
RCUTILS_CHECK_ALLOCATOR(allocator, return RMW_RET_INVALID_ARGUMENT);
RMW_CHECK_ARGUMENT_FOR_NULL(dst, RMW_RET_INVALID_ARGUMENT);
if (src == dst) {
RMW_SET_ERROR_MSG("src and dst must be different");
return RMW_RET_INVALID_ARGUMENT;
}

dst->automatic_discovery_range = src->automatic_discovery_range;
dst->static_peers =
allocator.zero_allocate(
src->static_peers_count,
sizeof(rmw_peer_address_t),
allocator.state);

if (!dst->static_peers) {
return RMW_RET_BAD_ALLOC;
rmw_ret_t ret = rmw_discovery_options_init(dst, src->static_peers_count, allocator);
if (RMW_RET_OK != ret) {
return ret;
}

dst->automatic_discovery_range = src->automatic_discovery_range;

for (size_t i = 0; i < src->static_peers_count; i++) {
strncpy(
dst->static_peers[i].peer_address,
Expand All @@ -102,21 +143,21 @@ rmw_discovery_options_copy(
dst->static_peers[i].peer_address[
RMW_DISCOVERY_OPTIONS_STATIC_PEERS_MAX_LENGTH - 1] = '\0';
}
dst->static_peers_count = src->static_peers_count;

return RMW_RET_OK;
}

rmw_ret_t
rmw_discovery_options_fini(
rmw_discovery_options_t * discovery_options,
rcutils_allocator_t allocator)
rmw_discovery_options_t * discovery_options)
{
RMW_CHECK_ARGUMENT_FOR_NULL(discovery_options, RMW_RET_INVALID_ARGUMENT);
RCUTILS_CHECK_ALLOCATOR(&allocator, return RMW_RET_INVALID_ARGUMENT);

if (discovery_options->static_peers_count > 0) {
allocator.deallocate(discovery_options->static_peers, allocator.state);
RCUTILS_CHECK_ALLOCATOR(&(discovery_options->allocator), return RMW_RET_INVALID_ARGUMENT);
discovery_options->allocator.deallocate(
discovery_options->static_peers,
discovery_options->allocator.state);
}
*discovery_options = rmw_get_zero_initialized_discovery_options();

Expand Down
9 changes: 9 additions & 0 deletions rmw/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ if(TARGET test_convert_rcutils_ret_to_rmw_ret)
target_link_libraries(test_convert_rcutils_ret_to_rmw_ret ${PROJECT_NAME})
endif()

ament_add_gmock(test_discovery_options
test_discovery_options.cpp
# Append the directory of librmw so it is found at test time.
APPEND_LIBRARY_DIRS "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
)
if(TARGET test_discovery_options)
target_link_libraries(test_discovery_options ${PROJECT_NAME})
endif()

ament_add_gmock(test_event
test_event.cpp
# Append the directory of librmw so it is found at test time.
Expand Down
143 changes: 143 additions & 0 deletions rmw/test/test_discovery_options.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Copyright 2023 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 "gmock/gmock.h"

#include "rmw/discovery_options.h"

#include "rcutils/allocator.h"
#include "rmw/error_handling.h"

TEST(discovery_options, zero_init_fini) {
rmw_discovery_options_t dopts = rmw_get_zero_initialized_discovery_options();
auto allocator = rcutils_get_default_allocator();
EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_init(&dopts, 0, &allocator));
EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_fini(&dopts));
}

TEST(discovery_options, init_invalid_args) {
rmw_discovery_options_t dopts = rmw_get_zero_initialized_discovery_options();
rmw_discovery_options_t dopts_valid = rmw_get_zero_initialized_discovery_options();
auto allocator = rcutils_get_default_allocator();

EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, rmw_discovery_options_init(NULL, 0, &allocator));
EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, rmw_discovery_options_init(&dopts, 0, NULL));
EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, rmw_discovery_options_init(NULL, 0, NULL));

EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_init(&dopts_valid, 5, &allocator));
EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, rmw_discovery_options_init(&dopts_valid, 5, &allocator));

EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_fini(&dopts_valid));
}

TEST(discovery_options, zero_are_equal) {
rmw_discovery_options_t dopts1 = rmw_get_zero_initialized_discovery_options();
rmw_discovery_options_t dopts2 = rmw_get_zero_initialized_discovery_options();

bool result = false;
EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_equal(&dopts1, &dopts2, &result));
EXPECT_TRUE(result);
}

TEST(discovery_options, unequal) {
auto allocator = rcutils_get_default_allocator();
{ // Different size static_peers size
rmw_discovery_options_t dopts1 = rmw_get_zero_initialized_discovery_options();
rmw_discovery_options_t dopts2 = rmw_get_zero_initialized_discovery_options();

EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_init(&dopts1, 0, &allocator));
EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_init(&dopts2, 1, &allocator));

bool result = true;
EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_equal(&dopts1, &dopts2, &result));
EXPECT_FALSE(result);

EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_fini(&dopts1));
EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_fini(&dopts2));
}
{ // Different discovery range
rmw_discovery_options_t dopts1 = rmw_get_zero_initialized_discovery_options();
rmw_discovery_options_t dopts2 = rmw_get_zero_initialized_discovery_options();

dopts1.automatic_discovery_range = RMW_AUTOMATIC_DISCOVERY_RANGE_LOCALHOST;
dopts2.automatic_discovery_range = RMW_AUTOMATIC_DISCOVERY_RANGE_OFF;

bool result = true;
EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_equal(&dopts1, &dopts2, &result));
EXPECT_FALSE(result);

EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_fini(&dopts1));
EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_fini(&dopts2));
}
{ // Different static peer
rmw_discovery_options_t dopts1 = rmw_get_zero_initialized_discovery_options();
rmw_discovery_options_t dopts2 = rmw_get_zero_initialized_discovery_options();

EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_init(&dopts1, 1, &allocator));
EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_init(&dopts2, 1, &allocator));

dopts1.static_peers[0].peer_address[0] = 'a';
dopts1.static_peers[0].peer_address[1] = '\0';
dopts2.static_peers[0].peer_address[0] = 'b';
dopts2.static_peers[0].peer_address[1] = '\0';

bool result = true;
EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_equal(&dopts1, &dopts2, &result));
EXPECT_FALSE(result);

EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_fini(&dopts1));
EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_fini(&dopts2));
}
}

TEST(discovery_options, copy_equal) {
auto allocator = rcutils_get_default_allocator();
rmw_discovery_options_t dopts1 = rmw_get_zero_initialized_discovery_options();
rmw_discovery_options_t dopts2 = rmw_get_zero_initialized_discovery_options();

EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_init(&dopts1, 1, &allocator));

dopts1.automatic_discovery_range = RMW_AUTOMATIC_DISCOVERY_RANGE_OFF;
dopts1.static_peers[0].peer_address[0] = 'a';
dopts1.static_peers[0].peer_address[1] = '\0';

EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_copy(&dopts1, &allocator, &dopts2));

EXPECT_EQ(dopts2.automatic_discovery_range, RMW_AUTOMATIC_DISCOVERY_RANGE_OFF);
EXPECT_EQ(dopts2.static_peers_count, 1);
EXPECT_EQ(dopts2.static_peers[0].peer_address[0], 'a');

bool result = false;
EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_equal(&dopts1, &dopts2, &result));
EXPECT_TRUE(result);
}

TEST(discovery_options, copy_invalid_args) {
auto allocator = rcutils_get_default_allocator();
rmw_discovery_options_t dopts1 = rmw_get_zero_initialized_discovery_options();
rmw_discovery_options_t dopts2 = rmw_get_zero_initialized_discovery_options();

EXPECT_EQ(RMW_RET_OK, rmw_discovery_options_init(&dopts1, 1, &allocator));

EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, rmw_discovery_options_copy(NULL, &allocator, &dopts2));
EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, rmw_discovery_options_copy(NULL, NULL, &dopts2));
EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, rmw_discovery_options_copy(NULL, &allocator, NULL));
EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, rmw_discovery_options_copy(NULL, NULL, NULL));
EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, rmw_discovery_options_copy(&dopts1, NULL, &dopts2));
EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, rmw_discovery_options_copy(&dopts1, NULL, NULL));
EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, rmw_discovery_options_copy(&dopts1, &allocator, NULL));
EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, rmw_discovery_options_copy(&dopts1, &allocator, &dopts1));
EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, rmw_discovery_options_copy(&dopts2, &allocator, &dopts1));
EXPECT_EQ(RMW_RET_INVALID_ARGUMENT, rmw_discovery_options_copy(&dopts2, &allocator, &dopts2));
}

0 comments on commit 2cf62e3

Please sign in to comment.