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

Complete rcutils API coverage #272

Merged
merged 20 commits into from
Aug 7, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
18 changes: 9 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ if(BUILD_TESTING)
osrf_testing_tools_cpp::memory_tools LIBRARY_PRELOAD_ENVIRONMENT_IS_AVAILABLE)

ament_add_gtest(test_logging test/test_logging.cpp)
target_link_libraries(test_logging ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools)
target_link_libraries(test_logging ${PROJECT_NAME} mimick osrf_testing_tools_cpp::memory_tools)
Blast545 marked this conversation as resolved.
Show resolved Hide resolved

add_executable(test_logging_long_messages test/test_logging_long_messages.cpp)
target_link_libraries(test_logging_long_messages ${PROJECT_NAME})
Expand Down Expand Up @@ -234,7 +234,7 @@ if(BUILD_TESTING)
test/test_char_array.cpp
)
if(TARGET test_char_array)
target_link_libraries(test_char_array ${PROJECT_NAME})
target_link_libraries(test_char_array ${PROJECT_NAME} mimick)
endif()

# Can't use C++ with stdatomic_helper.h
Expand Down Expand Up @@ -275,7 +275,7 @@ if(BUILD_TESTING)
test/test_split.cpp
)
if(TARGET test_split)
target_link_libraries(test_split ${PROJECT_NAME})
target_link_libraries(test_split ${PROJECT_NAME} mimick)
endif()

rcutils_custom_add_gtest(test_find
Expand Down Expand Up @@ -322,7 +322,7 @@ if(BUILD_TESTING)
)
if(TARGET test_filesystem)
ament_target_dependencies(test_filesystem "osrf_testing_tools_cpp")
target_link_libraries(test_filesystem ${PROJECT_NAME})
target_link_libraries(test_filesystem ${PROJECT_NAME} mimick)
target_compile_definitions(test_filesystem PRIVATE BUILD_DIR="${CMAKE_CURRENT_BINARY_DIR}")
endif()

Expand All @@ -337,7 +337,7 @@ if(BUILD_TESTING)
test/test_format_string.cpp
)
if(TARGET test_format_string)
target_link_libraries(test_format_string ${PROJECT_NAME})
target_link_libraries(test_format_string ${PROJECT_NAME} mimick)
endif()

rcutils_custom_add_gtest(test_string_map
Expand Down Expand Up @@ -375,14 +375,14 @@ if(BUILD_TESTING)
# which is appropriate when building the dll but not consuming it.
target_compile_definitions(dummy_shared_library PRIVATE "DUMMY_SHARED_LIBRARY_BUILDING_DLL")
endif()
target_link_libraries(test_shared_library ${PROJECT_NAME})
target_link_libraries(test_shared_library ${PROJECT_NAME} mimick)
endif()

rcutils_custom_add_gtest(test_time
test/test_time.cpp
ENV ${memory_tools_test_env_vars})
if(TARGET test_time)
target_link_libraries(test_time ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools)
target_link_libraries(test_time ${PROJECT_NAME} mimick osrf_testing_tools_cpp::memory_tools)
endif()

rcutils_custom_add_gtest(test_snprintf
Expand Down Expand Up @@ -436,7 +436,7 @@ if(BUILD_TESTING)
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)
target_link_libraries(test_logging_custom_env ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools mimick)
endif()

# RCUTILS_LOGGING_MAX_OUTPUT_FORMAT_LEN is defined as 2048, truncation should occur
Expand All @@ -452,7 +452,7 @@ if(BUILD_TESTING)
RCUTILS_COLORIZED_OUTPUT=0
)
if(TARGET test_logging_custom_env2)
target_link_libraries(test_logging_custom_env2 ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools)
target_link_libraries(test_logging_custom_env2 ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools mimick)
endif()

rcutils_custom_add_gtest(test_logging_bad_env test/test_logging_bad_env.cpp
Expand Down
172 changes: 172 additions & 0 deletions test/mocking_utils/filesystem.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// 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 MOCKING_UTILS__FILESYSTEM_HPP_
#define MOCKING_UTILS__FILESYSTEM_HPP_

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>

#ifndef _WIN32
#include <sys/types.h>
#include <dirent.h>
#else
#include <windows.h>
#endif

#include <map>
#include <string>
#include <type_traits>

#include "rcutils/macros.h"

#include "patch.hpp"

namespace mocking_utils
{
namespace filesystem
{

struct FileTypes
{
static constexpr mode_t REGULAR_FILE = S_IFREG;
static constexpr mode_t DIRECTORY = S_IFDIR;
};

struct Permissions
{
#ifndef _WIN32
static constexpr mode_t USER_READABLE = S_IRUSR;
static constexpr mode_t USER_WRITABLE = S_IWUSR;
#else
static constexpr mode_t USER_READABLE = _S_IREAD;
static constexpr mode_t USER_WRITABLE = _S_IWRITE;
#endif
};

template<size_t N>
class FileSystem
Copy link
Contributor

Choose a reason for hiding this comment

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

I know it's a bit subjective and I suggested the opposite on a different file, but this class doesn't seem to reuse much code across #ifdef blocks. Since it's the filesystem and each OS handles it differently, I think this file makes sense define the full class in single ifdef blocks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See 83140ec.

{
public:
explicit FileSystem(const std::string & target)
#ifndef _WIN32
: opendir_mock_(MOCKING_UTILS_PATCH_TARGET(target, opendir),
MOCKING_UTILS_PATCH_PROXY(opendir)),
#else
: find_first_file_mock_(MOCKING_UTILS_PATCH_TARGET(target, FindFirstFile),
MOCKING_UTILS_PATCH_PROXY(FindFirstFile)),
#endif
#ifndef _GNU_SOURCE
Copy link
Contributor

Choose a reason for hiding this comment

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

Also seems like a good candidate for combining with the ifndef block at line 88 below. Line 87 is the only line shared between the two cases.

stat_mock_(MOCKING_UTILS_PATCH_TARGET(target, stat),
MOCKING_UTILS_PATCH_PROXY(stat))
#else
__xstat_mock_(MOCKING_UTILS_PATCH_TARGET(target, __xstat),
MOCKING_UTILS_PATCH_PROXY(__xstat))
#endif
{
#ifndef _WIN32
opendir_mock_.then_call(std::bind(&FileSystem::do_opendir, this, std::placeholders::_1));
#else
find_first_file_mock_.then_call(
std::bind(
&FileSystem::do_FindFirstFile, this,
std::placeholders::_1, std::placeholders::_2))
#endif
#ifndef _GNU_SOURCE
stat_mock_.then_call(
std::bind(
&FileSystem::do_stat, this,
std::placeholders::_1, std::placeholders::_2));
#else
__xstat_mock_.then_call(
std::bind(
&FileSystem::do___xstat, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3));
#endif
}

void exhaust_file_descriptors()
{
#ifdef _WIN32
forced_errno_ = ERROR_NO_MORE_SEARCH_HANDLES;
#else
forced_errno_ = EMFILE;
#endif
}

struct stat & file_info(const std::string & path)
{
return files_info_[path];
}

private:
#ifndef _WIN32
DIR * do_opendir(const char *)
{
if (forced_errno_ != 0) {
errno = forced_errno_;
return NULL;
}
errno = ENOENT;
return NULL;
}
MOCKING_UTILS_PATCH_TYPE(N, opendir) opendir_mock_;
#else
HANDLE do_FindFirstFile(LPCSTR, LPWIN32_FIND_DATAA)
{
if (forced_errno_ != 0) {
SetLastError(forced_errno_);
return INVALID_HANDLE_VALUE;
}
SetLastError(ERROR_FILE_NOT_FOUND);
return INVALID_HANDLE_VALUE;
}

MOCKING_UTILS_PATCH_TYPE(N, FindFirstFile) find_first_file_mock_;
#endif

#ifndef _GNU_SOURCE
int do_stat(const char * path, struct stat * info)
{
#else
int do___xstat(int, const char * path, struct stat * info)
{
#endif
if (files_info_.count(path) == 0) {
errno = ENOENT;
return -1;
}
*info = files_info_[path];
return 0;
}

#ifndef _GNU_SOURCE
MOCKING_UTILS_PATCH_TYPE(N, stat) stat_mock_;
#else
MOCKING_UTILS_PATCH_TYPE(N, __xstat) __xstat_mock_;
#endif

int forced_errno_{0};
std::map<std::string, struct stat> files_info_;
};

} // namespace filesystem

/// Patch filesystem API, based on `what` binary object should be affected.
#define patch_filesystem(what) filesystem::FileSystem<__COUNTER__>(what)

} // namespace mocking_utils

#endif // MOCKING_UTILS__FILESYSTEM_HPP_
Loading