aboutsummaryrefslogtreecommitdiffstats
path: root/googlemock/include/gmock/gmock-spec-builders.h
diff options
context:
space:
mode:
Diffstat (limited to 'googlemock/include/gmock/gmock-spec-builders.h')
-rw-r--r--googlemock/include/gmock/gmock-spec-builders.h138
1 files changed, 92 insertions, 46 deletions
diff --git a/googlemock/include/gmock/gmock-spec-builders.h b/googlemock/include/gmock/gmock-spec-builders.h
index 80c13b55..4b5fc661 100644
--- a/googlemock/include/gmock/gmock-spec-builders.h
+++ b/googlemock/include/gmock/gmock-spec-builders.h
@@ -1350,12 +1350,6 @@ class ReferenceOrValueWrapper<T&> {
T* value_ptr_;
};
-// MSVC warns about using 'this' in base member initializer list, so
-// we need to temporarily disable the warning. We have to do it for
-// the entire class to suppress the warning, even though it's about
-// the constructor only.
-GTEST_DISABLE_MSC_WARNINGS_PUSH_(4355)
-
// C++ treats the void type specially. For example, you cannot define
// a void-typed variable or pass a void value to a function.
// ActionResultHolder<T> holds a value of type T, where T must be a
@@ -1786,18 +1780,85 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase {
}
}; // class FunctionMocker
-GTEST_DISABLE_MSC_WARNINGS_POP_() // 4355
-
// Reports an uninteresting call (whose description is in msg) in the
// manner specified by 'reaction'.
void ReportUninterestingCall(CallReaction reaction, const std::string& msg);
} // namespace internal
-// A MockFunction<F> class has one mock method whose type is F. It is
-// useful when you just want your test code to emit some messages and
-// have Google Mock verify the right messages are sent (and perhaps at
-// the right times). For example, if you are exercising code:
+namespace internal {
+
+template <typename F>
+class MockFunction;
+
+template <typename R, typename... Args>
+class MockFunction<R(Args...)> {
+ public:
+ MockFunction(const MockFunction&) = delete;
+ MockFunction& operator=(const MockFunction&) = delete;
+
+ std::function<R(Args...)> AsStdFunction() {
+ return [this](Args... args) -> R {
+ return this->Call(std::forward<Args>(args)...);
+ };
+ }
+
+ // Implementation detail: the expansion of the MOCK_METHOD macro.
+ R Call(Args... args) {
+ mock_.SetOwnerAndName(this, "Call");
+ return mock_.Invoke(std::forward<Args>(args)...);
+ }
+
+ MockSpec<R(Args...)> gmock_Call(Matcher<Args>... m) {
+ mock_.RegisterOwner(this);
+ return mock_.With(std::move(m)...);
+ }
+
+ MockSpec<R(Args...)> gmock_Call(const WithoutMatchers&, R (*)(Args...)) {
+ return this->gmock_Call(::testing::A<Args>()...);
+ }
+
+ protected:
+ MockFunction() = default;
+ ~MockFunction() = default;
+
+ private:
+ FunctionMocker<R(Args...)> mock_;
+};
+
+/*
+The SignatureOf<F> struct is a meta-function returning function signature
+corresponding to the provided F argument.
+
+It makes use of MockFunction easier by allowing it to accept more F arguments
+than just function signatures.
+
+Specializations provided here cover only a signature type itself and
+std::function. However, if need be it can be easily extended to cover also other
+types (like for example boost::function).
+*/
+
+template <typename F>
+struct SignatureOf;
+
+template <typename R, typename... Args>
+struct SignatureOf<R(Args...)> {
+ using type = R(Args...);
+};
+
+template <typename F>
+struct SignatureOf<std::function<F>> : SignatureOf<F> {};
+
+template <typename F>
+using SignatureOfT = typename SignatureOf<F>::type;
+
+} // namespace internal
+
+// A MockFunction<F> type has one mock method whose type is
+// internal::SignatureOfT<F>. It is useful when you just want your
+// test code to emit some messages and have Google Mock verify the
+// right messages are sent (and perhaps at the right times). For
+// example, if you are exercising code:
//
// Foo(1);
// Foo(2);
@@ -1831,49 +1892,34 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg);
// Bar("a") is called by which call to Foo().
//
// MockFunction<F> can also be used to exercise code that accepts
-// std::function<F> callbacks. To do so, use AsStdFunction() method
-// to create std::function proxy forwarding to original object's Call.
-// Example:
+// std::function<internal::SignatureOfT<F>> callbacks. To do so, use
+// AsStdFunction() method to create std::function proxy forwarding to
+// original object's Call. Example:
//
// TEST(FooTest, RunsCallbackWithBarArgument) {
// MockFunction<int(string)> callback;
// EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1));
// Foo(callback.AsStdFunction());
// }
+//
+// The internal::SignatureOfT<F> indirection allows to use other types
+// than just function signature type. This is typically useful when
+// providing a mock for a predefined std::function type. Example:
+//
+// using FilterPredicate = std::function<bool(string)>;
+// void MyFilterAlgorithm(FilterPredicate predicate);
+//
+// TEST(FooTest, FilterPredicateAlwaysAccepts) {
+// MockFunction<FilterPredicate> predicateMock;
+// EXPECT_CALL(predicateMock, Call(_)).WillRepeatedly(Return(true));
+// MyFilterAlgorithm(predicateMock.AsStdFunction());
+// }
template <typename F>
-class MockFunction;
+class MockFunction : public internal::MockFunction<internal::SignatureOfT<F>> {
+ using Base = internal::MockFunction<internal::SignatureOfT<F>>;
-template <typename R, typename... Args>
-class MockFunction<R(Args...)> {
public:
- MockFunction() {}
- MockFunction(const MockFunction&) = delete;
- MockFunction& operator=(const MockFunction&) = delete;
-
- std::function<R(Args...)> AsStdFunction() {
- return [this](Args... args) -> R {
- return this->Call(std::forward<Args>(args)...);
- };
- }
-
- // Implementation detail: the expansion of the MOCK_METHOD macro.
- R Call(Args... args) {
- mock_.SetOwnerAndName(this, "Call");
- return mock_.Invoke(std::forward<Args>(args)...);
- }
-
- internal::MockSpec<R(Args...)> gmock_Call(Matcher<Args>... m) {
- mock_.RegisterOwner(this);
- return mock_.With(std::move(m)...);
- }
-
- internal::MockSpec<R(Args...)> gmock_Call(const internal::WithoutMatchers&,
- R (*)(Args...)) {
- return this->gmock_Call(::testing::A<Args>()...);
- }
-
- private:
- internal::FunctionMocker<R(Args...)> mock_;
+ using Base::Base;
};
// The style guide prohibits "using" statements in a namespace scope