aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Jacobs <jacobsa@google.com>2022-05-10 20:08:19 -0700
committerCopybara-Service <copybara-worker@google.com>2022-05-10 20:08:51 -0700
commit6386897feb0a3f4fbe104fe1fa4570ec8158d9e5 (patch)
treecb6d08bbb74311f40fb3784b50c60b8478ee0ab6
parentbda85449f48f2d80a494c8c07766b6aba3170f3b (diff)
downloadgoogletest-6386897feb0a3f4fbe104fe1fa4570ec8158d9e5.zip
googletest-6386897feb0a3f4fbe104fe1fa4570ec8158d9e5.tar.gz
googletest-6386897feb0a3f4fbe104fe1fa4570ec8158d9e5.tar.bz2
gmock-actions: make OnceAction public.
So that it can be referenced in conversion operators for actions that need to know the concrete return type. PiperOrigin-RevId: 447889344 Change-Id: I643d3298bc8effd08741282a956c221f9d67d378
-rw-r--r--docs/gmock_cook_book.md63
-rw-r--r--googlemock/include/gmock/gmock-actions.h14
-rw-r--r--googlemock/test/gmock-actions_test.cc2
3 files changed, 59 insertions, 20 deletions
diff --git a/docs/gmock_cook_book.md b/docs/gmock_cook_book.md
index bf52fa8..b6abffa 100644
--- a/docs/gmock_cook_book.md
+++ b/docs/gmock_cook_book.md
@@ -3812,22 +3812,19 @@ Cardinality EvenNumber() {
.Times(EvenNumber());
```
-### Writing New Actions Quickly {#QuickNewActions}
+### Writing New Actions {#QuickNewActions}
If the built-in actions don't work for you, you can easily define your own one.
-Just define a functor class with a (possibly templated) call operator, matching
-the signature of your action.
+All you need is a call operator with a signature compatible with the mocked
+function. So you can use a lambda:
-```cpp
-struct Increment {
- template <typename T>
- T operator()(T* arg) {
- return ++(*arg);
- }
-}
+```
+MockFunction<int(int)> mock;
+EXPECT_CALL(mock, Call).WillOnce([](const int input) { return input * 7; });
+EXPECT_EQ(14, mock.AsStdFunction()(2));
```
-The same approach works with stateful functors (or any callable, really):
+Or a struct with a call operator (even a templated one):
```
struct MultiplyBy {
@@ -3835,12 +3832,54 @@ struct MultiplyBy {
T operator()(T arg) { return arg * multiplier; }
int multiplier;
-}
+};
// Then use:
// EXPECT_CALL(...).WillOnce(MultiplyBy{7});
```
+It's also fine for the callable to take no arguments, ignoring the arguments
+supplied to the mock function:
+
+```
+MockFunction<int(int)> mock;
+EXPECT_CALL(mock, Call).WillOnce([] { return 17; });
+EXPECT_EQ(17, mock.AsStdFunction()(0));
+```
+
+When used with `WillOnce`, the callable can assume it will be called at most
+once and is allowed to be a move-only type:
+
+```
+// An action that contains move-only types and has an &&-qualified operator,
+// demanding in the type system that it be called at most once. This can be
+// used with WillOnce, but the compiler will reject it if handed to
+// WillRepeatedly.
+struct MoveOnlyAction {
+ std::unique_ptr<int> move_only_state;
+ std::unique_ptr<int> operator()() && { return std::move(move_only_state); }
+};
+
+MockFunction<std::unique_ptr<int>()> mock;
+EXPECT_CALL(mock, Call).WillOnce(MoveOnlyAction{std::make_unique<int>(17)});
+EXPECT_THAT(mock.AsStdFunction()(), Pointee(Eq(17)));
+```
+
+More generally, to use with a mock function whose signature is `R(Args...)` the
+object can be anything convertible to `OnceAction<R(Args...)>` or
+`Action<R(Args...)`>. The difference between the two is that `OnceAction` has
+weaker requirements (`Action` requires a copy-constructible input that can be
+called repeatedly whereas `OnceAction` requires only move-constructible and
+supports `&&`-qualified call operators), but can be used only with `WillOnce`.
+`OnceAction` is typically relevant only when supporting move-only types or
+actions that want a type-system guarantee that they will be called at most once.
+
+Typically the `OnceAction` and `Action` templates need not be referenced
+directly in your actions: a struct or class with a call operator is sufficient,
+as in the examples above. But fancier polymorphic actions that need to know the
+specific return type of the mock function can define templated conversion
+operators to make that possible. See `gmock-actions.h` for examples.
+
#### Legacy macro-based Actions
Before C++11, the functor-based actions were not supported; the old way of
diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h
index c83a99a..e022c12 100644
--- a/googlemock/include/gmock/gmock-actions.h
+++ b/googlemock/include/gmock/gmock-actions.h
@@ -322,16 +322,18 @@ struct is_callable_r_impl<void_t<call_result_t<F, Args...>>, R, F, Args...>
template <typename R, typename F, typename... Args>
using is_callable_r = is_callable_r_impl<void, R, F, Args...>;
+} // namespace internal
+
// Specialized for function types below.
template <typename F>
class OnceAction;
// An action that can only be used once.
//
-// This is what is accepted by WillOnce, which doesn't require the underlying
-// action to be copy-constructible (only move-constructible), and promises to
-// invoke it as an rvalue reference. This allows the action to work with
-// move-only types like std::move_only_function in a type-safe manner.
+// This is accepted by WillOnce, which doesn't require the underlying action to
+// be copy-constructible (only move-constructible), and promises to invoke it as
+// an rvalue reference. This allows the action to work with move-only types like
+// std::move_only_function in a type-safe manner.
//
// For example:
//
@@ -501,8 +503,6 @@ class OnceAction<Result(Args...)> final {
std::function<Result(Args...)> function_;
};
-} // namespace internal
-
// When an unexpected function call is encountered, Google Mock will
// let it return a default value if the user has specified one for its
// return type, or if the return type has a built-in default value;
@@ -742,7 +742,7 @@ class Action<R(Args...)> {
// An action can be used as a OnceAction, since it's obviously safe to call it
// once.
- operator internal::OnceAction<F>() const { // NOLINT
+ operator OnceAction<F>() const { // NOLINT
// Return a OnceAction-compatible callable that calls Perform with the
// arguments it is provided. We could instead just return fun_, but then
// we'd need to handle the IsDoDefault() case separately.
diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc
index db112f1..7313b78 100644
--- a/googlemock/test/gmock-actions_test.cc
+++ b/googlemock/test/gmock-actions_test.cc
@@ -1920,7 +1920,7 @@ TEST(MockMethodTest, ActionSwallowsAllArguments) {
struct ActionWithTemplatedConversionOperators {
template <typename... Args>
- operator internal::OnceAction<int(Args...)>() && { // NOLINT
+ operator OnceAction<int(Args...)>() && { // NOLINT
return [] { return 17; };
}