Skip to content

Commit c749682

Browse files
authored
Complete subscription API test coverage (#734)
Signed-off-by: Michel Hidalgo <[email protected]>
1 parent e998571 commit c749682

File tree

4 files changed

+421
-83
lines changed

4 files changed

+421
-83
lines changed

rcl/package.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@
2525
<test_depend>ament_cmake_gtest</test_depend>
2626
<test_depend>ament_lint_auto</test_depend>
2727
<test_depend>ament_lint_common</test_depend>
28-
<test_depend>mimick_vendor</test_depend>
29-
<test_depend>rcpputils</test_depend>
30-
<test_depend>rmw</test_depend>
31-
<test_depend>rmw_implementation_cmake</test_depend>
3228
<test_depend>launch</test_depend>
3329
<test_depend>launch_testing</test_depend>
3430
<test_depend>launch_testing_ament_cmake</test_depend>
31+
<test_depend>mimick_vendor</test_depend>
3532
<test_depend>osrf_testing_tools_cpp</test_depend>
33+
<test_depend>rcpputils</test_depend>
34+
<test_depend>rmw</test_depend>
35+
<test_depend>rmw_implementation_cmake</test_depend>
3636
<test_depend>test_msgs</test_depend>
3737

3838
<group_depend>rcl_logging_packages</group_depend>

rcl/test/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
find_package(ament_cmake_gtest REQUIRED)
22
find_package(launch_testing_ament_cmake REQUIRED)
33

4+
find_package(mimick_vendor REQUIRED)
45
find_package(test_msgs REQUIRED)
56

67
find_package(mimick_vendor REQUIRED)
@@ -225,7 +226,7 @@ function(test_target_function)
225226
SRCS rcl/test_subscription.cpp rcl/wait_for_entity_helpers.cpp
226227
ENV ${rmw_implementation_env_var}
227228
APPEND_LIBRARY_DIRS ${extra_lib_dirs}
228-
LIBRARIES ${PROJECT_NAME}
229+
LIBRARIES ${PROJECT_NAME} mimick
229230
AMENT_DEPENDENCIES ${rmw_implementation} "osrf_testing_tools_cpp" "test_msgs"
230231
)
231232
if(rmw_implementation STREQUAL "rmw_fastrtps_cpp" OR

rcl/test/mocking_utils/patch.hpp

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,8 @@ class Patch<ID, ReturnT(ArgTs...)>
219219
* \return a mocking_utils::Patch instance.
220220
*/
221221
explicit Patch(const std::string & target, std::function<ReturnT(ArgTs...)> proxy)
222-
: proxy_(proxy)
222+
: target_(target), proxy_(proxy)
223223
{
224-
auto MMK_MANGLE(mock_type, create) =
225-
PatchTraits<ID, ReturnT(ArgTs...)>::MMK_MANGLE(mock_type, create);
226-
mock_ = mmk_mock(target.c_str(), mock_type);
227224
}
228225

229226
// Copy construction and assignment are disabled.
@@ -255,18 +252,14 @@ class Patch<ID, ReturnT(ArgTs...)>
255252
/// Inject a @p replacement for the patched function.
256253
Patch & then_call(std::function<ReturnT(ArgTs...)> replacement) &
257254
{
258-
auto type_erased_trampoline =
259-
reinterpret_cast<mmk_fn>(prepare_trampoline<ID>(replacement));
260-
mmk_when(proxy_(any<ArgTs>()...), .then_call = type_erased_trampoline);
255+
replace_with(replacement);
261256
return *this;
262257
}
263258

264259
/// Inject a @p replacement for the patched function.
265260
Patch && then_call(std::function<ReturnT(ArgTs...)> replacement) &&
266261
{
267-
auto type_erased_trampoline =
268-
reinterpret_cast<mmk_fn>(prepare_trampoline<ID>(replacement));
269-
mmk_when(proxy_(any<ArgTs>()...), .then_call = type_erased_trampoline);
262+
replace_with(replacement);
270263
return std::move(*this);
271264
}
272265

@@ -276,7 +269,21 @@ class Patch<ID, ReturnT(ArgTs...)>
276269
template<typename T>
277270
T any() {return mmk_any(T);}
278271

279-
mock_type mock_;
272+
void replace_with(std::function<ReturnT(ArgTs...)> replacement)
273+
{
274+
if (mock_) {
275+
throw std::logic_error("Cannot configure patch more than once");
276+
}
277+
auto type_erased_trampoline =
278+
reinterpret_cast<mmk_fn>(prepare_trampoline<ID>(replacement));
279+
auto MMK_MANGLE(mock_type, create) =
280+
PatchTraits<ID, ReturnT(ArgTs...)>::MMK_MANGLE(mock_type, create);
281+
mock_ = mmk_mock(target_.c_str(), mock_type);
282+
mmk_when(proxy_(any<ArgTs>()...), .then_call = type_erased_trampoline);
283+
}
284+
285+
mock_type mock_{nullptr};
286+
std::string target_;
280287
std::function<ReturnT(ArgTs...)> proxy_;
281288
};
282289

@@ -332,15 +339,29 @@ auto make_patch(const std::string & target, std::function<SignatureT> proxy)
332339
#define MOCKING_UTILS_PATCH_TARGET(scope, function) \
333340
(std::string(RCUTILS_STRINGIFY(function)) + "@" + (scope))
334341

335-
/// Patch a `function` with a used-provided `replacement` in a given `scope`.
336-
#define patch(scope, function, replacement) \
342+
/// Prepare a mocking_utils::Patch for patching a `function` in a given `scope`
343+
/// but defer applying any changes.
344+
#define prepare_patch(scope, function) \
337345
make_patch<__COUNTER__, decltype(function)>( \
338346
MOCKING_UTILS_PATCH_TARGET(scope, function), MOCKING_UTILS_PATCH_PROXY(function) \
339-
).then_call(replacement)
347+
)
340348

341-
/// Patch a function with a function that only returns a value
342-
#define patch_and_return(scope, function, return_value) \
343-
patch(scope, function, [&](auto && ...) {return return_value;})
349+
/// Patch a `function` with a used-provided `replacement` in a given `scope`.
350+
#define patch(scope, function, replacement) \
351+
prepare_patch(scope, function).then_call(replacement)
352+
353+
/// Patch a `function` to always yield a given `return_code` in a given `scope`.
354+
#define patch_and_return(scope, function, return_code) \
355+
patch(scope, function, [&](auto && ...) {return return_code;})
356+
357+
/// Patch a `function` to execute normally but always yield a given `return_code`
358+
/// in a given `scope`.
359+
#define inject_on_return(scope, function, return_code) \
360+
patch( \
361+
scope, function, ([&, base = function](auto && ... __args) { \
362+
static_cast<void>(base(std::forward<decltype(__args)>(__args)...)); \
363+
return return_code; \
364+
}))
344365

345366
} // namespace mocking_utils
346367

0 commit comments

Comments
 (0)