278 lines · c
1// Copyright 2008, Google Inc.2// All rights reserved.3//4// Redistribution and use in source and binary forms, with or without5// modification, are permitted provided that the following conditions are6// met:7//8// * Redistributions of source code must retain the above copyright9// notice, this list of conditions and the following disclaimer.10// * Redistributions in binary form must reproduce the above11// copyright notice, this list of conditions and the following disclaimer12// in the documentation and/or other materials provided with the13// distribution.14// * Neither the name of Google Inc. nor the names of its15// contributors may be used to endorse or promote products derived from16// this software without specific prior written permission.17//18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29 30// Implements class templates NiceMock, NaggyMock, and StrictMock.31//32// Given a mock class MockFoo that is created using Google Mock,33// NiceMock<MockFoo> is a subclass of MockFoo that allows34// uninteresting calls (i.e. calls to mock methods that have no35// EXPECT_CALL specs), NaggyMock<MockFoo> is a subclass of MockFoo36// that prints a warning when an uninteresting call occurs, and37// StrictMock<MockFoo> is a subclass of MockFoo that treats all38// uninteresting calls as errors.39//40// Currently a mock is naggy by default, so MockFoo and41// NaggyMock<MockFoo> behave like the same. However, we will soon42// switch the default behavior of mocks to be nice, as that in general43// leads to more maintainable tests. When that happens, MockFoo will44// stop behaving like NaggyMock<MockFoo> and start behaving like45// NiceMock<MockFoo>.46//47// NiceMock, NaggyMock, and StrictMock "inherit" the constructors of48// their respective base class. Therefore you can write49// NiceMock<MockFoo>(5, "a") to construct a nice mock where MockFoo50// has a constructor that accepts (int, const char*), for example.51//52// A known limitation is that NiceMock<MockFoo>, NaggyMock<MockFoo>,53// and StrictMock<MockFoo> only works for mock methods defined using54// the MOCK_METHOD* family of macros DIRECTLY in the MockFoo class.55// If a mock method is defined in a base class of MockFoo, the "nice"56// or "strict" modifier may not affect it, depending on the compiler.57// In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT58// supported.59 60// IWYU pragma: private, include "gmock/gmock.h"61// IWYU pragma: friend gmock/.*62 63#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_NICE_STRICT_H_64#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_NICE_STRICT_H_65 66#include <cstdint>67#include <type_traits>68 69#include "gmock/gmock-spec-builders.h"70#include "gmock/internal/gmock-port.h"71 72namespace testing {73template <class MockClass>74class NiceMock;75template <class MockClass>76class NaggyMock;77template <class MockClass>78class StrictMock;79 80namespace internal {81template <typename T>82std::true_type StrictnessModifierProbe(const NiceMock<T>&);83template <typename T>84std::true_type StrictnessModifierProbe(const NaggyMock<T>&);85template <typename T>86std::true_type StrictnessModifierProbe(const StrictMock<T>&);87std::false_type StrictnessModifierProbe(...);88 89template <typename T>90constexpr bool HasStrictnessModifier() {91 return decltype(StrictnessModifierProbe(std::declval<const T&>()))::value;92}93 94// Base classes that register and deregister with testing::Mock to alter the95// default behavior around uninteresting calls. Inheriting from one of these96// classes first and then MockClass ensures the MockClass constructor is run97// after registration, and that the MockClass destructor runs before98// deregistration. This guarantees that MockClass's constructor and destructor99// run with the same level of strictness as its instance methods.100 101#if defined(GTEST_OS_WINDOWS) && !defined(GTEST_OS_WINDOWS_MINGW) && \102 (defined(_MSC_VER) || defined(__clang__))103// We need to mark these classes with this declspec to ensure that104// the empty base class optimization is performed.105#define GTEST_INTERNAL_EMPTY_BASE_CLASS __declspec(empty_bases)106#else107#define GTEST_INTERNAL_EMPTY_BASE_CLASS108#endif109 110template <typename Base>111class NiceMockImpl {112 public:113 NiceMockImpl() {114 ::testing::Mock::AllowUninterestingCalls(reinterpret_cast<uintptr_t>(this));115 }116 117 ~NiceMockImpl() {118 ::testing::Mock::UnregisterCallReaction(reinterpret_cast<uintptr_t>(this));119 }120};121 122template <typename Base>123class NaggyMockImpl {124 public:125 NaggyMockImpl() {126 ::testing::Mock::WarnUninterestingCalls(reinterpret_cast<uintptr_t>(this));127 }128 129 ~NaggyMockImpl() {130 ::testing::Mock::UnregisterCallReaction(reinterpret_cast<uintptr_t>(this));131 }132};133 134template <typename Base>135class StrictMockImpl {136 public:137 StrictMockImpl() {138 ::testing::Mock::FailUninterestingCalls(reinterpret_cast<uintptr_t>(this));139 }140 141 ~StrictMockImpl() {142 ::testing::Mock::UnregisterCallReaction(reinterpret_cast<uintptr_t>(this));143 }144};145 146} // namespace internal147 148template <class MockClass>149class GTEST_INTERNAL_EMPTY_BASE_CLASS NiceMock150 : private internal::NiceMockImpl<MockClass>,151 public MockClass {152 public:153 static_assert(!internal::HasStrictnessModifier<MockClass>(),154 "Can't apply NiceMock to a class hierarchy that already has a "155 "strictness modifier. See "156 "https://google.github.io/googletest/"157 "gmock_cook_book.html#NiceStrictNaggy");158 NiceMock() : MockClass() {159 static_assert(sizeof(*this) == sizeof(MockClass),160 "The impl subclass shouldn't introduce any padding");161 }162 163 // Ideally, we would inherit base class's constructors through a using164 // declaration, which would preserve their visibility. However, many existing165 // tests rely on the fact that current implementation reexports protected166 // constructors as public. These tests would need to be cleaned up first.167 168 // Single argument constructor is special-cased so that it can be169 // made explicit.170 template <typename A>171 explicit NiceMock(A&& arg) : MockClass(std::forward<A>(arg)) {172 static_assert(sizeof(*this) == sizeof(MockClass),173 "The impl subclass shouldn't introduce any padding");174 }175 176 template <typename TArg1, typename TArg2, typename... An>177 NiceMock(TArg1&& arg1, TArg2&& arg2, An&&... args)178 : MockClass(std::forward<TArg1>(arg1), std::forward<TArg2>(arg2),179 std::forward<An>(args)...) {180 static_assert(sizeof(*this) == sizeof(MockClass),181 "The impl subclass shouldn't introduce any padding");182 }183 184 private:185 NiceMock(const NiceMock&) = delete;186 NiceMock& operator=(const NiceMock&) = delete;187};188 189template <class MockClass>190class GTEST_INTERNAL_EMPTY_BASE_CLASS NaggyMock191 : private internal::NaggyMockImpl<MockClass>,192 public MockClass {193 static_assert(!internal::HasStrictnessModifier<MockClass>(),194 "Can't apply NaggyMock to a class hierarchy that already has a "195 "strictness modifier. See "196 "https://google.github.io/googletest/"197 "gmock_cook_book.html#NiceStrictNaggy");198 199 public:200 NaggyMock() : MockClass() {201 static_assert(sizeof(*this) == sizeof(MockClass),202 "The impl subclass shouldn't introduce any padding");203 }204 205 // Ideally, we would inherit base class's constructors through a using206 // declaration, which would preserve their visibility. However, many existing207 // tests rely on the fact that current implementation reexports protected208 // constructors as public. These tests would need to be cleaned up first.209 210 // Single argument constructor is special-cased so that it can be211 // made explicit.212 template <typename A>213 explicit NaggyMock(A&& arg) : MockClass(std::forward<A>(arg)) {214 static_assert(sizeof(*this) == sizeof(MockClass),215 "The impl subclass shouldn't introduce any padding");216 }217 218 template <typename TArg1, typename TArg2, typename... An>219 NaggyMock(TArg1&& arg1, TArg2&& arg2, An&&... args)220 : MockClass(std::forward<TArg1>(arg1), std::forward<TArg2>(arg2),221 std::forward<An>(args)...) {222 static_assert(sizeof(*this) == sizeof(MockClass),223 "The impl subclass shouldn't introduce any padding");224 }225 226 private:227 NaggyMock(const NaggyMock&) = delete;228 NaggyMock& operator=(const NaggyMock&) = delete;229};230 231template <class MockClass>232class GTEST_INTERNAL_EMPTY_BASE_CLASS StrictMock233 : private internal::StrictMockImpl<MockClass>,234 public MockClass {235 public:236 static_assert(237 !internal::HasStrictnessModifier<MockClass>(),238 "Can't apply StrictMock to a class hierarchy that already has a "239 "strictness modifier. See "240 "https://google.github.io/googletest/"241 "gmock_cook_book.html#NiceStrictNaggy");242 StrictMock() : MockClass() {243 static_assert(sizeof(*this) == sizeof(MockClass),244 "The impl subclass shouldn't introduce any padding");245 }246 247 // Ideally, we would inherit base class's constructors through a using248 // declaration, which would preserve their visibility. However, many existing249 // tests rely on the fact that current implementation reexports protected250 // constructors as public. These tests would need to be cleaned up first.251 252 // Single argument constructor is special-cased so that it can be253 // made explicit.254 template <typename A>255 explicit StrictMock(A&& arg) : MockClass(std::forward<A>(arg)) {256 static_assert(sizeof(*this) == sizeof(MockClass),257 "The impl subclass shouldn't introduce any padding");258 }259 260 template <typename TArg1, typename TArg2, typename... An>261 StrictMock(TArg1&& arg1, TArg2&& arg2, An&&... args)262 : MockClass(std::forward<TArg1>(arg1), std::forward<TArg2>(arg2),263 std::forward<An>(args)...) {264 static_assert(sizeof(*this) == sizeof(MockClass),265 "The impl subclass shouldn't introduce any padding");266 }267 268 private:269 StrictMock(const StrictMock&) = delete;270 StrictMock& operator=(const StrictMock&) = delete;271};272 273#undef GTEST_INTERNAL_EMPTY_BASE_CLASS274 275} // namespace testing276 277#endif // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_NICE_STRICT_H_278