merging gmock-actions 2
This commit is contained in:
		
							parent
							
								
									bee1d13fcc
								
							
						
					
					
						commit
						88fc7d7552
					
				| @ -360,15 +360,21 @@ class Action { | ||||
| 
 | ||||
|   // Constructs a null Action.  Needed for storing Action objects in
 | ||||
|   // STL containers.
 | ||||
|   Action() : impl_(NULL) {} | ||||
|   Action() {} | ||||
| 
 | ||||
|   // Constructs an Action from its implementation.  A NULL impl is
 | ||||
|   // used to represent the "do-default" action.
 | ||||
| #if GTEST_LANG_CXX11 | ||||
|   // Construct an Action from a specified callable.
 | ||||
|   // This cannot take std::function directly, because then Action would not be
 | ||||
|   // directly constructible from lambda (it would require two conversions).
 | ||||
|   template <typename G, | ||||
|             typename = typename ::std::enable_if< | ||||
|                 ::std::is_constructible<::std::function<F>, G>::value>::type> | ||||
|   Action(G&& fun) : fun_(::std::forward<G>(fun)) {}  // NOLINT
 | ||||
| #endif | ||||
| 
 | ||||
|   // Constructs an Action from its implementation.
 | ||||
|   explicit Action(ActionInterface<F>* impl) : impl_(impl) {} | ||||
| 
 | ||||
|   // Copy constructor.
 | ||||
|   Action(const Action& action) : impl_(action.impl_) {} | ||||
| 
 | ||||
|   // This constructor allows us to turn an Action<Func> object into an
 | ||||
|   // Action<F>, as long as F's arguments can be implicitly converted
 | ||||
|   // to Func's and Func's return type can be implicitly converted to
 | ||||
| @ -377,7 +383,13 @@ class Action { | ||||
|   explicit Action(const Action<Func>& action); | ||||
| 
 | ||||
|   // Returns true iff this is the DoDefault() action.
 | ||||
|   bool IsDoDefault() const { return impl_.get() == NULL; } | ||||
|   bool IsDoDefault() const { | ||||
| #if GTEST_LANG_CXX11 | ||||
|     return impl_ == nullptr && fun_ == nullptr; | ||||
| #else | ||||
|     return impl_ == NULL; | ||||
| #endif | ||||
|   } | ||||
| 
 | ||||
|   // Performs the action.  Note that this method is const even though
 | ||||
|   // the corresponding method in ActionInterface is not.  The reason
 | ||||
| @ -385,14 +397,15 @@ class Action { | ||||
|   // another concrete action, not that the concrete action it binds to
 | ||||
|   // cannot change state.  (Think of the difference between a const
 | ||||
|   // pointer and a pointer to const.)
 | ||||
|   Result Perform(const ArgumentTuple& args) const { | ||||
|     internal::Assert( | ||||
|         !IsDoDefault(), __FILE__, __LINE__, | ||||
|         "You are using DoDefault() inside a composite action like " | ||||
|         "DoAll() or WithArgs().  This is not supported for technical " | ||||
|         "reasons.  Please instead spell out the default action, or " | ||||
|         "assign the default action to an Action variable and use " | ||||
|         "the variable in various places."); | ||||
|   Result Perform(ArgumentTuple args) const { | ||||
|     if (IsDoDefault()) { | ||||
|       internal::IllegalDoDefault(__FILE__, __LINE__); | ||||
|     } | ||||
| #if GTEST_LANG_CXX11 | ||||
|     if (fun_ != nullptr) { | ||||
|       return internal::Apply(fun_, ::std::move(args)); | ||||
|     } | ||||
| #endif | ||||
|     return impl_->Perform(args); | ||||
|   } | ||||
| 
 | ||||
| @ -400,6 +413,18 @@ class Action { | ||||
|   template <typename F1, typename F2> | ||||
|   friend class internal::ActionAdaptor; | ||||
| 
 | ||||
|   template <typename G> | ||||
|   friend class Action; | ||||
| 
 | ||||
|   // In C++11, Action can be implemented either as a generic functor (through
 | ||||
|   // std::function), or legacy ActionInterface. In C++98, only ActionInterface
 | ||||
|   // is available. The invariants are as follows:
 | ||||
|   // * in C++98, impl_ is null iff this is the default action
 | ||||
|   // * in C++11, at most one of fun_ & impl_ may be nonnull; both are null iff
 | ||||
|   //   this is the default action
 | ||||
| #if GTEST_LANG_CXX11 | ||||
|   ::std::function<F> fun_; | ||||
| #endif | ||||
|   internal::linked_ptr<ActionInterface<F> > impl_; | ||||
| }; | ||||
| 
 | ||||
| @ -531,6 +556,9 @@ struct ByMoveWrapper { | ||||
| // statement, and conversion of the result of Return to Action<T(U)> is a
 | ||||
| // good place for that.
 | ||||
| //
 | ||||
| // The real life example of the above scenario happens when an invocation
 | ||||
| // of gtl::Container() is passed into Return.
 | ||||
| //
 | ||||
| template <typename R> | ||||
| class ReturnAction { | ||||
|  public: | ||||
| @ -750,7 +778,7 @@ class DoDefaultAction { | ||||
|   // This template type conversion operator allows DoDefault() to be
 | ||||
|   // used in any function.
 | ||||
|   template <typename F> | ||||
|   operator Action<F>() const { return Action<F>(NULL); } | ||||
|   operator Action<F>() const { return Action<F>(); }  // NOLINT
 | ||||
| }; | ||||
| 
 | ||||
| // Implements the Assign action to set a given pointer referent to a
 | ||||
| @ -886,6 +914,28 @@ class InvokeMethodWithoutArgsAction { | ||||
|   GTEST_DISALLOW_ASSIGN_(InvokeMethodWithoutArgsAction); | ||||
| }; | ||||
| 
 | ||||
| // Implements the InvokeWithoutArgs(callback) action.
 | ||||
| template <typename CallbackType> | ||||
| class InvokeCallbackWithoutArgsAction { | ||||
|  public: | ||||
|   // The c'tor takes ownership of the callback.
 | ||||
|   explicit InvokeCallbackWithoutArgsAction(CallbackType* callback) | ||||
|       : callback_(callback) { | ||||
|     callback->CheckIsRepeatable();  // Makes sure the callback is permanent.
 | ||||
|   } | ||||
| 
 | ||||
|   // This type conversion operator template allows Invoke(callback) to
 | ||||
|   // be used wherever the callback's return type can be implicitly
 | ||||
|   // converted to that of the mock function.
 | ||||
|   template <typename Result, typename ArgumentTuple> | ||||
|   Result Perform(const ArgumentTuple&) const { return callback_->Run(); } | ||||
| 
 | ||||
|  private: | ||||
|   const internal::linked_ptr<CallbackType> callback_; | ||||
| 
 | ||||
|   GTEST_DISALLOW_ASSIGN_(InvokeCallbackWithoutArgsAction); | ||||
| }; | ||||
| 
 | ||||
| // Implements the IgnoreResult(action) action.
 | ||||
| template <typename A> | ||||
| class IgnoreResultAction { | ||||
| @ -1053,7 +1103,13 @@ typedef internal::IgnoredValue Unused; | ||||
| template <typename To> | ||||
| template <typename From> | ||||
| Action<To>::Action(const Action<From>& from) | ||||
|     : impl_(new internal::ActionAdaptor<To, From>(from)) {} | ||||
|     : | ||||
| #if GTEST_LANG_CXX11 | ||||
|       fun_(from.fun_), | ||||
| #endif | ||||
|       impl_(from.impl_ == NULL ? NULL | ||||
|                                : new internal::ActionAdaptor<To, From>(from)) { | ||||
| } | ||||
| 
 | ||||
| // Creates an action that returns 'value'.  'value' is passed by value
 | ||||
| // instead of const reference - otherwise Return("string literal")
 | ||||
|  | ||||
| @ -65,6 +65,7 @@ using testing::ReturnRef; | ||||
| using testing::ReturnRefOfCopy; | ||||
| using testing::SetArgPointee; | ||||
| using testing::SetArgumentPointee; | ||||
| using testing::Unused; | ||||
| using testing::_; | ||||
| using testing::get; | ||||
| using testing::internal::BuiltInDefaultValue; | ||||
| @ -705,6 +706,8 @@ class MockClass { | ||||
|   MOCK_METHOD0(MakeUniqueBase, std::unique_ptr<Base>()); | ||||
|   MOCK_METHOD0(MakeVectorUnique, std::vector<std::unique_ptr<int>>()); | ||||
|   MOCK_METHOD1(TakeUnique, int(std::unique_ptr<int>)); | ||||
|   MOCK_METHOD2(TakeUnique, | ||||
|                int(const std::unique_ptr<int>&, std::unique_ptr<int>)); | ||||
| #endif | ||||
| 
 | ||||
|  private: | ||||
| @ -756,7 +759,7 @@ TEST(DoDefaultDeathTest, DiesIfUsedInCompositeAction) { | ||||
| } | ||||
| 
 | ||||
| // Tests that DoDefault() returns the default value set by
 | ||||
| // DefaultValue<T>::Set() when it's not overridden by an ON_CALL().
 | ||||
| // DefaultValue<T>::Set() when it's not overriden by an ON_CALL().
 | ||||
| TEST(DoDefaultTest, ReturnsUserSpecifiedPerTypeDefaultValueWhenThereIsOne) { | ||||
|   DefaultValue<int>::Set(1); | ||||
|   MockClass mock; | ||||
| @ -1411,6 +1414,145 @@ TEST(MockMethodTest, CanReturnMoveOnlyValue_Invoke) { | ||||
|   EXPECT_EQ(7, *vresult[0]); | ||||
| } | ||||
| 
 | ||||
| TEST(MockMethodTest, CanTakeMoveOnlyValue) { | ||||
|   MockClass mock; | ||||
|   auto make = [](int i) { return std::unique_ptr<int>(new int(i)); }; | ||||
| 
 | ||||
|   EXPECT_CALL(mock, TakeUnique(_)).WillRepeatedly([](std::unique_ptr<int> i) { | ||||
|     return *i; | ||||
|   }); | ||||
|   // DoAll() does not compile, since it would move from its arguments twice.
 | ||||
|   // EXPECT_CALL(mock, TakeUnique(_, _))
 | ||||
|   //     .WillRepeatedly(DoAll(Invoke([](std::unique_ptr<int> j) {}),
 | ||||
|   //     Return(1)));
 | ||||
|   EXPECT_CALL(mock, TakeUnique(testing::Pointee(7))) | ||||
|       .WillOnce(Return(-7)) | ||||
|       .RetiresOnSaturation(); | ||||
|   EXPECT_CALL(mock, TakeUnique(testing::IsNull())) | ||||
|       .WillOnce(Return(-1)) | ||||
|       .RetiresOnSaturation(); | ||||
| 
 | ||||
|   EXPECT_EQ(5, mock.TakeUnique(make(5))); | ||||
|   EXPECT_EQ(-7, mock.TakeUnique(make(7))); | ||||
|   EXPECT_EQ(7, mock.TakeUnique(make(7))); | ||||
|   EXPECT_EQ(7, mock.TakeUnique(make(7))); | ||||
|   EXPECT_EQ(-1, mock.TakeUnique({})); | ||||
| 
 | ||||
|   // Some arguments are moved, some passed by reference.
 | ||||
|   auto lvalue = make(6); | ||||
|   EXPECT_CALL(mock, TakeUnique(_, _)) | ||||
|       .WillOnce([](const std::unique_ptr<int>& i, std::unique_ptr<int> j) { | ||||
|         return *i * *j; | ||||
|       }); | ||||
|   EXPECT_EQ(42, mock.TakeUnique(lvalue, make(7))); | ||||
| 
 | ||||
|   // The unique_ptr can be saved by the action.
 | ||||
|   std::unique_ptr<int> saved; | ||||
|   EXPECT_CALL(mock, TakeUnique(_)).WillOnce([&saved](std::unique_ptr<int> i) { | ||||
|     saved = std::move(i); | ||||
|     return 0; | ||||
|   }); | ||||
|   EXPECT_EQ(0, mock.TakeUnique(make(42))); | ||||
|   EXPECT_EQ(42, *saved); | ||||
| } | ||||
| 
 | ||||
| #endif  // GTEST_HAS_STD_UNIQUE_PTR_
 | ||||
| 
 | ||||
| #if GTEST_LANG_CXX11 | ||||
| // Tests for std::function based action.
 | ||||
| 
 | ||||
| int Add(int val, int& ref, int* ptr) {  // NOLINT
 | ||||
|   int result = val + ref + *ptr; | ||||
|   ref = 42; | ||||
|   *ptr = 43; | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| int Deref(std::unique_ptr<int> ptr) { return *ptr; } | ||||
| 
 | ||||
| struct Double { | ||||
|   template <typename T> | ||||
|   T operator()(T t) { return 2 * t; } | ||||
| }; | ||||
| 
 | ||||
| std::unique_ptr<int> UniqueInt(int i) { | ||||
|   return std::unique_ptr<int>(new int(i)); | ||||
| } | ||||
| 
 | ||||
| TEST(FunctorActionTest, ActionFromFunction) { | ||||
|   Action<int(int, int&, int*)> a = &Add; | ||||
|   int x = 1, y = 2, z = 3; | ||||
|   EXPECT_EQ(6, a.Perform(std::forward_as_tuple(x, y, &z))); | ||||
|   EXPECT_EQ(42, y); | ||||
|   EXPECT_EQ(43, z); | ||||
| 
 | ||||
|   Action<int(std::unique_ptr<int>)> a1 = &Deref; | ||||
|   EXPECT_EQ(7, a1.Perform(std::make_tuple(UniqueInt(7)))); | ||||
| } | ||||
| 
 | ||||
| TEST(FunctorActionTest, ActionFromLambda) { | ||||
|   Action<int(bool, int)> a1 = [](bool b, int i) { return b ? i : 0; }; | ||||
|   EXPECT_EQ(5, a1.Perform(make_tuple(true, 5))); | ||||
|   EXPECT_EQ(0, a1.Perform(make_tuple(false, 5))); | ||||
| 
 | ||||
|   std::unique_ptr<int> saved; | ||||
|   Action<void(std::unique_ptr<int>)> a2 = [&saved](std::unique_ptr<int> p) { | ||||
|     saved = std::move(p); | ||||
|   }; | ||||
|   a2.Perform(make_tuple(UniqueInt(5))); | ||||
|   EXPECT_EQ(5, *saved); | ||||
| } | ||||
| 
 | ||||
| TEST(FunctorActionTest, PolymorphicFunctor) { | ||||
|   Action<int(int)> ai = Double(); | ||||
|   EXPECT_EQ(2, ai.Perform(make_tuple(1))); | ||||
|   Action<double(double)> ad = Double();  // Double? Double double!
 | ||||
|   EXPECT_EQ(3.0, ad.Perform(make_tuple(1.5))); | ||||
| } | ||||
| 
 | ||||
| TEST(FunctorActionTest, TypeConversion) { | ||||
|   // Numeric promotions are allowed.
 | ||||
|   const Action<bool(int)> a1 = [](int i) { return i > 1; }; | ||||
|   const Action<int(bool)> a2 = Action<int(bool)>(a1); | ||||
|   EXPECT_EQ(1, a1.Perform(make_tuple(42))); | ||||
|   EXPECT_EQ(0, a2.Perform(make_tuple(42))); | ||||
| 
 | ||||
|   // Implicit constructors are allowed.
 | ||||
|   const Action<bool(std::string)> s1 = [](std::string s) { return !s.empty(); }; | ||||
|   const Action<int(const char*)> s2 = Action<int(const char*)>(s1); | ||||
|   EXPECT_EQ(0, s2.Perform(make_tuple(""))); | ||||
|   EXPECT_EQ(1, s2.Perform(make_tuple("hello"))); | ||||
| 
 | ||||
|   // Also between the lambda and the action itself.
 | ||||
|   const Action<bool(std::string)> x = [](Unused) { return 42; }; | ||||
|   EXPECT_TRUE(x.Perform(make_tuple("hello"))); | ||||
| } | ||||
| 
 | ||||
| TEST(FunctorActionTest, UnusedArguments) { | ||||
|   // Verify that users can ignore uninteresting arguments.
 | ||||
|   Action<int(int, std::unique_ptr<int>, const int&)> a = | ||||
|       [](int i, Unused, Unused) { return 2 * i; }; | ||||
|   EXPECT_EQ(6, a.Perform(make_tuple(3, UniqueInt(7), 9))); | ||||
| } | ||||
| 
 | ||||
| // Test that basic built-in actions work with move-only arguments.
 | ||||
| // TODO(rburny): Currently, almost all ActionInterface-based actions will not
 | ||||
| // work, even if they only try to use other, copyable arguments. Implement them
 | ||||
| // if necessary (but note that DoAll cannot work on non-copyable types anyway -
 | ||||
| // so maybe it's better to make users use lambdas instead.
 | ||||
| TEST(MoveOnlyArgumentsTest, ReturningActions) { | ||||
|   Action<int(std::unique_ptr<int>)> a = Return(1); | ||||
|   EXPECT_EQ(1, a.Perform(make_tuple(nullptr))); | ||||
| 
 | ||||
|   a = testing::WithoutArgs([]() { return 7; }); | ||||
|   EXPECT_EQ(7, a.Perform(make_tuple(nullptr))); | ||||
| 
 | ||||
|   Action<void(std::unique_ptr<int>, int*)> a2 = testing::SetArgPointee<1>(3); | ||||
|   int x = 0; | ||||
|   a2.Perform(make_tuple(nullptr, &x)); | ||||
|   EXPECT_EQ(x, 3); | ||||
| } | ||||
| 
 | ||||
| #endif  // GTEST_LANG_CXX11
 | ||||
| 
 | ||||
| }  // Unnamed namespace
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user