From 821183515fe845d090a8674758bedc5442982432 Mon Sep 17 00:00:00 2001 From: Michel Hidalgo Date: Fri, 25 Sep 2020 13:38:16 -0300 Subject: [PATCH] Add fault injection tests to all construction/destruction APIs. Signed-off-by: Michel Hidalgo --- test_rmw_implementation/CMakeLists.txt | 2 +- test_rmw_implementation/test/test_client.cpp | 38 +++++++++ .../test/test_create_destroy_node.cpp | 41 +++++++++ .../test/test_init_shutdown.cpp | 64 ++++++++++++++ .../test/test_publisher.cpp | 84 +++++++++++++++++++ test_rmw_implementation/test/test_service.cpp | 39 +++++++++ .../test/test_subscription.cpp | 43 ++++++++++ .../test/testing_macros.hpp | 5 ++ 8 files changed, 315 insertions(+), 1 deletion(-) diff --git a/test_rmw_implementation/CMakeLists.txt b/test_rmw_implementation/CMakeLists.txt index f522863c..88272252 100644 --- a/test_rmw_implementation/CMakeLists.txt +++ b/test_rmw_implementation/CMakeLists.txt @@ -72,7 +72,7 @@ if(BUILD_TESTING) ament_add_gtest(test_subscription${target_suffix} test/test_subscription.cpp ENV ${rmw_implementation_env_var} - TIMEOUT 80 + TIMEOUT 120 ) target_compile_definitions(test_subscription${target_suffix} PUBLIC "RMW_IMPLEMENTATION=${rmw_implementation}") diff --git a/test_rmw_implementation/test/test_client.cpp b/test_rmw_implementation/test/test_client.cpp index ce31149d..642b1460 100644 --- a/test_rmw_implementation/test/test_client.cpp +++ b/test_rmw_implementation/test/test_client.cpp @@ -149,6 +149,44 @@ TEST_F(CLASSNAME(TestClient, RMW_IMPLEMENTATION), create_with_bad_arguments) { EXPECT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; } +TEST_F(CLASSNAME(TestClient, RMW_IMPLEMENTATION), create_with_internal_errors) { + constexpr char service_name[] = "/test"; + const rosidl_service_type_support_t * ts = + ROSIDL_GET_SRV_TYPE_SUPPORT(test_msgs, srv, BasicTypes); + RCUTILS_FAULT_INJECTION_TEST( + { + rmw_client_t * client = + rmw_create_client(node, ts, service_name, &rmw_qos_profile_default); + if (client) { + int64_t count = rcutils_fault_injection_get_count(); + rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); + rmw_ret_t ret = rmw_destroy_client(node, client); + EXPECT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; + rcutils_fault_injection_set_count(count); + } else { + rmw_reset_error(); + } + }); +} + +TEST_F(CLASSNAME(TestClient, RMW_IMPLEMENTATION), destroy_with_internal_errors) { + constexpr char service_name[] = "/test"; + const rosidl_service_type_support_t * ts = + ROSIDL_GET_SRV_TYPE_SUPPORT(test_msgs, srv, BasicTypes); + RCUTILS_FAULT_INJECTION_TEST( + { + int64_t count = rcutils_fault_injection_get_count(); + rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); + rmw_client_t * client = + rmw_create_client(node, ts, service_name, &rmw_qos_profile_default); + ASSERT_NE(nullptr, client) << rmw_get_error_string().str; + rcutils_fault_injection_set_count(count); + if (RMW_RET_OK != rmw_destroy_client(node, client)) { + rmw_reset_error(); + } + }); +} + class CLASSNAME (TestClientUse, RMW_IMPLEMENTATION) : public CLASSNAME(TestClient, RMW_IMPLEMENTATION) { diff --git a/test_rmw_implementation/test/test_create_destroy_node.cpp b/test_rmw_implementation/test/test_create_destroy_node.cpp index 0f1e5de9..29e79628 100644 --- a/test_rmw_implementation/test/test_create_destroy_node.cpp +++ b/test_rmw_implementation/test/test_create_destroy_node.cpp @@ -14,12 +14,16 @@ #include +#include "osrf_testing_tools_cpp/memory_tools/memory_tools.hpp" + #include "rcutils/allocator.h" #include "rcutils/strdup.h" #include "rmw/error_handling.h" #include "rmw/rmw.h" +#include "./testing_macros.hpp" + #ifdef RMW_IMPLEMENTATION # define CLASSNAME_(NAME, SUFFIX) NAME ## __ ## SUFFIX @@ -131,3 +135,40 @@ TEST_F(CLASSNAME(TestNodeConstructionDestruction, RMW_IMPLEMENTATION), create_an ASSERT_NE(nullptr, node) << rmw_get_error_string().str; EXPECT_EQ(RMW_RET_OK, rmw_destroy_node(node)) << rmw_get_error_string().str; } + +TEST_F( + CLASSNAME(TestNodeConstructionDestruction, RMW_IMPLEMENTATION), + create_with_internal_errors) { + RCUTILS_FAULT_INJECTION_TEST( + { + constexpr char node_name[] = "my_node"; + constexpr char node_namespace[] = "/my_ns"; + rmw_node_t * node = rmw_create_node(&context, node_name, node_namespace); + if (node) { + int64_t count = rcutils_fault_injection_get_count(); + rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); + EXPECT_EQ(RMW_RET_OK, rmw_destroy_node(node)) << rmw_get_error_string().str; + rcutils_fault_injection_set_count(count); + } else { + rmw_reset_error(); + } + }); +} + +TEST_F( + CLASSNAME(TestNodeConstructionDestruction, RMW_IMPLEMENTATION), + destroy_with_internal_errors) { + RCUTILS_FAULT_INJECTION_TEST( + { + constexpr char node_name[] = "my_node"; + constexpr char node_namespace[] = "/my_ns"; + int64_t count = rcutils_fault_injection_get_count(); + rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); + rmw_node_t * node = rmw_create_node(&context, node_name, node_namespace); + ASSERT_NE(nullptr, node) << rmw_get_error_string().str; + rcutils_fault_injection_set_count(count); + if (RMW_RET_OK != rmw_destroy_node(node)) { + rmw_reset_error(); + } + }); +} diff --git a/test_rmw_implementation/test/test_init_shutdown.cpp b/test_rmw_implementation/test/test_init_shutdown.cpp index e7bb0d2c..267eb93b 100644 --- a/test_rmw_implementation/test/test_init_shutdown.cpp +++ b/test_rmw_implementation/test/test_init_shutdown.cpp @@ -14,12 +14,18 @@ #include +#include "osrf_testing_tools_cpp/memory_tools/memory_tools.hpp" + #include "rcutils/allocator.h" #include "rcutils/error_handling.h" +#include "rcutils/macros.h" #include "rcutils/strdup.h" +#include "rmw/error_handling.h" #include "rmw/rmw.h" +#include "./testing_macros.hpp" + #ifdef RMW_IMPLEMENTATION # define CLASSNAME_(NAME, SUFFIX) NAME ## __ ## SUFFIX # define CLASSNAME(NAME, SUFFIX) CLASSNAME_(NAME, SUFFIX) @@ -170,3 +176,61 @@ TEST_F(CLASSNAME(TestInitShutdown, RMW_IMPLEMENTATION), init_shutdown) { ret = rmw_context_fini(&context); EXPECT_EQ(RMW_RET_OK, ret) << rcutils_get_error_string().str; } + +TEST_F(CLASSNAME(TestInitShutdown, RMW_IMPLEMENTATION), init_with_internal_errors) { + RCUTILS_FAULT_INJECTION_TEST( + { + rmw_context_t context = rmw_get_zero_initialized_context(); + rmw_ret_t ret = rmw_init(&options, &context); + + int64_t count = rcutils_fault_injection_get_count(); + rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); + if (RMW_RET_OK == ret) { + EXPECT_EQ(RMW_RET_OK, rmw_shutdown(&context)) << rmw_get_error_string().str; + EXPECT_EQ(RMW_RET_OK, rmw_context_fini(&context)) << rmw_get_error_string().str; + } else { + rmw_reset_error(); + } + rcutils_fault_injection_set_count(count); + }); +} + +TEST_F(CLASSNAME(TestInitShutdown, RMW_IMPLEMENTATION), shutdown_with_internal_errors) { + RCUTILS_FAULT_INJECTION_TEST( + { + rmw_context_t context = rmw_get_zero_initialized_context(); + + int64_t count = rcutils_fault_injection_get_count(); + rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); + ASSERT_EQ(RMW_RET_OK, rmw_init(&options, &context)) << rmw_get_error_string().str; + rcutils_fault_injection_set_count(count); + + rmw_ret_t ret = rmw_shutdown(&context); + + count = rcutils_fault_injection_get_count(); + rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); + if (RMW_RET_OK != ret) { + rmw_reset_error(); + + EXPECT_EQ(RMW_RET_OK, rmw_shutdown(&context)) << rmw_get_error_string().str; + } + EXPECT_EQ(RMW_RET_OK, rmw_context_fini(&context)) << rmw_get_error_string().str; + rcutils_fault_injection_set_count(count); + }); +} + +TEST_F(CLASSNAME(TestInitShutdown, RMW_IMPLEMENTATION), context_fini_with_internal_errors) { + RCUTILS_FAULT_INJECTION_TEST( + { + rmw_context_t context = rmw_get_zero_initialized_context(); + int64_t count = rcutils_fault_injection_get_count(); + rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); + EXPECT_EQ(RMW_RET_OK, rmw_init(&options, &context)) << rmw_get_error_string().str; + EXPECT_EQ(RMW_RET_OK, rmw_shutdown(&context)) << rmw_get_error_string().str; + rcutils_fault_injection_set_count(count); + + if (RMW_RET_OK != rmw_context_fini(&context)) { + rmw_reset_error(); + } + }); +} diff --git a/test_rmw_implementation/test/test_publisher.cpp b/test_rmw_implementation/test/test_publisher.cpp index 62dfbde5..928744dd 100644 --- a/test_rmw_implementation/test/test_publisher.cpp +++ b/test_rmw_implementation/test/test_publisher.cpp @@ -15,8 +15,10 @@ #include #include "osrf_testing_tools_cpp/memory_tools/gtest_quickstart.hpp" +#include "osrf_testing_tools_cpp/scope_exit.hpp" #include "rcutils/allocator.h" +#include "rcutils/macros.h" #include "rcutils/strdup.h" #include "rmw/rmw.h" @@ -82,6 +84,27 @@ TEST_F(CLASSNAME(TestPublisher, RMW_IMPLEMENTATION), create_and_destroy) { EXPECT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; } +TEST_F(CLASSNAME(TestPublisher, RMW_IMPLEMENTATION), create_with_internal_errors) { + constexpr char topic_name[] = "/test"; + const rosidl_message_type_support_t * ts = + ROSIDL_GET_MSG_TYPE_SUPPORT(test_msgs, msg, BasicTypes); + + RCUTILS_FAULT_INJECTION_TEST( + { + rmw_publisher_options_t options = rmw_get_default_publisher_options(); + rmw_publisher_t * pub = + rmw_create_publisher(node, ts, topic_name, &rmw_qos_profile_default, &options); + if (pub) { + int64_t count = rcutils_fault_injection_get_count(); + rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); + EXPECT_EQ(RMW_RET_OK, rmw_destroy_publisher(node, pub)) << rmw_get_error_string().str; + rcutils_fault_injection_set_count(count); + } else { + rmw_reset_error(); + } + }); +} + TEST_F(CLASSNAME(TestPublisher, RMW_IMPLEMENTATION), create_and_destroy_native) { rmw_publisher_options_t options = rmw_get_default_publisher_options(); constexpr char topic_name[] = "test"; @@ -185,6 +208,26 @@ TEST_F(CLASSNAME(TestPublisher, RMW_IMPLEMENTATION), destroy_with_bad_arguments) rmw_reset_error(); } +TEST_F(CLASSNAME(TestPublisher, RMW_IMPLEMENTATION), destroy_with_internal_errors) { + constexpr char topic_name[] = "/test"; + const rosidl_message_type_support_t * ts = + ROSIDL_GET_MSG_TYPE_SUPPORT(test_msgs, msg, BasicTypes); + + RCUTILS_FAULT_INJECTION_TEST( + { + int64_t count = rcutils_fault_injection_get_count(); + rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); + rmw_publisher_options_t options = rmw_get_default_publisher_options(); + rmw_publisher_t * pub = + rmw_create_publisher(node, ts, topic_name, &rmw_qos_profile_default, &options); + ASSERT_NE(nullptr, pub) << rmw_get_error_string().str; + rcutils_fault_injection_set_count(count); + if (RMW_RET_OK != rmw_destroy_publisher(node, pub)) { + rmw_reset_error(); + } + }); +} + TEST_F(CLASSNAME(TestPublisher, RMW_IMPLEMENTATION), get_actual_qos_from_system_defaults) { rmw_publisher_options_t options = rmw_get_default_publisher_options(); constexpr char topic_name[] = "/test"; @@ -405,6 +448,20 @@ TEST_F( test_msgs__msg__BasicTypes__fini(&input_message); } +TEST_F(CLASSNAME(TestPublisherUse, RMW_IMPLEMENTATION), publish_with_internal_errors) { + test_msgs__msg__BasicTypes message{}; + ASSERT_TRUE(test_msgs__msg__BasicTypes__init(&message)); + rmw_publisher_allocation_t * null_allocation{nullptr}; // still a valid allocation + + RCUTILS_FAULT_INJECTION_TEST( + { + rmw_ret_t ret = rmw_publish(pub, &message, null_allocation); + if (RMW_RET_OK != ret) { + rmw_reset_error(); + } + }); +} + TEST_F( CLASSNAME(TestPublisherUse, RMW_IMPLEMENTATION), publish_serialized_message_with_bad_arguments) { @@ -434,6 +491,33 @@ TEST_F( RMW_RET_OK, rmw_serialized_message_fini(&serialized_message)) << rmw_get_error_string().str; } +TEST_F(CLASSNAME(TestPublisherUse, RMW_IMPLEMENTATION), publish_serialized_with_internal_errors) { + test_msgs__msg__BasicTypes message{}; + ASSERT_TRUE(test_msgs__msg__BasicTypes__init(&message)); + rcutils_allocator_t default_allocator = rcutils_get_default_allocator(); + rmw_serialized_message_t serialized_message = rmw_get_zero_initialized_serialized_message(); + rmw_ret_t ret = rmw_serialized_message_init(&serialized_message, 0lu, &default_allocator); + ASSERT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; + OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT( + { + rmw_ret_t ret = rmw_serialized_message_fini(&serialized_message); + EXPECT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; + }); + ret = rmw_serialize(&message, ts, &serialized_message); + ASSERT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; + rmw_publisher_allocation_t * null_allocation{nullptr}; // still a valid allocation + + RCUTILS_FAULT_INJECTION_TEST( + { + ret = rmw_publish_serialized_message( + pub, &serialized_message, null_allocation); + if (RMW_RET_OK != ret) { + rmw_reset_error(); + } + }); +} + + class CLASSNAME (TestPublisherUseLoan, RMW_IMPLEMENTATION) : public CLASSNAME(TestPublisherUse, RMW_IMPLEMENTATION) { diff --git a/test_rmw_implementation/test/test_service.cpp b/test_rmw_implementation/test/test_service.cpp index 2ef7cb3d..64b4ba82 100644 --- a/test_rmw_implementation/test/test_service.cpp +++ b/test_rmw_implementation/test/test_service.cpp @@ -149,6 +149,45 @@ TEST_F(CLASSNAME(TestService, RMW_IMPLEMENTATION), create_with_bad_arguments) { EXPECT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; } + +TEST_F(CLASSNAME(TestService, RMW_IMPLEMENTATION), create_with_internal_errors) { + constexpr char service_name[] = "/test"; + const rosidl_service_type_support_t * ts = + ROSIDL_GET_SRV_TYPE_SUPPORT(test_msgs, srv, BasicTypes); + RCUTILS_FAULT_INJECTION_TEST( + { + rmw_service_t * srv = + rmw_create_service(node, ts, service_name, &rmw_qos_profile_default); + if (srv) { + int64_t count = rcutils_fault_injection_get_count(); + rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); + rmw_ret_t ret = rmw_destroy_service(node, srv); + EXPECT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; + rcutils_fault_injection_set_count(count); + } else { + rmw_reset_error(); + } + }); +} + +TEST_F(CLASSNAME(TestService, RMW_IMPLEMENTATION), destroy_with_internal_errors) { + constexpr char service_name[] = "/test"; + const rosidl_service_type_support_t * ts = + ROSIDL_GET_SRV_TYPE_SUPPORT(test_msgs, srv, BasicTypes); + RCUTILS_FAULT_INJECTION_TEST( + { + int64_t count = rcutils_fault_injection_get_count(); + rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); + rmw_service_t * srv = + rmw_create_service(node, ts, service_name, &rmw_qos_profile_default); + ASSERT_NE(nullptr, srv) << rmw_get_error_string().str; + rcutils_fault_injection_set_count(count); + if (RMW_RET_OK != rmw_destroy_service(node, srv)) { + rmw_reset_error(); + } + }); +} + class CLASSNAME (TestServiceUse, RMW_IMPLEMENTATION) : public CLASSNAME(TestService, RMW_IMPLEMENTATION) { diff --git a/test_rmw_implementation/test/test_subscription.cpp b/test_rmw_implementation/test/test_subscription.cpp index 9d72d62c..f7bdc46f 100644 --- a/test_rmw_implementation/test/test_subscription.cpp +++ b/test_rmw_implementation/test/test_subscription.cpp @@ -157,6 +157,29 @@ TEST_F(CLASSNAME(TestSubscription, RMW_IMPLEMENTATION), create_with_bad_argument EXPECT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; } +TEST_F(CLASSNAME(TestSubscription, RMW_IMPLEMENTATION), create_with_internal_errors) { + constexpr char topic_name[] = "/test"; + const rosidl_message_type_support_t * ts = + ROSIDL_GET_MSG_TYPE_SUPPORT(test_msgs, msg, BasicTypes); + + RCUTILS_FAULT_INJECTION_TEST( + { + rmw_subscription_options_t options = rmw_get_default_subscription_options(); + rmw_subscription_t * sub = + rmw_create_subscription(node, ts, topic_name, &rmw_qos_profile_default, &options); + if (sub) { + int64_t count = rcutils_fault_injection_get_count(); + rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); + rmw_ret_t ret = rmw_destroy_subscription(node, sub); + EXPECT_EQ(RMW_RET_OK, ret) << rmw_get_error_string().str; + rcutils_fault_injection_set_count(count); + } else { + rmw_reset_error(); + } + }); +} + + TEST_F(CLASSNAME(TestSubscription, RMW_IMPLEMENTATION), destroy_with_bad_arguments) { rmw_subscription_options_t options = rmw_get_default_subscription_options(); constexpr char topic_name[] = "/test"; @@ -188,6 +211,26 @@ TEST_F(CLASSNAME(TestSubscription, RMW_IMPLEMENTATION), destroy_with_bad_argumen rmw_reset_error(); } +TEST_F(CLASSNAME(TestSubscription, RMW_IMPLEMENTATION), destroy_with_internal_errors) { + constexpr char topic_name[] = "/test"; + const rosidl_message_type_support_t * ts = + ROSIDL_GET_MSG_TYPE_SUPPORT(test_msgs, msg, BasicTypes); + + RCUTILS_FAULT_INJECTION_TEST( + { + int64_t count = rcutils_fault_injection_get_count(); + rcutils_fault_injection_set_count(RCUTILS_FAULT_INJECTION_NEVER_FAIL); + rmw_subscription_options_t options = rmw_get_default_subscription_options(); + rmw_subscription_t * sub = + rmw_create_subscription(node, ts, topic_name, &rmw_qos_profile_default, &options); + ASSERT_NE(nullptr, sub) << rmw_get_error_string().str; + rcutils_fault_injection_set_count(count); + if (RMW_RET_OK != rmw_destroy_subscription(node, sub)) { + rmw_reset_error(); + } + }); +} + TEST_F(CLASSNAME(TestSubscription, RMW_IMPLEMENTATION), get_actual_qos_from_system_defaults) { rmw_subscription_options_t options = rmw_get_default_subscription_options(); constexpr char topic_name[] = "/test"; diff --git a/test_rmw_implementation/test/testing_macros.hpp b/test_rmw_implementation/test/testing_macros.hpp index ec9d924d..bc8d3f5e 100644 --- a/test_rmw_implementation/test/testing_macros.hpp +++ b/test_rmw_implementation/test/testing_macros.hpp @@ -18,6 +18,11 @@ #include #include +#include "osrf_testing_tools_cpp/memory_tools/memory_tools.hpp" + +#include "rcutils/macros.h" +#include "rcutils/testing/fault_injection.h" + /// Retry until `timeout` expires, sleeping for `delay` in between attempts. /* * \note Time is measured against OS provided steady clock.