diff options
Diffstat (limited to 'googlemock/include/gmock/gmock-spec-builders.h')
-rw-r--r-- | googlemock/include/gmock/gmock-spec-builders.h | 213 |
1 files changed, 144 insertions, 69 deletions
diff --git a/googlemock/include/gmock/gmock-spec-builders.h b/googlemock/include/gmock/gmock-spec-builders.h index e58adfc..9dce224 100644 --- a/googlemock/include/gmock/gmock-spec-builders.h +++ b/googlemock/include/gmock/gmock-spec-builders.h @@ -106,9 +106,6 @@ template <typename F> class TypedExpectation; // Helper class for testing the Expectation class template. class ExpectationTester; -// Base class for function mockers. -template <typename F> 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<R>. 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 <typename F> - friend class internal::FunctionMockerBase; + friend class internal::FunctionMocker; template <typename M> 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 <typename F> - friend class ::testing::internal::FunctionMockerBase; + friend class ::testing::internal::FunctionMocker; template <typename F> friend class ::testing::internal::TypedExpectation; @@ -893,7 +890,7 @@ class TypedExpectation : public ExpectationBase { typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple; typedef typename Function<F>::Result Result; - TypedExpectation(FunctionMockerBase<F>* owner, const char* a_file, int a_line, + TypedExpectation(FunctionMocker<F>* 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 <typename Function> - 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<F>& GetCurrentAction( - const FunctionMockerBase<F>* mocker, - const ArgumentTuple& args) const - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + const Action<F>& GetCurrentAction(const FunctionMocker<F>* 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<F>* GetActionForArguments( - const FunctionMockerBase<F>* mocker, - const ArgumentTuple& args, - ::std::ostream* what, - ::std::ostream* why) - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + const Action<F>* GetActionForArguments(const FunctionMocker<F>* 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<F>* const owner_; + FunctionMocker<F>* const owner_; ArgumentMatcherTuple matchers_; Matcher<const ArgumentTuple&> extra_matcher_; Action<F> 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<F>* function_mocker, + MockSpec(internal::FunctionMocker<F>* 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<F>* const function_mocker_; + internal::FunctionMocker<F>* 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 <typename F> static ActionResultHolder* PerformDefaultAction( - const FunctionMockerBase<F>* func_mocker, + const FunctionMocker<F>* func_mocker, typename Function<F>::ArgumentTuple&& args, const std::string& call_description) { return new ActionResultHolder(Wrapper(func_mocker->PerformDefaultAction( @@ -1442,7 +1437,7 @@ class ActionResultHolder<void> : public UntypedActionResultHolderBase { // of an empty ActionResultHolder*. template <typename F> static ActionResultHolder* PerformDefaultAction( - const FunctionMockerBase<F>* func_mocker, + const FunctionMocker<F>* func_mocker, typename Function<F>::ArgumentTuple&& args, const std::string& call_description) { func_mocker->PerformDefaultAction(std::move(args), call_description); @@ -1463,22 +1458,39 @@ class ActionResultHolder<void> : 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 <typename F> -class FunctionMockerBase : public UntypedFunctionMockerBase { +class FunctionMocker; + +template <typename R, typename... Args> +class FunctionMocker<R(Args...)> : public UntypedFunctionMockerBase { + using F = R(Args...); + public: - typedef typename Function<F>::Result Result; - typedef typename Function<F>::ArgumentTuple ArgumentTuple; - typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple; + using Result = R; + using ArgumentTuple = std::tuple<Args...>; + using ArgumentMatcherTuple = std::tuple<Matcher<Args>...>; - 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<F>::ArgumentTuple&& args, + Result PerformDefaultAction(ArgumentTuple&& args, const std::string& call_description) const { const OnCallSpec<F>* const spec = this->FindOnCallSpec(args); @@ -1584,25 +1596,26 @@ class FunctionMockerBase : public UntypedFunctionMockerBase { g_gmock_mutex.Lock(); } - protected: - template <typename Function> - friend class MockSpec; - - typedef ActionResultHolder<Result> 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<F>::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<void*>(static_cast<const void*>(&args)); - std::unique_ptr<ResultHolder> holder( - DownCast_<ResultHolder*>(this->UntypedInvokeWith(untyped_args))); + Result Invoke(Args... args) GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { + ArgumentTuple tuple(std::forward<Args>(args)...); + std::unique_ptr<ResultHolder> holder(DownCast_<ResultHolder*>( + this->UntypedInvokeWith(static_cast<void*>(&tuple)))); return holder->Unwrap(); } + MockSpec<F> With(Matcher<Args>... m) { + return MockSpec<F>(this, ::std::make_tuple(std::move(m)...)); + } + + protected: + template <typename Function> + friend class MockSpec; + + typedef ActionResultHolder<Result> ResultHolder; + // Adds and returns a default action spec for this mock function. OnCallSpec<F>& 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<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: +// +// 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<void(string check_point_name)> 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<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: +// +// TEST(FooTest, RunsCallbackWithBarArgument) { +// MockFunction<int(string)> callback; +// EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1)); +// Foo(callback.AsStdFunction()); +// } +template <typename F> +class MockFunction; + +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: + mutable internal::FunctionMocker<R(Args...)> 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 |