Add fault-injection unit tests (coverage part 2/3) (#766)
* Fault injection tests for rcl_yaml Signed-off-by: Stephen Brawner <brawner@gmail.com> * PR Feedback Signed-off-by: Stephen Brawner <brawner@gmail.com> * Pause fault injection Signed-off-by: Stephen Brawner <brawner@gmail.com> * variant_copy Signed-off-by: Stephen Brawner <brawner@gmail.com>
This commit is contained in:
parent
79e2e044d3
commit
08bbdde860
4 changed files with 133 additions and 35 deletions
|
@ -72,6 +72,7 @@ if(BUILD_TESTING)
|
||||||
"rcutils"
|
"rcutils"
|
||||||
"osrf_testing_tools_cpp"
|
"osrf_testing_tools_cpp"
|
||||||
)
|
)
|
||||||
|
target_compile_definitions(test_namespace PUBLIC RCUTILS_ENABLE_FAULT_INJECTION)
|
||||||
target_link_libraries(test_namespace ${PROJECT_NAME})
|
target_link_libraries(test_namespace ${PROJECT_NAME})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -119,6 +120,7 @@ if(BUILD_TESTING)
|
||||||
"osrf_testing_tools_cpp"
|
"osrf_testing_tools_cpp"
|
||||||
)
|
)
|
||||||
target_link_libraries(test_parser ${PROJECT_NAME})
|
target_link_libraries(test_parser ${PROJECT_NAME})
|
||||||
|
target_compile_definitions(test_parser PUBLIC RCUTILS_ENABLE_FAULT_INJECTION)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_performance_test(benchmark_parse_yaml test/benchmark/benchmark_parse_yaml.cpp
|
add_performance_test(benchmark_parse_yaml test/benchmark/benchmark_parse_yaml.cpp
|
||||||
|
|
|
@ -104,3 +104,57 @@ TEST(TestNamespace, replace_ns) {
|
||||||
EXPECT_STREQ(expected_param_ns, ns_tracker.parameter_ns);
|
EXPECT_STREQ(expected_param_ns, ns_tracker.parameter_ns);
|
||||||
EXPECT_EQ(3u, ns_tracker.num_parameter_ns);
|
EXPECT_EQ(3u, ns_tracker.num_parameter_ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(TestNamespace, replace_ns_maybe_fail) {
|
||||||
|
rcutils_allocator_t allocator = rcutils_get_default_allocator();
|
||||||
|
namespace_tracker_t ns_tracker;
|
||||||
|
ns_tracker.node_ns = rcutils_strdup("node1/node2", allocator);
|
||||||
|
ASSERT_STREQ("node1/node2", ns_tracker.node_ns);
|
||||||
|
ns_tracker.parameter_ns = rcutils_strdup("param1.param2", allocator);
|
||||||
|
ASSERT_STREQ("param1.param2", ns_tracker.parameter_ns);
|
||||||
|
ns_tracker.num_node_ns = 2;
|
||||||
|
ns_tracker.num_parameter_ns = 2;
|
||||||
|
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
|
||||||
|
{
|
||||||
|
allocator.deallocate(ns_tracker.node_ns, allocator.state);
|
||||||
|
allocator.deallocate(ns_tracker.parameter_ns, allocator.state);
|
||||||
|
});
|
||||||
|
|
||||||
|
char * expected_ns = rcutils_strdup("new_ns1/new_ns2/new_ns3", allocator);
|
||||||
|
ASSERT_STREQ("new_ns1/new_ns2/new_ns3", expected_ns);
|
||||||
|
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
|
||||||
|
{
|
||||||
|
allocator.deallocate(expected_ns, allocator.state);
|
||||||
|
});
|
||||||
|
|
||||||
|
char * expected_param_ns =
|
||||||
|
rcutils_strdup("new_param1.new_param2.new_param3", allocator);
|
||||||
|
ASSERT_STREQ("new_param1.new_param2.new_param3", expected_param_ns);
|
||||||
|
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
|
||||||
|
{
|
||||||
|
allocator.deallocate(expected_param_ns, allocator.state);
|
||||||
|
});
|
||||||
|
|
||||||
|
RCUTILS_FAULT_INJECTION_TEST(
|
||||||
|
{
|
||||||
|
rcutils_ret_t ret =
|
||||||
|
replace_ns(&ns_tracker, expected_ns, 3, NS_TYPE_NODE, allocator);
|
||||||
|
if (RCUTILS_RET_OK != ret) {
|
||||||
|
EXPECT_EQ(nullptr, ns_tracker.node_ns);
|
||||||
|
rcutils_reset_error();
|
||||||
|
} else {
|
||||||
|
EXPECT_EQ(RCUTILS_RET_OK, ret) << rcutils_get_error_string().str;
|
||||||
|
EXPECT_STREQ(expected_ns, ns_tracker.node_ns);
|
||||||
|
EXPECT_EQ(3u, ns_tracker.num_node_ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = replace_ns(&ns_tracker, expected_param_ns, 3, NS_TYPE_PARAM, allocator);
|
||||||
|
if (RCUTILS_RET_OK != ret) {
|
||||||
|
EXPECT_EQ(nullptr, ns_tracker.parameter_ns);
|
||||||
|
rcutils_reset_error();
|
||||||
|
} else {
|
||||||
|
EXPECT_STREQ(expected_param_ns, ns_tracker.parameter_ns);
|
||||||
|
EXPECT_EQ(3u, ns_tracker.num_parameter_ns);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -12,11 +12,16 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
#include "osrf_testing_tools_cpp/scope_exit.hpp"
|
#include "osrf_testing_tools_cpp/scope_exit.hpp"
|
||||||
#include "rcl_yaml_param_parser/parser.h"
|
#include "rcl_yaml_param_parser/parser.h"
|
||||||
#include "rcutils/error_handling.h"
|
#include "rcutils/error_handling.h"
|
||||||
#include "rcutils/filesystem.h"
|
#include "rcutils/filesystem.h"
|
||||||
|
#include "rcutils/testing/fault_injection.h"
|
||||||
#include "./time_bomb_allocator_testing_utils.h"
|
#include "./time_bomb_allocator_testing_utils.h"
|
||||||
|
|
||||||
TEST(RclYamlParamParser, node_init_fini) {
|
TEST(RclYamlParamParser, node_init_fini) {
|
||||||
|
@ -308,46 +313,51 @@ TEST(RclYamlParamParser, test_parse_file_with_bad_allocator) {
|
||||||
{
|
{
|
||||||
allocator.deallocate(test_path, allocator.state);
|
allocator.deallocate(test_path, allocator.state);
|
||||||
});
|
});
|
||||||
char * path = rcutils_join_path(test_path, "correct_config.yaml", allocator);
|
|
||||||
ASSERT_TRUE(NULL != path) << rcutils_get_error_string().str;
|
|
||||||
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
|
|
||||||
{
|
|
||||||
allocator.deallocate(path, allocator.state);
|
|
||||||
});
|
|
||||||
ASSERT_TRUE(rcutils_exists(path)) << "No test YAML file found at " << path;
|
|
||||||
|
|
||||||
rcl_params_t * params_hdl = rcl_yaml_node_struct_init(allocator);
|
const std::vector<std::string> filenames = {
|
||||||
EXPECT_TRUE(rcl_parse_yaml_file(path, params_hdl));
|
"correct_config.yaml",
|
||||||
rcl_yaml_node_struct_fini(params_hdl);
|
"empty_string.yaml",
|
||||||
params_hdl = NULL;
|
"indented_name_space.yaml",
|
||||||
|
"max_num_params.yaml",
|
||||||
|
"multi_ns_correct.yaml",
|
||||||
|
"no_alias_support.yaml",
|
||||||
|
"no_value1.yaml",
|
||||||
|
"overlay.yaml",
|
||||||
|
"params_with_no_node.yaml",
|
||||||
|
"root_ns.yaml",
|
||||||
|
"seq_map1.yaml",
|
||||||
|
"seq_map2.yaml",
|
||||||
|
"string_array_with_quoted_number.yaml"
|
||||||
|
};
|
||||||
|
|
||||||
// Check sporadic failing malloc calls
|
for (auto & filename : filenames) {
|
||||||
for (int i = 0; i < 100; ++i) {
|
SCOPED_TRACE(filename);
|
||||||
params_hdl = rcl_yaml_node_struct_init(get_time_bomb_allocator());
|
char * path = rcutils_join_path(test_path, filename.c_str(), allocator);
|
||||||
ASSERT_TRUE(NULL != params_hdl) << rcutils_get_error_string().str;
|
ASSERT_TRUE(NULL != path) << rcutils_get_error_string().str;
|
||||||
|
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
|
||||||
|
{
|
||||||
|
allocator.deallocate(path, allocator.state);
|
||||||
|
});
|
||||||
|
ASSERT_TRUE(rcutils_exists(path)) << "No test YAML file found at " << path;
|
||||||
|
|
||||||
set_time_bomb_allocator_malloc_count(params_hdl->allocator, i);
|
RCUTILS_FAULT_INJECTION_TEST(
|
||||||
bool res = rcl_parse_yaml_file(path, params_hdl);
|
{
|
||||||
// Not verifying res is true or false here, because eventually it will come back with an ok
|
rcutils_allocator_t allocator = rcutils_get_default_allocator();
|
||||||
// result. We're just trying to make sure that bad allocations are properly handled
|
rcl_params_t * params_hdl = rcl_yaml_node_struct_init(allocator);
|
||||||
(void)res;
|
if (NULL == params_hdl) {
|
||||||
rcl_yaml_node_struct_fini(params_hdl);
|
continue;
|
||||||
params_hdl = NULL;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Check sporadic failing calloc calls
|
bool res = rcl_parse_yaml_file(path, params_hdl);
|
||||||
for (int i = 0; i < 100; ++i) {
|
// Not verifying res is true or false here, because eventually it will come back with an ok
|
||||||
params_hdl = rcl_yaml_node_struct_init(get_time_bomb_allocator());
|
// result. We're just trying to make sure that bad allocations are properly handled
|
||||||
ASSERT_TRUE(NULL != params_hdl) << rcutils_get_error_string().str;
|
(void)res;
|
||||||
|
|
||||||
set_time_bomb_allocator_calloc_count(params_hdl->allocator, i);
|
// If `rcutils_string_array_fini` fails, there will be a small memory leak here.
|
||||||
|
// However, it's necessary for coverage
|
||||||
bool res = rcl_parse_yaml_file(path, params_hdl);
|
rcl_yaml_node_struct_fini(params_hdl);
|
||||||
// Not verifying res is true or false here, because eventually it will come back with an ok
|
params_hdl = NULL;
|
||||||
// result. We're just trying to make sure that bad allocations are properly handled
|
});
|
||||||
(void)res;
|
|
||||||
rcl_yaml_node_struct_fini(params_hdl);
|
|
||||||
params_hdl = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -182,3 +182,35 @@ TEST(TestYamlVariant, copy_string_array_values) {
|
||||||
src_variant.string_array_value->data[i], dest_variant.string_array_value->data[i]);
|
src_variant.string_array_value->data[i], dest_variant.string_array_value->data[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(TestYamlVariant, copy_string_array_maybe_fail) {
|
||||||
|
rcl_variant_t src_variant{};
|
||||||
|
rcutils_allocator_t allocator = rcutils_get_default_allocator();
|
||||||
|
constexpr size_t size = 3u;
|
||||||
|
src_variant.string_array_value =
|
||||||
|
static_cast<rcutils_string_array_t *>(
|
||||||
|
allocator.allocate(sizeof(rcutils_string_array_t), allocator.state));
|
||||||
|
ASSERT_NE(nullptr, src_variant.string_array_value);
|
||||||
|
OSRF_TESTING_TOOLS_CPP_SCOPE_EXIT(
|
||||||
|
{
|
||||||
|
rcl_yaml_variant_fini(&src_variant, allocator);
|
||||||
|
});
|
||||||
|
*src_variant.string_array_value = rcutils_get_zero_initialized_string_array();
|
||||||
|
ASSERT_EQ(
|
||||||
|
RCUTILS_RET_OK, rcutils_string_array_init(src_variant.string_array_value, size, &allocator));
|
||||||
|
src_variant.string_array_value->size = size;
|
||||||
|
src_variant.string_array_value->data[0] = rcutils_strdup("string1", allocator);
|
||||||
|
src_variant.string_array_value->data[1] = rcutils_strdup("string2", allocator);
|
||||||
|
src_variant.string_array_value->data[2] = rcutils_strdup("string3", allocator);
|
||||||
|
for (size_t i = 0; i < size; ++i) {
|
||||||
|
ASSERT_NE(nullptr, src_variant.string_array_value->data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
RCUTILS_FAULT_INJECTION_TEST(
|
||||||
|
{
|
||||||
|
rcl_variant_t dest_variant{};
|
||||||
|
rcutils_ret_t ret = rcl_yaml_variant_copy(&dest_variant, &src_variant, allocator);
|
||||||
|
(void)ret;
|
||||||
|
rcl_yaml_variant_fini(&dest_variant, allocator);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue