diff options
author | yegorskii <yegorskii@yandex-team.com> | 2022-07-26 11:02:24 +0300 |
---|---|---|
committer | yegorskii <yegorskii@yandex-team.com> | 2022-07-26 11:02:24 +0300 |
commit | 0e2671e6b9f8c0cc55bc8123b48e76d3a1eae832 (patch) | |
tree | 1879fc4640531151d7e5fd7bfd22dcde8f862124 /contrib/restricted/googletest/googlemock/include/gmock/gmock-spec-builders.h | |
parent | 06d9fbac1232813e0109ce49b3b0f7d4447aa2c4 (diff) | |
download | ydb-0e2671e6b9f8c0cc55bc8123b48e76d3a1eae832.tar.gz |
add functions without overflow
Diffstat (limited to 'contrib/restricted/googletest/googlemock/include/gmock/gmock-spec-builders.h')
-rw-r--r-- | contrib/restricted/googletest/googlemock/include/gmock/gmock-spec-builders.h | 589 |
1 files changed, 317 insertions, 272 deletions
diff --git a/contrib/restricted/googletest/googlemock/include/gmock/gmock-spec-builders.h b/contrib/restricted/googletest/googlemock/include/gmock/gmock-spec-builders.h index 41323c1cc0..45cc605183 100644 --- a/contrib/restricted/googletest/googlemock/include/gmock/gmock-spec-builders.h +++ b/contrib/restricted/googletest/googlemock/include/gmock/gmock-spec-builders.h @@ -27,7 +27,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - // Google Mock - a framework for writing C++ mock classes. // // This file implements the ON_CALL() and EXPECT_CALL() macros. @@ -56,11 +55,13 @@ // where all clauses are optional, and .InSequence()/.After()/ // .WillOnce() can appear any number of times. -// GOOGLETEST_CM0002 DO NOT DELETE +// IWYU pragma: private, include "gmock/gmock.h" +// IWYU pragma: friend gmock/.* #ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_ #define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_ +#include <cstdint> #include <functional> #include <map> #include <memory> @@ -70,6 +71,7 @@ #include <type_traits> #include <utility> #include <vector> + #include "gmock/gmock-actions.h" #include "gmock/gmock-cardinalities.h" #include "gmock/gmock-matchers.h" @@ -78,7 +80,7 @@ #include "gtest/gtest.h" #if GTEST_HAS_EXCEPTIONS -# include <stdexcept> // NOLINT +#include <stdexcept> // NOLINT #endif GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ @@ -97,13 +99,15 @@ class ExpectationSet; namespace internal { // Implements a mock function. -template <typename F> class FunctionMocker; +template <typename F> +class FunctionMocker; // Base class for expectations. class ExpectationBase; // Implements an expectation. -template <typename F> class TypedExpectation; +template <typename F> +class TypedExpectation; // Helper class for testing the Expectation class template. class ExpectationTester; @@ -129,9 +133,6 @@ class NaggyMockImpl; // calls to ensure the integrity of the mock objects' states. GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_gmock_mutex); -// Untyped base class for ActionResultHolder<R>. -class UntypedActionResultHolderBase; - // Abstract base class of FunctionMocker. This is the // type-agnostic part of the function mocker interface. Its pure // virtual methods are implemented by FunctionMocker. @@ -154,27 +155,12 @@ class GTEST_API_ UntypedFunctionMockerBase { // responsibility to guarantee the correctness of the arguments' // types. - // Performs the default action with the given arguments and returns - // the action's result. The call description string will be used in - // the error message to describe the call in the case the default - // action fails. - // L = * - virtual UntypedActionResultHolderBase* UntypedPerformDefaultAction( - void* untyped_args, const std::string& call_description) const = 0; - - // Performs the given action with the given arguments and returns - // the action's result. - // L = * - virtual UntypedActionResultHolderBase* UntypedPerformAction( - const void* untyped_action, void* untyped_args) const = 0; - // Writes a message that the call is uninteresting (i.e. neither // explicitly expected nor explicitly unexpected) to the given // ostream. - virtual void UntypedDescribeUninterestingCall( - const void* untyped_args, - ::std::ostream* os) const - GTEST_LOCK_EXCLUDED_(g_gmock_mutex) = 0; + virtual void UntypedDescribeUninterestingCall(const void* untyped_args, + ::std::ostream* os) const + GTEST_LOCK_EXCLUDED_(g_gmock_mutex) = 0; // Returns the expectation that matches the given function arguments // (or NULL is there's no match); when a match is found, @@ -183,10 +169,9 @@ class GTEST_API_ UntypedFunctionMockerBase { // is_excessive is modified to indicate whether the call exceeds the // expected number. virtual const ExpectationBase* UntypedFindMatchingExpectation( - const void* untyped_args, - const void** untyped_action, bool* is_excessive, + const void* untyped_args, const void** untyped_action, bool* is_excessive, ::std::ostream* what, ::std::ostream* why) - GTEST_LOCK_EXCLUDED_(g_gmock_mutex) = 0; + GTEST_LOCK_EXCLUDED_(g_gmock_mutex) = 0; // Prints the given function arguments to the ostream. virtual void UntypedPrintArgs(const void* untyped_args, @@ -196,8 +181,7 @@ class GTEST_API_ UntypedFunctionMockerBase { // this information in the global mock registry. Will be called // whenever an EXPECT_CALL() or ON_CALL() is executed on this mock // method. - void RegisterOwner(const void* mock_obj) - GTEST_LOCK_EXCLUDED_(g_gmock_mutex); + void RegisterOwner(const void* mock_obj) GTEST_LOCK_EXCLUDED_(g_gmock_mutex); // Sets the mock object this mock method belongs to, and sets the // name of the mock function. Will be called upon each invocation @@ -208,20 +192,11 @@ class GTEST_API_ UntypedFunctionMockerBase { // Returns the mock object this mock method belongs to. Must be // called after RegisterOwner() or SetOwnerAndName() has been // called. - const void* MockObject() const - GTEST_LOCK_EXCLUDED_(g_gmock_mutex); + const void* MockObject() const GTEST_LOCK_EXCLUDED_(g_gmock_mutex); // Returns the name of this mock method. Must be called after // SetOwnerAndName() has been called. - const char* Name() const - GTEST_LOCK_EXCLUDED_(g_gmock_mutex); - - // Returns the result of invoking this mock function with the given - // arguments. This function can be safely called from multiple - // threads concurrently. The caller is responsible for deleting the - // result. - UntypedActionResultHolderBase* UntypedInvokeWith(void* untyped_args) - GTEST_LOCK_EXCLUDED_(g_gmock_mutex); + const char* Name() const GTEST_LOCK_EXCLUDED_(g_gmock_mutex); protected: typedef std::vector<const void*> UntypedOnCallSpecs; @@ -430,29 +405,28 @@ class GTEST_API_ Mock { // Tells Google Mock to allow uninteresting calls on the given mock // object. - static void AllowUninterestingCalls(const void* mock_obj) + static void AllowUninterestingCalls(uintptr_t mock_obj) GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex); // Tells Google Mock to warn the user about uninteresting calls on // the given mock object. - static void WarnUninterestingCalls(const void* mock_obj) + static void WarnUninterestingCalls(uintptr_t mock_obj) GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex); // Tells Google Mock to fail uninteresting calls on the given mock // object. - static void FailUninterestingCalls(const void* mock_obj) + static void FailUninterestingCalls(uintptr_t mock_obj) GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex); // Tells Google Mock the given mock object is being destroyed and // its entry in the call-reaction table should be removed. - static void UnregisterCallReaction(const void* mock_obj) + static void UnregisterCallReaction(uintptr_t mock_obj) GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex); // Returns the reaction Google Mock will have on uninteresting calls // made on the given mock object. static internal::CallReaction GetReactionOnUninterestingCalls( - const void* mock_obj) - GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex); + const void* mock_obj) GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex); // Verifies that all expectations on the given mock object have been // satisfied. Reports one or more Google Test non-fatal failures @@ -465,17 +439,16 @@ class GTEST_API_ Mock { GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex); // Registers a mock object and a mock method it owns. - static void Register( - const void* mock_obj, - internal::UntypedFunctionMockerBase* mocker) - GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex); + static void Register(const void* mock_obj, + internal::UntypedFunctionMockerBase* mocker) + GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex); // Tells Google Mock where in the source code mock_obj is used in an // ON_CALL or EXPECT_CALL. In case mock_obj is leaked, this // information helps the user identify which object it is. - static void RegisterUseByOnCallOrExpectCall( - const void* mock_obj, const char* file, int line) - GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex); + static void RegisterUseByOnCallOrExpectCall(const void* mock_obj, + const char* file, int line) + GTEST_LOCK_EXCLUDED_(internal::g_gmock_mutex); // Unregisters a mock method; removes the owning mock object from // the registry when the last mock method associated with it has @@ -632,7 +605,6 @@ class ExpectationSet { Expectation::Set expectations_; }; - // Sequence objects are used by a user to specify the relative order // in which the expectations should match. They are copyable (we rely // on the compiler-defined copy constructor and assignment operator). @@ -678,10 +650,12 @@ class GTEST_API_ InSequence { public: InSequence(); ~InSequence(); + private: bool sequence_created_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(InSequence); // NOLINT + InSequence(const InSequence&) = delete; + InSequence& operator=(const InSequence&) = delete; } GTEST_ATTRIBUTE_UNUSED_; namespace internal { @@ -784,40 +758,34 @@ class GTEST_API_ ExpectationBase { // the current thread. // Retires all pre-requisites of this expectation. - void RetireAllPreRequisites() - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex); + void RetireAllPreRequisites() GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex); // Returns true if and only if this expectation is retired. - bool is_retired() const - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + bool is_retired() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); return retired_; } // Retires this expectation. - void Retire() - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + void Retire() GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); retired_ = true; } // Returns true if and only if this expectation is satisfied. - bool IsSatisfied() const - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + bool IsSatisfied() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); return cardinality().IsSatisfiedByCallCount(call_count_); } // Returns true if and only if this expectation is saturated. - bool IsSaturated() const - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + bool IsSaturated() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); return cardinality().IsSaturatedByCallCount(call_count_); } // Returns true if and only if this expectation is over-saturated. - bool IsOverSaturated() const - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + bool IsOverSaturated() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); return cardinality().IsOverSaturatedByCallCount(call_count_); } @@ -832,15 +800,13 @@ class GTEST_API_ ExpectationBase { GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex); // Returns the number this expectation has been invoked. - int call_count() const - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + int call_count() const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); return call_count_; } // Increments the number this expectation has been invoked. - void IncrementCallCount() - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + void IncrementCallCount() GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); call_count_++; } @@ -849,8 +815,7 @@ class GTEST_API_ ExpectationBase { // WillRepeatedly() clauses) against the cardinality if this hasn't // been done before. Prints a warning if there are too many or too // few actions. - void CheckActionCountIfNotDone() const - GTEST_LOCK_EXCLUDED_(mutex_); + void CheckActionCountIfNotDone() const GTEST_LOCK_EXCLUDED_(mutex_); friend class ::testing::Sequence; friend class ::testing::internal::ExpectationTester; @@ -863,12 +828,12 @@ class GTEST_API_ ExpectationBase { // This group of fields are part of the spec and won't change after // an EXPECT_CALL() statement finishes. - const char* file_; // The file that contains the expectation. - int line_; // The line number of the expectation. + const char* file_; // The file that contains the expectation. + int line_; // The line number of the expectation. const std::string source_text_; // The EXPECT_CALL(...) source text. // True if and only if the cardinality is specified explicitly. bool cardinality_specified_; - Cardinality cardinality_; // The cardinality of the expectation. + Cardinality cardinality_; // The cardinality of the expectation. // The immediate pre-requisites (i.e. expectations that must be // satisfied before this expectation can be matched) of this // expectation. We use std::shared_ptr in the set because we want an @@ -887,12 +852,18 @@ class GTEST_API_ ExpectationBase { bool retires_on_saturation_; Clause last_clause_; mutable bool action_count_checked_; // Under mutex_. - mutable Mutex mutex_; // Protects action_count_checked_. -}; // class ExpectationBase + mutable Mutex mutex_; // Protects action_count_checked_. +}; // class ExpectationBase -// Impements an expectation for the given function type. template <typename F> -class TypedExpectation : public ExpectationBase { +class TypedExpectation; + +// Implements an expectation for the given function type. +template <typename R, typename... Args> +class TypedExpectation<R(Args...)> : public ExpectationBase { + private: + using F = R(Args...); + public: typedef typename Function<F>::ArgumentTuple ArgumentTuple; typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple; @@ -945,9 +916,7 @@ class TypedExpectation : public ExpectationBase { } // Implements the .Times() clause. - TypedExpectation& Times(int n) { - return Times(Exactly(n)); - } + TypedExpectation& Times(int n) { return Times(Exactly(n)); } // Implements the .InSequence() clause. TypedExpectation& InSequence(const Sequence& s) { @@ -1007,14 +976,31 @@ class TypedExpectation : public ExpectationBase { return After(s1, s2, s3, s4).After(s5); } - // Implements the .WillOnce() clause. - TypedExpectation& WillOnce(const Action<F>& action) { + // Preferred, type-safe overload: consume anything that can be directly + // converted to a OnceAction, except for Action<F> objects themselves. + TypedExpectation& WillOnce(OnceAction<F> once_action) { + // Call the overload below, smuggling the OnceAction as a copyable callable. + // We know this is safe because a WillOnce action will not be called more + // than once. + return WillOnce(Action<F>(ActionAdaptor{ + std::make_shared<OnceAction<F>>(std::move(once_action)), + })); + } + + // Fallback overload: accept Action<F> objects and those actions that define + // `operator Action<F>` but not `operator OnceAction<F>`. + // + // This is templated in order to cause the overload above to be preferred + // when the input is convertible to either type. + template <int&... ExplicitArgumentBarrier, typename = void> + TypedExpectation& WillOnce(Action<F> action) { ExpectSpecProperty(last_clause_ <= kWillOnce, ".WillOnce() cannot appear after " ".WillRepeatedly() or .RetiresOnSaturation()."); last_clause_ = kWillOnce; - untyped_actions_.push_back(new Action<F>(action)); + untyped_actions_.push_back(new Action<F>(std::move(action))); + if (!cardinality_specified()) { set_cardinality(Exactly(static_cast<int>(untyped_actions_.size()))); } @@ -1062,9 +1048,7 @@ class TypedExpectation : public ExpectationBase { // Returns the matchers for the arguments as specified inside the // EXPECT_CALL() macro. - const ArgumentMatcherTuple& matchers() const { - return matchers_; - } + const ArgumentMatcherTuple& matchers() const { return matchers_; } // Returns the matcher specified by the .With() clause. const Matcher<const ArgumentTuple&>& extra_matcher() const { @@ -1088,6 +1072,16 @@ class TypedExpectation : public ExpectationBase { template <typename Function> friend class FunctionMocker; + // An adaptor that turns a OneAction<F> into something compatible with + // Action<F>. Must be called at most once. + struct ActionAdaptor { + std::shared_ptr<OnceAction<R(Args...)>> once_action; + + R operator()(Args&&... args) const { + return std::move(*once_action).Call(std::forward<Args>(args)...); + } + }; + // Returns an Expectation object that references and co-owns this // expectation. Expectation GetHandle() override { return owner_->GetHandleOf(this); } @@ -1119,10 +1113,8 @@ class TypedExpectation : public ExpectationBase { // Describes the result of matching the arguments against this // expectation to the given ostream. - void ExplainMatchResultTo( - const ArgumentTuple& args, - ::std::ostream* os) const - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + void ExplainMatchResultTo(const ArgumentTuple& args, ::std::ostream* os) const + GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); if (is_retired()) { @@ -1181,9 +1173,9 @@ class TypedExpectation : public ExpectationBase { ::std::stringstream ss; DescribeLocationTo(&ss); ss << "Actions ran out in " << source_text() << "...\n" - << "Called " << count << " times, but only " - << action_count << " WillOnce()" - << (action_count == 1 ? " is" : "s are") << " specified - "; + << "Called " << count << " times, but only " << action_count + << " WillOnce()" << (action_count == 1 ? " is" : "s are") + << " specified - "; mocker->DescribeDefaultActionTo(args, &ss); Log(kWarning, ss.str(), 1); } @@ -1225,7 +1217,7 @@ class TypedExpectation : public ExpectationBase { } // Must be done after IncrementCount()! - *what << "Mock function call matches " << source_text() <<"...\n"; + *what << "Mock function call matches " << source_text() << "...\n"; return &(GetCurrentAction(mocker, args)); } @@ -1236,7 +1228,8 @@ class TypedExpectation : public ExpectationBase { Matcher<const ArgumentTuple&> extra_matcher_; Action<F> repeated_action_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(TypedExpectation); + TypedExpectation(const TypedExpectation&) = delete; + TypedExpectation& operator=(const TypedExpectation&) = delete; }; // class TypedExpectation // A MockSpec object is used by ON_CALL() or EXPECT_CALL() for @@ -1258,8 +1251,8 @@ template <typename F> class MockSpec { public: typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple; - typedef typename internal::Function<F>::ArgumentMatcherTuple - ArgumentMatcherTuple; + typedef + typename internal::Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple; // Constructs a MockSpec object, given the function mocker object // that the spec is associated with. @@ -1269,8 +1262,9 @@ class MockSpec { // Adds a new default action spec to the function mocker and returns // the newly created spec. - internal::OnCallSpec<F>& InternalDefaultActionSetAt( - const char* file, int line, const char* obj, const char* call) { + internal::OnCallSpec<F>& InternalDefaultActionSetAt(const char* file, + int line, const char* obj, + const char* call) { LogWithLocation(internal::kInfo, file, line, std::string("ON_CALL(") + obj + ", " + call + ") invoked"); return function_mocker_->AddNewOnCallSpec(file, line, matchers_); @@ -1278,13 +1272,14 @@ class MockSpec { // Adds a new expectation spec to the function mocker and returns // the newly created spec. - internal::TypedExpectation<F>& InternalExpectedAt( - const char* file, int line, const char* obj, const char* call) { + internal::TypedExpectation<F>& InternalExpectedAt(const char* file, int line, + const char* obj, + const char* call) { const std::string source_text(std::string("EXPECT_CALL(") + obj + ", " + call + ")"); LogWithLocation(internal::kInfo, file, line, source_text + " invoked"); - return function_mocker_->AddNewExpectation( - file, line, source_text, matchers_); + return function_mocker_->AddNewExpectation(file, line, source_text, + matchers_); } // This operator overload is used to swallow the superfluous parameter list @@ -1317,9 +1312,7 @@ template <typename T> class ReferenceOrValueWrapper { public: // Constructs a wrapper from the given value/reference. - explicit ReferenceOrValueWrapper(T value) - : value_(std::move(value)) { - } + explicit ReferenceOrValueWrapper(T value) : value_(std::move(value)) {} // Unwraps and returns the underlying value/reference, exactly as // originally passed. The behavior of calling this more than once on @@ -1330,9 +1323,7 @@ class ReferenceOrValueWrapper { // Always returns a const reference (more precisely, // const std::add_lvalue_reference<T>::type). The behavior of calling this // after calling Unwrap on the same object is unspecified. - const T& Peek() const { - return value_; - } + const T& Peek() const { return value_; } private: T value_; @@ -1346,8 +1337,7 @@ class ReferenceOrValueWrapper<T&> { // Workaround for debatable pass-by-reference lint warning (c-library-team // policy precludes NOLINT in this context) typedef T& reference; - explicit ReferenceOrValueWrapper(reference ref) - : value_ptr_(&ref) {} + explicit ReferenceOrValueWrapper(reference ref) : value_ptr_(&ref) {} T& Unwrap() { return *value_ptr_; } const T& Peek() const { return *value_ptr_; } @@ -1355,102 +1345,27 @@ class ReferenceOrValueWrapper<T&> { T* value_ptr_; }; -// 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 -// copyable type or void (T doesn't need to be default-constructable). -// It hides the syntactic difference between void and other types, and -// is used to unify the code for invoking both void-returning and -// non-void-returning mock functions. - -// Untyped base class for ActionResultHolder<T>. -class UntypedActionResultHolderBase { - public: - virtual ~UntypedActionResultHolderBase() {} - - // Prints the held value as an action's result to os. - virtual void PrintAsActionResult(::std::ostream* os) const = 0; -}; - -// This generic definition is used when T is not void. +// Prints the held value as an action's result to os. template <typename T> -class ActionResultHolder : public UntypedActionResultHolderBase { - public: - // Returns the held value. Must not be called more than once. - T Unwrap() { - return result_.Unwrap(); - } - - // Prints the held value as an action's result to os. - void PrintAsActionResult(::std::ostream* os) const override { - *os << "\n Returns: "; - // T may be a reference type, so we don't use UniversalPrint(). - UniversalPrinter<T>::Print(result_.Peek(), os); - } - - // Performs the given mock function's default action and returns the - // result in a new-ed ActionResultHolder. - template <typename F> - static ActionResultHolder* PerformDefaultAction( - const FunctionMocker<F>* func_mocker, - typename Function<F>::ArgumentTuple&& args, - const std::string& call_description) { - return new ActionResultHolder(Wrapper(func_mocker->PerformDefaultAction( - std::move(args), call_description))); - } - - // Performs the given action and returns the result in a new-ed - // ActionResultHolder. - template <typename F> - static ActionResultHolder* PerformAction( - const Action<F>& action, typename Function<F>::ArgumentTuple&& args) { - return new ActionResultHolder( - Wrapper(action.Perform(std::move(args)))); - } - - private: - typedef ReferenceOrValueWrapper<T> Wrapper; - - explicit ActionResultHolder(Wrapper result) - : result_(std::move(result)) { - } - - Wrapper result_; +void PrintAsActionResult(const T& result, std::ostream& os) { + os << "\n Returns: "; + // T may be a reference type, so we don't use UniversalPrint(). + UniversalPrinter<T>::Print(result, &os); +} - GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionResultHolder); -}; +// Reports an uninteresting call (whose description is in msg) in the +// manner specified by 'reaction'. +GTEST_API_ void ReportUninterestingCall(CallReaction reaction, + const std::string& msg); -// Specialization for T = void. -template <> -class ActionResultHolder<void> : public UntypedActionResultHolderBase { +// A generic RAII type that runs a user-provided function in its destructor. +class Cleanup final { public: - void Unwrap() { } - - void PrintAsActionResult(::std::ostream* /* os */) const override {} - - // Performs the given mock function's default action and returns ownership - // of an empty ActionResultHolder*. - template <typename F> - static ActionResultHolder* PerformDefaultAction( - const FunctionMocker<F>* func_mocker, - typename Function<F>::ArgumentTuple&& args, - const std::string& call_description) { - func_mocker->PerformDefaultAction(std::move(args), call_description); - return new ActionResultHolder; - } - - // Performs the given action and returns ownership of an empty - // ActionResultHolder*. - template <typename F> - static ActionResultHolder* PerformAction( - const Action<F>& action, typename Function<F>::ArgumentTuple&& args) { - action.Perform(std::move(args)); - return new ActionResultHolder; - } + explicit Cleanup(std::function<void()> f) : f_(std::move(f)) {} + ~Cleanup() { f_(); } private: - ActionResultHolder() {} - GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionResultHolder); + std::function<void()> f_; }; template <typename F> @@ -1495,14 +1410,12 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase { // Returns the ON_CALL spec that matches this mock function with the // given arguments; returns NULL if no matching ON_CALL is found. // L = * - const OnCallSpec<F>* FindOnCallSpec( - const ArgumentTuple& args) const { - for (UntypedOnCallSpecs::const_reverse_iterator it - = untyped_on_call_specs_.rbegin(); + const OnCallSpec<F>* FindOnCallSpec(const ArgumentTuple& args) const { + for (UntypedOnCallSpecs::const_reverse_iterator it = + untyped_on_call_specs_.rbegin(); it != untyped_on_call_specs_.rend(); ++it) { const OnCallSpec<F>* spec = static_cast<const OnCallSpec<F>*>(*it); - if (spec->Matches(args)) - return spec; + if (spec->Matches(args)) return spec; } return nullptr; @@ -1510,15 +1423,14 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase { // Performs the default action of this mock function on the given // arguments and returns the result. Asserts (or throws if - // exceptions are enabled) with a helpful call descrption if there + // exceptions are enabled) with a helpful call description if there // is no valid return value. This method doesn't depend on the // mutable state of this object, and thus can be called concurrently // without locking. // L = * Result PerformDefaultAction(ArgumentTuple&& args, const std::string& call_description) const { - const OnCallSpec<F>* const spec = - this->FindOnCallSpec(args); + const OnCallSpec<F>* const spec = this->FindOnCallSpec(args); if (spec != nullptr) { return spec->GetAction().Perform(std::move(args)); } @@ -1536,32 +1448,6 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase { return DefaultValue<Result>::Get(); } - // Performs the default action with the given arguments and returns - // the action's result. The call description string will be used in - // the error message to describe the call in the case the default - // action fails. The caller is responsible for deleting the result. - // L = * - UntypedActionResultHolderBase* UntypedPerformDefaultAction( - void* untyped_args, // must point to an ArgumentTuple - const std::string& call_description) const override { - ArgumentTuple* args = static_cast<ArgumentTuple*>(untyped_args); - return ResultHolder::PerformDefaultAction(this, std::move(*args), - call_description); - } - - // Performs the given action with the given arguments and returns - // the action's result. The caller is responsible for deleting the - // result. - // L = * - UntypedActionResultHolderBase* UntypedPerformAction( - const void* untyped_action, void* untyped_args) const override { - // Make a copy of the action before performing it, in case the - // action deletes the mock object (and thus deletes itself). - const Action<F> action = *static_cast<const Action<F>*>(untyped_action); - ArgumentTuple* args = static_cast<ArgumentTuple*>(untyped_args); - return ResultHolder::PerformAction(action, std::move(*args)); - } - // Implements UntypedFunctionMockerBase::ClearDefaultActionsLocked(): // clears the ON_CALL()s set on this mock function. void ClearDefaultActionsLocked() override @@ -1579,8 +1465,7 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase { untyped_on_call_specs_.swap(specs_to_delete); g_gmock_mutex.Unlock(); - for (UntypedOnCallSpecs::const_iterator it = - specs_to_delete.begin(); + for (UntypedOnCallSpecs::const_iterator it = specs_to_delete.begin(); it != specs_to_delete.end(); ++it) { delete static_cast<const OnCallSpec<F>*>(*it); } @@ -1594,10 +1479,7 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase { // arguments. This function can be safely called from multiple // threads concurrently. 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(); + return InvokeWith(ArgumentTuple(std::forward<Args>(args)...)); } MockSpec<F> With(Matcher<Args>... m) { @@ -1608,13 +1490,10 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase { 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, - const ArgumentMatcherTuple& m) - GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { + OnCallSpec<F>& AddNewOnCallSpec(const char* file, int line, + const ArgumentMatcherTuple& m) + GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line); OnCallSpec<F>* const on_call_spec = new OnCallSpec<F>(file, line, m); untyped_on_call_specs_.push_back(on_call_spec); @@ -1644,7 +1523,8 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase { } private: - template <typename Func> friend class TypedExpectation; + template <typename Func> + friend class TypedExpectation; // Some utilities needed for implementing UntypedInvokeWith(). @@ -1728,9 +1608,8 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase { // Returns the expectation that matches the arguments, or NULL if no // expectation matches them. - TypedExpectation<F>* FindMatchingExpectationLocked( - const ArgumentTuple& args) const - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + TypedExpectation<F>* FindMatchingExpectationLocked(const ArgumentTuple& args) + const GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); // See the definition of untyped_expectations_ for why access to // it is unprotected here. @@ -1747,11 +1626,10 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase { } // Returns a message that the arguments don't match any expectation. - void FormatUnexpectedCallMessageLocked( - const ArgumentTuple& args, - ::std::ostream* os, - ::std::ostream* why) const - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + void FormatUnexpectedCallMessageLocked(const ArgumentTuple& args, + ::std::ostream* os, + ::std::ostream* why) const + GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); *os << "\nUnexpected mock function call - "; DescribeDefaultActionTo(args, os); @@ -1760,15 +1638,14 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase { // Prints a list of expectations that have been tried against the // current mock function call. - void PrintTriedExpectationsLocked( - const ArgumentTuple& args, - ::std::ostream* why) const - GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { + void PrintTriedExpectationsLocked(const ArgumentTuple& args, + ::std::ostream* why) const + GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { g_gmock_mutex.AssertHeld(); const size_t count = untyped_expectations_.size(); *why << "Google Mock tried the following " << count << " " - << (count == 1 ? "expectation, but it didn't match" : - "expectations, but none matched") + << (count == 1 ? "expectation, but it didn't match" + : "expectations, but none matched") << ":\n"; for (size_t i = 0; i < count; i++) { TypedExpectation<F>* const expectation = @@ -1783,11 +1660,177 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase { expectation->DescribeCallCountTo(why); } } + + // Performs the given action (or the default if it's null) with the given + // arguments and returns the action's result. + // L = * + R PerformAction(const void* untyped_action, ArgumentTuple&& args, + const std::string& call_description) const { + if (untyped_action == nullptr) { + return PerformDefaultAction(std::move(args), call_description); + } + + // Make a copy of the action before performing it, in case the + // action deletes the mock object (and thus deletes itself). + const Action<F> action = *static_cast<const Action<F>*>(untyped_action); + return action.Perform(std::move(args)); + } + + // Is it possible to store an object of the supplied type in a local variable + // for the sake of printing it, then return it on to the caller? + template <typename T> + using can_print_result = internal::conjunction< + // void can't be stored as an object (and we also don't need to print it). + internal::negation<std::is_void<T>>, + // Non-moveable types can't be returned on to the user, so there's no way + // for us to intercept and print them. + std::is_move_constructible<T>>; + + // Perform the supplied action, printing the result to os. + template <typename T = R, + typename std::enable_if<can_print_result<T>::value, int>::type = 0> + R PerformActionAndPrintResult(const void* const untyped_action, + ArgumentTuple&& args, + const std::string& call_description, + std::ostream& os) { + R result = PerformAction(untyped_action, std::move(args), call_description); + + PrintAsActionResult(result, os); + return std::forward<R>(result); + } + + // An overload for when it's not possible to print the result. In this case we + // simply perform the action. + template <typename T = R, + typename std::enable_if< + internal::negation<can_print_result<T>>::value, int>::type = 0> + R PerformActionAndPrintResult(const void* const untyped_action, + ArgumentTuple&& args, + const std::string& call_description, + std::ostream&) { + return PerformAction(untyped_action, std::move(args), call_description); + } + + // Returns the result of invoking this mock function with the given + // arguments. This function can be safely called from multiple + // threads concurrently. + R InvokeWith(ArgumentTuple&& args) GTEST_LOCK_EXCLUDED_(g_gmock_mutex); }; // class FunctionMocker -// Reports an uninteresting call (whose description is in msg) in the -// manner specified by 'reaction'. -void ReportUninterestingCall(CallReaction reaction, const std::string& msg); +// Calculates the result of invoking this mock function with the given +// arguments, prints it, and returns it. +template <typename R, typename... Args> +R FunctionMocker<R(Args...)>::InvokeWith(ArgumentTuple&& args) + GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { + // See the definition of untyped_expectations_ for why access to it + // is unprotected here. + if (untyped_expectations_.size() == 0) { + // No expectation is set on this mock method - we have an + // uninteresting call. + + // We must get Google Mock's reaction on uninteresting calls + // made on this mock object BEFORE performing the action, + // because the action may DELETE the mock object and make the + // following expression meaningless. + const CallReaction reaction = + Mock::GetReactionOnUninterestingCalls(MockObject()); + + // True if and only if we need to print this call's arguments and return + // value. This definition must be kept in sync with + // the behavior of ReportUninterestingCall(). + const bool need_to_report_uninteresting_call = + // If the user allows this uninteresting call, we print it + // only when they want informational messages. + reaction == kAllow ? LogIsVisible(kInfo) : + // If the user wants this to be a warning, we print + // it only when they want to see warnings. + reaction == kWarn + ? LogIsVisible(kWarning) + : + // Otherwise, the user wants this to be an error, and we + // should always print detailed information in the error. + true; + + if (!need_to_report_uninteresting_call) { + // Perform the action without printing the call information. + return this->PerformDefaultAction( + std::move(args), "Function call: " + std::string(Name())); + } + + // Warns about the uninteresting call. + ::std::stringstream ss; + this->UntypedDescribeUninterestingCall(&args, &ss); + + // Perform the action, print the result, and then report the uninteresting + // call. + // + // We use RAII to do the latter in case R is void or a non-moveable type. In + // either case we can't assign it to a local variable. + const Cleanup report_uninteresting_call( + [&] { ReportUninterestingCall(reaction, ss.str()); }); + + return PerformActionAndPrintResult(nullptr, std::move(args), ss.str(), ss); + } + + bool is_excessive = false; + ::std::stringstream ss; + ::std::stringstream why; + ::std::stringstream loc; + const void* untyped_action = nullptr; + + // The UntypedFindMatchingExpectation() function acquires and + // releases g_gmock_mutex. + + const ExpectationBase* const untyped_expectation = + this->UntypedFindMatchingExpectation(&args, &untyped_action, + &is_excessive, &ss, &why); + const bool found = untyped_expectation != nullptr; + + // True if and only if we need to print the call's arguments + // and return value. + // This definition must be kept in sync with the uses of Expect() + // and Log() in this function. + const bool need_to_report_call = + !found || is_excessive || LogIsVisible(kInfo); + if (!need_to_report_call) { + // Perform the action without printing the call information. + return PerformAction(untyped_action, std::move(args), ""); + } + + ss << " Function call: " << Name(); + this->UntypedPrintArgs(&args, &ss); + + // In case the action deletes a piece of the expectation, we + // generate the message beforehand. + if (found && !is_excessive) { + untyped_expectation->DescribeLocationTo(&loc); + } + + // Perform the action, print the result, and then fail or log in whatever way + // is appropriate. + // + // We use RAII to do the latter in case R is void or a non-moveable type. In + // either case we can't assign it to a local variable. + const Cleanup handle_failures([&] { + ss << "\n" << why.str(); + + if (!found) { + // No expectation matches this call - reports a failure. + Expect(false, nullptr, -1, ss.str()); + } else if (is_excessive) { + // We had an upper-bound violation and the failure message is in ss. + Expect(false, untyped_expectation->file(), untyped_expectation->line(), + ss.str()); + } else { + // We had an expected call and the matching expectation is + // described in ss. + Log(kInfo, loc.str() + ss.str(), 2); + } + }); + + return PerformActionAndPrintResult(untyped_action, std::move(args), ss.str(), + ss); +} } // namespace internal @@ -1952,7 +1995,9 @@ using internal::MockSpec; // // Expects a call to const MockFoo::Bar(). // EXPECT_CALL(Const(foo), Bar()); template <typename T> -inline const T& Const(const T& x) { return x; } +inline const T& Const(const T& x) { + return x; +} // Constructs an Expectation object that references and co-owns exp. inline Expectation::Expectation(internal::ExpectationBase& exp) // NOLINT |