Compare commits

...

1 Commits

Author SHA1 Message Date
Chris Lalancette
ec5325cf5c More fixes for clang static analysis.
This is a smattering of changes to make clang static analysis
happier:

1.  It turns out that std::allocator::allocate does not return
nullptr on error (it throws an exception).  So there is no
reason to check for nullptr on the return, and a failing deleter
could indeed leak memory.  Instead catch any exceptions that
the deleter throws and manually deallocate and FAIL the test.
2.  It turns out that `get_parameter` can fail, so make sure
to initialize things we are checking against so that they will
fail if `get_parameter` fails for some reason.
3.  Many lambdas in test_function_traits.cpp are statically
asserted, but are never actually used at runtime.  Just
quiet down clang by using (void)name; on each of them.
4.  The C++ documentation that moved-from objects are in a
"valid but unspecified state".  To be truly cross-platform
(and please clang), don't do checks on the moved-from object.

Signed-off-by: Chris Lalancette <clalancette@openrobotics.org>
2021-10-27 14:22:47 -04:00
6 changed files with 30 additions and 21 deletions

View File

@@ -23,32 +23,33 @@ TEST(TestAllocatorCommon, retyped_allocate) {
void * untyped_allocator = &allocator;
void * allocated_mem =
rclcpp::allocator::retyped_allocate<std::allocator<char>>(1u, untyped_allocator);
// The more natural check here is ASSERT_NE(nullptr, ptr), but clang static
// analysis throws a false-positive memory leak warning. Use ASSERT_TRUE instead.
ASSERT_TRUE(nullptr != allocated_mem);
auto code = [&untyped_allocator, allocated_mem]() {
rclcpp::allocator::retyped_deallocate<int, std::allocator<int>>(
allocated_mem, untyped_allocator);
};
EXPECT_NO_THROW(code());
try {
code();
} catch (const std::exception &) {
allocator.deallocate(static_cast<int *>(allocated_mem), 1u);
FAIL() << "Failed to delete memory with retyped_deallocate";
}
allocated_mem = allocator.allocate(1);
// The more natural check here is ASSERT_NE(nullptr, ptr), but clang static
// analysis throws a false-positive memory leak warning. Use ASSERT_TRUE instead.
ASSERT_TRUE(nullptr != allocated_mem);
void * reallocated_mem =
rclcpp::allocator::retyped_reallocate<int, std::allocator<int>>(
allocated_mem, 2u, untyped_allocator);
// The more natural check here is ASSERT_NE(nullptr, ptr), but clang static
// analysis throws a false-positive memory leak warning. Use ASSERT_TRUE instead.
ASSERT_TRUE(nullptr != reallocated_mem);
auto code2 = [&untyped_allocator, reallocated_mem]() {
rclcpp::allocator::retyped_deallocate<int, std::allocator<int>>(
reallocated_mem, untyped_allocator);
};
EXPECT_NO_THROW(code2());
try {
code2();
} catch (const std::exception &) {
allocator.deallocate(static_cast<int *>(reallocated_mem), 1);
FAIL() << "Failed to delete reallocated memory with retyped_deallocate";
}
}
TEST(TestAllocatorCommon, get_rcl_allocator) {

View File

@@ -38,12 +38,13 @@ TEST(TestAllocatorDeleter, construct_destruct) {
TEST(TestAllocatorDeleter, delete) {
std::allocator<int> allocator;
int * some_mem = allocator.allocate(1u);
// The more natural check here is ASSERT_NE(nullptr, ptr), but clang static
// analysis throws a false-positive memory leak warning. Use ASSERT_TRUE instead.
ASSERT_TRUE(nullptr != some_mem);
rclcpp::allocator::AllocatorDeleter<std::allocator<int>> deleter(&allocator);
EXPECT_NO_THROW(deleter(some_mem));
try {
deleter(some_mem);
} catch (const std::exception &) {
allocator.deallocate(some_mem, 1u);
FAIL() << "Failed to delete memory with rclcpp::allocator::AllocatorDeleter";
}
}
TEST(TestAllocatorDeleter, set_allocator_for_deleter_AllocatorDeleter) {

View File

@@ -394,6 +394,7 @@ TEST(TestFunctionTraits, argument_types) {
auto bind_one_bool = std::bind(
&ObjectMember::callback_one_bool, &object_member, std::placeholders::_1);
(void)bind_one_bool;
static_assert(
std::is_same<
bool,
@@ -403,6 +404,7 @@ TEST(TestFunctionTraits, argument_types) {
auto bind_one_bool_const = std::bind(
&ObjectMember::callback_one_bool_const, &object_member, std::placeholders::_1);
(void)bind_one_bool_const;
static_assert(
std::is_same<
bool,
@@ -414,6 +416,7 @@ TEST(TestFunctionTraits, argument_types) {
&ObjectMember::callback_two_bools, &object_member, std::placeholders::_1,
std::placeholders::_2);
(void)bind_two_bools;
static_assert(
std::is_same<
bool,
@@ -430,6 +433,7 @@ TEST(TestFunctionTraits, argument_types) {
&ObjectMember::callback_one_bool_one_float, &object_member, std::placeholders::_1,
std::placeholders::_2);
(void)bind_one_bool_one_float;
static_assert(
std::is_same<
bool,
@@ -448,6 +452,7 @@ TEST(TestFunctionTraits, argument_types) {
auto bind_one_int = std::bind(func_one_int, std::placeholders::_1);
(void)bind_one_int;
static_assert(
std::is_same<
int,
@@ -456,6 +461,7 @@ TEST(TestFunctionTraits, argument_types) {
auto bind_two_ints = std::bind(func_two_ints, std::placeholders::_1, std::placeholders::_2);
(void)bind_two_ints;
static_assert(
std::is_same<
int,
@@ -471,6 +477,7 @@ TEST(TestFunctionTraits, argument_types) {
auto bind_one_int_one_char = std::bind(
func_one_int_one_char, std::placeholders::_1, std::placeholders::_2);
(void)bind_one_int_one_char;
static_assert(
std::is_same<
int,
@@ -573,6 +580,7 @@ TEST(TestFunctionTraits, check_arguments) {
auto bind_one_bool = std::bind(
&ObjectMember::callback_one_bool, &object_member, std::placeholders::_1);
(void)bind_one_bool;
// Test std::bind functions
static_assert(
rclcpp::function_traits::check_arguments<decltype(bind_one_bool), bool>::value,
@@ -581,6 +589,7 @@ TEST(TestFunctionTraits, check_arguments) {
auto bind_one_bool_const = std::bind(
&ObjectMember::callback_one_bool_const, &object_member, std::placeholders::_1);
(void)bind_one_bool_const;
// Test std::bind functions
static_assert(
rclcpp::function_traits::check_arguments<decltype(bind_one_bool_const), bool>::value,
@@ -746,6 +755,7 @@ TEST_F(TestMember, bind_member_functor) {
&TestMember::MemberFunctor, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3);
(void)bind_member_functor;
static_assert(
rclcpp::function_traits::check_arguments<decltype(bind_member_functor), int, float,
std::string>::value,

View File

@@ -186,7 +186,6 @@ TEST_F(TestLoanedMessage, move_loaned_message) {
auto loaned_msg_moved_to = LoanedMessageT(std::move(loaned_msg_to_move));
ASSERT_TRUE(loaned_msg_moved_to.is_valid());
ASSERT_FALSE(loaned_msg_to_move.is_valid());
loaned_msg_moved_to.get().float32_value = 42.0f;
ASSERT_EQ(42.0f, loaned_msg_moved_to.get().float32_value);

View File

@@ -1896,7 +1896,7 @@ TEST_F(TestNode, get_parameter_undeclared_parameters_not_allowed) {
}
// version that returns bool and never throws, but is templated to store in a primitive type
{
int value;
int value = 0;
EXPECT_TRUE(node->get_parameter(name, value));
EXPECT_EQ(value, 42);
}
@@ -1953,7 +1953,7 @@ TEST_F(TestNode, get_parameter_undeclared_parameters_allowed) {
}
// version that returns bool and never throws, but is templated to store in a primitive type
{
int value;
int value = 0;
EXPECT_TRUE(node->get_parameter(name, value));
EXPECT_EQ(value, 42);
}

View File

@@ -67,8 +67,6 @@ TEST(TestSerializedMessage, various_constructors) {
rclcpp::SerializedMessage yet_another_serialized_message(std::move(other_serialized_message));
auto & yet_another_rcl_handle = yet_another_serialized_message.get_rcl_serialized_message();
EXPECT_TRUE(nullptr == other_rcl_handle.buffer);
EXPECT_EQ(0u, other_serialized_message.capacity());
EXPECT_EQ(0u, other_serialized_message.size());
EXPECT_TRUE(nullptr != yet_another_rcl_handle.buffer);
EXPECT_EQ(content_size, yet_another_serialized_message.size());
EXPECT_EQ(content_size, yet_another_serialized_message.capacity());