mirror of
https://github.com/google/googletest.git
synced 2024-12-28 19:15:24 +08:00
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
This commit is contained in:
parent
adeef19294
commit
fc1e778899
@ -618,7 +618,7 @@ composite action - trying to do so will result in a run-time error.
|
|||||||
<!-- mdformat off(no multiline tables) -->
|
<!-- 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. |
|
| `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. |
|
| `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. |
|
| `WithArgs<N1, N2, ..., Nk>(a)` | Pass the selected (0-based) arguments of the mock function to action `a` and perform it. |
|
||||||
|
@ -1032,9 +1032,13 @@ struct WithArgsAction {
|
|||||||
template <typename... Actions>
|
template <typename... Actions>
|
||||||
struct DoAllAction {
|
struct DoAllAction {
|
||||||
private:
|
private:
|
||||||
template <typename... Args, size_t... I>
|
template <typename T>
|
||||||
std::vector<Action<void(Args...)>> Convert(IndexSequence<I...>) const {
|
using NonFinalType =
|
||||||
return {std::get<I>(actions)...};
|
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:
|
public:
|
||||||
@ -1043,17 +1047,17 @@ struct DoAllAction {
|
|||||||
template <typename R, typename... Args>
|
template <typename R, typename... Args>
|
||||||
operator Action<R(Args...)>() const { // NOLINT
|
operator Action<R(Args...)>() const { // NOLINT
|
||||||
struct Op {
|
struct Op {
|
||||||
std::vector<Action<void(Args...)>> converted;
|
std::vector<Action<void(NonFinalType<Args>...)>> converted;
|
||||||
Action<R(Args...)> last;
|
Action<R(Args...)> last;
|
||||||
R operator()(Args... args) const {
|
R operator()(Args... args) const {
|
||||||
auto tuple_args = std::forward_as_tuple(std::forward<Args>(args)...);
|
|
||||||
for (auto& a : converted) {
|
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)};
|
std::get<sizeof...(Actions) - 1>(actions)};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1093,7 +1097,8 @@ struct DoAllAction {
|
|||||||
typedef internal::IgnoredValue Unused;
|
typedef internal::IgnoredValue Unused;
|
||||||
|
|
||||||
// Creates an action that does actions a1, a2, ..., sequentially in
|
// 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>
|
template <typename... Action>
|
||||||
internal::DoAllAction<typename std::decay<Action>::type...> DoAll(
|
internal::DoAllAction<typename std::decay<Action>::type...> DoAll(
|
||||||
Action&&... action) {
|
Action&&... action) {
|
||||||
|
@ -422,6 +422,33 @@ TEST(DoAllTest, TenActions) {
|
|||||||
EXPECT_EQ('g', g);
|
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
|
// The ACTION*() macros trigger warning C4100 (unreferenced formal
|
||||||
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
|
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
|
||||||
// the macro definition, as the warnings are generated when the macro
|
// the macro definition, as the warnings are generated when the macro
|
||||||
|
Loading…
x
Reference in New Issue
Block a user