Skip to content

Commit

Permalink
Support move-only and &&-qualified actions in WithArgs.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 444671005
Change-Id: I7df5f038caf17afb60d4fb35434ff0b656d4c954
  • Loading branch information
jacobsa authored and Copybara-Service committed Apr 26, 2022
1 parent e33c2b2 commit c144d78
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 9 deletions.
57 changes: 50 additions & 7 deletions googlemock/include/gmock/gmock-actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -1279,17 +1279,60 @@ class IgnoreResultAction {

template <typename InnerAction, size_t... I>
struct WithArgsAction {
InnerAction action;
InnerAction inner_action;

// The inner action could be anything convertible to Action<X>.
// We use the conversion operator to detect the signature of the inner Action.
// The signature of the function as seen by the inner action, given an out
// action with the given result and argument types.
template <typename R, typename... Args>
using InnerSignature =
R(typename std::tuple_element<I, std::tuple<Args...>>::type...);

// Rather than a call operator, we must define conversion operators to
// particular action types. This is necessary for embedded actions like
// DoDefault(), which rely on an action conversion operators rather than
// providing a call operator because even with a particular set of arguments
// they don't have a fixed return type.

template <typename R, typename... Args,
typename std::enable_if<
std::is_convertible<
InnerAction,
// Unfortunately we can't use the InnerSignature alias here;
// MSVC complains about the I parameter pack not being
// expanded (error C3520) despite it being expanded in the
// type alias.
OnceAction<R(typename std::tuple_element<
I, std::tuple<Args...>>::type...)>>::value,
int>::type = 0>
operator OnceAction<R(Args...)>() && { // NOLINT
struct OA {
OnceAction<InnerSignature<R, Args...>> inner_action;

R operator()(Args&&... args) && {
return std::move(inner_action)
.Call(std::get<I>(
std::forward_as_tuple(std::forward<Args>(args)...))...);
}
};

return OA{std::move(inner_action)};
}

template <typename R, typename... Args,
typename std::enable_if<
std::is_convertible<
const InnerAction&,
// Unfortunately we can't use the InnerSignature alias here;
// MSVC complains about the I parameter pack not being
// expanded (error C3520) despite it being expanded in the
// type alias.
Action<R(typename std::tuple_element<
I, std::tuple<Args...>>::type...)>>::value,
int>::type = 0>
operator Action<R(Args...)>() const { // NOLINT
using TupleType = std::tuple<Args...>;
Action<R(typename std::tuple_element<I, TupleType>::type...)> converted(
action);
Action<InnerSignature<R, Args...>> converted(inner_action);

return [converted](Args... args) -> R {
return [converted](Args&&... args) -> R {
return converted.Perform(std::forward_as_tuple(
std::get<I>(std::forward_as_tuple(std::forward<Args>(args)...))...));
};
Expand Down
25 changes: 23 additions & 2 deletions googlemock/test/gmock-actions_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1444,8 +1444,29 @@ TEST(WithArgsTest, ReturnReference) {

TEST(WithArgsTest, InnerActionWithConversion) {
Action<Derived*()> inner = [] { return nullptr; };
Action<Base*(double)> a = testing::WithoutArgs(inner);
EXPECT_EQ(nullptr, a.Perform(std::make_tuple(1.1)));

MockFunction<Base*(double)> mock;
EXPECT_CALL(mock, Call)
.WillOnce(WithoutArgs(inner))
.WillRepeatedly(WithoutArgs(inner));

EXPECT_EQ(nullptr, mock.AsStdFunction()(1.1));
EXPECT_EQ(nullptr, mock.AsStdFunction()(1.1));
}

// It should be possible to use an &&-qualified inner action as long as the
// whole shebang is used as an rvalue with WillOnce.
TEST(WithArgsTest, RefQualifiedInnerAction) {
struct SomeAction {
int operator()(const int arg) && {
EXPECT_EQ(17, arg);
return 19;
}
};

MockFunction<int(int, int)> mock;
EXPECT_CALL(mock, Call).WillOnce(WithArg<1>(SomeAction{}));
EXPECT_EQ(19, mock.AsStdFunction()(0, 17));
}

#if !GTEST_OS_WINDOWS_MOBILE
Expand Down

0 comments on commit c144d78

Please sign in to comment.