From 844fa94976acbcd01dc2de0a0cc7efc4f97274df Mon Sep 17 00:00:00 2001 From: "zhanyong.wan" Date: Fri, 1 Mar 2013 01:54:22 +0000 Subject: [PATCH] Implements NaggyMock. --- include/gmock/gmock-generated-nice-strict.h | 157 ++++++++++++++++-- .../gmock/gmock-generated-nice-strict.h.pump | 117 ++++++------- include/gmock/gmock-spec-builders.h | 3 + test/gmock-nice-strict_test.cc | 106 +++++++++++- 4 files changed, 302 insertions(+), 81 deletions(-) diff --git a/include/gmock/gmock-generated-nice-strict.h b/include/gmock/gmock-generated-nice-strict.h index 6099e81e..4095f4d5 100644 --- a/include/gmock/gmock-generated-nice-strict.h +++ b/include/gmock/gmock-generated-nice-strict.h @@ -1,4 +1,6 @@ -// This file was GENERATED by a script. DO NOT EDIT BY HAND!!! +// This file was GENERATED by command: +// pump.py gmock-generated-nice-strict.h.pump +// DO NOT EDIT BY HAND!!! // Copyright 2008, Google Inc. // All rights reserved. @@ -31,26 +33,36 @@ // // Author: wan@google.com (Zhanyong Wan) -// Implements class templates NiceMock and StrictMock. +// Implements class templates NiceMock, NaggyMock, and StrictMock. // // Given a mock class MockFoo that is created using Google Mock, // NiceMock is a subclass of MockFoo that allows // uninteresting calls (i.e. calls to mock methods that have no -// EXPECT_CALL specs), and StrictMock is a subclass of -// MockFoo that treats all uninteresting calls as errors. +// EXPECT_CALL specs), NaggyMock is a subclass of MockFoo +// that prints a warning when an uninteresting call occurs, and +// StrictMock is a subclass of MockFoo that treats all +// uninteresting calls as errors. // -// NiceMock and StrictMock "inherits" the constructors of their -// respective base class, with up-to 10 arguments. Therefore you can -// write NiceMock(5, "a") to construct a nice mock where -// MockFoo has a constructor that accepts (int, const char*), for -// example. +// Currently a mock is naggy by default, so MockFoo and +// NaggyMock behave like the same. However, we will soon +// switch the default behavior of mocks to be nice, as that in general +// leads to more maintainable tests. When that happens, MockFoo will +// stop behaving like NaggyMock and start behaving like +// NiceMock. // -// A known limitation is that NiceMock and -// StrictMock only works for mock methods defined using the -// MOCK_METHOD* family of macros DIRECTLY in the MockFoo class. If a -// mock method is defined in a base class of MockFoo, the "nice" or -// "strict" modifier may not affect it, depending on the compiler. In -// particular, nesting NiceMock and StrictMock is NOT supported. +// NiceMock, NaggyMock, and StrictMock "inherit" the constructors of +// their respective base class, with up-to 10 arguments. Therefore +// you can write NiceMock(5, "a") to construct a nice mock +// where MockFoo has a constructor that accepts (int, const char*), +// for example. +// +// A known limitation is that NiceMock, NaggyMock, +// and StrictMock only works for mock methods defined using +// the MOCK_METHOD* family of macros DIRECTLY in the MockFoo class. +// If a mock method is defined in a base class of MockFoo, the "nice" +// or "strict" modifier may not affect it, depending on the compiler. +// In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT +// supported. // // Another known limitation is that the constructors of the base mock // cannot have arguments passed by non-const reference, which are @@ -160,6 +172,102 @@ class NiceMock : public MockClass { GTEST_DISALLOW_COPY_AND_ASSIGN_(NiceMock); }; +template +class NaggyMock : public MockClass { + public: + // We don't factor out the constructor body to a common method, as + // we have to avoid a possible clash with members of MockClass. + NaggyMock() { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + // C++ doesn't (yet) allow inheritance of constructors, so we have + // to define it for each arity. + template + explicit NaggyMock(const A1& a1) : MockClass(a1) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + template + NaggyMock(const A1& a1, const A2& a2) : MockClass(a1, a2) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3, + const A4& a4) : MockClass(a1, a2, a3, a4) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5) : MockClass(a1, a2, a3, a4, a5) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5, + a6, a7) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1, + a2, a3, a4, a5, a6, a7, a8) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7, const A8& a8, + const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, + const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + virtual ~NaggyMock() { + ::testing::Mock::UnregisterCallReaction( + internal::ImplicitCast_(this)); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(NaggyMock); +}; + template class StrictMock : public MockClass { public: @@ -170,6 +278,8 @@ class StrictMock : public MockClass { internal::ImplicitCast_(this)); } + // C++ doesn't (yet) allow inheritance of constructors, so we have + // to define it for each arity. template explicit StrictMock(const A1& a1) : MockClass(a1) { ::testing::Mock::FailUninterestingCalls( @@ -258,15 +368,28 @@ class StrictMock : public MockClass { // user errors of nesting nice and strict mocks. They do NOT catch // all possible errors. -// These specializations are declared but not defined, as NiceMock and -// StrictMock cannot be nested. +// These specializations are declared but not defined, as NiceMock, +// NaggyMock, and StrictMock cannot be nested. + template class NiceMock >; template +class NiceMock >; +template class NiceMock >; + +template +class NaggyMock >; +template +class NaggyMock >; +template +class NaggyMock >; + template class StrictMock >; template +class StrictMock >; +template class StrictMock >; } // namespace testing diff --git a/include/gmock/gmock-generated-nice-strict.h.pump b/include/gmock/gmock-generated-nice-strict.h.pump index b7964db3..3ee1ce7f 100644 --- a/include/gmock/gmock-generated-nice-strict.h.pump +++ b/include/gmock/gmock-generated-nice-strict.h.pump @@ -34,26 +34,36 @@ $var n = 10 $$ The maximum arity we support. // // Author: wan@google.com (Zhanyong Wan) -// Implements class templates NiceMock and StrictMock. +// Implements class templates NiceMock, NaggyMock, and StrictMock. // // Given a mock class MockFoo that is created using Google Mock, // NiceMock is a subclass of MockFoo that allows // uninteresting calls (i.e. calls to mock methods that have no -// EXPECT_CALL specs), and StrictMock is a subclass of -// MockFoo that treats all uninteresting calls as errors. +// EXPECT_CALL specs), NaggyMock is a subclass of MockFoo +// that prints a warning when an uninteresting call occurs, and +// StrictMock is a subclass of MockFoo that treats all +// uninteresting calls as errors. // -// NiceMock and StrictMock "inherits" the constructors of their -// respective base class, with up-to $n arguments. Therefore you can -// write NiceMock(5, "a") to construct a nice mock where -// MockFoo has a constructor that accepts (int, const char*), for -// example. +// Currently a mock is naggy by default, so MockFoo and +// NaggyMock behave like the same. However, we will soon +// switch the default behavior of mocks to be nice, as that in general +// leads to more maintainable tests. When that happens, MockFoo will +// stop behaving like NaggyMock and start behaving like +// NiceMock. // -// A known limitation is that NiceMock and -// StrictMock only works for mock methods defined using the -// MOCK_METHOD* family of macros DIRECTLY in the MockFoo class. If a -// mock method is defined in a base class of MockFoo, the "nice" or -// "strict" modifier may not affect it, depending on the compiler. In -// particular, nesting NiceMock and StrictMock is NOT supported. +// NiceMock, NaggyMock, and StrictMock "inherit" the constructors of +// their respective base class, with up-to $n arguments. Therefore +// you can write NiceMock(5, "a") to construct a nice mock +// where MockFoo has a constructor that accepts (int, const char*), +// for example. +// +// A known limitation is that NiceMock, NaggyMock, +// and StrictMock only works for mock methods defined using +// the MOCK_METHOD* family of macros DIRECTLY in the MockFoo class. +// If a mock method is defined in a base class of MockFoo, the "nice" +// or "strict" modifier may not affect it, depending on the compiler. +// In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT +// supported. // // Another known limitation is that the constructors of the base mock // cannot have arguments passed by non-const reference, which are @@ -67,21 +77,32 @@ $var n = 10 $$ The maximum arity we support. namespace testing { +$range kind 0..2 +$for kind [[ + +$var clazz=[[$if kind==0 [[NiceMock]] + $elif kind==1 [[NaggyMock]] + $else [[StrictMock]]]] + +$var method=[[$if kind==0 [[AllowUninterestingCalls]] + $elif kind==1 [[WarnUninterestingCalls]] + $else [[FailUninterestingCalls]]]] + template -class NiceMock : public MockClass { +class $clazz : public MockClass { public: // We don't factor out the constructor body to a common method, as // we have to avoid a possible clash with members of MockClass. - NiceMock() { - ::testing::Mock::AllowUninterestingCalls( + $clazz() { + ::testing::Mock::$method( internal::ImplicitCast_(this)); } // C++ doesn't (yet) allow inheritance of constructors, so we have // to define it for each arity. template - explicit NiceMock(const A1& a1) : MockClass(a1) { - ::testing::Mock::AllowUninterestingCalls( + explicit $clazz(const A1& a1) : MockClass(a1) { + ::testing::Mock::$method( internal::ImplicitCast_(this)); } @@ -89,70 +110,50 @@ $range i 2..n $for i [[ $range j 1..i template <$for j, [[typename A$j]]> - NiceMock($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) { - ::testing::Mock::AllowUninterestingCalls( + $clazz($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) { + ::testing::Mock::$method( internal::ImplicitCast_(this)); } ]] - virtual ~NiceMock() { + virtual ~$clazz() { ::testing::Mock::UnregisterCallReaction( internal::ImplicitCast_(this)); } private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(NiceMock); + GTEST_DISALLOW_COPY_AND_ASSIGN_($clazz); }; -template -class StrictMock : public MockClass { - public: - // We don't factor out the constructor body to a common method, as - // we have to avoid a possible clash with members of MockClass. - StrictMock() { - ::testing::Mock::FailUninterestingCalls( - internal::ImplicitCast_(this)); - } - - template - explicit StrictMock(const A1& a1) : MockClass(a1) { - ::testing::Mock::FailUninterestingCalls( - internal::ImplicitCast_(this)); - } - -$for i [[ -$range j 1..i - template <$for j, [[typename A$j]]> - StrictMock($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) { - ::testing::Mock::FailUninterestingCalls( - internal::ImplicitCast_(this)); - } - - ]] - virtual ~StrictMock() { - ::testing::Mock::UnregisterCallReaction( - internal::ImplicitCast_(this)); - } - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(StrictMock); -}; // The following specializations catch some (relatively more common) // user errors of nesting nice and strict mocks. They do NOT catch // all possible errors. -// These specializations are declared but not defined, as NiceMock and -// StrictMock cannot be nested. +// These specializations are declared but not defined, as NiceMock, +// NaggyMock, and StrictMock cannot be nested. + template class NiceMock >; template +class NiceMock >; +template class NiceMock >; + +template +class NaggyMock >; +template +class NaggyMock >; +template +class NaggyMock >; + template class StrictMock >; template +class StrictMock >; +template class StrictMock >; } // namespace testing diff --git a/include/gmock/gmock-spec-builders.h b/include/gmock/gmock-spec-builders.h index 59f1d71e..4c2dca98 100644 --- a/include/gmock/gmock-spec-builders.h +++ b/include/gmock/gmock-spec-builders.h @@ -399,6 +399,9 @@ class GTEST_API_ Mock { template friend class NiceMock; + template + friend class NaggyMock; + template friend class StrictMock; diff --git a/test/gmock-nice-strict_test.cc b/test/gmock-nice-strict_test.cc index 315a8221..9b83d88e 100644 --- a/test/gmock-nice-strict_test.cc +++ b/test/gmock-nice-strict_test.cc @@ -54,6 +54,7 @@ namespace gmock_nice_strict_test { using testing::internal::string; using testing::GMOCK_FLAG(verbose); using testing::HasSubstr; +using testing::NaggyMock; using testing::NiceMock; using testing::StrictMock; @@ -116,7 +117,7 @@ TEST(NiceMockTest, NoWarningForUninterestingCall) { CaptureStdout(); nice_foo.DoThis(); nice_foo.DoThat(true); - EXPECT_STREQ("", GetCapturedStdout().c_str()); + EXPECT_EQ("", GetCapturedStdout()); } // Tests that a nice mock generates no warning for uninteresting calls @@ -129,7 +130,7 @@ TEST(NiceMockTest, NoWarningForUninterestingCallAfterDeath) { CaptureStdout(); nice_foo->DoThis(); - EXPECT_STREQ("", GetCapturedStdout().c_str()); + EXPECT_EQ("", GetCapturedStdout()); } // Tests that a nice mock generates informational logs for @@ -141,12 +142,12 @@ TEST(NiceMockTest, InfoForUninterestingCall) { GMOCK_FLAG(verbose) = "info"; CaptureStdout(); nice_foo.DoThis(); - EXPECT_THAT(std::string(GetCapturedStdout()), + EXPECT_THAT(GetCapturedStdout(), HasSubstr("Uninteresting mock function call")); CaptureStdout(); nice_foo.DoThat(true); - EXPECT_THAT(std::string(GetCapturedStdout()), + EXPECT_THAT(GetCapturedStdout(), HasSubstr("Uninteresting mock function call")); GMOCK_FLAG(verbose) = saved_flag; } @@ -192,7 +193,7 @@ TEST(NiceMockTest, NonDefaultConstructor10) { #if !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE // Tests that NiceMock compiles where Mock is a user-defined -// class (as opposed to ::testing::Mock). We had to workaround an +// class (as opposed to ::testing::Mock). We had to work around an // MSVC 8.0 bug that caused the symbol Mock used in the definition of // NiceMock to be looked up in the wrong context, and this test // ensures that our fix works. @@ -206,6 +207,99 @@ TEST(NiceMockTest, AcceptsClassNamedMock) { } #endif // !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE +#if GTEST_HAS_STREAM_REDIRECTION + +// Tests that a naggy mock generates warnings for uninteresting calls. +TEST(NaggyMockTest, WarningForUninterestingCall) { + const string saved_flag = GMOCK_FLAG(verbose); + GMOCK_FLAG(verbose) = "warning"; + + NaggyMock naggy_foo; + + CaptureStdout(); + naggy_foo.DoThis(); + naggy_foo.DoThat(true); + EXPECT_THAT(GetCapturedStdout(), + HasSubstr("Uninteresting mock function call")); + + GMOCK_FLAG(verbose) = saved_flag; +} + +// Tests that a naggy mock generates a warning for an uninteresting call +// that deletes the mock object. +TEST(NaggyMockTest, WarningForUninterestingCallAfterDeath) { + const string saved_flag = GMOCK_FLAG(verbose); + GMOCK_FLAG(verbose) = "warning"; + + NaggyMock* const naggy_foo = new NaggyMock; + + ON_CALL(*naggy_foo, DoThis()) + .WillByDefault(Invoke(naggy_foo, &MockFoo::Delete)); + + CaptureStdout(); + naggy_foo->DoThis(); + EXPECT_THAT(GetCapturedStdout(), + HasSubstr("Uninteresting mock function call")); + + GMOCK_FLAG(verbose) = saved_flag; +} + +#endif // GTEST_HAS_STREAM_REDIRECTION + +// Tests that a naggy mock allows expected calls. +TEST(NaggyMockTest, AllowsExpectedCall) { + NaggyMock naggy_foo; + + EXPECT_CALL(naggy_foo, DoThis()); + naggy_foo.DoThis(); +} + +// Tests that an unexpected call on a naggy mock fails. +TEST(NaggyMockTest, UnexpectedCallFails) { + NaggyMock naggy_foo; + + EXPECT_CALL(naggy_foo, DoThis()).Times(0); + EXPECT_NONFATAL_FAILURE(naggy_foo.DoThis(), + "called more times than expected"); +} + +// Tests that NaggyMock works with a mock class that has a non-default +// constructor. +TEST(NaggyMockTest, NonDefaultConstructor) { + NaggyMock naggy_bar("hi"); + EXPECT_EQ("hi", naggy_bar.str()); + + naggy_bar.This(); + naggy_bar.That(5, true); +} + +// Tests that NaggyMock works with a mock class that has a 10-ary +// non-default constructor. +TEST(NaggyMockTest, NonDefaultConstructor10) { + NaggyMock naggy_bar('0', '1', "2", "3", '4', '5', + "6", "7", true, false); + EXPECT_EQ("01234567TF", naggy_bar.str()); + + naggy_bar.This(); + naggy_bar.That(5, true); +} + +#if !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE +// Tests that NaggyMock compiles where Mock is a user-defined +// class (as opposed to ::testing::Mock). We had to work around an +// MSVC 8.0 bug that caused the symbol Mock used in the definition of +// NaggyMock to be looked up in the wrong context, and this test +// ensures that our fix works. +// +// We have to skip this test on Symbian and Windows Mobile, as it +// causes the program to crash there, for reasons unclear to us yet. +TEST(NaggyMockTest, AcceptsClassNamedMock) { + NaggyMock< ::Mock> naggy; + EXPECT_CALL(naggy, DoThis()); + naggy.DoThis(); +} +#endif // !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE + // Tests that a strict mock allows expected calls. TEST(StrictMockTest, AllowsExpectedCall) { StrictMock strict_foo; @@ -266,7 +360,7 @@ TEST(StrictMockTest, NonDefaultConstructor10) { #if !GTEST_OS_SYMBIAN && !GTEST_OS_WINDOWS_MOBILE // Tests that StrictMock compiles where Mock is a user-defined -// class (as opposed to ::testing::Mock). We had to workaround an +// class (as opposed to ::testing::Mock). We had to work around an // MSVC 8.0 bug that caused the symbol Mock used in the definition of // StrictMock to be looked up in the wrong context, and this test // ensures that our fix works.