From 9ed96008fbe843675b92955d7461b93e2106ce6d Mon Sep 17 00:00:00 2001 From: Stephen Brawner Date: Mon, 1 Jun 2020 14:14:00 -0700 Subject: [PATCH 1/6] Increase testing coverage of rcutils Signed-off-by: Stephen Brawner --- CMakeLists.txt | 42 ++++- .../time_bomb_allocator_testing_utils.h | 146 +++++++++++++++++ test/test_array_list.cpp | 23 +++ test/test_char_array.cpp | 19 ++- test/test_filesystem.cpp | 13 ++ test/test_format_string.cpp | 9 ++ test/test_get_env.cpp | 13 ++ test/test_hash_map.cpp | 13 +- test/test_logging.cpp | 7 + test/test_logging_bad_env.cpp | 22 +++ test/test_logging_console_output_handler.cpp | 94 +++++++++++ test/test_logging_enable_for.cpp | 45 ++++++ test/test_process.cpp | 16 +- test/test_repl_str.cpp | 27 ++++ test/test_shared_library.cpp | 3 + test/test_split.cpp | 43 ++++- test/test_strerror.cpp | 8 + test/test_string_array.cpp | 4 + test/test_string_map.cpp | 151 ++++++++++++++++++ 19 files changed, 688 insertions(+), 10 deletions(-) create mode 100644 include/rcutils/testing_utils/time_bomb_allocator_testing_utils.h create mode 100644 test/test_logging_bad_env.cpp create mode 100644 test/test_logging_console_output_handler.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index afe07795..539ae6c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -415,30 +415,66 @@ if(BUILD_TESTING) RCUTILS_CONSOLE_OUTPUT_FORMAT="[{severity}] [{time},{time_as_nanoseconds}] [{name},{function_name},{file_name}]: {line_number}-{message}" RCUTILS_CONSOLE_STDOUT_LINE_BUFFERED=1 RCUTILS_LOGGING_BUFFERED_STREAM=1 + RCUTILS_LOGGING_USE_STDOUT=1 RCUTILS_COLORIZED_OUTPUT=1 ) if(TARGET test_logging_custom_env) target_link_libraries(test_logging_custom_env ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools) endif() + # RCUTILS_LOGGING_MAX_OUTPUT_FORMAT_LEN is defined as 2048, truncation should occur + foreach(i RANGE 0 100) + set(_output_format "${_output_format} [{severity}] [{time},{time_as_nanoseconds}] [{name},{function_name},{file_name}]: {line_number}-{message}") + endforeach(i) rcutils_custom_add_gtest(test_logging_custom_env2 test/test_logging_custom_env.cpp ENV - RCUTILS_CONSOLE_OUTPUT_FORMAT="[{severity}] [{time},{time_as_nanoseconds}] [{name},{function_name},{file_name}]: {line_number}-{message}" + RCUTILS_CONSOLE_OUTPUT_FORMAT="${_output_format}" RCUTILS_CONSOLE_STDOUT_LINE_BUFFERED=0 - RCUTILS_LOGGING_BUFFERED_STREAM=0 + RCUTILS_LOGGING_USE_STDOUT=0 RCUTILS_COLORIZED_OUTPUT=0 + RCUTILS_LOGGING_BUFFERED_STREAM=0 ) if(TARGET test_logging_custom_env2) target_link_libraries(test_logging_custom_env2 ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools) endif() + rcutils_custom_add_gtest(test_logging_bad_env test/test_logging_bad_env.cpp + ENV + RCUTILS_LOGGING_USE_STDOUT=42 + ) + if(TARGET test_logging_bad_env) + target_link_libraries(test_logging_bad_env ${PROJECT_NAME}) + endif() + + rcutils_custom_add_gtest(test_logging_bad_env2 test/test_logging_bad_env.cpp + ENV + RCUTILS_COLORIZED_OUTPUT=42 + ) + if(TARGET test_logging_bad_env2) + target_link_libraries(test_logging_bad_env2 ${PROJECT_NAME}) + endif() + + rcutils_custom_add_gtest(test_logging_bad_env3 test/test_logging_bad_env.cpp + ENV + RCUTILS_LOGGING_BUFFERED_STREAM=42 + ) + if(TARGET test_logging_bad_env3) + target_link_libraries(test_logging_bad_env3 ${PROJECT_NAME}) + endif() + rcutils_custom_add_gtest(test_logging_enable_for test/test_logging_enable_for.cpp ) if(TARGET test_logging_enable_for) - target_link_libraries(test_logging_enable_for ${PROJECT_NAME}) + target_link_libraries(test_logging_enable_for ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools) endif() + rcutils_custom_add_gtest(test_logging_console_output_handler + test/test_logging_console_output_handler.cpp + ) + if(TARGET test_logging_console_output_handler) + target_link_libraries(test_logging_console_output_handler ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools) + endif() endif() diff --git a/include/rcutils/testing_utils/time_bomb_allocator_testing_utils.h b/include/rcutils/testing_utils/time_bomb_allocator_testing_utils.h new file mode 100644 index 00000000..ead59347 --- /dev/null +++ b/include/rcutils/testing_utils/time_bomb_allocator_testing_utils.h @@ -0,0 +1,146 @@ +// Copyright 2020 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. + +#ifndef RCUTILS__TESTING_UTILS__TIME_BOMB_ALLOCATOR_TESTING_UTILS_H_ +#define RCUTILS__TESTING_UTILS__TIME_BOMB_ALLOCATOR_TESTING_UTILS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +#include "rcutils/allocator.h" + +typedef struct __time_bomb_allocator_state +{ + // Set these to negative if you want to disable time bomb for the associated function call. + int malloc_count_until_failure; + int realloc_count_until_failure; + int free_count_until_failure; + int calloc_count_until_failure; +} __time_bomb_allocator_state; + +static void * +time_bomb_malloc(size_t size, void * state) +{ + if (((__time_bomb_allocator_state *)state)->malloc_count_until_failure >= 0 && + ((__time_bomb_allocator_state *)state)->malloc_count_until_failure-- == 0) + { + printf("Malloc time bomb countdown reached 0, returning nullptr\n"); + return nullptr; + } + return rcutils_get_default_allocator().allocate(size, rcutils_get_default_allocator().state); +} + +static void * +time_bomb_realloc(void * pointer, size_t size, void * state) +{ + if (((__time_bomb_allocator_state *)state)->realloc_count_until_failure >= 0 && + ((__time_bomb_allocator_state *)state)->realloc_count_until_failure-- == 0) + { + printf("Realloc time bomb countdown reached 0, returning nullptr\n"); + return nullptr; + } + return rcutils_get_default_allocator().reallocate( + pointer, size, rcutils_get_default_allocator().state); +} + +static void +time_bomb_free(void * pointer, void * state) +{ + if (((__time_bomb_allocator_state *)state)->free_count_until_failure >= 0 && + ((__time_bomb_allocator_state *)state)->free_count_until_failure-- == 0) + { + printf("Free time bomb countdown reached 0, not freeing memory\n"); + return; + } + rcutils_get_default_allocator().deallocate(pointer, rcutils_get_default_allocator().state); +} + +static void * +time_bomb_calloc(size_t number_of_elements, size_t size_of_element, void * state) +{ + if (((__time_bomb_allocator_state *)state)->calloc_count_until_failure >= 0 && + ((__time_bomb_allocator_state *)state)->calloc_count_until_failure-- == 0) + { + printf("Calloc time bomb countdown reached 0, returning nullptr\n"); + return nullptr; + } + return rcutils_get_default_allocator().zero_allocate( + number_of_elements, size_of_element, rcutils_get_default_allocator().state); +} + +/** + * This allocator uses the rcutils default allocator functions, but decrements a time bomb counter + * for each function call. When the counter reaches 0, that call will fail. + * In the case of the allocating functions, it will return a nullptr. In the case of free, + * it will fail to free the memory. + * + * Use this allocator when you need a fixed amount of calls to succeed before it fails. + * + * Set the count to negative for the time bomb effect to be disabled for that function. + */ +static inline rcutils_allocator_t +get_time_bomb_allocator(void) +{ + static __time_bomb_allocator_state state; + state.malloc_count_until_failure = -1; + state.realloc_count_until_failure = -1; + state.free_count_until_failure = -1; + state.calloc_count_until_failure = -1; + auto time_bomb_allocator = rcutils_get_default_allocator(); + time_bomb_allocator.allocate = time_bomb_malloc; + time_bomb_allocator.deallocate = time_bomb_free; + time_bomb_allocator.reallocate = time_bomb_realloc; + time_bomb_allocator.zero_allocate = time_bomb_calloc; + time_bomb_allocator.state = &state; + return time_bomb_allocator; +} + +/** + * Set count to the number of times you want the call to succeed before it fails. + * After it fails once, it will succeed until this count is reset. + * Set it to a negative value to disable the time bomb effect for that function. + */ +static inline void +set_time_bomb_allocator_malloc_count(rcutils_allocator_t & time_bomb_allocator, int count) +{ + ((__time_bomb_allocator_state *)time_bomb_allocator.state)->malloc_count_until_failure = count; +} + +static inline void +set_time_bomb_allocator_realloc_count(rcutils_allocator_t & time_bomb_allocator, int count) +{ + ((__time_bomb_allocator_state *)time_bomb_allocator.state)->realloc_count_until_failure = count; +} + +static inline void +set_time_bomb_allocator_free_count(rcutils_allocator_t & time_bomb_allocator, int count) +{ + ((__time_bomb_allocator_state *)time_bomb_allocator.state)->free_count_until_failure = count; +} + +static inline void +set_time_bomb_allocator_calloc_count(rcutils_allocator_t & time_bomb_allocator, int count) +{ + ((__time_bomb_allocator_state *)time_bomb_allocator.state)->calloc_count_until_failure = count; +} + +#ifdef __cplusplus +} +#endif + +#endif // RCUTILS__TESTING_UTILS__TIME_BOMB_ALLOCATOR_TESTING_UTILS_H_ diff --git a/test/test_array_list.cpp b/test/test_array_list.cpp index c1763323..4c62c578 100644 --- a/test/test_array_list.cpp +++ b/test/test_array_list.cpp @@ -17,11 +17,13 @@ #include #include "./allocator_testing_utils.h" +#include "rcutils/testing_utils/time_bomb_allocator_testing_utils.h" #include "rcutils/allocator.h" #include "rcutils/error_handling.h" #include "rcutils/types/array_list.h" auto failing_allocator = get_failing_allocator(); +auto time_bomb_allocator = get_time_bomb_allocator(); class ArrayListTest : public ::testing::Test { @@ -80,6 +82,20 @@ TEST_F(ArrayListTest, init_null_allocator_fails) { EXPECT_EQ(RCUTILS_RET_INVALID_ARGUMENT, ret) << rcutils_get_error_string().str; } +TEST_F(ArrayListTest, fail_allocate_impl) { + rcutils_allocator_t time_bomb_allocator = get_time_bomb_allocator(); + set_time_bomb_allocator_malloc_count(time_bomb_allocator, 0); + rcutils_ret_t ret = rcutils_array_list_init(&list, 2, sizeof(uint32_t), &time_bomb_allocator); + EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret) << rcutils_get_error_string().str; +} + +TEST_F(ArrayListTest, fail_allocate_impl_list) { + rcutils_allocator_t time_bomb_allocator = get_time_bomb_allocator(); + set_time_bomb_allocator_malloc_count(time_bomb_allocator, 1); + rcutils_ret_t ret = rcutils_array_list_init(&list, 2, sizeof(uint32_t), &time_bomb_allocator); + EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret) << rcutils_get_error_string().str; +} + TEST_F(ArrayListTest, init_success) { rcutils_ret_t ret = rcutils_array_list_init(&list, 2, sizeof(uint32_t), &allocator); EXPECT_EQ(RCUTILS_RET_OK, ret) << rcutils_get_error_string().str; @@ -364,8 +380,15 @@ TEST_F(ArrayListPreInitTest, init_list_twice_fails) { } TEST_F(ArrayListTest, init_list_bad_allocator_fail) { + // Allocating array-list->impl fails + set_time_bomb_allocator_malloc_count(time_bomb_allocator, 0); rcutils_ret_t ret = rcutils_array_list_init(&list, 2, sizeof(uint32_t), &failing_allocator); EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret) << rcutils_get_error_string().str; + + // Allocating array-list->impl->list fails + set_time_bomb_allocator_malloc_count(time_bomb_allocator, 1); + ret = rcutils_array_list_init(&list, 2, sizeof(uint32_t), &failing_allocator); + EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret) << rcutils_get_error_string().str; } typedef struct allocator_state diff --git a/test/test_char_array.cpp b/test/test_char_array.cpp index 620e6f9c..48e9c4cd 100644 --- a/test/test_char_array.cpp +++ b/test/test_char_array.cpp @@ -80,6 +80,12 @@ TEST_F(ArrayCharTest, resize) { EXPECT_EQ(11lu, char_array.buffer_capacity); EXPECT_EQ(5lu, char_array.buffer_length); + // Resize to same capacity, nothing to be done + ret = rcutils_char_array_resize(&char_array, 11); + ASSERT_EQ(RCUTILS_RET_OK, ret); + EXPECT_EQ(11lu, char_array.buffer_capacity); + EXPECT_EQ(5lu, char_array.buffer_length); + char_array.buffer_length = snprintf( char_array.buffer, char_array.buffer_capacity, "0987654321") + 1; EXPECT_STREQ("0987654321", char_array.buffer); @@ -95,6 +101,18 @@ TEST_F(ArrayCharTest, resize) { // cleanup only 3 fields EXPECT_EQ(RCUTILS_RET_OK, rcutils_char_array_fini(&char_array)); + + allocator = get_failing_allocator(); + ret = rcutils_char_array_init(&char_array, 0, &allocator); + ASSERT_EQ(RCUTILS_RET_OK, ret); + + // Force a failing allocation on resizing + char_array.owns_buffer = false; + ret = rcutils_char_array_resize(&char_array, 3); + ASSERT_EQ(RCUTILS_RET_BAD_ALLOC, ret); + + // Nothing to cleanup, but it should be ok + EXPECT_EQ(RCUTILS_RET_OK, rcutils_char_array_fini(&char_array)); } TEST_F(ArrayCharTest, vsprintf_fail) { @@ -107,7 +125,6 @@ TEST_F(ArrayCharTest, vsprintf_fail) { EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret); rcutils_reset_error(); - char_array.allocator = allocator; EXPECT_EQ(RCUTILS_RET_OK, rcutils_char_array_fini(&char_array)); } diff --git a/test/test_filesystem.cpp b/test/test_filesystem.cpp index 3b0431a0..df93be07 100644 --- a/test/test_filesystem.cpp +++ b/test/test_filesystem.cpp @@ -44,6 +44,9 @@ class TestFilesystemFixture : public ::testing::Test TEST_F(TestFilesystemFixture, get_cwd_nullptr) { EXPECT_FALSE(rcutils_get_cwd(NULL, sizeof(this->cwd))); EXPECT_FALSE(rcutils_get_cwd(this->cwd, 0)); + + // ERANGE, including a null terminating character, cwd should always be longer than 1 char + EXPECT_FALSE(rcutils_get_cwd(this->cwd, 1)); } TEST_F(TestFilesystemFixture, join_path) { @@ -241,6 +244,16 @@ TEST_F(TestFilesystemFixture, is_readable_and_writable) { ASSERT_FALSE(nullptr == path); EXPECT_TRUE(rcutils_is_readable_and_writable(path)); } + { + char * path = + rcutils_join_path(this->test_path, "dummy_readable_file.txt", g_allocator); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + g_allocator.deallocate(path, g_allocator.state); + }); + ASSERT_FALSE(nullptr == path); + EXPECT_TRUE(rcutils_is_readable_and_writable(path)); + } { char * path = rcutils_join_path(this->test_path, "dummy_readable_writable_file.txt", g_allocator); diff --git a/test/test_format_string.cpp b/test/test_format_string.cpp index 10f09b4b..cc48f16d 100644 --- a/test/test_format_string.cpp +++ b/test/test_format_string.cpp @@ -38,6 +38,15 @@ TEST(test_format_string_limit, nominal) { allocator.deallocate(formatted, allocator.state); } } + + { + auto allocator = rcutils_get_default_allocator(); + char * formatted = rcutils_format_string_limit(allocator, 3, "string is too long %s", "test"); + EXPECT_STREQ("st", formatted); + if (formatted) { + allocator.deallocate(formatted, allocator.state); + } + } } TEST(test_format_string_limit, invalid_arguments) { diff --git a/test/test_get_env.cpp b/test/test_get_env.cpp index 998e4ede..561689aa 100644 --- a/test/test_get_env.cpp +++ b/test/test_get_env.cpp @@ -16,6 +16,7 @@ #include +#include "rcutils/env.h" #include "rcutils/get_env.h" /* Tests rcutils_get_env. @@ -49,4 +50,16 @@ TEST(TestGetEnv, test_get_env) { TEST(TestGetEnv, test_get_home) { EXPECT_STRNE(NULL, rcutils_get_home_dir()); + + const char * home = NULL; + const char * ret = rcutils_get_env("HOME", &home); + EXPECT_EQ(NULL, ret); + +#ifdef _WIN32 + EXPECT_TRUE(rcutils_set_env("USERPROFILE", NULL)); + EXPECT_EQ(NULL, rcutils_get_home_dir()); +#else + EXPECT_TRUE(rcutils_set_env("HOME", NULL)); + EXPECT_EQ(NULL, rcutils_get_home_dir()); +#endif } diff --git a/test/test_hash_map.cpp b/test/test_hash_map.cpp index fa9fea62..df7d366f 100644 --- a/test/test_hash_map.cpp +++ b/test/test_hash_map.cpp @@ -16,7 +16,7 @@ #include -#include "./allocator_testing_utils.h" +#include "rcutils/testing_utils/time_bomb_allocator_testing_utils.h" #include "rcutils/allocator.h" #include "rcutils/error_handling.h" #include "rcutils/types/hash_map.h" @@ -131,11 +131,20 @@ TEST_F(HashMapBaseTest, init_map_allocator_NULL_fails) { } TEST_F(HashMapBaseTest, init_map_failing_allocator) { - rcutils_allocator_t failing_allocator = get_failing_allocator(); + rcutils_allocator_t failing_allocator = get_time_bomb_allocator(); + // Check allocating hash_map->impl fails + set_time_bomb_allocator_malloc_count(failing_allocator, 0); rcutils_ret_t ret = rcutils_hash_map_init( &map, 2, sizeof(uint32_t), sizeof(uint32_t), test_hash_map_uint32_hash_func, test_uint32_cmp, &failing_allocator); EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret) << rcutils_get_error_string().str; + + // Check allocate hash_map->impl fails + set_time_bomb_allocator_malloc_count(failing_allocator, 1); + ret = rcutils_hash_map_init( + &map, 2, sizeof(uint32_t), sizeof(uint32_t), + test_hash_map_uint32_hash_func, test_uint32_cmp, &failing_allocator); + EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret) << rcutils_get_error_string().str; } TEST_F(HashMapBaseTest, init_map_success) { diff --git a/test/test_logging.cpp b/test/test_logging.cpp index 8903ee9e..3e5fc145 100644 --- a/test/test_logging.cpp +++ b/test/test_logging.cpp @@ -34,6 +34,9 @@ TEST(CLASSNAME(TestLogging, RMW_IMPLEMENTATION), test_logging_initialization) { OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( { EXPECT_EQ(RCUTILS_RET_OK, rcutils_logging_shutdown()); + + // Ok to shutdown after it's already been shutdown + EXPECT_EQ(RCUTILS_RET_OK, rcutils_logging_shutdown()); }); EXPECT_TRUE(g_rcutils_logging_initialized); ASSERT_EQ(RCUTILS_RET_OK, rcutils_logging_initialize()); @@ -238,6 +241,10 @@ TEST(CLASSNAME(TestLogging, RMW_IMPLEMENTATION), test_logger_severities) { RCUTILS_RET_INVALID_ARGUMENT, rcutils_logging_set_logger_level("rcutils_test_loggers", -1)); rcutils_reset_error(); + ASSERT_EQ( + RCUTILS_RET_INVALID_ARGUMENT, + rcutils_logging_set_logger_level("rcutils_test_loggers", 21)); + rcutils_reset_error(); ASSERT_EQ( RCUTILS_RET_INVALID_ARGUMENT, rcutils_logging_set_logger_level("rcutils_test_loggers", 51)); diff --git a/test/test_logging_bad_env.cpp b/test/test_logging_bad_env.cpp new file mode 100644 index 00000000..ebe9feb4 --- /dev/null +++ b/test/test_logging_bad_env.cpp @@ -0,0 +1,22 @@ +// Copyright 2020 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 "rcutils/logging.h" + +TEST(TestBadCustomEnv, test_initialize) { + EXPECT_FALSE(g_rcutils_logging_initialized); + ASSERT_EQ(RCUTILS_RET_INVALID_ARGUMENT, rcutils_logging_initialize()); +} diff --git a/test/test_logging_console_output_handler.cpp b/test/test_logging_console_output_handler.cpp new file mode 100644 index 00000000..6731554d --- /dev/null +++ b/test/test_logging_console_output_handler.cpp @@ -0,0 +1,94 @@ +// Copyright 2020 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 "osrf_testing_tools_cpp/scope_exit.hpp" +#include "rcutils/logging.h" + +static void call_handler( + const rcutils_log_location_t * location, + int severity, const char * name, rcutils_time_point_value_t timestamp, + const char * format, ...) +{ + va_list args; + va_start(args, format); + rcutils_logging_console_output_handler(location, severity, name, timestamp, format, &args); + va_end(args); +} + +TEST(TestLoggingConsoleOutputHandler, typical_inputs) { + ASSERT_EQ(RCUTILS_RET_OK, rcutils_logging_initialize()); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + EXPECT_EQ(RCUTILS_RET_OK, rcutils_logging_shutdown()); + }); + + rcutils_log_location_t log_location = { + "test_function", + "test_file", + 1, + }; + const char * log_name = "test_name"; + rcutils_time_point_value_t timestamp = 1; + const char * format = "%s - %s"; + call_handler( + &log_location, RCUTILS_LOG_SEVERITY_DEBUG, log_name, timestamp, format, "part1", "part2"); + call_handler( + &log_location, RCUTILS_LOG_SEVERITY_INFO, log_name, timestamp, format, "part1", "part2"); + call_handler( + &log_location, RCUTILS_LOG_SEVERITY_WARN, log_name, timestamp, format, "part1", "part2"); + call_handler( + &log_location, RCUTILS_LOG_SEVERITY_ERROR, log_name, timestamp, format, "part1", "part2"); + call_handler( + &log_location, RCUTILS_LOG_SEVERITY_FATAL, log_name, timestamp, format, "part1", "part2"); +} + +// This handler function uses fprintf to print to stdout/stderr so there are no outputs to check +TEST(TestLoggingConsoleOutputHandler, bad_inputs) { + rcutils_log_location_t log_location = { + "test_function", + "test_file", + 1, + }; + const char * log_name = "test_name"; + rcutils_time_point_value_t timestamp = 1; + const char * format = "%s - %s"; + + // Check !g_rcutils_logging_initialized + call_handler( + &log_location, RCUTILS_LOG_SEVERITY_DEBUG, log_name, timestamp, format, "part1", "part2"); + + ASSERT_EQ(RCUTILS_RET_OK, rcutils_logging_initialize()); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + EXPECT_EQ(RCUTILS_RET_OK, rcutils_logging_shutdown()); + }); + + call_handler( + nullptr, RCUTILS_LOG_SEVERITY_INFO, log_name, timestamp, format, "part1", "part2"); + call_handler( + &log_location, RCUTILS_LOG_SEVERITY_UNSET, log_name, timestamp, format, "part1", "part2"); + call_handler( + &log_location, RCUTILS_LOG_SEVERITY_INFO, nullptr, timestamp, format, "part1", "part2"); + call_handler( + &log_location, RCUTILS_LOG_SEVERITY_INFO, log_name, 0, format, "part1", "part2"); + + // If format is NULL, this call will segfault on some (but not all) systems + call_handler( + &log_location, RCUTILS_LOG_SEVERITY_INFO, log_name, timestamp, "bad format", "part1", "part2"); +} diff --git a/test/test_logging_enable_for.cpp b/test/test_logging_enable_for.cpp index 059feaf6..a043a196 100644 --- a/test/test_logging_enable_for.cpp +++ b/test/test_logging_enable_for.cpp @@ -16,6 +16,7 @@ #include +#include "osrf_testing_tools_cpp/scope_exit.hpp" #include "rcutils/logging.h" TEST(test_logging_logger_is_enabled_for, test_logging_logger_is_enabled_for) { @@ -60,3 +61,47 @@ TEST(test_logging_logger_is_enabled_for, test_logging_logger_is_enabled_for) { "rmw_fastrtps_cpp", RCUTILS_LOG_SEVERITY_FATAL); ASSERT_TRUE(ret); } + +TEST(test_logging_logger_is_enabled_for, test_logger_is_enabled_for) { + EXPECT_FALSE( + rcutils_logging_logger_is_enabled_for("rcutils_test_loggers", RCUTILS_LOG_SEVERITY_DEBUG)); + EXPECT_TRUE( + rcutils_logging_logger_is_enabled_for("rcutils_test_loggers", RCUTILS_LOG_SEVERITY_FATAL)); + + ASSERT_EQ(RCUTILS_RET_OK, rcutils_logging_initialize()); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + EXPECT_EQ(RCUTILS_RET_OK, rcutils_logging_shutdown()); + }); + + EXPECT_TRUE( + rcutils_logging_logger_is_enabled_for("rcutils_test_loggers", RCUTILS_LOG_SEVERITY_INFO)); + + ASSERT_EQ( + RCUTILS_RET_OK, + rcutils_logging_set_logger_level( + "rcutils_test_loggers", RCUTILS_LOG_SEVERITY_WARN)); + + EXPECT_FALSE( + rcutils_logging_logger_is_enabled_for("rcutils_test_loggers", RCUTILS_LOG_SEVERITY_INFO)); + + EXPECT_FALSE(rcutils_logging_logger_is_enabled_for("rcutils_test_loggers", -1)); + EXPECT_TRUE(rcutils_logging_logger_is_enabled_for("rcutils_test_loggers", 1000)); + + // These should all resort to default logging severity + EXPECT_FALSE(rcutils_logging_logger_is_enabled_for("", RCUTILS_LOG_SEVERITY_DEBUG)); + EXPECT_TRUE(rcutils_logging_logger_is_enabled_for("", RCUTILS_LOG_SEVERITY_FATAL)); + + EXPECT_FALSE(rcutils_logging_logger_is_enabled_for(NULL, RCUTILS_LOG_SEVERITY_DEBUG)); + EXPECT_TRUE(rcutils_logging_logger_is_enabled_for(NULL, RCUTILS_LOG_SEVERITY_FATAL)); + + EXPECT_TRUE( + rcutils_logging_logger_is_enabled_for("name_that_doesn't_exist", RCUTILS_LOG_SEVERITY_FATAL)); + EXPECT_FALSE( + rcutils_logging_logger_is_enabled_for("name_that_doesn't_exist", RCUTILS_LOG_SEVERITY_DEBUG)); + + EXPECT_TRUE( + rcutils_logging_logger_is_enabled_for("name.that.doesn't.exist", RCUTILS_LOG_SEVERITY_FATAL)); + EXPECT_FALSE( + rcutils_logging_logger_is_enabled_for("name.that.doesn't.exist", RCUTILS_LOG_SEVERITY_DEBUG)); +} diff --git a/test/test_process.cpp b/test/test_process.cpp index be074394..24a026bf 100644 --- a/test/test_process.cpp +++ b/test/test_process.cpp @@ -18,6 +18,7 @@ #include "rcutils/allocator.h" #include "rcutils/error_handling.h" #include "rcutils/process.h" +#include "rcutils/testing_utils/time_bomb_allocator_testing_utils.h" TEST(TestProcess, test_get_pid) { EXPECT_NE(rcutils_get_pid(), 0); @@ -25,9 +26,20 @@ TEST(TestProcess, test_get_pid) { TEST(TestProcess, test_get_executable_name) { rcutils_allocator_t allocator = rcutils_get_default_allocator(); - rcutils_allocator_t failing_allocator = get_failing_allocator(); + rcutils_allocator_t time_bomb_allocator = get_time_bomb_allocator(); + + // Allocating executable_name fails + set_time_bomb_allocator_malloc_count(time_bomb_allocator, 0); + EXPECT_STREQ(NULL, rcutils_get_executable_name(time_bomb_allocator)); + + // Allocating intermediate fails +#if defined __APPLE__ || defined __FreeBSD__ || defined __GNUC__ + set_time_bomb_allocator_malloc_count(time_bomb_allocator, 1); + EXPECT_STREQ(NULL, rcutils_get_executable_name(time_bomb_allocator)); +#elif defined _WIN32 || defined __CYGWIN__ + // This allocation doesn't happen on windows +#endif - EXPECT_STREQ(NULL, rcutils_get_executable_name(failing_allocator)); char * exec_name = rcutils_get_executable_name(allocator); EXPECT_STREQ("test_process", exec_name); allocator.deallocate(exec_name, allocator.state); diff --git a/test/test_repl_str.cpp b/test/test_repl_str.cpp index 00d8b6cb..ba787341 100644 --- a/test/test_repl_str.cpp +++ b/test/test_repl_str.cpp @@ -62,4 +62,31 @@ TEST(test_repl_str, nominal) { char * out = rcutils_repl_str(typical.c_str(), "{bar}", "", &failing_allocator); EXPECT_EQ(NULL, out); } + + // no matches + { + std::string typical = "foo/{bar}/baz"; + char * out = rcutils_repl_str(typical.c_str(), "no match", "n/a", &allocator); + EXPECT_STREQ(typical.c_str(), out); + allocator.deallocate(out, allocator.state); + } + + // no matches and bad allocator + { + std::string typical = "foo/{bar}/baz"; + rcutils_allocator_t failing_allocator = get_failing_allocator(); + char * out = rcutils_repl_str(typical.c_str(), "no match", "n/a", &failing_allocator); + EXPECT_EQ(NULL, out); + } + + // Force cache_sz_inc to exceed cache_sz_inc_max + { + std::stringstream ss; + for (size_t i = 0; i < 1048576; ++i) { + ss << "f"; + } + char * out = rcutils_repl_str(ss.str().c_str(), "f", "longer replacementment", &allocator); + EXPECT_NE(nullptr, out); + allocator.deallocate(out, allocator.state); + } } diff --git a/test/test_shared_library.cpp b/test/test_shared_library.cpp index 275514a5..d14a914e 100644 --- a/test/test_shared_library.cpp +++ b/test/test_shared_library.cpp @@ -46,6 +46,9 @@ TEST_F(TestSharedLibrary, basic_load) { EXPECT_TRUE(lib.lib_pointer == NULL); EXPECT_FALSE(rcutils_is_shared_library_loaded(&lib)); + ret = rcutils_get_platform_library_name("dummy_shared_library", library_path, 1024, true); + ASSERT_EQ(RCUTILS_RET_OK, ret); + ret = rcutils_get_platform_library_name("dummy_shared_library", library_path, 1024, false); ASSERT_EQ(RCUTILS_RET_OK, ret); diff --git a/test/test_split.cpp b/test/test_split.cpp index 4494ba20..a27723f8 100644 --- a/test/test_split.cpp +++ b/test/test_split.cpp @@ -18,6 +18,7 @@ #include "rcutils/error_handling.h" #include "rcutils/split.h" #include "rcutils/types/string_array.h" +#include "rcutils/testing_utils/time_bomb_allocator_testing_utils.h" #define ENABLE_LOGGING 1 @@ -63,9 +64,19 @@ TEST(test_split, split) { RCUTILS_RET_INVALID_ARGUMENT, rcutils_split("Test", '/', rcutils_get_default_allocator(), NULL)); + // Allocating string_array->data fails + rcutils_allocator_t time_bomb_allocator = get_time_bomb_allocator(); + set_time_bomb_allocator_malloc_count(time_bomb_allocator, 0); EXPECT_EQ( RCUTILS_RET_ERROR, - rcutils_split("Test", '/', get_failing_allocator(), &tokens_fail)); + rcutils_split("Test", '/', time_bomb_allocator, &tokens_fail)); + + // Allocating string_array->data[0] fails + set_time_bomb_allocator_malloc_count(time_bomb_allocator, 1); + EXPECT_EQ( + RCUTILS_RET_ERROR, + rcutils_split("hello/world", '/', time_bomb_allocator, &tokens_fail)); + rcutils_string_array_t tokens0 = test_split("", '/', 0); ret = rcutils_string_array_fini(&tokens0); @@ -149,9 +160,37 @@ TEST(test_split, split) { TEST(test_split, split_last) { rcutils_ret_t ret = RCUTILS_RET_OK; rcutils_string_array_t tokens_fail; + + // Allocating string_array fails + rcutils_allocator_t time_bomb_allocator = get_time_bomb_allocator(); + set_time_bomb_allocator_calloc_count(time_bomb_allocator, 0); + EXPECT_EQ( + RCUTILS_RET_BAD_ALLOC, + rcutils_split_last("Test", '/', time_bomb_allocator, &tokens_fail)); + + // Allocating string_array->data[0] fails + set_time_bomb_allocator_malloc_count(time_bomb_allocator, 0); + EXPECT_EQ( + RCUTILS_RET_BAD_ALLOC, + rcutils_split_last("Test", '/', time_bomb_allocator, &tokens_fail)); + + // Allocating string_array fails, found_last != string_size + set_time_bomb_allocator_calloc_count(time_bomb_allocator, 0); + EXPECT_EQ( + RCUTILS_RET_BAD_ALLOC, + rcutils_split_last("hello/world", '/', time_bomb_allocator, &tokens_fail)); + + // Allocating string_array->data[0] fails, found_last != string_size + set_time_bomb_allocator_malloc_count(time_bomb_allocator, 0); + EXPECT_EQ( + RCUTILS_RET_BAD_ALLOC, + rcutils_split_last("hello/world", '/', time_bomb_allocator, &tokens_fail)); + + // Allocating string_array->data[1] fails, found_last != string_size + set_time_bomb_allocator_malloc_count(time_bomb_allocator, 1); EXPECT_EQ( RCUTILS_RET_BAD_ALLOC, - rcutils_split_last("Test", '/', get_failing_allocator(), &tokens_fail)); + rcutils_split_last("hello/world", '/', time_bomb_allocator, &tokens_fail)); rcutils_string_array_t tokens0 = test_split_last("", '/', 0); ret = rcutils_string_array_fini(&tokens0); diff --git a/test/test_strerror.cpp b/test/test_strerror.cpp index 9020933d..8701f89d 100644 --- a/test/test_strerror.cpp +++ b/test/test_strerror.cpp @@ -43,4 +43,12 @@ TEST(test_strerror, get_error) { rcutils_strerror(error_string, sizeof(error_string)); ASSERT_STREQ(error_string, "No such file or directory"); + +#if (!defined(_WIN32)) && (!( \ + defined(_GNU_SOURCE) && (!defined(ANDROID) || __ANDROID_API__ >= 23))) + // Hopefully this does not become a valid errno. + errno = 12345; + rcutils_strerror(error_string, sizeof(error_string)); + ASSERT_STREQ(error_string, "Failed to get error"); +#endif } diff --git a/test/test_string_array.cpp b/test/test_string_array.cpp index ab7574cf..176a363a 100644 --- a/test/test_string_array.cpp +++ b/test/test_string_array.cpp @@ -35,6 +35,8 @@ TEST(test_string_array, boot_string_array) { ret = rcutils_string_array_fini(&sa0); ASSERT_EQ(RCUTILS_RET_OK, ret); + EXPECT_EQ(RCUTILS_RET_INVALID_ARGUMENT, rcutils_string_array_init(NULL, 2, &allocator)); + rcutils_reset_error(); EXPECT_EQ(RCUTILS_RET_INVALID_ARGUMENT, rcutils_string_array_init(&sa0, 2, NULL)); rcutils_reset_error(); EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, rcutils_string_array_init(&sa0, 2, &failing_allocator)); @@ -57,6 +59,8 @@ TEST(test_string_array, boot_string_array) { rcutils_string_array_t sa3 = rcutils_get_zero_initialized_string_array(); ASSERT_EQ(RCUTILS_RET_OK, rcutils_string_array_init(&sa3, 3, &allocator)); sa3.allocator.allocate = NULL; + ASSERT_EQ(RCUTILS_RET_INVALID_ARGUMENT, rcutils_string_array_fini(NULL)); + rcutils_reset_error(); ASSERT_EQ(RCUTILS_RET_INVALID_ARGUMENT, rcutils_string_array_fini(&sa3)); rcutils_reset_error(); sa3.allocator = allocator; diff --git a/test/test_string_map.cpp b/test/test_string_map.cpp index 1c934d94..33eb2edf 100644 --- a/test/test_string_map.cpp +++ b/test/test_string_map.cpp @@ -74,6 +74,17 @@ TEST(test_string_map, lifecycle) { EXPECT_EQ(RCUTILS_RET_OK, ret) << rcutils_get_error_string().str; } + // init and then fini with requested SIZE_MAX capacity + { + rcutils_string_map_t string_map = rcutils_get_zero_initialized_string_map(); + ret = rcutils_string_map_init(&string_map, SIZE_MAX, allocator); + EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret); + EXPECT_TRUE(rcutils_error_is_set()); + rcutils_reset_error(); + ret = rcutils_string_map_fini(&string_map); + EXPECT_EQ(RCUTILS_RET_OK, ret) << rcutils_get_error_string().str; + } + // init on non-zero initialized { rcutils_string_map_t string_map; @@ -372,6 +383,100 @@ TEST(test_string_map, reserve_and_clear) { } } + // initialize to 10, set, set, request reserve 0, should set capacity to size + { + rcutils_string_map_t string_map = rcutils_get_zero_initialized_string_map(); + ret = rcutils_string_map_init(&string_map, 10, allocator); + ASSERT_EQ(RCUTILS_RET_OK, ret); + + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + EXPECT_EQ( + RCUTILS_RET_OK, + rcutils_string_map_fini(&string_map)) << rcutils_get_error_string().str; + rcutils_reset_error(); + }); + + { + size_t expected = 10; + size_t capacity = 42; + ret = rcutils_string_map_get_capacity(&string_map, &capacity); + EXPECT_EQ(RCUTILS_RET_OK, ret); + EXPECT_EQ(expected, capacity); + + expected = 0; + size_t size = 42; + ret = rcutils_string_map_get_size(&string_map, &size); + EXPECT_EQ(RCUTILS_RET_OK, ret); + EXPECT_EQ(expected, size); + } + + ret = rcutils_string_map_set_no_resize(&string_map, "key1", "value1"); + ASSERT_EQ(RCUTILS_RET_OK, ret); + + { + size_t expected = 10; + size_t capacity = 42; + ret = rcutils_string_map_get_capacity(&string_map, &capacity); + EXPECT_EQ(RCUTILS_RET_OK, ret); + EXPECT_EQ(expected, capacity); + + expected = 1; + size_t size = 42; + ret = rcutils_string_map_get_size(&string_map, &size); + EXPECT_EQ(RCUTILS_RET_OK, ret); + EXPECT_EQ(expected, size); + } + + ret = rcutils_string_map_set_no_resize(&string_map, "key2", "value2"); + ASSERT_EQ(RCUTILS_RET_OK, ret); + + { + size_t expected = 10; + size_t capacity = 42; + ret = rcutils_string_map_get_capacity(&string_map, &capacity); + EXPECT_EQ(RCUTILS_RET_OK, ret); + EXPECT_EQ(expected, capacity); + + expected = 2; + size_t size = 42; + ret = rcutils_string_map_get_size(&string_map, &size); + EXPECT_EQ(RCUTILS_RET_OK, ret); + EXPECT_EQ(expected, size); + } + + { + size_t expected = 10; + size_t capacity = 42; + ret = rcutils_string_map_get_capacity(&string_map, &capacity); + EXPECT_EQ(RCUTILS_RET_OK, ret); + EXPECT_EQ(expected, capacity); + + expected = 2; + size_t size = 42; + ret = rcutils_string_map_get_size(&string_map, &size); + EXPECT_EQ(RCUTILS_RET_OK, ret); + EXPECT_EQ(expected, size); + } + + ret = rcutils_string_map_reserve(&string_map, 0); + ASSERT_EQ(RCUTILS_RET_OK, ret); + + { + size_t expected = 2; + size_t capacity = 42; + ret = rcutils_string_map_get_capacity(&string_map, &capacity); + EXPECT_EQ(RCUTILS_RET_OK, ret); + EXPECT_EQ(expected, capacity); + + expected = 2; + size_t size = 42; + ret = rcutils_string_map_get_size(&string_map, &size); + EXPECT_EQ(RCUTILS_RET_OK, ret); + EXPECT_EQ(expected, size); + } + } + // initialize to 0, clear { rcutils_string_map_t string_map = rcutils_get_zero_initialized_string_map(); @@ -658,6 +763,31 @@ TEST(test_string_map, set_no_resize) { rcutils_reset_error(); } + // use failing allocator, but key already exists + { + set_failing_allocator_is_failing(failing_allocator, false); + rcutils_string_map_t string_map = rcutils_get_zero_initialized_string_map(); + ret = rcutils_string_map_init(&string_map, 1, failing_allocator); + ASSERT_EQ(RCUTILS_RET_OK, ret); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + set_failing_allocator_is_failing(failing_allocator, false); + EXPECT_EQ( + RCUTILS_RET_OK, + rcutils_string_map_fini(&string_map)) << rcutils_get_error_string().str; + rcutils_reset_error(); + }); + + ret = rcutils_string_map_set_no_resize(&string_map, "key1", "value1"); + ASSERT_EQ(RCUTILS_RET_OK, ret) << rcutils_get_error_string().str; + + + set_failing_allocator_is_failing(failing_allocator, true); + ret = rcutils_string_map_set_no_resize(&string_map, "key1", "value2"); + EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret) << rcutils_get_error_string().str; + rcutils_reset_error(); + } + // pass NULL for string_map { ret = rcutils_string_map_set_no_resize(NULL, "key1", "value1"); @@ -946,6 +1076,27 @@ TEST(test_string_map, set) { rcutils_reset_error(); } + // use failing allocator, but key already exists + { + set_failing_allocator_is_failing(failing_allocator, false); + rcutils_string_map_t string_map = rcutils_get_zero_initialized_string_map(); + ret = rcutils_string_map_init(&string_map, 1, failing_allocator); + ASSERT_EQ(RCUTILS_RET_OK, ret); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + set_failing_allocator_is_failing(failing_allocator, false); + EXPECT_EQ( + RCUTILS_RET_OK, + rcutils_string_map_fini(&string_map)) << rcutils_get_error_string().str; + rcutils_reset_error(); + }); + + set_failing_allocator_is_failing(failing_allocator, true); + ret = rcutils_string_map_set(&string_map, "key1", "value1"); + EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret) << rcutils_get_error_string().str; + rcutils_reset_error(); + } + // pass NULL for string_map { ret = rcutils_string_map_set(NULL, "key1", "value1"); From 1aef73c3150b8b11f70a8c4bf1f395cf7960db74 Mon Sep 17 00:00:00 2001 From: Stephen Brawner Date: Tue, 2 Jun 2020 14:44:24 -0700 Subject: [PATCH 2/6] PR Fixup and some cleanup Signed-off-by: Stephen Brawner --- test/test_array_list.cpp | 12 ------------ test/test_char_array.cpp | 1 + test/test_hash_map.cpp | 2 +- test/test_logging_console_output_handler.cpp | 5 ++++- test/test_repl_str.cpp | 2 +- test/test_shared_library.cpp | 2 ++ test/test_strerror.cpp | 4 +++- 7 files changed, 12 insertions(+), 16 deletions(-) diff --git a/test/test_array_list.cpp b/test/test_array_list.cpp index 4c62c578..d6b1adf8 100644 --- a/test/test_array_list.cpp +++ b/test/test_array_list.cpp @@ -379,18 +379,6 @@ TEST_F(ArrayListPreInitTest, init_list_twice_fails) { EXPECT_EQ(RCUTILS_RET_INVALID_ARGUMENT, ret) << rcutils_get_error_string().str; } -TEST_F(ArrayListTest, init_list_bad_allocator_fail) { - // Allocating array-list->impl fails - set_time_bomb_allocator_malloc_count(time_bomb_allocator, 0); - rcutils_ret_t ret = rcutils_array_list_init(&list, 2, sizeof(uint32_t), &failing_allocator); - EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret) << rcutils_get_error_string().str; - - // Allocating array-list->impl->list fails - set_time_bomb_allocator_malloc_count(time_bomb_allocator, 1); - ret = rcutils_array_list_init(&list, 2, sizeof(uint32_t), &failing_allocator); - EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret) << rcutils_get_error_string().str; -} - typedef struct allocator_state { bool is_failing; diff --git a/test/test_char_array.cpp b/test/test_char_array.cpp index 48e9c4cd..05012d8b 100644 --- a/test/test_char_array.cpp +++ b/test/test_char_array.cpp @@ -125,6 +125,7 @@ TEST_F(ArrayCharTest, vsprintf_fail) { EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret); rcutils_reset_error(); + char_array.allocator = allocator; EXPECT_EQ(RCUTILS_RET_OK, rcutils_char_array_fini(&char_array)); } diff --git a/test/test_hash_map.cpp b/test/test_hash_map.cpp index df7d366f..44a239eb 100644 --- a/test/test_hash_map.cpp +++ b/test/test_hash_map.cpp @@ -139,7 +139,7 @@ TEST_F(HashMapBaseTest, init_map_failing_allocator) { test_hash_map_uint32_hash_func, test_uint32_cmp, &failing_allocator); EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret) << rcutils_get_error_string().str; - // Check allocate hash_map->impl fails + // Check allocate hash_map->impl->map fails set_time_bomb_allocator_malloc_count(failing_allocator, 1); ret = rcutils_hash_map_init( &map, 2, sizeof(uint32_t), sizeof(uint32_t), diff --git a/test/test_logging_console_output_handler.cpp b/test/test_logging_console_output_handler.cpp index 6731554d..f4990348 100644 --- a/test/test_logging_console_output_handler.cpp +++ b/test/test_logging_console_output_handler.cpp @@ -31,6 +31,8 @@ static void call_handler( va_end(args); } +// There are no outputs of the handler function, and the only result are fprintf() calls. +// This is just a smoke test to check that the code can handle simple inputs cleanly. TEST(TestLoggingConsoleOutputHandler, typical_inputs) { ASSERT_EQ(RCUTILS_RET_OK, rcutils_logging_initialize()); OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( @@ -58,7 +60,8 @@ TEST(TestLoggingConsoleOutputHandler, typical_inputs) { &log_location, RCUTILS_LOG_SEVERITY_FATAL, log_name, timestamp, format, "part1", "part2"); } -// This handler function uses fprintf to print to stdout/stderr so there are no outputs to check +// There are no outputs of the handler function, and the only result are fprintf() calls. +// This is just a smoke test to check that the code can handle bad inputs cleanly. TEST(TestLoggingConsoleOutputHandler, bad_inputs) { rcutils_log_location_t log_location = { "test_function", diff --git a/test/test_repl_str.cpp b/test/test_repl_str.cpp index ba787341..4c629d00 100644 --- a/test/test_repl_str.cpp +++ b/test/test_repl_str.cpp @@ -85,7 +85,7 @@ TEST(test_repl_str, nominal) { for (size_t i = 0; i < 1048576; ++i) { ss << "f"; } - char * out = rcutils_repl_str(ss.str().c_str(), "f", "longer replacementment", &allocator); + char * out = rcutils_repl_str(ss.str().c_str(), "f", "longer replacement", &allocator); EXPECT_NE(nullptr, out); allocator.deallocate(out, allocator.state); } diff --git a/test/test_shared_library.cpp b/test/test_shared_library.cpp index d14a914e..73c2d8f0 100644 --- a/test/test_shared_library.cpp +++ b/test/test_shared_library.cpp @@ -46,6 +46,8 @@ TEST_F(TestSharedLibrary, basic_load) { EXPECT_TRUE(lib.lib_pointer == NULL); EXPECT_FALSE(rcutils_is_shared_library_loaded(&lib)); + // Check debug name works first because rcutils_load_shared_library should be called on + // non-debug symbol name ret = rcutils_get_platform_library_name("dummy_shared_library", library_path, 1024, true); ASSERT_EQ(RCUTILS_RET_OK, ret); diff --git a/test/test_strerror.cpp b/test/test_strerror.cpp index 8701f89d..eeeb5a05 100644 --- a/test/test_strerror.cpp +++ b/test/test_strerror.cpp @@ -49,6 +49,8 @@ TEST(test_strerror, get_error) { // Hopefully this does not become a valid errno. errno = 12345; rcutils_strerror(error_string, sizeof(error_string)); - ASSERT_STREQ(error_string, "Failed to get error"); + ASSERT_STREQ(error_string, "Failed to get error") << + "Calling rcutils_strerror with an errno of '" << errno << + "' did not cause the expected error message."; #endif } From a23b9a0e65202d82a16ce640178ae516f3a1b86f Mon Sep 17 00:00:00 2001 From: Stephen Brawner Date: Wed, 3 Jun 2020 14:55:32 -0700 Subject: [PATCH 3/6] Rebasing and moving time_bomb_allocator into test directory Signed-off-by: Stephen Brawner --- CMakeLists.txt | 2 +- test/test_array_list.cpp | 2 +- test/test_hash_map.cpp | 2 +- test/test_process.cpp | 6 ++---- test/test_split.cpp | 2 +- test/test_string_map.cpp | 5 ++++- .../time_bomb_allocator_testing_utils.h | 6 +++--- 7 files changed, 13 insertions(+), 12 deletions(-) rename {include/rcutils/testing_utils => test}/time_bomb_allocator_testing_utils.h (95%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 539ae6c7..39d82608 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -430,9 +430,9 @@ if(BUILD_TESTING) ENV RCUTILS_CONSOLE_OUTPUT_FORMAT="${_output_format}" RCUTILS_CONSOLE_STDOUT_LINE_BUFFERED=0 + RCUTILS_LOGGING_BUFFERED_STREAM=0 RCUTILS_LOGGING_USE_STDOUT=0 RCUTILS_COLORIZED_OUTPUT=0 - RCUTILS_LOGGING_BUFFERED_STREAM=0 ) if(TARGET test_logging_custom_env2) target_link_libraries(test_logging_custom_env2 ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools) diff --git a/test/test_array_list.cpp b/test/test_array_list.cpp index d6b1adf8..05f92b9d 100644 --- a/test/test_array_list.cpp +++ b/test/test_array_list.cpp @@ -17,7 +17,7 @@ #include #include "./allocator_testing_utils.h" -#include "rcutils/testing_utils/time_bomb_allocator_testing_utils.h" +#include "./time_bomb_allocator_testing_utils.h" #include "rcutils/allocator.h" #include "rcutils/error_handling.h" #include "rcutils/types/array_list.h" diff --git a/test/test_hash_map.cpp b/test/test_hash_map.cpp index 44a239eb..8f67c3d3 100644 --- a/test/test_hash_map.cpp +++ b/test/test_hash_map.cpp @@ -16,7 +16,7 @@ #include -#include "rcutils/testing_utils/time_bomb_allocator_testing_utils.h" +#include "./time_bomb_allocator_testing_utils.h" #include "rcutils/allocator.h" #include "rcutils/error_handling.h" #include "rcutils/types/hash_map.h" diff --git a/test/test_process.cpp b/test/test_process.cpp index 24a026bf..cbec8352 100644 --- a/test/test_process.cpp +++ b/test/test_process.cpp @@ -15,10 +15,10 @@ #include #include "./allocator_testing_utils.h" +#include "./time_bomb_allocator_testing_utils.h" #include "rcutils/allocator.h" #include "rcutils/error_handling.h" #include "rcutils/process.h" -#include "rcutils/testing_utils/time_bomb_allocator_testing_utils.h" TEST(TestProcess, test_get_pid) { EXPECT_NE(rcutils_get_pid(), 0); @@ -32,12 +32,10 @@ TEST(TestProcess, test_get_executable_name) { set_time_bomb_allocator_malloc_count(time_bomb_allocator, 0); EXPECT_STREQ(NULL, rcutils_get_executable_name(time_bomb_allocator)); - // Allocating intermediate fails + // Allocating intermediate fails. This allocation doesn't happen on windows #if defined __APPLE__ || defined __FreeBSD__ || defined __GNUC__ set_time_bomb_allocator_malloc_count(time_bomb_allocator, 1); EXPECT_STREQ(NULL, rcutils_get_executable_name(time_bomb_allocator)); -#elif defined _WIN32 || defined __CYGWIN__ - // This allocation doesn't happen on windows #endif char * exec_name = rcutils_get_executable_name(allocator); diff --git a/test/test_split.cpp b/test/test_split.cpp index a27723f8..40bdfdeb 100644 --- a/test/test_split.cpp +++ b/test/test_split.cpp @@ -15,10 +15,10 @@ #include "gtest/gtest.h" #include "./allocator_testing_utils.h" +#include "./time_bomb_allocator_testing_utils.h" #include "rcutils/error_handling.h" #include "rcutils/split.h" #include "rcutils/types/string_array.h" -#include "rcutils/testing_utils/time_bomb_allocator_testing_utils.h" #define ENABLE_LOGGING 1 diff --git a/test/test_string_map.cpp b/test/test_string_map.cpp index 33eb2edf..a2034de5 100644 --- a/test/test_string_map.cpp +++ b/test/test_string_map.cpp @@ -1091,8 +1091,11 @@ TEST(test_string_map, set) { rcutils_reset_error(); }); - set_failing_allocator_is_failing(failing_allocator, true); ret = rcutils_string_map_set(&string_map, "key1", "value1"); + ASSERT_EQ(RCUTILS_RET_OK, ret) << rcutils_get_error_string().str; + + set_failing_allocator_is_failing(failing_allocator, true); + ret = rcutils_string_map_set(&string_map, "key1", "value2"); EXPECT_EQ(RCUTILS_RET_BAD_ALLOC, ret) << rcutils_get_error_string().str; rcutils_reset_error(); } diff --git a/include/rcutils/testing_utils/time_bomb_allocator_testing_utils.h b/test/time_bomb_allocator_testing_utils.h similarity index 95% rename from include/rcutils/testing_utils/time_bomb_allocator_testing_utils.h rename to test/time_bomb_allocator_testing_utils.h index ead59347..61d402cc 100644 --- a/include/rcutils/testing_utils/time_bomb_allocator_testing_utils.h +++ b/test/time_bomb_allocator_testing_utils.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef RCUTILS__TESTING_UTILS__TIME_BOMB_ALLOCATOR_TESTING_UTILS_H_ -#define RCUTILS__TESTING_UTILS__TIME_BOMB_ALLOCATOR_TESTING_UTILS_H_ +#ifndef TIME_BOMB_ALLOCATOR_TESTING_UTILS_H_ +#define TIME_BOMB_ALLOCATOR_TESTING_UTILS_H_ #ifdef __cplusplus extern "C" @@ -143,4 +143,4 @@ set_time_bomb_allocator_calloc_count(rcutils_allocator_t & time_bomb_allocator, } #endif -#endif // RCUTILS__TESTING_UTILS__TIME_BOMB_ALLOCATOR_TESTING_UTILS_H_ +#endif // TIME_BOMB_ALLOCATOR_TESTING_UTILS_H_ From 3b25d1f44074915cfff88cc11e6d382d1a190044 Mon Sep 17 00:00:00 2001 From: Stephen Brawner Date: Wed, 3 Jun 2020 17:23:40 -0700 Subject: [PATCH 4/6] PR Fixup Signed-off-by: Stephen Brawner --- test/test_get_env.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/test/test_get_env.cpp b/test/test_get_env.cpp index 561689aa..edb29ef4 100644 --- a/test/test_get_env.cpp +++ b/test/test_get_env.cpp @@ -50,15 +50,22 @@ TEST(TestGetEnv, test_get_env) { TEST(TestGetEnv, test_get_home) { EXPECT_STRNE(NULL, rcutils_get_home_dir()); - const char * home = NULL; - const char * ret = rcutils_get_env("HOME", &home); - EXPECT_EQ(NULL, ret); #ifdef _WIN32 + // Assert pre-condition that USERPROFILE is defined + const char * ret = rcutils_get_env("USERPROFILE", &home); + ASSERT_EQ(NULL, ret); + + // Check USERPROFILE is not defined EXPECT_TRUE(rcutils_set_env("USERPROFILE", NULL)); EXPECT_EQ(NULL, rcutils_get_home_dir()); #else + // Assert pre-condition that HOME is defined + const char * ret = rcutils_get_env("HOME", &home); + ASSERT_EQ(NULL, ret); + + // Check HOME is not defined EXPECT_TRUE(rcutils_set_env("HOME", NULL)); EXPECT_EQ(NULL, rcutils_get_home_dir()); #endif From 97abb9b1d849bb8adb5df4297410fa11a9008b49 Mon Sep 17 00:00:00 2001 From: Stephen Brawner Date: Wed, 3 Jun 2020 17:50:03 -0700 Subject: [PATCH 5/6] Memory leak Signed-off-by: Stephen Brawner --- test/test_string_array.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_string_array.cpp b/test/test_string_array.cpp index 176a363a..7bbdbcc6 100644 --- a/test/test_string_array.cpp +++ b/test/test_string_array.cpp @@ -69,6 +69,7 @@ TEST(test_string_array, boot_string_array) { rcutils_string_array_t sa4 = rcutils_get_zero_initialized_string_array(); ASSERT_EQ(RCUTILS_RET_OK, rcutils_string_array_init(&sa4, 0, &allocator)); ASSERT_EQ(0u, sa4.size); + ASSERT_EQ(RCUTILS_RET_OK, rcutils_string_array_fini(&sa4)); } TEST(test_string_array, string_array_cmp) { From 8b216743f9085639369be59e9788983a25758024 Mon Sep 17 00:00:00 2001 From: Stephen Brawner Date: Wed, 3 Jun 2020 17:59:58 -0700 Subject: [PATCH 6/6] Other mem leak Signed-off-by: Stephen Brawner --- test/test_shared_library.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/test_shared_library.cpp b/test/test_shared_library.cpp index 73c2d8f0..ca1b203a 100644 --- a/test/test_shared_library.cpp +++ b/test/test_shared_library.cpp @@ -158,6 +158,10 @@ TEST_F(TestSharedLibrary, error_symbol) { ASSERT_EQ(RCUTILS_RET_OK, ret); is_symbol = rcutils_has_symbol(&lib, "symbol"); EXPECT_FALSE(is_symbol); + + // unload shared_library + ret = rcutils_unload_shared_library(&lib); + ASSERT_EQ(RCUTILS_RET_OK, ret); } TEST_F(TestSharedLibrary, basic_symbol) {