From 48ec64092a38621210ecd835fde61d76861269c1 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 3 Aug 2020 10:34:37 -0400 Subject: [PATCH] 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: 324600664 --- googlemock/docs/cheat_sheet.md | 2 +- googlemock/include/gmock/gmock-actions.h | 17 +++++++++++------ googlemock/test/gmock-generated-actions_test.cc | 9 +++++++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/googlemock/docs/cheat_sheet.md b/googlemock/docs/cheat_sheet.md index 85620f71..b47e00f3 100644 --- a/googlemock/docs/cheat_sheet.md +++ b/googlemock/docs/cheat_sheet.md @@ -616,7 +616,7 @@ composite action - trying to do so will result in a run-time error. | | | | :----------------------------- | :------------------------------------------ | -| `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(a)` | Pass the `N`-th (0-based) argument of the mock function to action `a` and perform it. | | `WithArgs(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 79054dbc..4f7c1dd4 100644 --- a/googlemock/include/gmock/gmock-actions.h +++ b/googlemock/include/gmock/gmock-actions.h @@ -1032,8 +1032,13 @@ struct WithArgsAction { template struct DoAllAction { private: + template + using NonFinalType = + typename std::conditional::value, T, const T&>::type; + template - std::vector> Convert(IndexSequence) const { + std::vector...)>> Convert( + IndexSequence) const { return {std::get(actions)...}; } @@ -1043,14 +1048,13 @@ struct DoAllAction { template operator Action() const { // NOLINT struct Op { - std::vector> converted; + std::vector...)>> converted; Action last; R operator()(Args... args) const { - auto tuple_args = std::forward_as_tuple(std::forward(args)...); for (auto& a : converted) { - a.Perform(tuple_args); + a.Perform(std::forward_as_tuple(std::forward(args)...)); } - return last.Perform(tuple_args); + return last.Perform(std::forward_as_tuple(std::forward(args)...)); } }; return Op{Convert(MakeIndexSequence()), @@ -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 internal::DoAllAction::type...> DoAll( Action&&... action) { diff --git a/googlemock/test/gmock-generated-actions_test.cc b/googlemock/test/gmock-generated-actions_test.cc index ef39dff7..3ec83e25 100644 --- a/googlemock/test/gmock-generated-actions_test.cc +++ b/googlemock/test/gmock-generated-actions_test.cc @@ -422,6 +422,15 @@ TEST(DoAllTest, TenActions) { EXPECT_EQ('g', g); } +TEST(DoAllTest, MoveOnlyArgs) { + bool ran_first = false; + Action)> a = + DoAll(InvokeWithoutArgs([&] { ran_first = true; }), + [](std::unique_ptr p) { return *p; }); + EXPECT_EQ(7, a.Perform(std::make_tuple(std::unique_ptr(new 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