summaryrefslogtreecommitdiffstats
path: root/googlemock
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2020-08-17 16:07:02 (GMT)
committervslashg <gfalcon@google.com>2020-08-24 03:50:54 (GMT)
commitfc1e7788993bd1418f80d64eb430bd9ac023db68 (patch)
tree635927e3cece061c1c042d90c1ef71f32b0b8098 /googlemock
parentadeef192947fbc0f68fa14a6c494c8df32177508 (diff)
downloadgoogletest-fc1e7788993bd1418f80d64eb430bd9ac023db68.zip
googletest-fc1e7788993bd1418f80d64eb430bd9ac023db68.tar.gz
googletest-fc1e7788993bd1418f80d64eb430bd9ac023db68.tar.bz2
Googletest export
Fix DoAll to work with move-only sink arguments. This changes types of the first n - 1 actions so that they only get a readonly view of the arguments. The last action will accept move only objects. PiperOrigin-RevId: 327031893
Diffstat (limited to 'googlemock')
-rw-r--r--googlemock/docs/cheat_sheet.md2
-rw-r--r--googlemock/include/gmock/gmock-actions.h23
-rw-r--r--googlemock/test/gmock-generated-actions_test.cc27
3 files changed, 42 insertions, 10 deletions
diff --git a/googlemock/docs/cheat_sheet.md b/googlemock/docs/cheat_sheet.md
index 2500260..cc7e699 100644
--- a/googlemock/docs/cheat_sheet.md
+++ b/googlemock/docs/cheat_sheet.md
@@ -618,7 +618,7 @@ composite action - trying to do so will result in a run-time error.
<!-- mdformat off(no multiline tables) -->
| | |
| :----------------------------- | :------------------------------------------ |
-| `DoAll(a1, a2, ..., an)` | Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void. |
+| `DoAll(a1, a2, ..., an)` | Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void and will receive a readonly view of the arguments. |
| `IgnoreResult(a)` | Perform action `a` and ignore its result. `a` must not return void. |
| `WithArg<N>(a)` | Pass the `N`-th (0-based) argument of the mock function to action `a` and perform it. |
| `WithArgs<N1, N2, ..., Nk>(a)` | Pass the selected (0-based) arguments of the mock function to action `a` and perform it. |
diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h
index 79054db..3aba9ec 100644
--- a/googlemock/include/gmock/gmock-actions.h
+++ b/googlemock/include/gmock/gmock-actions.h
@@ -1032,9 +1032,13 @@ struct WithArgsAction {
template <typename... Actions>
struct DoAllAction {
private:
- template <typename... Args, size_t... I>
- std::vector<Action<void(Args...)>> Convert(IndexSequence<I...>) const {
- return {std::get<I>(actions)...};
+ template <typename T>
+ using NonFinalType =
+ typename std::conditional<std::is_scalar<T>::value, T, const T&>::type;
+
+ template <typename ActionT, size_t... I>
+ std::vector<ActionT> Convert(IndexSequence<I...>) const {
+ return {ActionT(std::get<I>(actions))...};
}
public:
@@ -1043,17 +1047,17 @@ struct DoAllAction {
template <typename R, typename... Args>
operator Action<R(Args...)>() const { // NOLINT
struct Op {
- std::vector<Action<void(Args...)>> converted;
+ std::vector<Action<void(NonFinalType<Args>...)>> converted;
Action<R(Args...)> last;
R operator()(Args... args) const {
- auto tuple_args = std::forward_as_tuple(std::forward<Args>(args)...);
for (auto& a : converted) {
- a.Perform(tuple_args);
+ a.Perform(std::forward_as_tuple(std::forward<Args>(args)...));
}
- return last.Perform(tuple_args);
+ return last.Perform(std::forward_as_tuple(std::forward<Args>(args)...));
}
};
- return Op{Convert<Args...>(MakeIndexSequence<sizeof...(Actions) - 1>()),
+ return Op{Convert<Action<void(NonFinalType<Args>...)>>(
+ MakeIndexSequence<sizeof...(Actions) - 1>()),
std::get<sizeof...(Actions) - 1>(actions)};
}
};
@@ -1093,7 +1097,8 @@ struct DoAllAction {
typedef internal::IgnoredValue Unused;
// Creates an action that does actions a1, a2, ..., sequentially in
-// each invocation.
+// each invocation. All but the last action will have a readonly view of the
+// arguments.
template <typename... Action>
internal::DoAllAction<typename std::decay<Action>::type...> DoAll(
Action&&... action) {
diff --git a/googlemock/test/gmock-generated-actions_test.cc b/googlemock/test/gmock-generated-actions_test.cc
index ef39dff..6490616 100644
--- a/googlemock/test/gmock-generated-actions_test.cc
+++ b/googlemock/test/gmock-generated-actions_test.cc
@@ -422,6 +422,33 @@ TEST(DoAllTest, TenActions) {
EXPECT_EQ('g', g);
}
+TEST(DoAllTest, NoArgs) {
+ bool ran_first = false;
+ Action<bool()> a =
+ DoAll([&] { ran_first = true; }, [&] { return ran_first; });
+ EXPECT_TRUE(a.Perform({}));
+}
+
+TEST(DoAllTest, MoveOnlyArgs) {
+ bool ran_first = false;
+ Action<int(std::unique_ptr<int>)> a =
+ DoAll(InvokeWithoutArgs([&] { ran_first = true; }),
+ [](std::unique_ptr<int> p) { return *p; });
+ EXPECT_EQ(7, a.Perform(std::make_tuple(std::unique_ptr<int>(new int(7)))));
+ EXPECT_TRUE(ran_first);
+}
+
+TEST(DoAllTest, ImplicitlyConvertsActionArguments) {
+ bool ran_first = false;
+ // Action<void(std::vector<int>)> isn't an
+ // Action<void(const std::vector<int>&) but can be converted.
+ Action<void(std::vector<int>)> first = [&] { ran_first = true; };
+ Action<int(std::vector<int>)> a =
+ DoAll(first, [](std::vector<int> arg) { return arg.front(); });
+ EXPECT_EQ(7, a.Perform(std::make_tuple(std::vector<int>{7})));
+ EXPECT_TRUE(ran_first);
+}
+
// The ACTION*() macros trigger warning C4100 (unreferenced formal
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
// the macro definition, as the warnings are generated when the macro