File: gmock_move_support.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (78 lines) | stat: -rw-r--r-- 2,899 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// 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>

// Moves the `I`th argument to `out`. Analogous to `testing::SaveArg()`, which
// copies instead.
//
// Example:
//
//   std::unique_ptr<int> result;
//   EXPECT_CALL(mocked_object, Method).WillOnce(MoveArg<0>(&result));
//   mocked_object.Method(std::make_unique<int>(123));
//   EXPECT_THAT(result, Pointee(Eq(123)));
//
// Important: it is not possible to use multiple `MoveArg()` actions in a single
// `DoAll()`: per the googlemock documentation, all but the last action receive
// a read-only view of the arguments. Allowing an intermediate action to consume
// the arguments would leave the original arguments in an unspecified state for
// invoking subsequent actions, which is dubious.
//
// A simple workaround is to use `Invoke()` with a lambda instead, e.g.
//
//   std::unique_ptr<int> int_result;
//   std::unique_ptr<double> double_result;
//   EXPECT_CALL(mocked_object, Method).WillOnce(Invoke(
//       [&] (auto&& arg1, auto&& arg2) {
//         int_result = std::move(arg1);
//         double_result = std::move(arg2);
//         return 42;
//       }));
//   EXPECT_EQ(42, mocked_object.Method(std::make_unique<int>(123),
//                                      std::make_unique<double>(0.5)));
//   EXPECT_THAT(int_result, Pointee(Eq(123)));
//   EXPECT_THAT(double_result, Pointee(DoubleEq(0.5)));

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 is a convenience helper for code that wants to write the following:
//
//   DoAll(MoveArg<N>(&saved_arg), Return(value))
//
// The above is not actually possible to write because:
// - `DoAll()` requires that its final action has a return type that matches the
//   mocked call's return type. So `Return()` must be last.
// - But any actions before the last receive a read-only view of the arguments.
//   So `MoveArg()` receives a read-only view and cannot move out of it.
//
// Example:
//
//   std::unique_ptr<int> result;
//   EXPECT_CALL(mocked_object, Method).WillOnce(
//       MoveArgAndReturn<0>(&result, true));
//   EXPECT_TRUE(mocked_object.Method(std::make_unique<int>(123)));
//   EXPECT_THAT(int_result, Pointee(Eq(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_