diff --git a/googlemock/include/gmock/gmock-spec-builders.h b/googlemock/include/gmock/gmock-spec-builders.h index 80c13b5549..21f250f907 100644 --- a/googlemock/include/gmock/gmock-spec-builders.h +++ b/googlemock/include/gmock/gmock-spec-builders.h @@ -1794,10 +1794,77 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg); } // namespace internal -// A MockFunction 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 +class MockFunction; + +template +class MockFunction { + public: + MockFunction() {}; + MockFunction(const MockFunction&) = delete; + MockFunction& operator=(const MockFunction&) = delete; + + std::function AsStdFunction() { + return [this](Args... args) -> R { + return this->Call(std::forward(args)...); + }; + } + + // Implementation detail: the expansion of the MOCK_METHOD macro. + R Call(Args... args) { + mock_.SetOwnerAndName(this, "Call"); + return mock_.Invoke(std::forward(args)...); + } + + MockSpec gmock_Call(Matcher... m) { + mock_.RegisterOwner(this); + return mock_.With(std::move(m)...); + } + + MockSpec gmock_Call(const WithoutMatchers&, + R (*)(Args...)) { + return this->gmock_Call(::testing::A()...); + } + + private: + FunctionMocker mock_; +}; + +/* +The SignatureOf 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 +struct SignatureOf; + +template +struct SignatureOf { + using type = R(Args...); +}; + +template +struct SignatureOf> : SignatureOf {}; + +template +using SignatureOfT = typename SignatureOf::type; + +} // namespace internal + +// A MockFunction type has one mock method whose type is +// internal::SignatureOfT. 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,50 +1898,30 @@ void ReportUninterestingCall(CallReaction reaction, const std::string& msg); // Bar("a") is called by which call to Foo(). // // MockFunction can also be used to exercise code that accepts -// std::function callbacks. To do so, use AsStdFunction() method -// to create std::function proxy forwarding to original object's Call. -// Example: +// std::function> callbacks. To do so, use +// AsStdFunction() method to create std::function proxy forwarding to +// original object's Call. Example: // // TEST(FooTest, RunsCallbackWithBarArgument) { // MockFunction callback; // EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1)); // Foo(callback.AsStdFunction()); // } +// +// The SignatureOfT 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 predicate = std::function; +// void MyFilterAlgorithm(predicate pred); +// +// TEST(FooTest, PredicateAlwaysAccepts) { +// MockFunction pred_mock; +// EXPECT_CALL(pred_mock, Call(_)).WillRepeatedly(Return(true)); +// MyFilterAlgorithm(pred_mock.AsStdFunction()); +// } template -class MockFunction; - -template -class MockFunction { - public: - MockFunction() {} - MockFunction(const MockFunction&) = delete; - MockFunction& operator=(const MockFunction&) = delete; - - std::function AsStdFunction() { - return [this](Args... args) -> R { - return this->Call(std::forward(args)...); - }; - } - - // Implementation detail: the expansion of the MOCK_METHOD macro. - R Call(Args... args) { - mock_.SetOwnerAndName(this, "Call"); - return mock_.Invoke(std::forward(args)...); - } - - internal::MockSpec gmock_Call(Matcher... m) { - mock_.RegisterOwner(this); - return mock_.With(std::move(m)...); - } - - internal::MockSpec gmock_Call(const internal::WithoutMatchers&, - R (*)(Args...)) { - return this->gmock_Call(::testing::A()...); - } - - private: - internal::FunctionMocker mock_; -}; +using MockFunction = internal::MockFunction>; // The style guide prohibits "using" statements in a namespace scope // inside a header file. However, the MockSpec class template is diff --git a/googlemock/test/gmock-function-mocker_test.cc b/googlemock/test/gmock-function-mocker_test.cc index 90d6b5f136..0f4608c8da 100644 --- a/googlemock/test/gmock-function-mocker_test.cc +++ b/googlemock/test/gmock-function-mocker_test.cc @@ -40,6 +40,7 @@ # include #endif // GTEST_OS_WINDOWS +#include #include #include #include @@ -567,6 +568,27 @@ TEST(MockMethodOverloadedMockMethodTest, CanOverloadOnConstnessInMacroBody) { EXPECT_EQ(3, const_mock->Overloaded(1)); } +template +class MockMethodMockFunctionSignatureTest : public ::testing::Test { +}; + +using SignatureTypes = ::testing::Types< + void(), + int(), + void(int), + int(bool, int), + int(bool, char, int, int, int, int, int, char, int, bool) +>; +TYPED_TEST_SUITE(MockMethodMockFunctionSignatureTest, SignatureTypes); + +TYPED_TEST(MockMethodMockFunctionSignatureTest, MockFunctionOfSignatureIsTheSameTypeAsMockFunctionOfStdFunction) { + using signature = TypeParam; + using expected = MockFunction; + using actual = MockFunction>; + constexpr auto is_same = std::is_same::value; + EXPECT_TRUE(is_same); +} + TEST(MockMethodMockFunctionTest, WorksForVoidNullary) { MockFunction foo; EXPECT_CALL(foo, Call()); diff --git a/googlemock/test/gmock-generated-function-mockers_test.cc b/googlemock/test/gmock-generated-function-mockers_test.cc index dff3a9f0fa..09d35fc8c0 100644 --- a/googlemock/test/gmock-generated-function-mockers_test.cc +++ b/googlemock/test/gmock-generated-function-mockers_test.cc @@ -41,8 +41,10 @@ # include #endif // GTEST_OS_WINDOWS +#include #include #include +#include #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -557,6 +559,27 @@ TEST(OverloadedMockMethodTest, CanOverloadOnConstnessInMacroBody) { EXPECT_EQ(3, const_mock->Overloaded(1)); } +template +class MockFunctionSignatureTest : public ::testing::Test { +}; + +using SignatureTypes = ::testing::Types< + void(), + int(), + void(int), + int(bool, int), + int(bool, char, int, int, int, int, int, char, int, bool) +>; +TYPED_TEST_SUITE(MockFunctionSignatureTest, SignatureTypes); + +TYPED_TEST(MockFunctionSignatureTest, MockFunctionOfSignatureIsTheSameTypeAsMockFunctionOfStdFunction) { + using signature = TypeParam; + using expected = MockFunction; + using actual = MockFunction>; + constexpr auto is_same = std::is_same::value; + EXPECT_TRUE(is_same); +} + TEST(MockFunctionTest, WorksForVoidNullary) { MockFunction foo; EXPECT_CALL(foo, Call());