From de5be0eb28b74ecd6335e3bd61d9dc8914ce0e57 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 8 Nov 2018 11:14:50 -0500 Subject: Googletest export Move FunctionMocker and MockFunction out of the pump file and implement with variadic templates. PiperOrigin-RevId: 220640265 --- .../gmock/gmock-generated-function-mockers.h | 562 --------------------- .../gmock/gmock-generated-function-mockers.h.pump | 118 ----- googlemock/include/gmock/gmock-spec-builders.h | 213 +++++--- 3 files changed, 144 insertions(+), 749 deletions(-) diff --git a/googlemock/include/gmock/gmock-generated-function-mockers.h b/googlemock/include/gmock/gmock-generated-function-mockers.h index 38a7d15d..cbd7b59d 100644 --- a/googlemock/include/gmock/gmock-generated-function-mockers.h +++ b/googlemock/include/gmock/gmock-generated-function-mockers.h @@ -52,281 +52,6 @@ namespace testing { namespace internal { - -template -class FunctionMockerBase; - -// Note: class FunctionMocker really belongs to the ::testing -// namespace. However if we define it in ::testing, MSVC will -// complain when classes in ::testing::internal declare it as a -// friend class template. To workaround this compiler bug, we define -// FunctionMocker in ::testing::internal and import it into ::testing. -template -class FunctionMocker; - -template -class FunctionMocker : public - internal::FunctionMockerBase { - public: - typedef R F(); - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - MockSpec With() { - return MockSpec(this, ::std::make_tuple()); - } - - R Invoke() { - // Even though gcc and MSVC don't enforce it, 'this->' is required - // by the C++ standard [14.6.4] here, as the base class type is - // dependent on the template argument (and thus shouldn't be - // looked into when resolving InvokeWith). - return this->InvokeWith(ArgumentTuple()); - } -}; - -template -class FunctionMocker : public - internal::FunctionMockerBase { - public: - typedef R F(A1); - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - MockSpec With(const Matcher& m1) { - return MockSpec(this, ::std::make_tuple(m1)); - } - - R Invoke(A1 a1) { - // Even though gcc and MSVC don't enforce it, 'this->' is required - // by the C++ standard [14.6.4] here, as the base class type is - // dependent on the template argument (and thus shouldn't be - // looked into when resolving InvokeWith). - return this->InvokeWith(ArgumentTuple(std::forward(a1))); - } -}; - -template -class FunctionMocker : public - internal::FunctionMockerBase { - public: - typedef R F(A1, A2); - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - MockSpec With(const Matcher& m1, const Matcher& m2) { - return MockSpec(this, ::std::make_tuple(m1, m2)); - } - - R Invoke(A1 a1, A2 a2) { - // Even though gcc and MSVC don't enforce it, 'this->' is required - // by the C++ standard [14.6.4] here, as the base class type is - // dependent on the template argument (and thus shouldn't be - // looked into when resolving InvokeWith). - return this->InvokeWith(ArgumentTuple(std::forward(a1), - std::forward(a2))); - } -}; - -template -class FunctionMocker : public - internal::FunctionMockerBase { - public: - typedef R F(A1, A2, A3); - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - MockSpec With(const Matcher& m1, const Matcher& m2, - const Matcher& m3) { - return MockSpec(this, ::std::make_tuple(m1, m2, m3)); - } - - R Invoke(A1 a1, A2 a2, A3 a3) { - // Even though gcc and MSVC don't enforce it, 'this->' is required - // by the C++ standard [14.6.4] here, as the base class type is - // dependent on the template argument (and thus shouldn't be - // looked into when resolving InvokeWith). - return this->InvokeWith(ArgumentTuple(std::forward(a1), - std::forward(a2), std::forward(a3))); - } -}; - -template -class FunctionMocker : public - internal::FunctionMockerBase { - public: - typedef R F(A1, A2, A3, A4); - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - MockSpec With(const Matcher& m1, const Matcher& m2, - const Matcher& m3, const Matcher& m4) { - return MockSpec(this, ::std::make_tuple(m1, m2, m3, m4)); - } - - R Invoke(A1 a1, A2 a2, A3 a3, A4 a4) { - // Even though gcc and MSVC don't enforce it, 'this->' is required - // by the C++ standard [14.6.4] here, as the base class type is - // dependent on the template argument (and thus shouldn't be - // looked into when resolving InvokeWith). - return this->InvokeWith(ArgumentTuple(std::forward(a1), - std::forward(a2), std::forward(a3), std::forward(a4))); - } -}; - -template -class FunctionMocker : public - internal::FunctionMockerBase { - public: - typedef R F(A1, A2, A3, A4, A5); - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - MockSpec With(const Matcher& m1, const Matcher& m2, - const Matcher& m3, const Matcher& m4, const Matcher& m5) { - return MockSpec(this, ::std::make_tuple(m1, m2, m3, m4, m5)); - } - - R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { - // Even though gcc and MSVC don't enforce it, 'this->' is required - // by the C++ standard [14.6.4] here, as the base class type is - // dependent on the template argument (and thus shouldn't be - // looked into when resolving InvokeWith). - return this->InvokeWith(ArgumentTuple(std::forward(a1), - std::forward(a2), std::forward(a3), std::forward(a4), - std::forward(a5))); - } -}; - -template -class FunctionMocker : public - internal::FunctionMockerBase { - public: - typedef R F(A1, A2, A3, A4, A5, A6); - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - MockSpec With(const Matcher& m1, const Matcher& m2, - const Matcher& m3, const Matcher& m4, const Matcher& m5, - const Matcher& m6) { - return MockSpec(this, ::std::make_tuple(m1, m2, m3, m4, m5, m6)); - } - - R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { - // Even though gcc and MSVC don't enforce it, 'this->' is required - // by the C++ standard [14.6.4] here, as the base class type is - // dependent on the template argument (and thus shouldn't be - // looked into when resolving InvokeWith). - return this->InvokeWith(ArgumentTuple(std::forward(a1), - std::forward(a2), std::forward(a3), std::forward(a4), - std::forward(a5), std::forward(a6))); - } -}; - -template -class FunctionMocker : public - internal::FunctionMockerBase { - public: - typedef R F(A1, A2, A3, A4, A5, A6, A7); - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - MockSpec With(const Matcher& m1, const Matcher& m2, - const Matcher& m3, const Matcher& m4, const Matcher& m5, - const Matcher& m6, const Matcher& m7) { - return MockSpec(this, ::std::make_tuple(m1, m2, m3, m4, m5, m6, m7)); - } - - R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { - // Even though gcc and MSVC don't enforce it, 'this->' is required - // by the C++ standard [14.6.4] here, as the base class type is - // dependent on the template argument (and thus shouldn't be - // looked into when resolving InvokeWith). - return this->InvokeWith(ArgumentTuple(std::forward(a1), - std::forward(a2), std::forward(a3), std::forward(a4), - std::forward(a5), std::forward(a6), std::forward(a7))); - } -}; - -template -class FunctionMocker : public - internal::FunctionMockerBase { - public: - typedef R F(A1, A2, A3, A4, A5, A6, A7, A8); - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - MockSpec With(const Matcher& m1, const Matcher& m2, - const Matcher& m3, const Matcher& m4, const Matcher& m5, - const Matcher& m6, const Matcher& m7, const Matcher& m8) { - return MockSpec(this, ::std::make_tuple(m1, m2, m3, m4, m5, m6, m7, m8)); - } - - R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) { - // Even though gcc and MSVC don't enforce it, 'this->' is required - // by the C++ standard [14.6.4] here, as the base class type is - // dependent on the template argument (and thus shouldn't be - // looked into when resolving InvokeWith). - return this->InvokeWith(ArgumentTuple(std::forward(a1), - std::forward(a2), std::forward(a3), std::forward(a4), - std::forward(a5), std::forward(a6), std::forward(a7), - std::forward(a8))); - } -}; - -template -class FunctionMocker : public - internal::FunctionMockerBase { - public: - typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9); - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - MockSpec With(const Matcher& m1, const Matcher& m2, - const Matcher& m3, const Matcher& m4, const Matcher& m5, - const Matcher& m6, const Matcher& m7, const Matcher& m8, - const Matcher& m9) { - return MockSpec(this, ::std::make_tuple(m1, m2, m3, m4, m5, m6, m7, m8, - m9)); - } - - R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) { - // Even though gcc and MSVC don't enforce it, 'this->' is required - // by the C++ standard [14.6.4] here, as the base class type is - // dependent on the template argument (and thus shouldn't be - // looked into when resolving InvokeWith). - return this->InvokeWith(ArgumentTuple(std::forward(a1), - std::forward(a2), std::forward(a3), std::forward(a4), - std::forward(a5), std::forward(a6), std::forward(a7), - std::forward(a8), std::forward(a9))); - } -}; - -template -class FunctionMocker : public - internal::FunctionMockerBase { - public: - typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10); - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - MockSpec With(const Matcher& m1, const Matcher& m2, - const Matcher& m3, const Matcher& m4, const Matcher& m5, - const Matcher& m6, const Matcher& m7, const Matcher& m8, - const Matcher& m9, const Matcher& m10) { - return MockSpec(this, ::std::make_tuple(m1, m2, m3, m4, m5, m6, m7, m8, - m9, m10)); - } - - R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, - A10 a10) { - // Even though gcc and MSVC don't enforce it, 'this->' is required - // by the C++ standard [14.6.4] here, as the base class type is - // dependent on the template argument (and thus shouldn't be - // looked into when resolving InvokeWith). - return this->InvokeWith(ArgumentTuple(std::forward(a1), - std::forward(a2), std::forward(a3), std::forward(a4), - std::forward(a5), std::forward(a6), std::forward(a7), - std::forward(a8), std::forward(a9), std::forward(a10))); - } -}; - // Removes the given pointer; this is a helper for the expectation setter method // for parameterless matchers. // @@ -1036,293 +761,6 @@ using internal::FunctionMocker; #define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \ GMOCK_METHOD10_(typename, const, ct, m, __VA_ARGS__) -// 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: -// -// Foo(1); -// Foo(2); -// Foo(3); -// -// and want to verify that Foo(1) and Foo(3) both invoke -// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write: -// -// TEST(FooTest, InvokesBarCorrectly) { -// MyMock mock; -// MockFunction check; -// { -// InSequence s; -// -// EXPECT_CALL(mock, Bar("a")); -// EXPECT_CALL(check, Call("1")); -// EXPECT_CALL(check, Call("2")); -// EXPECT_CALL(mock, Bar("a")); -// } -// Foo(1); -// check.Call("1"); -// Foo(2); -// check.Call("2"); -// Foo(3); -// } -// -// The expectation spec says that the first Bar("a") must happen -// before check point "1", the second Bar("a") must happen after check -// point "2", and nothing should happen between the two check -// points. The explicit check points make it easy to tell which -// 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: -// -// TEST(FooTest, RunsCallbackWithBarArgument) { -// MockFunction callback; -// EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1)); -// Foo(callback.AsStdFunction()); -// } -template -class MockFunction; - -template -class MockFunction { - public: - MockFunction() {} - - MOCK_METHOD0_T(Call, R()); - -#if GTEST_HAS_STD_FUNCTION_ - ::std::function AsStdFunction() { - return [this]() -> R { - return this->Call(); - }; - } -#endif // GTEST_HAS_STD_FUNCTION_ - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); -}; - -template -class MockFunction { - public: - MockFunction() {} - - MOCK_METHOD1_T(Call, R(A0)); - -#if GTEST_HAS_STD_FUNCTION_ - ::std::function AsStdFunction() { - return [this](A0 a0) -> R { - return this->Call(::std::forward(a0)); - }; - } -#endif // GTEST_HAS_STD_FUNCTION_ - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); -}; - -template -class MockFunction { - public: - MockFunction() {} - - MOCK_METHOD2_T(Call, R(A0, A1)); - -#if GTEST_HAS_STD_FUNCTION_ - ::std::function AsStdFunction() { - return [this](A0 a0, A1 a1) -> R { - return this->Call(::std::forward(a0), ::std::forward(a1)); - }; - } -#endif // GTEST_HAS_STD_FUNCTION_ - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); -}; - -template -class MockFunction { - public: - MockFunction() {} - - MOCK_METHOD3_T(Call, R(A0, A1, A2)); - -#if GTEST_HAS_STD_FUNCTION_ - ::std::function AsStdFunction() { - return [this](A0 a0, A1 a1, A2 a2) -> R { - return this->Call(::std::forward(a0), ::std::forward(a1), - ::std::forward(a2)); - }; - } -#endif // GTEST_HAS_STD_FUNCTION_ - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); -}; - -template -class MockFunction { - public: - MockFunction() {} - - MOCK_METHOD4_T(Call, R(A0, A1, A2, A3)); - -#if GTEST_HAS_STD_FUNCTION_ - ::std::function AsStdFunction() { - return [this](A0 a0, A1 a1, A2 a2, A3 a3) -> R { - return this->Call(::std::forward(a0), ::std::forward(a1), - ::std::forward(a2), ::std::forward(a3)); - }; - } -#endif // GTEST_HAS_STD_FUNCTION_ - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); -}; - -template -class MockFunction { - public: - MockFunction() {} - - MOCK_METHOD5_T(Call, R(A0, A1, A2, A3, A4)); - -#if GTEST_HAS_STD_FUNCTION_ - ::std::function AsStdFunction() { - return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) -> R { - return this->Call(::std::forward(a0), ::std::forward(a1), - ::std::forward(a2), ::std::forward(a3), - ::std::forward(a4)); - }; - } -#endif // GTEST_HAS_STD_FUNCTION_ - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); -}; - -template -class MockFunction { - public: - MockFunction() {} - - MOCK_METHOD6_T(Call, R(A0, A1, A2, A3, A4, A5)); - -#if GTEST_HAS_STD_FUNCTION_ - ::std::function AsStdFunction() { - return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -> R { - return this->Call(::std::forward(a0), ::std::forward(a1), - ::std::forward(a2), ::std::forward(a3), - ::std::forward(a4), ::std::forward(a5)); - }; - } -#endif // GTEST_HAS_STD_FUNCTION_ - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); -}; - -template -class MockFunction { - public: - MockFunction() {} - - MOCK_METHOD7_T(Call, R(A0, A1, A2, A3, A4, A5, A6)); - -#if GTEST_HAS_STD_FUNCTION_ - ::std::function AsStdFunction() { - return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) -> R { - return this->Call(::std::forward(a0), ::std::forward(a1), - ::std::forward(a2), ::std::forward(a3), - ::std::forward(a4), ::std::forward(a5), - ::std::forward(a6)); - }; - } -#endif // GTEST_HAS_STD_FUNCTION_ - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); -}; - -template -class MockFunction { - public: - MockFunction() {} - - MOCK_METHOD8_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7)); - -#if GTEST_HAS_STD_FUNCTION_ - ::std::function AsStdFunction() { - return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) -> R { - return this->Call(::std::forward(a0), ::std::forward(a1), - ::std::forward(a2), ::std::forward(a3), - ::std::forward(a4), ::std::forward(a5), - ::std::forward(a6), ::std::forward(a7)); - }; - } -#endif // GTEST_HAS_STD_FUNCTION_ - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); -}; - -template -class MockFunction { - public: - MockFunction() {} - - MOCK_METHOD9_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8)); - -#if GTEST_HAS_STD_FUNCTION_ - ::std::function AsStdFunction() { - return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, - A8 a8) -> R { - return this->Call(::std::forward(a0), ::std::forward(a1), - ::std::forward(a2), ::std::forward(a3), - ::std::forward(a4), ::std::forward(a5), - ::std::forward(a6), ::std::forward(a7), - ::std::forward(a8)); - }; - } -#endif // GTEST_HAS_STD_FUNCTION_ - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); -}; - -template -class MockFunction { - public: - MockFunction() {} - - MOCK_METHOD10_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)); - -#if GTEST_HAS_STD_FUNCTION_ - ::std::function AsStdFunction() { - return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, - A8 a8, A9 a9) -> R { - return this->Call(::std::forward(a0), ::std::forward(a1), - ::std::forward(a2), ::std::forward(a3), - ::std::forward(a4), ::std::forward(a5), - ::std::forward(a6), ::std::forward(a7), - ::std::forward(a8), ::std::forward(a9)); - }; - } -#endif // GTEST_HAS_STD_FUNCTION_ - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); -}; - } // namespace testing #endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ diff --git a/googlemock/include/gmock/gmock-generated-function-mockers.h.pump b/googlemock/include/gmock/gmock-generated-function-mockers.h.pump index 183e652c..73b68b9d 100644 --- a/googlemock/include/gmock/gmock-generated-function-mockers.h.pump +++ b/googlemock/include/gmock/gmock-generated-function-mockers.h.pump @@ -54,49 +54,7 @@ $var n = 10 $$ The maximum arity we support. namespace testing { namespace internal { -template -class FunctionMockerBase; - -// Note: class FunctionMocker really belongs to the ::testing -// namespace. However if we define it in ::testing, MSVC will -// complain when classes in ::testing::internal declare it as a -// friend class template. To workaround this compiler bug, we define -// FunctionMocker in ::testing::internal and import it into ::testing. -template -class FunctionMocker; - - $range i 0..n -$for i [[ -$range j 1..i -$var typename_As = [[$for j [[, typename A$j]]]] -$var As = [[$for j, [[A$j]]]] -$var as = [[$for j, [[std::forward(a$j)]]]] -$var Aas = [[$for j, [[A$j a$j]]]] -$var ms = [[$for j, [[m$j]]]] -$var matchers = [[$for j, [[const Matcher& m$j]]]] -template -class FunctionMocker : public - internal::FunctionMockerBase { - public: - typedef R F($As); - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - MockSpec With($matchers) { - return MockSpec(this, ::std::make_tuple($ms)); - } - - R Invoke($Aas) { - // Even though gcc and MSVC don't enforce it, 'this->' is required - // by the C++ standard [14.6.4] here, as the base class type is - // dependent on the template argument (and thus shouldn't be - // looked into when resolving InvokeWith). - return this->InvokeWith(ArgumentTuple($as)); - } -}; - - -]] // Removes the given pointer; this is a helper for the expectation setter method // for parameterless matchers. // @@ -269,82 +227,6 @@ $for i [[ ]] -// 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: -// -// Foo(1); -// Foo(2); -// Foo(3); -// -// and want to verify that Foo(1) and Foo(3) both invoke -// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write: -// -// TEST(FooTest, InvokesBarCorrectly) { -// MyMock mock; -// MockFunction check; -// { -// InSequence s; -// -// EXPECT_CALL(mock, Bar("a")); -// EXPECT_CALL(check, Call("1")); -// EXPECT_CALL(check, Call("2")); -// EXPECT_CALL(mock, Bar("a")); -// } -// Foo(1); -// check.Call("1"); -// Foo(2); -// check.Call("2"); -// Foo(3); -// } -// -// The expectation spec says that the first Bar("a") must happen -// before check point "1", the second Bar("a") must happen after check -// point "2", and nothing should happen between the two check -// points. The explicit check points make it easy to tell which -// 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: -// -// TEST(FooTest, RunsCallbackWithBarArgument) { -// MockFunction callback; -// EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1)); -// Foo(callback.AsStdFunction()); -// } -template -class MockFunction; - - -$for i [[ -$range j 0..i-1 -$var ArgTypes = [[$for j, [[A$j]]]] -$var ArgValues = [[$for j, [[::std::forward(a$j)]]]] -$var ArgDecls = [[$for j, [[A$j a$j]]]] -template -class MockFunction { - public: - MockFunction() {} - - MOCK_METHOD$i[[]]_T(Call, R($ArgTypes)); - -#if GTEST_HAS_STD_FUNCTION_ - ::std::function AsStdFunction() { - return [this]($ArgDecls) -> R { - return this->Call($ArgValues); - }; - } -#endif // GTEST_HAS_STD_FUNCTION_ - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); -}; - - -]] } // namespace testing #endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ diff --git a/googlemock/include/gmock/gmock-spec-builders.h b/googlemock/include/gmock/gmock-spec-builders.h index e58adfcb..9dce2247 100644 --- a/googlemock/include/gmock/gmock-spec-builders.h +++ b/googlemock/include/gmock/gmock-spec-builders.h @@ -106,9 +106,6 @@ template class TypedExpectation; // Helper class for testing the Expectation class template. class ExpectationTester; -// Base class for function mockers. -template class FunctionMockerBase; - // Protects the mock object registry (in class Mock), all function // mockers, and all expectations. // @@ -125,9 +122,9 @@ GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_gmock_mutex); // Untyped base class for ActionResultHolder. class UntypedActionResultHolderBase; -// Abstract base class of FunctionMockerBase. This is the +// Abstract base class of FunctionMocker. This is the // type-agnostic part of the function mocker interface. Its pure -// virtual methods are implemented by FunctionMockerBase. +// virtual methods are implemented by FunctionMocker. class GTEST_API_ UntypedFunctionMockerBase { public: UntypedFunctionMockerBase(); @@ -415,7 +412,7 @@ class GTEST_API_ Mock { // Needed for a function mocker to register itself (so that we know // how to clear a mock object). template - friend class internal::FunctionMockerBase; + friend class internal::FunctionMocker; template friend class NiceMock; @@ -478,7 +475,7 @@ class GTEST_API_ Mock { // Unregisters a mock method; removes the owning mock object from // the registry when the last mock method associated with it has // been unregistered. This is called only in the destructor of - // FunctionMockerBase. + // FunctionMocker. static void UnregisterLocked(internal::UntypedFunctionMockerBase* mocker) GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex); }; // class Mock @@ -534,7 +531,7 @@ class GTEST_API_ Expectation { friend class ::testing::internal::UntypedFunctionMockerBase; template - friend class ::testing::internal::FunctionMockerBase; + friend class ::testing::internal::FunctionMocker; template friend class ::testing::internal::TypedExpectation; @@ -893,7 +890,7 @@ class TypedExpectation : public ExpectationBase { typedef typename Function::ArgumentMatcherTuple ArgumentMatcherTuple; typedef typename Function::Result Result; - TypedExpectation(FunctionMockerBase* owner, const char* a_file, int a_line, + TypedExpectation(FunctionMocker* owner, const char* a_file, int a_line, const std::string& a_source_text, const ArgumentMatcherTuple& m) : ExpectationBase(a_file, a_line, a_source_text), @@ -1082,7 +1079,7 @@ class TypedExpectation : public ExpectationBase { private: template - friend class FunctionMockerBase; + friend class FunctionMocker; // Returns an Expectation object that references and co-owns this // expectation. @@ -1161,10 +1158,9 @@ class TypedExpectation : public ExpectationBase { } // Returns the action that should be taken for the current invocation. - const Action& GetCurrentAction( - const FunctionMockerBase* mocker, - const ArgumentTuple& args) const - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + const Action& GetCurrentAction(const FunctionMocker* mocker, + const ArgumentTuple& args) const + GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); const int count = call_count(); Assert(count >= 1, __FILE__, __LINE__, @@ -1199,12 +1195,11 @@ class TypedExpectation : public ExpectationBase { // Mock does it to 'why'. This method is not const as it calls // IncrementCallCount(). A return value of NULL means the default // action. - const Action* GetActionForArguments( - const FunctionMockerBase* mocker, - const ArgumentTuple& args, - ::std::ostream* what, - ::std::ostream* why) - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + const Action* GetActionForArguments(const FunctionMocker* mocker, + const ArgumentTuple& args, + ::std::ostream* what, + ::std::ostream* why) + GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); if (IsSaturated()) { // We have an excessive call. @@ -1233,7 +1228,7 @@ class TypedExpectation : public ExpectationBase { // All the fields below won't change once the EXPECT_CALL() // statement finishes. - FunctionMockerBase* const owner_; + FunctionMocker* const owner_; ArgumentMatcherTuple matchers_; Matcher extra_matcher_; Action repeated_action_; @@ -1265,7 +1260,7 @@ class MockSpec { // Constructs a MockSpec object, given the function mocker object // that the spec is associated with. - MockSpec(internal::FunctionMockerBase* function_mocker, + MockSpec(internal::FunctionMocker* function_mocker, const ArgumentMatcherTuple& matchers) : function_mocker_(function_mocker), matchers_(matchers) {} @@ -1301,7 +1296,7 @@ class MockSpec { friend class internal::FunctionMocker; // The function mocker that owns this spec. - internal::FunctionMockerBase* const function_mocker_; + internal::FunctionMocker* const function_mocker_; // The argument matchers specified in the spec. ArgumentMatcherTuple matchers_; @@ -1402,7 +1397,7 @@ class ActionResultHolder : public UntypedActionResultHolderBase { // result in a new-ed ActionResultHolder. template static ActionResultHolder* PerformDefaultAction( - const FunctionMockerBase* func_mocker, + const FunctionMocker* func_mocker, typename Function::ArgumentTuple&& args, const std::string& call_description) { return new ActionResultHolder(Wrapper(func_mocker->PerformDefaultAction( @@ -1442,7 +1437,7 @@ class ActionResultHolder : public UntypedActionResultHolderBase { // of an empty ActionResultHolder*. template static ActionResultHolder* PerformDefaultAction( - const FunctionMockerBase* func_mocker, + const FunctionMocker* func_mocker, typename Function::ArgumentTuple&& args, const std::string& call_description) { func_mocker->PerformDefaultAction(std::move(args), call_description); @@ -1463,22 +1458,39 @@ class ActionResultHolder : public UntypedActionResultHolderBase { GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionResultHolder); }; -// The base of the function mocker class for the given function type. -// We put the methods in this class instead of its child to avoid code -// bloat. template -class FunctionMockerBase : public UntypedFunctionMockerBase { +class FunctionMocker; + +template +class FunctionMocker : public UntypedFunctionMockerBase { + using F = R(Args...); + public: - typedef typename Function::Result Result; - typedef typename Function::ArgumentTuple ArgumentTuple; - typedef typename Function::ArgumentMatcherTuple ArgumentMatcherTuple; + using Result = R; + using ArgumentTuple = std::tuple; + using ArgumentMatcherTuple = std::tuple...>; - FunctionMockerBase() {} + FunctionMocker() {} + + // There is no generally useful and implementable semantics of + // copying a mock object, so copying a mock is usually a user error. + // Thus we disallow copying function mockers. If the user really + // wants to copy a mock object, they should implement their own copy + // operation, for example: + // + // class MockFoo : public Foo { + // public: + // // Defines a copy constructor explicitly. + // MockFoo(const MockFoo& src) {} + // ... + // }; + FunctionMocker(const FunctionMocker&) = delete; + FunctionMocker& operator=(const FunctionMocker&) = delete; // The destructor verifies that all expectations on this mock // function have been satisfied. If not, it will report Google Test // non-fatal failures for the violations. - virtual ~FunctionMockerBase() + virtual ~FunctionMocker() GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { MutexLock l(&g_gmock_mutex); VerifyAndClearExpectationsLocked(); @@ -1509,7 +1521,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase { // mutable state of this object, and thus can be called concurrently // without locking. // L = * - Result PerformDefaultAction(typename Function::ArgumentTuple&& args, + Result PerformDefaultAction(ArgumentTuple&& args, const std::string& call_description) const { const OnCallSpec* const spec = this->FindOnCallSpec(args); @@ -1584,25 +1596,26 @@ class FunctionMockerBase : public UntypedFunctionMockerBase { g_gmock_mutex.Lock(); } - protected: - template - friend class MockSpec; - - typedef ActionResultHolder ResultHolder; - // Returns the result of invoking this mock function with the given // arguments. This function can be safely called from multiple // threads concurrently. - Result InvokeWith(typename Function::ArgumentTuple&& args) - GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { - // const_cast is required since in C++98 we still pass ArgumentTuple around - // by const& instead of rvalue reference. - void* untyped_args = const_cast(static_cast(&args)); - std::unique_ptr holder( - DownCast_(this->UntypedInvokeWith(untyped_args))); + Result Invoke(Args... args) GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { + ArgumentTuple tuple(std::forward(args)...); + std::unique_ptr holder(DownCast_( + this->UntypedInvokeWith(static_cast(&tuple)))); return holder->Unwrap(); } + MockSpec With(Matcher... m) { + return MockSpec(this, ::std::make_tuple(std::move(m)...)); + } + + protected: + template + friend class MockSpec; + + typedef ActionResultHolder ResultHolder; + // Adds and returns a default action spec for this mock function. OnCallSpec& AddNewOnCallSpec( const char* file, int line, @@ -1779,36 +1792,98 @@ class FunctionMockerBase : public UntypedFunctionMockerBase { expectation->DescribeCallCountTo(why); } } - - // There is no generally useful and implementable semantics of - // copying a mock object, so copying a mock is usually a user error. - // Thus we disallow copying function mockers. If the user really - // wants to copy a mock object, they should implement their own copy - // operation, for example: - // - // class MockFoo : public Foo { - // public: - // // Defines a copy constructor explicitly. - // MockFoo(const MockFoo& src) {} - // ... - // }; - GTEST_DISALLOW_COPY_AND_ASSIGN_(FunctionMockerBase); -}; // class FunctionMockerBase +}; // class FunctionMocker GTEST_DISABLE_MSC_WARNINGS_POP_() // 4355 -// Implements methods of FunctionMockerBase. - -// Verifies that all expectations on this mock function have been -// satisfied. Reports one or more Google Test non-fatal failures and -// returns false if not. - // 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 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: +// +// Foo(1); +// Foo(2); +// Foo(3); +// +// and want to verify that Foo(1) and Foo(3) both invoke +// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write: +// +// TEST(FooTest, InvokesBarCorrectly) { +// MyMock mock; +// MockFunction check; +// { +// InSequence s; +// +// EXPECT_CALL(mock, Bar("a")); +// EXPECT_CALL(check, Call("1")); +// EXPECT_CALL(check, Call("2")); +// EXPECT_CALL(mock, Bar("a")); +// } +// Foo(1); +// check.Call("1"); +// Foo(2); +// check.Call("2"); +// Foo(3); +// } +// +// The expectation spec says that the first Bar("a") must happen +// before check point "1", the second Bar("a") must happen after check +// point "2", and nothing should happen between the two check +// points. The explicit check points make it easy to tell which +// 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: +// +// TEST(FooTest, RunsCallbackWithBarArgument) { +// MockFunction callback; +// EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1)); +// Foo(callback.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: + mutable internal::FunctionMocker mock_; +}; + // The style guide prohibits "using" statements in a namespace scope // inside a header file. However, the MockSpec class template is // meant to be defined in the ::testing namespace. The following line -- cgit v1.2.3