blob: 0a7de742b19ccaa4766c9462c20e58fe92c1684b [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_TEST_GMOCK_MOVE_SUPPORT_H_
#define BASE_TEST_GMOCK_MOVE_SUPPORT_H_
#include <cstddef>
#include <tuple>
#include <utility>
// A similar action as testing::SaveArg, but it does an assignment with
// std::move() instead of always performing a copy.
template <size_t I = 0, typename T>
auto MoveArg(T* out) {
return [out](auto&&... args) {
*out = std::move(std::get<I>(std::tie(args...)));
};
}
// Moves the `I`th argument to `*out` and returns `return_value`.
// This addresses that `DoAll(MoveArg(), Return())` does not work for moveable
// types passed by value, since the first action only receives a read-only view
// of its arguments.
//
// Example:
//
// using MoveOnly = std::unique<int>;
// struct MockFoo {
// MOCK_METHOD(bool, Fun, (MoveOnly), ());
// };
//
// MoveOnly result;
// MockFoo foo;
// EXPECT_CALL(foo, Fun).WillOnce(MoveArgAndReturn(&result, true));
// EXPECT_TRUE(foo.Fun(std::make_unique<int>(123)));
// EXPECT_THAT(result, testing::Pointee(123));
template <size_t I = 0, typename T1, typename T2>
auto MoveArgAndReturn(T1* out, T2&& return_value) {
return [out, value = std::forward<T2>(return_value)](auto&&... args) mutable {
*out = std::move(std::get<I>(std::tie(args...)));
return std::forward<T2>(value);
};
}
#endif // BASE_TEST_GMOCK_MOVE_SUPPORT_H_