Add support for std::function in MockFunction (#2277)
This commit is contained in:
		@@ -1786,10 +1786,80 @@ 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);
 | 
			
		||||
@@ -1823,49 +1893,33 @@ 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;
 | 
			
		||||
 | 
			
		||||
template <typename R, typename... Args>
 | 
			
		||||
class MockFunction<R(Args...)> {
 | 
			
		||||
class MockFunction : public internal::MockFunction<internal::SignatureOfT<F>> {
 | 
			
		||||
  using Base = internal::MockFunction<internal::SignatureOfT<F>>;
 | 
			
		||||
 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
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,7 @@
 | 
			
		||||
# include <objbase.h>
 | 
			
		||||
#endif  // GTEST_OS_WINDOWS
 | 
			
		||||
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
@@ -802,12 +803,30 @@ using MockMethodMockFunctionSignatureTypes = Types<
 | 
			
		||||
>;
 | 
			
		||||
TYPED_TEST_SUITE(MockMethodMockFunctionSignatureTest, MockMethodMockFunctionSignatureTypes);
 | 
			
		||||
 | 
			
		||||
TYPED_TEST(MockMethodMockFunctionSignatureTest, IsMockFunctionTemplateArgumentDeduced) {
 | 
			
		||||
TYPED_TEST(MockMethodMockFunctionSignatureTest, IsMockFunctionTemplateArgumentDeducedForRawSignature) {
 | 
			
		||||
  using Argument = TypeParam;
 | 
			
		||||
  MockFunction<Argument> foo;
 | 
			
		||||
  EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<Argument>(foo));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TYPED_TEST(MockMethodMockFunctionSignatureTest, IsMockFunctionTemplateArgumentDeducedForStdFunction) {
 | 
			
		||||
  using Argument = std::function<TypeParam>;
 | 
			
		||||
  MockFunction<Argument> foo;
 | 
			
		||||
  EXPECT_TRUE(IsMockFunctionTemplateArgumentDeducedTo<Argument>(foo));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TYPED_TEST(MockMethodMockFunctionSignatureTest, IsMockFunctionCallMethodSignatureTheSameForRawSignatureAndStdFunction) {
 | 
			
		||||
  using ForRawSignature = decltype(&MockFunction<TypeParam>::Call);
 | 
			
		||||
  using ForStdFunction = decltype(&MockFunction<std::function<TypeParam>>::Call);
 | 
			
		||||
  EXPECT_TRUE((std::is_same<ForRawSignature, ForStdFunction>::value));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TYPED_TEST(MockMethodMockFunctionSignatureTest, IsMockFunctionAsStdFunctionMethodSignatureTheSameForRawSignatureAndStdFunction) {
 | 
			
		||||
  using ForRawSignature = decltype(&MockFunction<TypeParam>::AsStdFunction);
 | 
			
		||||
  using ForStdFunction = decltype(&MockFunction<std::function<TypeParam>>::AsStdFunction);
 | 
			
		||||
  EXPECT_TRUE((std::is_same<ForRawSignature, ForStdFunction>::value));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct MockMethodSizes0 {
 | 
			
		||||
  MOCK_METHOD(void, func, ());
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user