From 1324e2d706d739217cceae361259a5cc01d1ff41 Mon Sep 17 00:00:00 2001 From: Victor Costan Date: Mon, 9 Apr 2018 21:57:54 -0700 Subject: [PATCH] Remove multiple inheritance from "unintesting call" mock classes. Internal CL 156157936, which was published in commit fe402c27790ff1cc9a7e17c5d0aea4ebe7fd8a71, introduced undefined behavior by casting a base class (internal::{Naggy,Nice,Strict}Base, using the curiously recurring template pattern) pointer to a derived class ({Naggy,Nice,Strict}Mock), in the base class' constructor. At that point, the object isn't guaranteed to have taken on the shape of the derived class, and casting is undefined behavior. The undefined behavior was caught by Chrome's CFI build bot [1], and prevents rolling googletest past that commit / CL. This commit simplifies the {Naggy,Nice,Strict}Mock class hierarchy in a way that removes the undefined behavior. [1] https://www.chromium.org/developers/testing/control-flow-integrity --- .../gmock/gmock-generated-nice-strict.h | 332 +++++++++--------- .../gmock/gmock-generated-nice-strict.h.pump | 70 ++-- .../include/gmock/gmock-spec-builders.h | 11 +- googlemock/test/gmock-nice-strict_test.cc | 21 ++ 4 files changed, 224 insertions(+), 210 deletions(-) diff --git a/googlemock/include/gmock/gmock-generated-nice-strict.h b/googlemock/include/gmock/gmock-generated-nice-strict.h index af71fbdf..5e1386b4 100644 --- a/googlemock/include/gmock/gmock-generated-nice-strict.h +++ b/googlemock/include/gmock/gmock-generated-nice-strict.h @@ -71,329 +71,345 @@ namespace testing { -namespace internal { - -// NiceMockBase serves as a mix-in to establish the "uninteresting call" -// behavior for NiceMock on construction. It accomplishes this via CRTP to get -// access to the derived MockClass. template -class NiceMockBase { - protected: - NiceMockBase(); - - ~NiceMockBase(); -}; - -} // namespace internal - -template -class NiceMock : public MockClass, public internal::NiceMockBase { +class NiceMock : public MockClass { public: - NiceMock() : MockClass() {} + NiceMock() : MockClass() { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } #if GTEST_LANG_CXX11 - // Ideally, we would inherit base class's constructors through a using - // declaration, which would preserve their visibility. However, many existing - // tests rely on the fact that current implementation reexports protected - // constructors as public. These tests would need to be cleaned up first. - // Single argument constructor is special-cased so that it can be // made explicit. template - explicit NiceMock(A&& arg) : MockClass(std::forward(arg)) {} + explicit NiceMock(A&& arg) : MockClass(std::forward(arg)) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } template NiceMock(A1&& arg1, A2&& arg2, An&&... args) : MockClass(std::forward(arg1), std::forward(arg2), - std::forward(args)...) {} + std::forward(args)...) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } #else // C++98 doesn't have variadic templates, so we have to define one // for each arity. template - explicit NiceMock(const A1& a1) : MockClass(a1) {} + explicit NiceMock(const A1& a1) : MockClass(a1) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } template - NiceMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {} + NiceMock(const A1& a1, const A2& a2) : MockClass(a1, a2) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } template - NiceMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) {} + NiceMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } template NiceMock(const A1& a1, const A2& a2, const A3& a3, - const A4& a4) : MockClass(a1, a2, a3, a4) {} + const A4& a4) : MockClass(a1, a2, a3, a4) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } template NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, - const A5& a5) : MockClass(a1, a2, a3, a4, a5) {} + const A5& a5) : MockClass(a1, a2, a3, a4, a5) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } template NiceMock(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) {} + const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } template NiceMock(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) {} + a6, a7) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } template NiceMock(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) {} + a2, a3, a4, a5, a6, a7, a8) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } template NiceMock(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) {} + const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } template NiceMock(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) {} + const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } #endif // GTEST_LANG_CXX11 + ~NiceMock() { + ::testing::Mock::UnregisterCallReaction( + internal::ImplicitCast_(this)); + } + private: GTEST_DISALLOW_COPY_AND_ASSIGN_(NiceMock); }; -namespace internal { - -template -NiceMockBase::NiceMockBase() { - ::testing::Mock::AllowUninterestingCalls( - internal::ImplicitCast_( - static_cast *>(this))); -} - -template -NiceMockBase::~NiceMockBase() { - ::testing::Mock::UnregisterCallReaction( - internal::ImplicitCast_( - static_cast*>(this))); -} - -} // namespace internal - -namespace internal { - -// NaggyMockBase serves as a mix-in to establish the "uninteresting call" -// behavior for NaggyMock on construction. It accomplishes this via CRTP to get -// access to the derived MockClass. template -class NaggyMockBase { - protected: - NaggyMockBase(); - - ~NaggyMockBase(); -}; - -} // namespace internal - -template -class NaggyMock : public MockClass, public internal::NaggyMockBase { +class NaggyMock : public MockClass { public: - NaggyMock() : MockClass() {} + NaggyMock() : MockClass() { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } #if GTEST_LANG_CXX11 - // Ideally, we would inherit base class's constructors through a using - // declaration, which would preserve their visibility. However, many existing - // tests rely on the fact that current implementation reexports protected - // constructors as public. These tests would need to be cleaned up first. - // Single argument constructor is special-cased so that it can be // made explicit. template - explicit NaggyMock(A&& arg) : MockClass(std::forward(arg)) {} + explicit NaggyMock(A&& arg) : MockClass(std::forward(arg)) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } template NaggyMock(A1&& arg1, A2&& arg2, An&&... args) : MockClass(std::forward(arg1), std::forward(arg2), - std::forward(args)...) {} + std::forward(args)...) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } #else // C++98 doesn't have variadic templates, so we have to define one // for each arity. template - explicit NaggyMock(const A1& a1) : MockClass(a1) {} + explicit NaggyMock(const A1& a1) : MockClass(a1) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } template - NaggyMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {} + 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) {} + 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) {} + 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) {} + 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) {} + 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) {} + 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) {} + 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) {} + 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) {} + const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } #endif // GTEST_LANG_CXX11 + ~NaggyMock() { + ::testing::Mock::UnregisterCallReaction( + internal::ImplicitCast_(this)); + } + private: GTEST_DISALLOW_COPY_AND_ASSIGN_(NaggyMock); }; -namespace internal { - -template -NaggyMockBase::NaggyMockBase() { - ::testing::Mock::WarnUninterestingCalls( - internal::ImplicitCast_( - static_cast *>(this))); -} - -template -NaggyMockBase::~NaggyMockBase() { - ::testing::Mock::UnregisterCallReaction( - internal::ImplicitCast_( - static_cast*>(this))); -} - -} // namespace internal - -namespace internal { - -// StrictMockBase serves as a mix-in to establish the "uninteresting call" -// behavior for StrictMock on construction. It accomplishes this via CRTP to get -// access to the derived MockClass. template -class StrictMockBase { - protected: - StrictMockBase(); - - ~StrictMockBase(); -}; - -} // namespace internal - -template -class StrictMock : public MockClass, - public internal::StrictMockBase { +class StrictMock : public MockClass { public: - StrictMock() : MockClass() {} + StrictMock() : MockClass() { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } #if GTEST_LANG_CXX11 - // Ideally, we would inherit base class's constructors through a using - // declaration, which would preserve their visibility. However, many existing - // tests rely on the fact that current implementation reexports protected - // constructors as public. These tests would need to be cleaned up first. - // Single argument constructor is special-cased so that it can be // made explicit. template - explicit StrictMock(A&& arg) : MockClass(std::forward(arg)) {} + explicit StrictMock(A&& arg) : MockClass(std::forward(arg)) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } template StrictMock(A1&& arg1, A2&& arg2, An&&... args) : MockClass(std::forward(arg1), std::forward(arg2), - std::forward(args)...) {} + std::forward(args)...) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } #else // C++98 doesn't have variadic templates, so we have to define one // for each arity. template - explicit StrictMock(const A1& a1) : MockClass(a1) {} + explicit StrictMock(const A1& a1) : MockClass(a1) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } template - StrictMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {} + StrictMock(const A1& a1, const A2& a2) : MockClass(a1, a2) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } template - StrictMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, - a3) {} + StrictMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } template StrictMock(const A1& a1, const A2& a2, const A3& a3, - const A4& a4) : MockClass(a1, a2, a3, a4) {} + const A4& a4) : MockClass(a1, a2, a3, a4) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } template StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, - const A5& a5) : MockClass(a1, a2, a3, a4, a5) {} + const A5& a5) : MockClass(a1, a2, a3, a4, a5) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } template StrictMock(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) {} + const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } template StrictMock(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) {} + a6, a7) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } template StrictMock(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) {} + a2, a3, a4, a5, a6, a7, a8) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } template StrictMock(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) {} + const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } template StrictMock(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) {} + const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } #endif // GTEST_LANG_CXX11 + ~StrictMock() { + ::testing::Mock::UnregisterCallReaction( + internal::ImplicitCast_(this)); + } + private: GTEST_DISALLOW_COPY_AND_ASSIGN_(StrictMock); }; -namespace internal { - -template -StrictMockBase::StrictMockBase() { - ::testing::Mock::FailUninterestingCalls( - internal::ImplicitCast_( - static_cast *>(this))); -} - -template -StrictMockBase::~StrictMockBase() { - ::testing::Mock::UnregisterCallReaction( - internal::ImplicitCast_( - static_cast*>(this))); -} - -} // namespace internal - // The following specializations catch some (relatively more common) // user errors of nesting nice and strict mocks. They do NOT catch // all possible errors. diff --git a/googlemock/include/gmock/gmock-generated-nice-strict.h.pump b/googlemock/include/gmock/gmock-generated-nice-strict.h.pump index 378c40f1..2e50e982 100644 --- a/googlemock/include/gmock/gmock-generated-nice-strict.h.pump +++ b/googlemock/include/gmock/gmock-generated-nice-strict.h.pump @@ -83,79 +83,61 @@ $var method=[[$if kind==0 [[AllowUninterestingCalls]] $elif kind==1 [[WarnUninterestingCalls]] $else [[FailUninterestingCalls]]]] -namespace internal { - -// $clazz[[]]Base serves as a mix-in to establish the "uninteresting call" -// behavior for $clazz on construction. It accomplishes this via CRTP to get -// access to the derived MockClass. template -class $clazz[[]]Base { - protected: - $clazz[[]]Base(); - - ~$clazz[[]]Base(); -}; - -} // namespace internal - -template -class $clazz : public MockClass, public internal::$clazz[[]]Base { +class $clazz : public MockClass { public: - $clazz() : MockClass() {} + $clazz() : MockClass() { + ::testing::Mock::$method( + internal::ImplicitCast_(this)); + } #if GTEST_LANG_CXX11 - // Ideally, we would inherit base class's constructors through a using - // declaration, which would preserve their visibility. However, many existing - // tests rely on the fact that current implementation reexports protected - // constructors as public. These tests would need to be cleaned up first. - // Single argument constructor is special-cased so that it can be // made explicit. template - explicit $clazz(A&& arg) : MockClass(std::forward(arg)) {} + explicit $clazz(A&& arg) : MockClass(std::forward(arg)) { + ::testing::Mock::$method( + internal::ImplicitCast_(this)); + } template $clazz(A1&& arg1, A2&& arg2, An&&... args) : MockClass(std::forward(arg1), std::forward(arg2), - std::forward(args)...) {} + std::forward(args)...) { + ::testing::Mock::$method( + internal::ImplicitCast_(this)); + } #else // C++98 doesn't have variadic templates, so we have to define one // for each arity. template - explicit $clazz(const A1& a1) : MockClass(a1) {} + explicit $clazz(const A1& a1) : MockClass(a1) { + ::testing::Mock::$method( + internal::ImplicitCast_(this)); + } $range i 2..n $for i [[ $range j 1..i template <$for j, [[typename A$j]]> - $clazz($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) {} + $clazz($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) { + ::testing::Mock::$method( + internal::ImplicitCast_(this)); + } ]] #endif // GTEST_LANG_CXX11 + ~$clazz() { + ::testing::Mock::UnregisterCallReaction( + internal::ImplicitCast_(this)); + } + private: GTEST_DISALLOW_COPY_AND_ASSIGN_($clazz); }; -namespace internal { - -template -$clazz[[]]Base::$clazz[[]]Base() { - ::testing::Mock::$method( - internal::ImplicitCast_( - static_cast<$clazz *>(this))); -} - -template -$clazz[[]]Base::~$clazz[[]]Base() { - ::testing::Mock::UnregisterCallReaction( - internal::ImplicitCast_( - static_cast<$clazz*>(this))); -} - -} // namespace internal - ]] // The following specializations catch some (relatively more common) diff --git a/googlemock/include/gmock/gmock-spec-builders.h b/googlemock/include/gmock/gmock-spec-builders.h index 6d7f9200..a7be7d15 100644 --- a/googlemock/include/gmock/gmock-spec-builders.h +++ b/googlemock/include/gmock/gmock-spec-builders.h @@ -103,11 +103,6 @@ class ExpectationTester; // Base class for function mockers. template class FunctionMockerBase; -// Uninteresting call behavior mixins. -template class NiceMockBase; -template class NaggyMockBase; -template class StrictMockBase; - // Protects the mock object registry (in class Mock), all function // mockers, and all expectations. // @@ -408,13 +403,13 @@ class GTEST_API_ Mock { friend class internal::FunctionMockerBase; template - friend class internal::NiceMockBase; + friend class NiceMock; template - friend class internal::NaggyMockBase; + friend class NaggyMock; template - friend class internal::StrictMockBase; + friend class StrictMock; // Tells Google Mock to allow uninteresting calls on the given mock // object. diff --git a/googlemock/test/gmock-nice-strict_test.cc b/googlemock/test/gmock-nice-strict_test.cc index 0eac6439..7812f626 100644 --- a/googlemock/test/gmock-nice-strict_test.cc +++ b/googlemock/test/gmock-nice-strict_test.cc @@ -259,6 +259,13 @@ TEST(NiceMockTest, NonDefaultConstructor10) { nice_bar.That(5, true); } +TEST(NiceMockTest, AllowLeak) { + NiceMock* leaked = new NiceMock; + Mock::AllowLeak(leaked); + EXPECT_CALL(*leaked, DoThis()); + leaked->DoThis(); +} + #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 work around an @@ -352,6 +359,13 @@ TEST(NaggyMockTest, NonDefaultConstructor10) { naggy_bar.That(5, true); } +TEST(NaggyMockTest, AllowLeak) { + NaggyMock* leaked = new NaggyMock; + Mock::AllowLeak(leaked); + EXPECT_CALL(*leaked, DoThis()); + leaked->DoThis(); +} + #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 @@ -426,6 +440,13 @@ TEST(StrictMockTest, NonDefaultConstructor10) { "Uninteresting mock function call"); } +TEST(StrictMockTest, AllowLeak) { + StrictMock* leaked = new StrictMock; + Mock::AllowLeak(leaked); + EXPECT_CALL(*leaked, DoThis()); + leaked->DoThis(); +} + #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 work around an