diff --git a/rcl/test/CMakeLists.txt b/rcl/test/CMakeLists.txt index fcc4eafab..21d47f8d5 100644 --- a/rcl/test/CMakeLists.txt +++ b/rcl/test/CMakeLists.txt @@ -158,7 +158,7 @@ function(test_target_function) SRCS rcl/test_init.cpp ENV ${rmw_implementation_env_var} ${memory_tools_ld_preload_env_var} APPEND_LIBRARY_DIRS ${extra_lib_dirs} - LIBRARIES ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools + LIBRARIES ${PROJECT_NAME} mimick osrf_testing_tools_cpp::memory_tools AMENT_DEPENDENCIES ${rmw_implementation} ) @@ -288,7 +288,7 @@ function(test_target_function) SRCS rcl/test_rmw_impl_id_check_func.cpp ENV ${rmw_implementation_env_var} APPEND_LIBRARY_DIRS ${extra_lib_dirs} - LIBRARIES ${PROJECT_NAME} + LIBRARIES ${PROJECT_NAME} mimick AMENT_DEPENDENCIES ${rmw_implementation} ) @@ -361,7 +361,7 @@ rcl_add_custom_gtest(test_validate_enclave_name rcl_add_custom_gtest(test_domain_id SRCS rcl/test_domain_id.cpp APPEND_LIBRARY_DIRS ${extra_lib_dirs} - LIBRARIES ${PROJECT_NAME} + LIBRARIES ${PROJECT_NAME} mimick ) rcl_add_custom_gtest(test_localhost @@ -399,7 +399,7 @@ rcl_add_custom_gtest(test_common rcl_add_custom_gtest(test_log_level SRCS rcl/test_log_level.cpp APPEND_LIBRARY_DIRS ${extra_lib_dirs} - LIBRARIES ${PROJECT_NAME} + LIBRARIES ${PROJECT_NAME} mimick AMENT_DEPENDENCIES "osrf_testing_tools_cpp" ) diff --git a/rcl/test/rcl/test_domain_id.cpp b/rcl/test/rcl/test_domain_id.cpp index b5d4616bc..55a0413a5 100644 --- a/rcl/test/rcl/test_domain_id.cpp +++ b/rcl/test/rcl/test_domain_id.cpp @@ -20,6 +20,8 @@ #include "rcl/error_handling.h" #include "rcutils/env.h" +#include "../mocking_utils/patch.hpp" + TEST(TestGetDomainId, test_nominal) { ASSERT_TRUE(rcutils_set_env("ROS_DOMAIN_ID", "42")); size_t domain_id = RCL_DEFAULT_DOMAIN_ID; @@ -50,3 +52,13 @@ TEST(TestGetDomainId, test_nominal) { EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, rcl_get_default_domain_id(nullptr)); } + +TEST(TestGetDomainId, test_mock_get_default_domain_id) { + auto mock = mocking_utils::patch_and_return( + "lib:rcl", rcutils_get_env, "argument env_name is null"); + size_t domain_id = RCL_DEFAULT_DOMAIN_ID; + EXPECT_EQ(RCL_RET_ERROR, rcl_get_default_domain_id(&domain_id)); + EXPECT_EQ(RCL_DEFAULT_DOMAIN_ID, domain_id); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); +} diff --git a/rcl/test/rcl/test_init.cpp b/rcl/test/rcl/test_init.cpp index efcddd7cc..1586e3285 100644 --- a/rcl/test/rcl/test_init.cpp +++ b/rcl/test/rcl/test_init.cpp @@ -25,6 +25,7 @@ #include "rcutils/snprintf.h" #include "./allocator_testing_utils.h" +#include "../mocking_utils/patch.hpp" #include "../src/rcl/init_options_impl.h" #ifdef RMW_IMPLEMENTATION @@ -104,16 +105,34 @@ struct FakeTestArgv */ TEST_F(CLASSNAME(TestRCLFixture, RMW_IMPLEMENTATION), test_rcl_init_options_init) { rcl_init_options_t init_options = rcl_get_zero_initialized_init_options(); - rcl_ret_t ret = rcl_init_options_init(&init_options, rcl_get_default_allocator()); + + // fini a not empty options + rcl_ret_t ret = rcl_init_options_fini(&init_options); + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str; + rcl_reset_error(); + + // Expected usage + ret = rcl_init_options_init(&init_options, rcl_get_default_allocator()); ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( { EXPECT_EQ(RCL_RET_OK, rcl_init_options_fini(&init_options)) << rcl_get_error_string().str; }); + // Already init ret = rcl_init_options_init(&init_options, rcl_get_default_allocator()); EXPECT_EQ(RCL_RET_ALREADY_INIT, ret) << rcl_get_error_string().str; rcl_reset_error(); + + // nullptr + ret = rcl_init_options_init(nullptr, rcl_get_default_allocator()); + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str; + rcl_reset_error(); + + // nullptr + ret = rcl_init_options_fini(nullptr); + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str; + rcl_reset_error(); } /* Tests calling rcl_init() with invalid arguments fails. @@ -364,6 +383,7 @@ TEST_F(CLASSNAME(TestRCLFixture, RMW_IMPLEMENTATION), test_rcl_get_instance_id) TEST_F(CLASSNAME(TestRCLFixture, RMW_IMPLEMENTATION), test_rcl_init_options_access) { rcl_init_options_t init_options = rcl_get_zero_initialized_init_options(); + rcl_init_options_t not_ini_init_options = rcl_get_zero_initialized_init_options(); rcl_ret_t ret = rcl_init_options_init(&init_options, rcl_get_default_allocator()); ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( @@ -375,14 +395,21 @@ TEST_F(CLASSNAME(TestRCLFixture, RMW_IMPLEMENTATION), test_rcl_init_options_acce ASSERT_NE(nullptr, options); EXPECT_EQ(0u, options->instance_id); EXPECT_EQ(nullptr, options->impl); + EXPECT_EQ(NULL, rcl_init_options_get_rmw_init_options(nullptr)); + EXPECT_EQ(NULL, rcl_init_options_get_rmw_init_options(¬_ini_init_options)); const rcl_allocator_t * options_allocator = rcl_init_options_get_allocator(&init_options); EXPECT_TRUE(rcutils_allocator_is_valid(options_allocator)); + EXPECT_EQ(NULL, rcl_init_options_get_allocator(nullptr)); + EXPECT_EQ(NULL, rcl_init_options_get_allocator(¬_ini_init_options)); size_t domain_id; ret = rcl_init_options_get_domain_id(NULL, &domain_id); ASSERT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str; rcl_reset_error(); + ret = rcl_init_options_get_domain_id(¬_ini_init_options, &domain_id); + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str; + rcl_reset_error(); ret = rcl_init_options_get_domain_id(&init_options, NULL); ASSERT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str; rcl_reset_error(); @@ -392,6 +419,9 @@ TEST_F(CLASSNAME(TestRCLFixture, RMW_IMPLEMENTATION), test_rcl_init_options_acce ret = rcl_init_options_set_domain_id(NULL, domain_id); ASSERT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str; rcl_reset_error(); + ret = rcl_init_options_set_domain_id(¬_ini_init_options, domain_id); + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, ret) << rcl_get_error_string().str; + rcl_reset_error(); ret = rcl_init_options_get_domain_id(&init_options, &domain_id); ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; @@ -403,6 +433,14 @@ TEST_F(CLASSNAME(TestRCLFixture, RMW_IMPLEMENTATION), test_rcl_init_options_acce EXPECT_EQ(0U, domain_id); rcl_init_options_t init_options_dst = rcl_get_zero_initialized_init_options(); + + // nullptr copy cases + EXPECT_EQ( + RCL_RET_INVALID_ARGUMENT, rcl_init_options_copy(nullptr, &init_options_dst)); + EXPECT_EQ( + RCL_RET_INVALID_ARGUMENT, rcl_init_options_copy(&init_options, nullptr)); + + // Expected usage copy ASSERT_EQ(RCL_RET_OK, rcl_init_options_copy(&init_options, &init_options_dst)); ret = rcl_init_options_get_domain_id(&init_options_dst, &domain_id); ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; @@ -410,3 +448,67 @@ TEST_F(CLASSNAME(TestRCLFixture, RMW_IMPLEMENTATION), test_rcl_init_options_acce EXPECT_EQ(RCL_RET_ALREADY_INIT, rcl_init_options_copy(&init_options, &init_options_dst)); EXPECT_EQ(RCL_RET_OK, rcl_init_options_fini(&init_options_dst)); } + +// Define dummy comparison operators for rcutils_allocator_t type for use with the Mimick Library +MOCKING_UTILS_BOOL_OPERATOR_RETURNS_FALSE(rcutils_allocator_t, ==) +MOCKING_UTILS_BOOL_OPERATOR_RETURNS_FALSE(rcutils_allocator_t, <) +MOCKING_UTILS_BOOL_OPERATOR_RETURNS_FALSE(rcutils_allocator_t, >) +MOCKING_UTILS_BOOL_OPERATOR_RETURNS_FALSE(rcutils_allocator_t, !=) + +// Tests rcl_init_options_init() mocked to fail +TEST_F(CLASSNAME(TestRCLFixture, RMW_IMPLEMENTATION), test_mocked_rcl_init_options_ini) { + rcl_init_options_t init_options = rcl_get_zero_initialized_init_options(); + auto mock = mocking_utils::patch_and_return("lib:rcl", rmw_init_options_init, RMW_RET_ERROR); + EXPECT_EQ(RCL_RET_ERROR, rcl_init_options_init(&init_options, rcl_get_default_allocator())); + rcl_reset_error(); +} + +// Tests rcl_init_options_fini() mocked to fail +TEST_F(CLASSNAME(TestRCLFixture, RMW_IMPLEMENTATION), test_mocked_rcl_init_options_fini) { + rcl_init_options_t init_options = rcl_get_zero_initialized_init_options(); + rcl_ret_t ret = rcl_init_options_init(&init_options, rcl_get_default_allocator()); + ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; + auto mock = mocking_utils::inject_on_return("lib:rcl", rmw_init_options_fini, RMW_RET_ERROR); + EXPECT_EQ(RCL_RET_ERROR, rcl_init_options_fini(&init_options)); + rcl_reset_error(); +} + +// Mock rcl_init_options_copy to fail +TEST_F(CLASSNAME(TestRCLFixture, RMW_IMPLEMENTATION), test_rcl_init_copy_mocked_fail_fini) { + rcl_init_options_t init_options = rcl_get_zero_initialized_init_options(); + rcl_ret_t ret = rcl_init_options_init(&init_options, rcl_get_default_allocator()); + ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + EXPECT_EQ(RCL_RET_OK, rcl_init_options_fini(&init_options)) << rcl_get_error_string().str; + }); + rcl_init_options_t init_options_dst = rcl_get_zero_initialized_init_options(); + auto mock = mocking_utils::inject_on_return("lib:rcl", rmw_init_options_fini, RMW_RET_ERROR); + EXPECT_EQ(RCL_RET_ERROR, rcl_init_options_copy(&init_options, &init_options_dst)); + rcl_reset_error(); +} + +// Mock rcl_init_options_copy to fail +TEST_F(CLASSNAME(TestRCLFixture, RMW_IMPLEMENTATION), test_rcl_init_options_copy_fail_rmw_copy) { + rcl_init_options_t init_options = rcl_get_zero_initialized_init_options(); + rcl_ret_t ret = rcl_init_options_init(&init_options, rcl_get_default_allocator()); + ASSERT_EQ(RCL_RET_OK, ret) << rcl_get_error_string().str; + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + EXPECT_EQ(RCL_RET_OK, rcl_init_options_fini(&init_options)) << rcl_get_error_string().str; + }); + rcl_init_options_t init_options_dst = rcl_get_zero_initialized_init_options(); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + // dst is in a invalid state after failed copy + EXPECT_EQ( + RCL_RET_INVALID_ARGUMENT, + rcl_init_options_fini(&init_options_dst)) << rcl_get_error_string().str; + rcl_reset_error(); + }); + + // rmw_init_options_copy error is logged + auto mock = mocking_utils::patch_and_return("lib:rcl", rmw_init_options_copy, RMW_RET_ERROR); + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, rcl_init_options_copy(&init_options, &init_options_dst)); + rcl_reset_error(); +} diff --git a/rcl/test/rcl/test_log_level.cpp b/rcl/test/rcl/test_log_level.cpp index cddd8bac4..fbbe51944 100644 --- a/rcl/test/rcl/test_log_level.cpp +++ b/rcl/test/rcl/test_log_level.cpp @@ -14,12 +14,15 @@ #include +#include "rcl/allocator.h" #include "rcl/rcl.h" #include "rcl/log_level.h" #include "rcl/error_handling.h" #include "rcutils/logging.h" #include "./arg_macros.hpp" +#include "./allocator_testing_utils.h" +#include "../mocking_utils/patch.hpp" int setup_and_parse_log_level_args(const char * log_level_string) { @@ -178,6 +181,24 @@ TEST(TestLogLevel, multiple_log_level_rightmost_prevail) { EXPECT_EQ(RCUTILS_LOG_SEVERITY_INFO, log_levels.logger_settings[0].level); } +TEST(TestLogLevel, multiple_log_level_names) { + rcl_log_levels_t log_levels = rcl_get_zero_initialized_log_levels(); + GET_LOG_LEVEL_FROM_ARGUMENTS( + log_levels, "process_name", "--ros-args", + "--log-level", "debug", "--log-level", "rcl:=debug", + "--log-level", "test:=info"); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + EXPECT_EQ(RCL_RET_OK, rcl_log_levels_fini(&log_levels)); + }); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_DEBUG, log_levels.default_logger_level); + EXPECT_EQ(2ul, log_levels.num_logger_settings); + EXPECT_STREQ("rcl", log_levels.logger_settings[0].name); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_DEBUG, log_levels.logger_settings[0].level); + EXPECT_STREQ("test", log_levels.logger_settings[1].name); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_INFO, log_levels.logger_settings[1].level); +} + TEST(TestLogLevel, log_level_dot_logger_name) { rcl_log_levels_t log_levels = rcl_get_zero_initialized_log_levels(); GET_LOG_LEVEL_FROM_ARGUMENTS( @@ -193,6 +214,183 @@ TEST(TestLogLevel, log_level_dot_logger_name) { EXPECT_EQ(RCUTILS_LOG_SEVERITY_INFO, log_levels.logger_settings[0].level); } +TEST(TestLogLevel, log_level_init_fini) { + rcl_log_levels_t log_levels = rcl_get_zero_initialized_log_levels(); + rcl_allocator_t allocator = rcl_get_default_allocator(); + + // Test zero size ini/fini + const size_t zero_count = 0; + EXPECT_EQ( + RCL_RET_OK, + rcl_log_levels_init(&log_levels, &allocator, zero_count)); + EXPECT_EQ(RCL_RET_OK, rcl_log_levels_fini(&log_levels)); + + const size_t capacity_count = 1; + EXPECT_EQ( + RCL_RET_OK, + rcl_log_levels_init(&log_levels, &allocator, capacity_count)); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + EXPECT_EQ(RCL_RET_OK, rcl_log_levels_fini(&log_levels)); + }); + + EXPECT_EQ( + RCL_RET_INVALID_ARGUMENT, + rcl_log_levels_init(nullptr, &allocator, capacity_count)); + EXPECT_EQ( + RCL_RET_INVALID_ARGUMENT, + rcl_log_levels_init(&log_levels, nullptr, capacity_count)); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + EXPECT_EQ( + RCL_RET_INVALID_ARGUMENT, + rcl_log_levels_init(&log_levels, &allocator, capacity_count)); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + + rcl_allocator_t bad_allocator = get_failing_allocator(); + rcl_log_levels_t empty_log_levels = rcl_get_zero_initialized_log_levels(); + EXPECT_EQ( + RCL_RET_BAD_ALLOC, rcl_log_levels_init(&empty_log_levels, &bad_allocator, capacity_count)); + + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, rcl_log_levels_fini(nullptr)); +} + +TEST(TestLogLevel, logger_log_level_copy) { + // Init to debug level to test before copy + rcl_log_levels_t log_levels = rcl_get_zero_initialized_log_levels(); + GET_LOG_LEVEL_FROM_ARGUMENTS( + log_levels, "process_name", "--ros-args", + "--log-level", "rcl:=debug"); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + EXPECT_EQ(RCL_RET_OK, rcl_log_levels_fini(&log_levels)); + }); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_UNSET, log_levels.default_logger_level); + EXPECT_EQ(1ul, log_levels.num_logger_settings); + EXPECT_STREQ("rcl", log_levels.logger_settings[0].name); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_DEBUG, log_levels.logger_settings[0].level); + + // Expected usage + rcl_log_levels_t copied_log_levels = rcl_get_zero_initialized_log_levels(); + EXPECT_EQ(RCL_RET_OK, rcl_log_levels_copy(&log_levels, &copied_log_levels)); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_UNSET, copied_log_levels.default_logger_level); + EXPECT_EQ(log_levels.default_logger_level, copied_log_levels.default_logger_level); + EXPECT_EQ(1ul, copied_log_levels.num_logger_settings); + EXPECT_EQ(log_levels.num_logger_settings, copied_log_levels.num_logger_settings); + EXPECT_STREQ("rcl", copied_log_levels.logger_settings[0].name); + EXPECT_STREQ(log_levels.logger_settings[0].name, copied_log_levels.logger_settings[0].name); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_DEBUG, copied_log_levels.logger_settings[0].level); + EXPECT_EQ(log_levels.logger_settings[0].level, copied_log_levels.logger_settings[0].level); + + // Bad usage + rcl_log_levels_t empty_log_levels = rcl_get_zero_initialized_log_levels(); + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, rcl_log_levels_copy(nullptr, &empty_log_levels)); + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, rcl_log_levels_copy(&log_levels, nullptr)); + // Already copied + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, rcl_log_levels_copy(&log_levels, &copied_log_levels)); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + + // null alloc + rcl_allocator_t saved_allocator = log_levels.allocator; + log_levels.allocator = {NULL, NULL, NULL, NULL, NULL}; + EXPECT_EQ(RCL_RET_INVALID_ARGUMENT, rcl_log_levels_copy(&log_levels, &empty_log_levels)); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + + // bad allocation + rcl_allocator_t bad_allocator = get_failing_allocator(); + log_levels.allocator = bad_allocator; + EXPECT_EQ(RCL_RET_BAD_ALLOC, rcl_log_levels_copy(&log_levels, &empty_log_levels)); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + + log_levels.allocator = saved_allocator; +} + +TEST(TestLogLevel, test_add_logger_setting) { + rcl_log_levels_t log_levels = rcl_get_zero_initialized_log_levels(); + rcl_allocator_t allocator = rcl_get_default_allocator(); + size_t logger_count = 2u; + EXPECT_EQ( + RCL_RET_OK, rcl_log_levels_init(&log_levels, &allocator, logger_count)); + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + EXPECT_EQ(RCL_RET_OK, rcl_log_levels_fini(&log_levels)); + }); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_UNSET, log_levels.default_logger_level); + EXPECT_EQ(0ul, log_levels.num_logger_settings); + + // Invalid arguments + EXPECT_EQ( + RCL_RET_INVALID_ARGUMENT, + rcl_log_levels_add_logger_setting(nullptr, "rcl", RCUTILS_LOG_SEVERITY_DEBUG)); + + rcl_log_levels_t not_ini_log_levels = rcl_get_zero_initialized_log_levels(); + EXPECT_EQ( + RCL_RET_INVALID_ARGUMENT, + rcl_log_levels_add_logger_setting(¬_ini_log_levels, "rcl", RCUTILS_LOG_SEVERITY_DEBUG)); + + EXPECT_EQ( + RCL_RET_INVALID_ARGUMENT, + rcl_log_levels_add_logger_setting(&log_levels, nullptr, RCUTILS_LOG_SEVERITY_DEBUG)); + + rcl_allocator_t saved_allocator = log_levels.allocator; + log_levels.allocator = {NULL, NULL, NULL, NULL, NULL}; + EXPECT_EQ( + RCL_RET_INVALID_ARGUMENT, + rcl_log_levels_add_logger_setting(&log_levels, "rcl", RCUTILS_LOG_SEVERITY_DEBUG)); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + + rcl_allocator_t bad_allocator = get_failing_allocator(); + log_levels.allocator = bad_allocator; + EXPECT_EQ( + RCL_RET_BAD_ALLOC, + rcl_log_levels_add_logger_setting(&log_levels, "rcl", RCUTILS_LOG_SEVERITY_DEBUG)); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + log_levels.allocator = saved_allocator; + + // Expected usage + EXPECT_EQ( + RCL_RET_OK, rcl_log_levels_add_logger_setting(&log_levels, "rcl", RCUTILS_LOG_SEVERITY_DEBUG)); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_UNSET, log_levels.default_logger_level); + EXPECT_EQ(1ul, log_levels.num_logger_settings); + EXPECT_STREQ("rcl", log_levels.logger_settings[0].name); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_DEBUG, log_levels.logger_settings[0].level); + + EXPECT_EQ( + RCL_RET_OK, + rcl_log_levels_add_logger_setting(&log_levels, "rcutils", RCUTILS_LOG_SEVERITY_INFO)); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_UNSET, log_levels.default_logger_level); + EXPECT_EQ(2ul, log_levels.num_logger_settings); + EXPECT_STREQ("rcl", log_levels.logger_settings[0].name); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_DEBUG, log_levels.logger_settings[0].level); + EXPECT_STREQ("rcutils", log_levels.logger_settings[1].name); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_INFO, log_levels.logger_settings[1].level); + + // Can't add more than logger_count + EXPECT_EQ( + RCL_RET_ERROR, + rcl_log_levels_add_logger_setting(&log_levels, "rmw", RCUTILS_LOG_SEVERITY_DEBUG)); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + EXPECT_EQ(2ul, log_levels.num_logger_settings); + + // Replacing saved logger + EXPECT_EQ( + RCL_RET_OK, + rcl_log_levels_add_logger_setting(&log_levels, "rcl", RCUTILS_LOG_SEVERITY_INFO)); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_UNSET, log_levels.default_logger_level); + EXPECT_EQ(2ul, log_levels.num_logger_settings); + EXPECT_STREQ("rcl", log_levels.logger_settings[0].name); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_INFO, log_levels.logger_settings[0].level); + EXPECT_STREQ("rcutils", log_levels.logger_settings[1].name); + EXPECT_EQ(RCUTILS_LOG_SEVERITY_INFO, log_levels.logger_settings[1].level); +} + int main(int argc, char ** argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/rcl/test/rcl/test_rmw_impl_id_check_func.cpp b/rcl/test/rcl/test_rmw_impl_id_check_func.cpp index 64da8c35c..7d576f3d7 100644 --- a/rcl/test/rcl/test_rmw_impl_id_check_func.cpp +++ b/rcl/test/rcl/test_rmw_impl_id_check_func.cpp @@ -15,11 +15,15 @@ #include #include "rcutils/env.h" +#include "rcutils/strdup.h" +#include "rcl/allocator.h" #include "rcl/error_handling.h" #include "rcl/rcl.h" #include "rcl/rmw_implementation_identifier_check.h" +#include "../mocking_utils/patch.hpp" + TEST(TestRmwCheck, test_rmw_check_id_impl) { EXPECT_EQ(RCL_RET_OK, rcl_rmw_implementation_identifier_check()); } @@ -70,3 +74,81 @@ TEST(TestRmwCheck, test_failing_configuration) { EXPECT_TRUE(rcutils_set_env(RMW_IMPLEMENTATION_ENV_VAR_NAME, expected_rmw_impl_env)); EXPECT_TRUE(rcutils_set_env(RCL_ASSERT_RMW_ID_MATCHES_ENV_VAR_NAME, expected_rmw_id_matches)); } + +// Define dummy comparison operators for rcutils_allocator_t type for use with the Mimick Library +MOCKING_UTILS_BOOL_OPERATOR_RETURNS_FALSE(rcutils_allocator_t, ==) +MOCKING_UTILS_BOOL_OPERATOR_RETURNS_FALSE(rcutils_allocator_t, <) +MOCKING_UTILS_BOOL_OPERATOR_RETURNS_FALSE(rcutils_allocator_t, >) +MOCKING_UTILS_BOOL_OPERATOR_RETURNS_FALSE(rcutils_allocator_t, !=) + +// Mock internal calls to external libraries to fail +TEST(TestRmwCheck, test_mock_rmw_impl_check) { + { + // Fail reading RMW_IMPLEMENTATION_ENV_VAR_NAME + auto mock = mocking_utils::patch_and_return( + "lib:rcl", rcutils_get_env, "invalid arg"); + EXPECT_EQ(RCL_RET_ERROR, rcl_rmw_implementation_identifier_check()); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + } + { + // Fail copying RMW_IMPLEMENTATION_ENV_VAR_NAME env result + auto mock = mocking_utils::patch_and_return( + "lib:rcl", rcutils_strdup, static_cast(NULL)); + EXPECT_EQ(RCL_RET_BAD_ALLOC, rcl_rmw_implementation_identifier_check()); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + } + { + // Fail reading RCL_ASSERT_RMW_ID_MATCHES_ENV_VAR_NAME + auto mock = mocking_utils::patch( + "lib:rcl", rcutils_get_env, [](auto, const char ** env_value) { + static int counter = 1; + *env_value = ""; + if (counter == 1) { + counter++; + return static_cast(NULL); + } else { + return "argument env_value is null"; + } + }); + EXPECT_EQ(RCL_RET_ERROR, rcl_rmw_implementation_identifier_check()); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + } + { + // Fail copying RCL_ASSERT_RMW_ID_MATCHES_ENV_VAR_NAME env result + // Set the variable, as is not set by default + const char * expected_rmw_id_matches = NULL; + const char * get_env_id_matches_name = rcutils_get_env( + RCL_ASSERT_RMW_ID_MATCHES_ENV_VAR_NAME, + &expected_rmw_id_matches); + EXPECT_EQ(NULL, get_env_id_matches_name); + EXPECT_TRUE(rcutils_set_env(RCL_ASSERT_RMW_ID_MATCHES_ENV_VAR_NAME, "some_random_name")); + + auto mock = mocking_utils::patch( + "lib:rcl", rcutils_strdup, + [base = rcutils_strdup](const char * str, auto allocator) + { + static int counter = 1; + if (counter == 1) { + counter++; + return base(str, allocator); + } else { + return static_cast(NULL); + } + }); + EXPECT_EQ(RCL_RET_BAD_ALLOC, rcl_rmw_implementation_identifier_check()); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + EXPECT_TRUE(rcutils_set_env(RCL_ASSERT_RMW_ID_MATCHES_ENV_VAR_NAME, expected_rmw_id_matches)); + } + { + // Fail reading rmw_impl_identifier + auto mock = mocking_utils::patch_and_return( + "lib:rcl", rmw_get_implementation_identifier, static_cast(NULL)); + EXPECT_EQ(RCL_RET_ERROR, rcl_rmw_implementation_identifier_check()); + EXPECT_TRUE(rcl_error_is_set()); + rcl_reset_error(); + } +}