Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fault-injection unit tests (coverage part 2/3) #766

Merged
merged 4 commits into from
Sep 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions rcl_yaml_param_parser/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ if(BUILD_TESTING)
"rcutils"
"osrf_testing_tools_cpp"
)
target_compile_definitions(test_namespace PUBLIC RCUTILS_ENABLE_FAULT_INJECTION)
target_link_libraries(test_namespace ${PROJECT_NAME})
endif()

Expand Down Expand Up @@ -114,6 +115,7 @@ if(BUILD_TESTING)
"osrf_testing_tools_cpp"
)
target_link_libraries(test_parser ${PROJECT_NAME})
target_compile_definitions(test_parser PUBLIC RCUTILS_ENABLE_FAULT_INJECTION)
endif()

ament_add_gtest(test_yaml_variant
Expand Down
54 changes: 54 additions & 0 deletions rcl_yaml_param_parser/test/test_namespace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,57 @@ TEST(TestNamespace, replace_ns) {
EXPECT_STREQ(expected_param_ns, ns_tracker.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);
}
});
}
88 changes: 49 additions & 39 deletions rcl_yaml_param_parser/test/test_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
#include <vector>

#include "gtest/gtest.h"

#include "osrf_testing_tools_cpp/scope_exit.hpp"
#include "rcl_yaml_param_parser/parser.h"
#include "rcutils/error_handling.h"
#include "rcutils/filesystem.h"
#include "rcutils/testing/fault_injection.h"
#include "./time_bomb_allocator_testing_utils.h"

TEST(RclYamlParamParser, node_init_fini) {
Expand Down Expand Up @@ -308,46 +313,51 @@ TEST(RclYamlParamParser, test_parse_file_with_bad_allocator) {
{
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);
EXPECT_TRUE(rcl_parse_yaml_file(path, params_hdl));
rcl_yaml_node_struct_fini(params_hdl);
params_hdl = NULL;

// Check sporadic failing malloc calls
for (int i = 0; i < 100; ++i) {
params_hdl = rcl_yaml_node_struct_init(get_time_bomb_allocator());
ASSERT_TRUE(NULL != params_hdl) << rcutils_get_error_string().str;

set_time_bomb_allocator_malloc_count(params_hdl->allocator, i);
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
// 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;
}

// Check sporadic failing calloc calls
for (int i = 0; i < 100; ++i) {
params_hdl = rcl_yaml_node_struct_init(get_time_bomb_allocator());
ASSERT_TRUE(NULL != params_hdl) << rcutils_get_error_string().str;

set_time_bomb_allocator_calloc_count(params_hdl->allocator, i);

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
// 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;
const std::vector<std::string> filenames = {
"correct_config.yaml",
"empty_string.yaml",
"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"
};

for (auto & filename : filenames) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brawner nit: can be made const?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think const is already deduced by auto since filenames is const.

SCOPED_TRACE(filename);
char * path = rcutils_join_path(test_path, filename.c_str(), 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;

RCUTILS_FAULT_INJECTION_TEST(
{
rcutils_allocator_t allocator = rcutils_get_default_allocator();
rcl_params_t * params_hdl = rcl_yaml_node_struct_init(allocator);
if (NULL == params_hdl) {
continue;
}

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
// result. We're just trying to make sure that bad allocations are properly handled
(void)res;

// If `rcutils_string_array_fini` fails, there will be a small memory leak here.
// However, it's necessary for coverage
rcl_yaml_node_struct_fini(params_hdl);
params_hdl = NULL;
});
}
}

Expand Down
32 changes: 32 additions & 0 deletions rcl_yaml_param_parser/test/test_yaml_variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,35 @@ TEST(TestYamlVariant, copy_string_array_values) {
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);
});
}