Skip to content

Commit 9e004d7

Browse files
committed
Mock system calls in rcutils API implementation.
Signed-off-by: Michel Hidalgo <[email protected]>
1 parent eabfb01 commit 9e004d7

File tree

11 files changed

+630
-22
lines changed

11 files changed

+630
-22
lines changed

CMakeLists.txt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ if(BUILD_TESTING)
181181
osrf_testing_tools_cpp::memory_tools LIBRARY_PRELOAD_ENVIRONMENT_IS_AVAILABLE)
182182

183183
ament_add_gtest(test_logging test/test_logging.cpp)
184-
target_link_libraries(test_logging ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools)
184+
target_link_libraries(test_logging ${PROJECT_NAME} mimick osrf_testing_tools_cpp::memory_tools)
185185

186186
add_executable(test_logging_long_messages test/test_logging_long_messages.cpp)
187187
target_link_libraries(test_logging_long_messages ${PROJECT_NAME})
@@ -234,7 +234,7 @@ if(BUILD_TESTING)
234234
test/test_char_array.cpp
235235
)
236236
if(TARGET test_char_array)
237-
target_link_libraries(test_char_array ${PROJECT_NAME})
237+
target_link_libraries(test_char_array ${PROJECT_NAME} mimick)
238238
endif()
239239

240240
# Can't use C++ with stdatomic_helper.h
@@ -275,7 +275,7 @@ if(BUILD_TESTING)
275275
test/test_split.cpp
276276
)
277277
if(TARGET test_split)
278-
target_link_libraries(test_split ${PROJECT_NAME})
278+
target_link_libraries(test_split ${PROJECT_NAME} mimick)
279279
endif()
280280

281281
rcutils_custom_add_gtest(test_find
@@ -322,7 +322,7 @@ if(BUILD_TESTING)
322322
)
323323
if(TARGET test_filesystem)
324324
ament_target_dependencies(test_filesystem "osrf_testing_tools_cpp")
325-
target_link_libraries(test_filesystem ${PROJECT_NAME})
325+
target_link_libraries(test_filesystem ${PROJECT_NAME} mimick)
326326
target_compile_definitions(test_filesystem PRIVATE BUILD_DIR="${CMAKE_CURRENT_BINARY_DIR}")
327327
endif()
328328

@@ -337,7 +337,7 @@ if(BUILD_TESTING)
337337
test/test_format_string.cpp
338338
)
339339
if(TARGET test_format_string)
340-
target_link_libraries(test_format_string ${PROJECT_NAME})
340+
target_link_libraries(test_format_string ${PROJECT_NAME} mimick)
341341
endif()
342342

343343
rcutils_custom_add_gtest(test_string_map
@@ -375,14 +375,14 @@ if(BUILD_TESTING)
375375
# which is appropriate when building the dll but not consuming it.
376376
target_compile_definitions(dummy_shared_library PRIVATE "DUMMY_SHARED_LIBRARY_BUILDING_DLL")
377377
endif()
378-
target_link_libraries(test_shared_library ${PROJECT_NAME})
378+
target_link_libraries(test_shared_library ${PROJECT_NAME} mimick)
379379
endif()
380380

381381
rcutils_custom_add_gtest(test_time
382382
test/test_time.cpp
383383
ENV ${memory_tools_test_env_vars})
384384
if(TARGET test_time)
385-
target_link_libraries(test_time ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools)
385+
target_link_libraries(test_time ${PROJECT_NAME} mimick osrf_testing_tools_cpp::memory_tools)
386386
endif()
387387

388388
rcutils_custom_add_gtest(test_snprintf
@@ -436,7 +436,7 @@ if(BUILD_TESTING)
436436
RCUTILS_COLORIZED_OUTPUT=1
437437
)
438438
if(TARGET test_logging_custom_env)
439-
target_link_libraries(test_logging_custom_env ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools)
439+
target_link_libraries(test_logging_custom_env ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools mimick)
440440
endif()
441441

442442
# RCUTILS_LOGGING_MAX_OUTPUT_FORMAT_LEN is defined as 2048, truncation should occur
@@ -452,7 +452,7 @@ if(BUILD_TESTING)
452452
RCUTILS_COLORIZED_OUTPUT=0
453453
)
454454
if(TARGET test_logging_custom_env2)
455-
target_link_libraries(test_logging_custom_env2 ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools)
455+
target_link_libraries(test_logging_custom_env2 ${PROJECT_NAME} osrf_testing_tools_cpp::memory_tools mimick)
456456
endif()
457457

458458
rcutils_custom_add_gtest(test_logging_bad_env test/test_logging_bad_env.cpp

test/mocking_utils/filesystem.hpp

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// Copyright 2020 Open Source Robotics Foundation, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef MOCKING_UTILS__FILESYSTEM_HPP_
16+
#define MOCKING_UTILS__FILESYSTEM_HPP_
17+
18+
#include <stdio.h>
19+
#include <string.h>
20+
#include <sys/stat.h>
21+
22+
#ifndef _WIN32
23+
#include <sys/types.h>
24+
#include <dirent.h>
25+
#else
26+
#include <windows.h>
27+
#endif
28+
29+
#include <map>
30+
#include <string>
31+
#include <type_traits>
32+
33+
#include "rcutils/macros.h"
34+
35+
#include "patch.hpp"
36+
37+
namespace mocking_utils
38+
{
39+
namespace filesystem
40+
{
41+
42+
struct FileTypes
43+
{
44+
static constexpr mode_t REGULAR_FILE = S_IFREG;
45+
static constexpr mode_t DIRECTORY = S_IFDIR;
46+
};
47+
48+
struct Permissions
49+
{
50+
#ifndef _WIN32
51+
static constexpr mode_t USER_READABLE = S_IRUSR;
52+
static constexpr mode_t USER_WRITABLE = S_IWUSR;
53+
#else
54+
static constexpr mode_t USER_READABLE = _S_IREAD;
55+
static constexpr mode_t USER_WRITABLE = _S_IWRITE;
56+
#endif
57+
};
58+
59+
template<size_t N>
60+
class FileSystem
61+
{
62+
public:
63+
explicit FileSystem(const std::string & target)
64+
#ifndef _WIN32
65+
: opendir_mock_(MOCKING_UTILS_PATCH_TARGET(target, opendir),
66+
MOCKING_UTILS_PATCH_PROXY(opendir)),
67+
#else
68+
: find_first_file_mock_(MOCKING_UTILS_PATCH_TARGET(target, FindFirstFile),
69+
MOCKING_UTILS_PATCH_PROXY(FindFirstFile)),
70+
#endif
71+
#ifndef _GNU_SOURCE
72+
stat_mock_(MOCKING_UTILS_PATCH_TARGET(target, stat),
73+
MOCKING_UTILS_PATCH_PROXY(stat))
74+
#else
75+
__xstat_mock_(MOCKING_UTILS_PATCH_TARGET(target, __xstat),
76+
MOCKING_UTILS_PATCH_PROXY(__xstat))
77+
#endif
78+
{
79+
#ifndef _WIN32
80+
opendir_mock_.then_call(std::bind(&FileSystem::do_opendir, this, std::placeholders::_1));
81+
#else
82+
find_first_file_mock_.then_call(
83+
std::bind(
84+
&FileSystem::do_FindFirstFile, this,
85+
std::placeholders::_1, std::placeholders::_2))
86+
#endif
87+
#ifndef _GNU_SOURCE
88+
stat_mock_.then_call(
89+
std::bind(
90+
&FileSystem::do_stat, this,
91+
std::placeholders::_1, std::placeholders::_2));
92+
#else
93+
__xstat_mock_.then_call(
94+
std::bind(
95+
&FileSystem::do___xstat, this, std::placeholders::_1,
96+
std::placeholders::_2, std::placeholders::_3));
97+
#endif
98+
}
99+
100+
void exhaust_file_descriptors()
101+
{
102+
#ifdef _WIN32
103+
forced_errno_ = ERROR_NO_MORE_SEARCH_HANDLES;
104+
#else
105+
forced_errno_ = EMFILE;
106+
#endif
107+
}
108+
109+
struct stat & file_info(const std::string & path)
110+
{
111+
return files_info_[path];
112+
}
113+
114+
private:
115+
#ifndef _WIN32
116+
DIR * do_opendir(const char *)
117+
{
118+
if (forced_errno_ != 0) {
119+
errno = forced_errno_;
120+
return NULL;
121+
}
122+
errno = ENOENT;
123+
return NULL;
124+
}
125+
MOCKING_UTILS_PATCH_TYPE(N, opendir) opendir_mock_;
126+
#else
127+
HANDLE do_FindFirstFile(LPCSTR, LPWIN32_FIND_DATAA)
128+
{
129+
if (forced_errno_ != 0) {
130+
SetLastError(forced_errno_);
131+
return INVALID_HANDLE_VALUE;
132+
}
133+
SetLastError(ERROR_FILE_NOT_FOUND);
134+
return INVALID_HANDLE_VALUE;
135+
}
136+
137+
MOCKING_UTILS_PATCH_TYPE(N, FindFirstFile) find_first_file_mock_;
138+
#endif
139+
140+
#ifndef _GNU_SOURCE
141+
int do_stat(const char * path, struct stat * info)
142+
{
143+
#else
144+
int do___xstat(int, const char * path, struct stat * info)
145+
{
146+
#endif
147+
if (files_info_.count(path) == 0) {
148+
errno = ENOENT;
149+
return -1;
150+
}
151+
*info = files_info_[path];
152+
return 0;
153+
}
154+
155+
#ifndef _GNU_SOURCE
156+
MOCKING_UTILS_PATCH_TYPE(N, stat) stat_mock_;
157+
#else
158+
MOCKING_UTILS_PATCH_TYPE(N, __xstat) __xstat_mock_;
159+
#endif
160+
161+
int forced_errno_{0};
162+
std::map<std::string, struct stat> files_info_;
163+
};
164+
165+
} // namespace filesystem
166+
167+
/// Patch filesystem API, based on `what` binary object should be affected.
168+
#define patch_filesystem(what) filesystem::FileSystem<__COUNTER__>(what)
169+
170+
} // namespace mocking_utils
171+
172+
#endif // MOCKING_UTILS__FILESYSTEM_HPP_

0 commit comments

Comments
 (0)