Commit de5be0eb authored by Abseil Team's avatar Abseil Team Committed by Gennadiy Civil
Browse files

Googletest export

Move FunctionMocker and MockFunction out of the pump file and implement with variadic templates.

PiperOrigin-RevId: 220640265
parent 105579a6
...@@ -52,281 +52,6 @@ ...@@ -52,281 +52,6 @@
namespace testing { namespace testing {
namespace internal { namespace internal {
template <typename F>
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 <typename F>
class FunctionMocker;
template <typename R>
class FunctionMocker<R()> : public
internal::FunctionMockerBase<R()> {
public:
typedef R F();
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
MockSpec<F> With() {
return MockSpec<F>(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 <typename R, typename A1>
class FunctionMocker<R(A1)> : public
internal::FunctionMockerBase<R(A1)> {
public:
typedef R F(A1);
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
MockSpec<F> With(const Matcher<A1>& m1) {
return MockSpec<F>(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>(a1)));
}
};
template <typename R, typename A1, typename A2>
class FunctionMocker<R(A1, A2)> : public
internal::FunctionMockerBase<R(A1, A2)> {
public:
typedef R F(A1, A2);
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
MockSpec<F> With(const Matcher<A1>& m1, const Matcher<A2>& m2) {
return MockSpec<F>(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>(a1),
std::forward<A2>(a2)));
}
};
template <typename R, typename A1, typename A2, typename A3>
class FunctionMocker<R(A1, A2, A3)> : public
internal::FunctionMockerBase<R(A1, A2, A3)> {
public:
typedef R F(A1, A2, A3);
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
MockSpec<F> With(const Matcher<A1>& m1, const Matcher<A2>& m2,
const Matcher<A3>& m3) {
return MockSpec<F>(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>(a1),
std::forward<A2>(a2), std::forward<A3>(a3)));
}
};
template <typename R, typename A1, typename A2, typename A3, typename A4>
class FunctionMocker<R(A1, A2, A3, A4)> : public
internal::FunctionMockerBase<R(A1, A2, A3, A4)> {
public:
typedef R F(A1, A2, A3, A4);
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
MockSpec<F> With(const Matcher<A1>& m1, const Matcher<A2>& m2,
const Matcher<A3>& m3, const Matcher<A4>& m4) {
return MockSpec<F>(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>(a1),
std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4)));
}
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
typename A5>
class FunctionMocker<R(A1, A2, A3, A4, A5)> : public
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5)> {
public:
typedef R F(A1, A2, A3, A4, A5);
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
MockSpec<F> With(const Matcher<A1>& m1, const Matcher<A2>& m2,
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5) {
return MockSpec<F>(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>(a1),
std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4),
std::forward<A5>(a5)));
}
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
typename A5, typename A6>
class FunctionMocker<R(A1, A2, A3, A4, A5, A6)> : public
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6)> {
public:
typedef R F(A1, A2, A3, A4, A5, A6);
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
MockSpec<F> With(const Matcher<A1>& m1, const Matcher<A2>& m2,
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
const Matcher<A6>& m6) {
return MockSpec<F>(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>(a1),
std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4),
std::forward<A5>(a5), std::forward<A6>(a6)));
}
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
typename A5, typename A6, typename A7>
class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7)> : public
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7)> {
public:
typedef R F(A1, A2, A3, A4, A5, A6, A7);
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
MockSpec<F> With(const Matcher<A1>& m1, const Matcher<A2>& m2,
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
const Matcher<A6>& m6, const Matcher<A7>& m7) {
return MockSpec<F>(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>(a1),
std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4),
std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7)));
}
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
typename A5, typename A6, typename A7, typename A8>
class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8)> : public
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8)> {
public:
typedef R F(A1, A2, A3, A4, A5, A6, A7, A8);
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
MockSpec<F> With(const Matcher<A1>& m1, const Matcher<A2>& m2,
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8) {
return MockSpec<F>(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>(a1),
std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4),
std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7),
std::forward<A8>(a8)));
}
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
typename A5, typename A6, typename A7, typename A8, typename A9>
class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> : public
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
public:
typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9);
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
MockSpec<F> With(const Matcher<A1>& m1, const Matcher<A2>& m2,
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8,
const Matcher<A9>& m9) {
return MockSpec<F>(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>(a1),
std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4),
std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7),
std::forward<A8>(a8), std::forward<A9>(a9)));
}
};
template <typename R, typename A1, typename A2, typename A3, typename A4,
typename A5, typename A6, typename A7, typename A8, typename A9,
typename A10>
class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> : public
internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> {
public:
typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
MockSpec<F> With(const Matcher<A1>& m1, const Matcher<A2>& m2,
const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8,
const Matcher<A9>& m9, const Matcher<A10>& m10) {
return MockSpec<F>(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>(a1),
std::forward<A2>(a2), std::forward<A3>(a3), std::forward<A4>(a4),
std::forward<A5>(a5), std::forward<A6>(a6), std::forward<A7>(a7),
std::forward<A8>(a8), std::forward<A9>(a9), std::forward<A10>(a10)));
}
};
// Removes the given pointer; this is a helper for the expectation setter method // Removes the given pointer; this is a helper for the expectation setter method
// for parameterless matchers. // for parameterless matchers.
// //
...@@ -1036,293 +761,6 @@ using internal::FunctionMocker; ...@@ -1036,293 +761,6 @@ using internal::FunctionMocker;
#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \ #define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \
GMOCK_METHOD10_(typename, const, ct, m, __VA_ARGS__) GMOCK_METHOD10_(typename, const, ct, m, __VA_ARGS__)
// 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>
class MockFunction<R()> {
public:
MockFunction() {}
MOCK_METHOD0_T(Call, R());
#if GTEST_HAS_STD_FUNCTION_
::std::function<R()> AsStdFunction() {
return [this]() -> R {
return this->Call();
};
}
#endif // GTEST_HAS_STD_FUNCTION_
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
};
template <typename R, typename A0>
class MockFunction<R(A0)> {
public:
MockFunction() {}
MOCK_METHOD1_T(Call, R(A0));
#if GTEST_HAS_STD_FUNCTION_
::std::function<R(A0)> AsStdFunction() {
return [this](A0 a0) -> R {
return this->Call(::std::forward<A0>(a0));
};
}
#endif // GTEST_HAS_STD_FUNCTION_
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
};
template <typename R, typename A0, typename A1>
class MockFunction<R(A0, A1)> {
public:
MockFunction() {}
MOCK_METHOD2_T(Call, R(A0, A1));
#if GTEST_HAS_STD_FUNCTION_
::std::function<R(A0, A1)> AsStdFunction() {
return [this](A0 a0, A1 a1) -> R {
return this->Call(::std::forward<A0>(a0), ::std::forward<A1>(a1));
};
}
#endif // GTEST_HAS_STD_FUNCTION_
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
};
template <typename R, typename A0, typename A1, typename A2>
class MockFunction<R(A0, A1, A2)> {
public:
MockFunction() {}
MOCK_METHOD3_T(Call, R(A0, A1, A2));
#if GTEST_HAS_STD_FUNCTION_
::std::function<R(A0, A1, A2)> AsStdFunction() {
return [this](A0 a0, A1 a1, A2 a2) -> R {
return this->Call(::std::forward<A0>(a0), ::std::forward<A1>(a1),
::std::forward<A2>(a2));
};
}
#endif // GTEST_HAS_STD_FUNCTION_
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
};
template <typename R, typename A0, typename A1, typename A2, typename A3>
class MockFunction<R(A0, A1, A2, A3)> {
public:
MockFunction() {}
MOCK_METHOD4_T(Call, R(A0, A1, A2, A3));
#if GTEST_HAS_STD_FUNCTION_
::std::function<R(A0, A1, A2, A3)> AsStdFunction() {
return [this](A0 a0, A1 a1, A2 a2, A3 a3) -> R {
return this->Call(::std::forward<A0>(a0), ::std::forward<A1>(a1),
::std::forward<A2>(a2), ::std::forward<A3>(a3));
};
}
#endif // GTEST_HAS_STD_FUNCTION_
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
};
template <typename R, typename A0, typename A1, typename A2, typename A3,
typename A4>
class MockFunction<R(A0, A1, A2, A3, A4)> {
public:
MockFunction() {}
MOCK_METHOD5_T(Call, R(A0, A1, A2, A3, A4));
#if GTEST_HAS_STD_FUNCTION_
::std::function<R(A0, A1, A2, A3, A4)> AsStdFunction() {
return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) -> R {
return this->Call(::std::forward<A0>(a0), ::std::forward<A1>(a1),
::std::forward<A2>(a2), ::std::forward<A3>(a3),
::std::forward<A4>(a4));
};
}
#endif // GTEST_HAS_STD_FUNCTION_
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
};
template <typename R, typename A0, typename A1, typename A2, typename A3,
typename A4, typename A5>
class MockFunction<R(A0, A1, A2, A3, A4, A5)> {
public:
MockFunction() {}
MOCK_METHOD6_T(Call, R(A0, A1, A2, A3, A4, A5));
#if GTEST_HAS_STD_FUNCTION_
::std::function<R(A0, A1, A2, A3, A4, A5)> AsStdFunction() {
return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -> R {
return this->Call(::std::forward<A0>(a0), ::std::forward<A1>(a1),
::std::forward<A2>(a2), ::std::forward<A3>(a3),
::std::forward<A4>(a4), ::std::forward<A5>(a5));
};
}
#endif // GTEST_HAS_STD_FUNCTION_
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
};
template <typename R, typename A0, typename A1, typename A2, typename A3,
typename A4, typename A5, typename A6>
class MockFunction<R(A0, A1, A2, A3, A4, A5, A6)> {
public:
MockFunction() {}
MOCK_METHOD7_T(Call, R(A0, A1, A2, A3, A4, A5, A6));
#if GTEST_HAS_STD_FUNCTION_
::std::function<R(A0, A1, A2, A3, A4, A5, A6)> AsStdFunction() {
return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) -> R {
return this->Call(::std::forward<A0>(a0), ::std::forward<A1>(a1),
::std::forward<A2>(a2), ::std::forward<A3>(a3),
::std::forward<A4>(a4), ::std::forward<A5>(a5),
::std::forward<A6>(a6));
};
}
#endif // GTEST_HAS_STD_FUNCTION_
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
};
template <typename R, typename A0, typename A1, typename A2, typename A3,
typename A4, typename A5, typename A6, typename A7>
class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7)> {
public:
MockFunction() {}
MOCK_METHOD8_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7));
#if GTEST_HAS_STD_FUNCTION_
::std::function<R(A0, A1, A2, A3, A4, A5, A6, A7)> 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>(a0), ::std::forward<A1>(a1),
::std::forward<A2>(a2), ::std::forward<A3>(a3),
::std::forward<A4>(a4), ::std::forward<A5>(a5),
::std::forward<A6>(a6), ::std::forward<A7>(a7));
};
}
#endif // GTEST_HAS_STD_FUNCTION_
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
};
template <typename R, typename A0, typename A1, typename A2, typename A3,
typename A4, typename A5, typename A6, typename A7, typename A8>
class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7, A8)> {
public:
MockFunction() {}
MOCK_METHOD9_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8));
#if GTEST_HAS_STD_FUNCTION_
::std::function<R(A0, A1, A2, A3, A4, A5, A6, A7, A8)> 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>(a0), ::std::forward<A1>(a1),
::std::forward<A2>(a2), ::std::forward<A3>(a3),
::std::forward<A4>(a4), ::std::forward<A5>(a5),
::std::forward<A6>(a6), ::std::forward<A7>(a7),
::std::forward<A8>(a8));
};
}
#endif // GTEST_HAS_STD_FUNCTION_
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
};
template <typename R, typename A0, typename A1, typename A2, typename A3,
typename A4, typename A5, typename A6, typename A7, typename A8,
typename A9>
class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
public:
MockFunction() {}
MOCK_METHOD10_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9));
#if GTEST_HAS_STD_FUNCTION_
::std::function<R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)> 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>(a0), ::std::forward<A1>(a1),
::std::forward<A2>(a2), ::std::forward<A3>(a3),
::std::forward<A4>(a4), ::std::forward<A5>(a5),
::std::forward<A6>(a6), ::std::forward<A7>(a7),
::std::forward<A8>(a8), ::std::forward<A9>(a9));
};
}
#endif // GTEST_HAS_STD_FUNCTION_
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
};
} // namespace testing } // namespace testing
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ #endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
...@@ -54,49 +54,7 @@ $var n = 10 $$ The maximum arity we support. ...@@ -54,49 +54,7 @@ $var n = 10 $$ The maximum arity we support.
namespace testing { namespace testing {
namespace internal { namespace internal {
template <typename F>
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 <typename F>
class FunctionMocker;
$range i 0..n $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>(a$j)]]]]
$var Aas = [[$for j, [[A$j a$j]]]]
$var ms = [[$for j, [[m$j]]]]
$var matchers = [[$for j, [[const Matcher<A$j>& m$j]]]]
template <typename R$typename_As>
class FunctionMocker<R($As)> : public
internal::FunctionMockerBase<R($As)> {
public:
typedef R F($As);
typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
MockSpec<F> With($matchers) {
return MockSpec<F>(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 // Removes the given pointer; this is a helper for the expectation setter method
// for parameterless matchers. // for parameterless matchers.
// //
...@@ -269,82 +227,6 @@ $for i [[ ...@@ -269,82 +227,6 @@ $for i [[
]] ]]
// 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;
$for i [[
$range j 0..i-1
$var ArgTypes = [[$for j, [[A$j]]]]
$var ArgValues = [[$for j, [[::std::forward<A$j>(a$j)]]]]
$var ArgDecls = [[$for j, [[A$j a$j]]]]
template <typename R$for j [[, typename A$j]]>
class MockFunction<R($ArgTypes)> {
public:
MockFunction() {}
MOCK_METHOD$i[[]]_T(Call, R($ArgTypes));
#if GTEST_HAS_STD_FUNCTION_
::std::function<R($ArgTypes)> AsStdFunction() {
return [this]($ArgDecls) -> R {
return this->Call($ArgValues);
};
}
#endif // GTEST_HAS_STD_FUNCTION_
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
};
]]
} // namespace testing } // namespace testing
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ #endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
...@@ -106,9 +106,6 @@ template <typename F> class TypedExpectation; ...@@ -106,9 +106,6 @@ template <typename F> class TypedExpectation;
// Helper class for testing the Expectation class template. // Helper class for testing the Expectation class template.
class ExpectationTester; class ExpectationTester;
// Base class for function mockers.
template <typename F> class FunctionMockerBase;
// Protects the mock object registry (in class Mock), all function // Protects the mock object registry (in class Mock), all function
// mockers, and all expectations. // mockers, and all expectations.
// //
...@@ -125,9 +122,9 @@ GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_gmock_mutex); ...@@ -125,9 +122,9 @@ GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_gmock_mutex);
// Untyped base class for ActionResultHolder<R>. // Untyped base class for ActionResultHolder<R>.
class UntypedActionResultHolderBase; 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 // 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 { class GTEST_API_ UntypedFunctionMockerBase {
public: public:
UntypedFunctionMockerBase(); UntypedFunctionMockerBase();
...@@ -415,7 +412,7 @@ class GTEST_API_ Mock { ...@@ -415,7 +412,7 @@ class GTEST_API_ Mock {
// Needed for a function mocker to register itself (so that we know // Needed for a function mocker to register itself (so that we know
// how to clear a mock object). // how to clear a mock object).
template <typename F> template <typename F>
friend class internal::FunctionMockerBase; friend class internal::FunctionMocker;
template <typename M> template <typename M>
friend class NiceMock; friend class NiceMock;
...@@ -478,7 +475,7 @@ class GTEST_API_ Mock { ...@@ -478,7 +475,7 @@ class GTEST_API_ Mock {
// Unregisters a mock method; removes the owning mock object from // Unregisters a mock method; removes the owning mock object from
// the registry when the last mock method associated with it has // the registry when the last mock method associated with it has
// been unregistered. This is called only in the destructor of // been unregistered. This is called only in the destructor of
// FunctionMockerBase. // FunctionMocker.
static void UnregisterLocked(internal::UntypedFunctionMockerBase* mocker) static void UnregisterLocked(internal::UntypedFunctionMockerBase* mocker)
GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex); GTEST_EXCLUSIVE_LOCK_REQUIRED_(internal::g_gmock_mutex);
}; // class Mock }; // class Mock
...@@ -534,7 +531,7 @@ class GTEST_API_ Expectation { ...@@ -534,7 +531,7 @@ class GTEST_API_ Expectation {
friend class ::testing::internal::UntypedFunctionMockerBase; friend class ::testing::internal::UntypedFunctionMockerBase;
template <typename F> template <typename F>
friend class ::testing::internal::FunctionMockerBase; friend class ::testing::internal::FunctionMocker;
template <typename F> template <typename F>
friend class ::testing::internal::TypedExpectation; friend class ::testing::internal::TypedExpectation;
...@@ -893,7 +890,7 @@ class TypedExpectation : public ExpectationBase { ...@@ -893,7 +890,7 @@ class TypedExpectation : public ExpectationBase {
typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple; typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
typedef typename Function<F>::Result Result; 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 std::string& a_source_text,
const ArgumentMatcherTuple& m) const ArgumentMatcherTuple& m)
: ExpectationBase(a_file, a_line, a_source_text), : ExpectationBase(a_file, a_line, a_source_text),
...@@ -1082,7 +1079,7 @@ class TypedExpectation : public ExpectationBase { ...@@ -1082,7 +1079,7 @@ class TypedExpectation : public ExpectationBase {
private: private:
template <typename Function> template <typename Function>
friend class FunctionMockerBase; friend class FunctionMocker;
// Returns an Expectation object that references and co-owns this // Returns an Expectation object that references and co-owns this
// expectation. // expectation.
...@@ -1161,8 +1158,7 @@ class TypedExpectation : public ExpectationBase { ...@@ -1161,8 +1158,7 @@ class TypedExpectation : public ExpectationBase {
} }
// Returns the action that should be taken for the current invocation. // Returns the action that should be taken for the current invocation.
const Action<F>& GetCurrentAction( const Action<F>& GetCurrentAction(const FunctionMocker<F>* mocker,
const FunctionMockerBase<F>* mocker,
const ArgumentTuple& args) const const ArgumentTuple& args) const
GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) { GTEST_EXCLUSIVE_LOCK_REQUIRED_(g_gmock_mutex) {
g_gmock_mutex.AssertHeld(); g_gmock_mutex.AssertHeld();
...@@ -1199,8 +1195,7 @@ class TypedExpectation : public ExpectationBase { ...@@ -1199,8 +1195,7 @@ class TypedExpectation : public ExpectationBase {
// Mock does it to 'why'. This method is not const as it calls // Mock does it to 'why'. This method is not const as it calls
// IncrementCallCount(). A return value of NULL means the default // IncrementCallCount(). A return value of NULL means the default
// action. // action.
const Action<F>* GetActionForArguments( const Action<F>* GetActionForArguments(const FunctionMocker<F>* mocker,
const FunctionMockerBase<F>* mocker,
const ArgumentTuple& args, const ArgumentTuple& args,
::std::ostream* what, ::std::ostream* what,
::std::ostream* why) ::std::ostream* why)
...@@ -1233,7 +1228,7 @@ class TypedExpectation : public ExpectationBase { ...@@ -1233,7 +1228,7 @@ class TypedExpectation : public ExpectationBase {
// All the fields below won't change once the EXPECT_CALL() // All the fields below won't change once the EXPECT_CALL()
// statement finishes. // statement finishes.
FunctionMockerBase<F>* const owner_; FunctionMocker<F>* const owner_;
ArgumentMatcherTuple matchers_; ArgumentMatcherTuple matchers_;
Matcher<const ArgumentTuple&> extra_matcher_; Matcher<const ArgumentTuple&> extra_matcher_;
Action<F> repeated_action_; Action<F> repeated_action_;
...@@ -1265,7 +1260,7 @@ class MockSpec { ...@@ -1265,7 +1260,7 @@ class MockSpec {
// Constructs a MockSpec object, given the function mocker object // Constructs a MockSpec object, given the function mocker object
// that the spec is associated with. // that the spec is associated with.
MockSpec(internal::FunctionMockerBase<F>* function_mocker, MockSpec(internal::FunctionMocker<F>* function_mocker,
const ArgumentMatcherTuple& matchers) const ArgumentMatcherTuple& matchers)
: function_mocker_(function_mocker), matchers_(matchers) {} : function_mocker_(function_mocker), matchers_(matchers) {}
...@@ -1301,7 +1296,7 @@ class MockSpec { ...@@ -1301,7 +1296,7 @@ class MockSpec {
friend class internal::FunctionMocker; friend class internal::FunctionMocker;
// The function mocker that owns this spec. // 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. // The argument matchers specified in the spec.
ArgumentMatcherTuple matchers_; ArgumentMatcherTuple matchers_;
...@@ -1402,7 +1397,7 @@ class ActionResultHolder : public UntypedActionResultHolderBase { ...@@ -1402,7 +1397,7 @@ class ActionResultHolder : public UntypedActionResultHolderBase {
// result in a new-ed ActionResultHolder. // result in a new-ed ActionResultHolder.
template <typename F> template <typename F>
static ActionResultHolder* PerformDefaultAction( static ActionResultHolder* PerformDefaultAction(
const FunctionMockerBase<F>* func_mocker, const FunctionMocker<F>* func_mocker,
typename Function<F>::ArgumentTuple&& args, typename Function<F>::ArgumentTuple&& args,
const std::string& call_description) { const std::string& call_description) {
return new ActionResultHolder(Wrapper(func_mocker->PerformDefaultAction( return new ActionResultHolder(Wrapper(func_mocker->PerformDefaultAction(
...@@ -1442,7 +1437,7 @@ class ActionResultHolder<void> : public UntypedActionResultHolderBase { ...@@ -1442,7 +1437,7 @@ class ActionResultHolder<void> : public UntypedActionResultHolderBase {
// of an empty ActionResultHolder*. // of an empty ActionResultHolder*.
template <typename F> template <typename F>
static ActionResultHolder* PerformDefaultAction( static ActionResultHolder* PerformDefaultAction(
const FunctionMockerBase<F>* func_mocker, const FunctionMocker<F>* func_mocker,
typename Function<F>::ArgumentTuple&& args, typename Function<F>::ArgumentTuple&& args,
const std::string& call_description) { const std::string& call_description) {
func_mocker->PerformDefaultAction(std::move(args), call_description); func_mocker->PerformDefaultAction(std::move(args), call_description);
...@@ -1463,22 +1458,39 @@ class ActionResultHolder<void> : public UntypedActionResultHolderBase { ...@@ -1463,22 +1458,39 @@ class ActionResultHolder<void> : public UntypedActionResultHolderBase {
GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionResultHolder); 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> 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: public:
typedef typename Function<F>::Result Result; using Result = R;
typedef typename Function<F>::ArgumentTuple ArgumentTuple; using ArgumentTuple = std::tuple<Args...>;
typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple; using ArgumentMatcherTuple = std::tuple<Matcher<Args>...>;
FunctionMocker() {}
FunctionMockerBase() {} // 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 // The destructor verifies that all expectations on this mock
// function have been satisfied. If not, it will report Google Test // function have been satisfied. If not, it will report Google Test
// non-fatal failures for the violations. // non-fatal failures for the violations.
virtual ~FunctionMockerBase() virtual ~FunctionMocker()
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
MutexLock l(&g_gmock_mutex); MutexLock l(&g_gmock_mutex);
VerifyAndClearExpectationsLocked(); VerifyAndClearExpectationsLocked();
...@@ -1509,7 +1521,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase { ...@@ -1509,7 +1521,7 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
// mutable state of this object, and thus can be called concurrently // mutable state of this object, and thus can be called concurrently
// without locking. // without locking.
// L = * // L = *
Result PerformDefaultAction(typename Function<F>::ArgumentTuple&& args, Result PerformDefaultAction(ArgumentTuple&& args,
const std::string& call_description) const { const std::string& call_description) const {
const OnCallSpec<F>* const spec = const OnCallSpec<F>* const spec =
this->FindOnCallSpec(args); this->FindOnCallSpec(args);
...@@ -1584,25 +1596,26 @@ class FunctionMockerBase : public UntypedFunctionMockerBase { ...@@ -1584,25 +1596,26 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
g_gmock_mutex.Lock(); 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 // Returns the result of invoking this mock function with the given
// arguments. This function can be safely called from multiple // arguments. This function can be safely called from multiple
// threads concurrently. // threads concurrently.
Result InvokeWith(typename Function<F>::ArgumentTuple&& args) Result Invoke(Args... args) GTEST_LOCK_EXCLUDED_(g_gmock_mutex) {
GTEST_LOCK_EXCLUDED_(g_gmock_mutex) { ArgumentTuple tuple(std::forward<Args>(args)...);
// const_cast is required since in C++98 we still pass ArgumentTuple around std::unique_ptr<ResultHolder> holder(DownCast_<ResultHolder*>(
// by const& instead of rvalue reference. this->UntypedInvokeWith(static_cast<void*>(&tuple))));
void* untyped_args = const_cast<void*>(static_cast<const void*>(&args));
std::unique_ptr<ResultHolder> holder(
DownCast_<ResultHolder*>(this->UntypedInvokeWith(untyped_args)));
return holder->Unwrap(); 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. // Adds and returns a default action spec for this mock function.
OnCallSpec<F>& AddNewOnCallSpec( OnCallSpec<F>& AddNewOnCallSpec(
const char* file, int line, const char* file, int line,
...@@ -1779,36 +1792,98 @@ class FunctionMockerBase : public UntypedFunctionMockerBase { ...@@ -1779,36 +1792,98 @@ class FunctionMockerBase : public UntypedFunctionMockerBase {
expectation->DescribeCallCountTo(why); expectation->DescribeCallCountTo(why);
} }
} }
}; // class 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) {}
// ...
// };
GTEST_DISALLOW_COPY_AND_ASSIGN_(FunctionMockerBase);
}; // class FunctionMockerBase
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4355 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 // Reports an uninteresting call (whose description is in msg) in the
// manner specified by 'reaction'. // manner specified by 'reaction'.
void ReportUninterestingCall(CallReaction reaction, const std::string& msg); void ReportUninterestingCall(CallReaction reaction, const std::string& msg);
} // namespace internal } // 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 // The style guide prohibits "using" statements in a namespace scope
// inside a header file. However, the MockSpec class template is // inside a header file. However, the MockSpec class template is
// meant to be defined in the ::testing namespace. The following line // meant to be defined in the ::testing namespace. The following line
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment