Add ByMove() modifier for the Return() action. Pull in gtest 695.
This commit is contained in:
		
							parent
							
								
									5b9cbbb16d
								
							
						
					
					
						commit
						3d1c78b2bf
					
				| @ -459,6 +459,14 @@ class ActionAdaptor : public ActionInterface<F1> { | |||||||
|   GTEST_DISALLOW_ASSIGN_(ActionAdaptor); |   GTEST_DISALLOW_ASSIGN_(ActionAdaptor); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | // Helper struct to specialize ReturnAction to execute a move instead of a copy
 | ||||||
|  | // on return. Useful for move-only types, but could be used on any type.
 | ||||||
|  | template <typename T> | ||||||
|  | struct ByMoveWrapper { | ||||||
|  |   explicit ByMoveWrapper(T value) : payload(move(value)) {} | ||||||
|  |   T payload; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| // Implements the polymorphic Return(x) action, which can be used in
 | // Implements the polymorphic Return(x) action, which can be used in
 | ||||||
| // any function that returns the type of x, regardless of the argument
 | // any function that returns the type of x, regardless of the argument
 | ||||||
| // types.
 | // types.
 | ||||||
| @ -489,7 +497,7 @@ class ReturnAction { | |||||||
|   // Constructs a ReturnAction object from the value to be returned.
 |   // Constructs a ReturnAction object from the value to be returned.
 | ||||||
|   // 'value' is passed by value instead of by const reference in order
 |   // 'value' is passed by value instead of by const reference in order
 | ||||||
|   // to allow Return("string literal") to compile.
 |   // to allow Return("string literal") to compile.
 | ||||||
|   explicit ReturnAction(R value) : value_(value) {} |   explicit ReturnAction(R value) : value_(new R(move(value))) {} | ||||||
| 
 | 
 | ||||||
|   // This template type conversion operator allows Return(x) to be
 |   // This template type conversion operator allows Return(x) to be
 | ||||||
|   // used in ANY function that returns x's type.
 |   // used in ANY function that returns x's type.
 | ||||||
| @ -505,14 +513,14 @@ class ReturnAction { | |||||||
|     // in the Impl class. But both definitions must be the same.
 |     // in the Impl class. But both definitions must be the same.
 | ||||||
|     typedef typename Function<F>::Result Result; |     typedef typename Function<F>::Result Result; | ||||||
|     GTEST_COMPILE_ASSERT_( |     GTEST_COMPILE_ASSERT_( | ||||||
|         !internal::is_reference<Result>::value, |         !is_reference<Result>::value, | ||||||
|         use_ReturnRef_instead_of_Return_to_return_a_reference); |         use_ReturnRef_instead_of_Return_to_return_a_reference); | ||||||
|     return Action<F>(new Impl<F>(value_)); |     return Action<F>(new Impl<R, F>(value_)); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  private: |  private: | ||||||
|   // Implements the Return(x) action for a particular function type F.
 |   // Implements the Return(x) action for a particular function type F.
 | ||||||
|   template <typename F> |   template <typename R_, typename F> | ||||||
|   class Impl : public ActionInterface<F> { |   class Impl : public ActionInterface<F> { | ||||||
|    public: |    public: | ||||||
|     typedef typename Function<F>::Result Result; |     typedef typename Function<F>::Result Result; | ||||||
| @ -525,20 +533,45 @@ class ReturnAction { | |||||||
|     // Result to call.  ImplicitCast_ forces the compiler to convert R to
 |     // Result to call.  ImplicitCast_ forces the compiler to convert R to
 | ||||||
|     // Result without considering explicit constructors, thus resolving the
 |     // Result without considering explicit constructors, thus resolving the
 | ||||||
|     // ambiguity. value_ is then initialized using its copy constructor.
 |     // ambiguity. value_ is then initialized using its copy constructor.
 | ||||||
|     explicit Impl(R value) |     explicit Impl(const linked_ptr<R>& value) | ||||||
|         : value_(::testing::internal::ImplicitCast_<Result>(value)) {} |         : value_(ImplicitCast_<Result>(*value)) {} | ||||||
| 
 | 
 | ||||||
|     virtual Result Perform(const ArgumentTuple&) { return value_; } |     virtual Result Perform(const ArgumentTuple&) { return value_; } | ||||||
| 
 | 
 | ||||||
|    private: |    private: | ||||||
|     GTEST_COMPILE_ASSERT_(!internal::is_reference<Result>::value, |     GTEST_COMPILE_ASSERT_(!is_reference<Result>::value, | ||||||
|                           Result_cannot_be_a_reference_type); |                           Result_cannot_be_a_reference_type); | ||||||
|     Result value_; |     Result value_; | ||||||
| 
 | 
 | ||||||
|     GTEST_DISALLOW_ASSIGN_(Impl); |     GTEST_DISALLOW_ASSIGN_(Impl); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   R value_; |   // Partially specialize for ByMoveWrapper. This version of ReturnAction will
 | ||||||
|  |   // move its contents instead.
 | ||||||
|  |   template <typename R_, typename F> | ||||||
|  |   class Impl<ByMoveWrapper<R_>, F> : public ActionInterface<F> { | ||||||
|  |    public: | ||||||
|  |     typedef typename Function<F>::Result Result; | ||||||
|  |     typedef typename Function<F>::ArgumentTuple ArgumentTuple; | ||||||
|  | 
 | ||||||
|  |     explicit Impl(const linked_ptr<R>& wrapper) | ||||||
|  |         : performed_(false), wrapper_(wrapper) {} | ||||||
|  | 
 | ||||||
|  |     virtual Result Perform(const ArgumentTuple&) { | ||||||
|  |       GTEST_CHECK_(!performed_) | ||||||
|  |           << "A ByMove() action should only be performed once."; | ||||||
|  |       performed_ = true; | ||||||
|  |       return move(wrapper_->payload); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |    private: | ||||||
|  |     bool performed_; | ||||||
|  |     const linked_ptr<R> wrapper_; | ||||||
|  | 
 | ||||||
|  |     GTEST_DISALLOW_ASSIGN_(Impl); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const linked_ptr<R> value_; | ||||||
| 
 | 
 | ||||||
|   GTEST_DISALLOW_ASSIGN_(ReturnAction); |   GTEST_DISALLOW_ASSIGN_(ReturnAction); | ||||||
| }; | }; | ||||||
| @ -977,7 +1010,7 @@ Action<To>::Action(const Action<From>& from) | |||||||
| // will trigger a compiler error about using array as initializer.
 | // will trigger a compiler error about using array as initializer.
 | ||||||
| template <typename R> | template <typename R> | ||||||
| internal::ReturnAction<R> Return(R value) { | internal::ReturnAction<R> Return(R value) { | ||||||
|   return internal::ReturnAction<R>(value); |   return internal::ReturnAction<R>(internal::move(value)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Creates an action that returns NULL.
 | // Creates an action that returns NULL.
 | ||||||
| @ -1004,6 +1037,15 @@ inline internal::ReturnRefOfCopyAction<R> ReturnRefOfCopy(const R& x) { | |||||||
|   return internal::ReturnRefOfCopyAction<R>(x); |   return internal::ReturnRefOfCopyAction<R>(x); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Modifies the parent action (a Return() action) to perform a move of the
 | ||||||
|  | // argument instead of a copy.
 | ||||||
|  | // Return(ByMove()) actions can only be executed once and will assert this
 | ||||||
|  | // invariant.
 | ||||||
|  | template <typename R> | ||||||
|  | internal::ByMoveWrapper<R> ByMove(R x) { | ||||||
|  |   return internal::ByMoveWrapper<R>(internal::move(x)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Creates an action that does the default action for the give mock function.
 | // Creates an action that does the default action for the give mock function.
 | ||||||
| inline internal::DoDefaultAction DoDefault() { | inline internal::DoDefaultAction DoDefault() { | ||||||
|   return internal::DoDefaultAction(); |   return internal::DoDefaultAction(); | ||||||
|  | |||||||
| @ -1302,15 +1302,12 @@ template <typename T> | |||||||
| class ReferenceOrValueWrapper { | class ReferenceOrValueWrapper { | ||||||
|  public: |  public: | ||||||
|   // Constructs a wrapper from the given value/reference.
 |   // Constructs a wrapper from the given value/reference.
 | ||||||
|   explicit ReferenceOrValueWrapper(T value) |   explicit ReferenceOrValueWrapper(T value) : value_(move(value)) {} | ||||||
|       : value_(GTEST_MOVE_(value)) {} |  | ||||||
| 
 | 
 | ||||||
|   // Unwraps and returns the underlying value/reference, exactly as
 |   // Unwraps and returns the underlying value/reference, exactly as
 | ||||||
|   // originally passed. The behavior of calling this more than once on
 |   // originally passed. The behavior of calling this more than once on
 | ||||||
|   // the same object is unspecified.
 |   // the same object is unspecified.
 | ||||||
|   T Unwrap() { |   T Unwrap() { return move(value_); } | ||||||
|     return GTEST_MOVE_(value_); |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   // Provides nondestructive access to the underlying value/reference.
 |   // Provides nondestructive access to the underlying value/reference.
 | ||||||
|   // Always returns a const reference (more precisely,
 |   // Always returns a const reference (more precisely,
 | ||||||
| @ -1407,8 +1404,7 @@ class ActionResultHolder : public UntypedActionResultHolderBase { | |||||||
|  private: |  private: | ||||||
|   typedef ReferenceOrValueWrapper<T> Wrapper; |   typedef ReferenceOrValueWrapper<T> Wrapper; | ||||||
| 
 | 
 | ||||||
|   explicit ActionResultHolder(Wrapper result) |   explicit ActionResultHolder(Wrapper result) : result_(move(result)) {} | ||||||
|       : result_(GTEST_MOVE_(result)) {} |  | ||||||
| 
 | 
 | ||||||
|   Wrapper result_; |   Wrapper result_; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -57,6 +57,7 @@ using testing::_; | |||||||
| using testing::Action; | using testing::Action; | ||||||
| using testing::ActionInterface; | using testing::ActionInterface; | ||||||
| using testing::Assign; | using testing::Assign; | ||||||
|  | using testing::ByMove; | ||||||
| using testing::ByRef; | using testing::ByRef; | ||||||
| using testing::DefaultValue; | using testing::DefaultValue; | ||||||
| using testing::DoDefault; | using testing::DoDefault; | ||||||
| @ -638,6 +639,7 @@ class MockClass { | |||||||
|   MOCK_METHOD0(Foo, MyClass()); |   MOCK_METHOD0(Foo, MyClass()); | ||||||
| #if GTEST_HAS_STD_UNIQUE_PTR_ | #if GTEST_HAS_STD_UNIQUE_PTR_ | ||||||
|   MOCK_METHOD0(MakeUnique, std::unique_ptr<int>()); |   MOCK_METHOD0(MakeUnique, std::unique_ptr<int>()); | ||||||
|  |   MOCK_METHOD0(MakeUniqueBase, std::unique_ptr<Base>()); | ||||||
|   MOCK_METHOD0(MakeVectorUnique, std::vector<std::unique_ptr<int>>()); |   MOCK_METHOD0(MakeVectorUnique, std::vector<std::unique_ptr<int>>()); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| @ -1285,7 +1287,42 @@ std::vector<std::unique_ptr<int>> VectorUniquePtrSource() { | |||||||
|   return out; |   return out; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST(MockMethodTest, CanReturnMoveOnlyValue) { | TEST(MockMethodTest, CanReturnMoveOnlyValue_Return) { | ||||||
|  |   MockClass mock; | ||||||
|  |   std::unique_ptr<int> i(new int(19)); | ||||||
|  |   EXPECT_CALL(mock, MakeUnique()).WillOnce(Return(ByMove(std::move(i)))); | ||||||
|  |   EXPECT_CALL(mock, MakeVectorUnique()) | ||||||
|  |       .WillOnce(Return(ByMove(VectorUniquePtrSource()))); | ||||||
|  |   Derived* d = new Derived; | ||||||
|  |   EXPECT_CALL(mock, MakeUniqueBase()) | ||||||
|  |       .WillOnce(Return(ByMove(std::unique_ptr<Derived>(d)))); | ||||||
|  | 
 | ||||||
|  |   std::unique_ptr<int> result1 = mock.MakeUnique(); | ||||||
|  |   EXPECT_EQ(19, *result1); | ||||||
|  | 
 | ||||||
|  |   std::vector<std::unique_ptr<int>> vresult = mock.MakeVectorUnique(); | ||||||
|  |   EXPECT_EQ(1, vresult.size()); | ||||||
|  |   EXPECT_NE(nullptr, vresult[0]); | ||||||
|  |   EXPECT_EQ(7, *vresult[0]); | ||||||
|  | 
 | ||||||
|  |   std::unique_ptr<Base> result2 = mock.MakeUniqueBase(); | ||||||
|  |   EXPECT_EQ(d, result2.get()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | TEST(MockMethodTest, CanReturnMoveOnlyValue_DoAllReturn) { | ||||||
|  |   testing::MockFunction<void()> mock_function; | ||||||
|  |   MockClass mock; | ||||||
|  |   std::unique_ptr<int> i(new int(19)); | ||||||
|  |   EXPECT_CALL(mock_function, Call()); | ||||||
|  |   EXPECT_CALL(mock, MakeUnique()).WillOnce(DoAll( | ||||||
|  |       InvokeWithoutArgs(&mock_function, &testing::MockFunction<void()>::Call), | ||||||
|  |       Return(ByMove(std::move(i))))); | ||||||
|  | 
 | ||||||
|  |   std::unique_ptr<int> result1 = mock.MakeUnique(); | ||||||
|  |   EXPECT_EQ(19, *result1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | TEST(MockMethodTest, CanReturnMoveOnlyValue_Invoke) { | ||||||
|   MockClass mock; |   MockClass mock; | ||||||
| 
 | 
 | ||||||
|   // Check default value
 |   // Check default value
 | ||||||
| @ -1294,8 +1331,7 @@ TEST(MockMethodTest, CanReturnMoveOnlyValue) { | |||||||
|   }); |   }); | ||||||
|   EXPECT_EQ(42, *mock.MakeUnique()); |   EXPECT_EQ(42, *mock.MakeUnique()); | ||||||
| 
 | 
 | ||||||
|   EXPECT_CALL(mock, MakeUnique()) |   EXPECT_CALL(mock, MakeUnique()).WillRepeatedly(Invoke(UniquePtrSource)); | ||||||
|       .WillRepeatedly(Invoke(UniquePtrSource)); |  | ||||||
|   EXPECT_CALL(mock, MakeVectorUnique()) |   EXPECT_CALL(mock, MakeVectorUnique()) | ||||||
|       .WillRepeatedly(Invoke(VectorUniquePtrSource)); |       .WillRepeatedly(Invoke(VectorUniquePtrSource)); | ||||||
|   std::unique_ptr<int> result1 = mock.MakeUnique(); |   std::unique_ptr<int> result1 = mock.MakeUnique(); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user