Skip to content

Commit

Permalink
Complete subscription API test coverage (#734)
Browse files Browse the repository at this point in the history
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
  • Loading branch information
hidmic authored Aug 12, 2020
1 parent e998571 commit c749682
Show file tree
Hide file tree
Showing 4 changed files with 421 additions and 83 deletions.
8 changes: 4 additions & 4 deletions rcl/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@
<test_depend>ament_cmake_gtest</test_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<test_depend>mimick_vendor</test_depend>
<test_depend>rcpputils</test_depend>
<test_depend>rmw</test_depend>
<test_depend>rmw_implementation_cmake</test_depend>
<test_depend>launch</test_depend>
<test_depend>launch_testing</test_depend>
<test_depend>launch_testing_ament_cmake</test_depend>
<test_depend>mimick_vendor</test_depend>
<test_depend>osrf_testing_tools_cpp</test_depend>
<test_depend>rcpputils</test_depend>
<test_depend>rmw</test_depend>
<test_depend>rmw_implementation_cmake</test_depend>
<test_depend>test_msgs</test_depend>

<group_depend>rcl_logging_packages</group_depend>
Expand Down
3 changes: 2 additions & 1 deletion rcl/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
find_package(ament_cmake_gtest REQUIRED)
find_package(launch_testing_ament_cmake REQUIRED)

find_package(mimick_vendor REQUIRED)
find_package(test_msgs REQUIRED)

find_package(mimick_vendor REQUIRED)
Expand Down Expand Up @@ -225,7 +226,7 @@ function(test_target_function)
SRCS rcl/test_subscription.cpp rcl/wait_for_entity_helpers.cpp
ENV ${rmw_implementation_env_var}
APPEND_LIBRARY_DIRS ${extra_lib_dirs}
LIBRARIES ${PROJECT_NAME}
LIBRARIES ${PROJECT_NAME} mimick
AMENT_DEPENDENCIES ${rmw_implementation} "osrf_testing_tools_cpp" "test_msgs"
)
if(rmw_implementation STREQUAL "rmw_fastrtps_cpp" OR
Expand Down
55 changes: 38 additions & 17 deletions rcl/test/mocking_utils/patch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,8 @@ class Patch<ID, ReturnT(ArgTs...)>
* \return a mocking_utils::Patch instance.
*/
explicit Patch(const std::string & target, std::function<ReturnT(ArgTs...)> proxy)
: proxy_(proxy)
: target_(target), proxy_(proxy)
{
auto MMK_MANGLE(mock_type, create) =
PatchTraits<ID, ReturnT(ArgTs...)>::MMK_MANGLE(mock_type, create);
mock_ = mmk_mock(target.c_str(), mock_type);
}

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

/// Inject a @p replacement for the patched function.
Patch && then_call(std::function<ReturnT(ArgTs...)> replacement) &&
{
auto type_erased_trampoline =
reinterpret_cast<mmk_fn>(prepare_trampoline<ID>(replacement));
mmk_when(proxy_(any<ArgTs>()...), .then_call = type_erased_trampoline);
replace_with(replacement);
return std::move(*this);
}

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

mock_type mock_;
void replace_with(std::function<ReturnT(ArgTs...)> replacement)
{
if (mock_) {
throw std::logic_error("Cannot configure patch more than once");
}
auto type_erased_trampoline =
reinterpret_cast<mmk_fn>(prepare_trampoline<ID>(replacement));
auto MMK_MANGLE(mock_type, create) =
PatchTraits<ID, ReturnT(ArgTs...)>::MMK_MANGLE(mock_type, create);
mock_ = mmk_mock(target_.c_str(), mock_type);
mmk_when(proxy_(any<ArgTs>()...), .then_call = type_erased_trampoline);
}

mock_type mock_{nullptr};
std::string target_;
std::function<ReturnT(ArgTs...)> proxy_;
};

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

/// Patch a `function` with a used-provided `replacement` in a given `scope`.
#define patch(scope, function, replacement) \
/// Prepare a mocking_utils::Patch for patching a `function` in a given `scope`
/// but defer applying any changes.
#define prepare_patch(scope, function) \
make_patch<__COUNTER__, decltype(function)>( \
MOCKING_UTILS_PATCH_TARGET(scope, function), MOCKING_UTILS_PATCH_PROXY(function) \
).then_call(replacement)
)

/// Patch a function with a function that only returns a value
#define patch_and_return(scope, function, return_value) \
patch(scope, function, [&](auto && ...) {return return_value;})
/// Patch a `function` with a used-provided `replacement` in a given `scope`.
#define patch(scope, function, replacement) \
prepare_patch(scope, function).then_call(replacement)

/// Patch a `function` to always yield a given `return_code` in a given `scope`.
#define patch_and_return(scope, function, return_code) \
patch(scope, function, [&](auto && ...) {return return_code;})

/// Patch a `function` to execute normally but always yield a given `return_code`
/// in a given `scope`.
#define inject_on_return(scope, function, return_code) \
patch( \
scope, function, ([&, base = function](auto && ... __args) { \
static_cast<void>(base(std::forward<decltype(__args)>(__args)...)); \
return return_code; \
}))

} // namespace mocking_utils

Expand Down
Loading

0 comments on commit c749682

Please sign in to comment.