Skip to content

Commit 590080e

Browse files
committed
Made modifiers inheritable
* Mock object can be made Strict/Nice/Naggy by inheritance
1 parent e54519b commit 590080e

File tree

2 files changed

+86
-103
lines changed

2 files changed

+86
-103
lines changed

googlemock/include/gmock/gmock-nice-strict.h

+51-103
Original file line numberDiff line numberDiff line change
@@ -70,26 +70,11 @@
7070
#include "gmock/internal/gmock-port.h"
7171

7272
namespace testing {
73-
template <class MockClass>
74-
class NiceMock;
75-
template <class MockClass>
76-
class NaggyMock;
77-
template <class MockClass>
78-
class StrictMock;
7973

80-
namespace internal {
81-
template <typename T>
82-
std::true_type StrictnessModifierProbe(const NiceMock<T>&);
83-
template <typename T>
84-
std::true_type StrictnessModifierProbe(const NaggyMock<T>&);
85-
template <typename T>
86-
std::true_type StrictnessModifierProbe(const StrictMock<T>&);
87-
std::false_type StrictnessModifierProbe(...);
74+
template <class StrictNessModifier, class MockClass>
75+
class StrictNessBase;
8876

89-
template <typename T>
90-
constexpr bool HasStrictnessModifier() {
91-
return decltype(StrictnessModifierProbe(std::declval<const T&>()))::value;
92-
}
77+
namespace internal {
9378

9479
// Base classes that register and deregister with testing::Mock to alter the
9580
// default behavior around uninteresting calls. Inheriting from one of these
@@ -143,61 +128,58 @@ class StrictMockImpl {
143128
}
144129
};
145130

131+
template <typename T>
132+
std::true_type StrictnessModifierProbe(
133+
const StrictNessBase<internal::NiceMockImpl<T>, T>&);
134+
template <typename T>
135+
std::true_type StrictnessModifierProbe(
136+
const StrictNessBase<internal::NaggyMockImpl<T>, T>&);
137+
template <typename T>
138+
std::true_type StrictnessModifierProbe(
139+
const StrictNessBase<internal::StrictMockImpl<T>, T>&);
140+
std::false_type StrictnessModifierProbe(...);
141+
142+
template <typename T>
143+
constexpr bool HasStrictnessModifier() {
144+
return decltype(StrictnessModifierProbe(std::declval<const T&>()))::value;
145+
}
146+
146147
} // namespace internal
147148

148-
template <class MockClass>
149-
class GTEST_INTERNAL_EMPTY_BASE_CLASS NiceMock
150-
: private internal::NiceMockImpl<MockClass>,
151-
public MockClass {
149+
template <class StrictNessModifier, class MockClass>
150+
class GTEST_INTERNAL_EMPTY_BASE_CLASS StrictNessBase
151+
: public StrictNessModifier {
152152
public:
153-
static_assert(!internal::HasStrictnessModifier<MockClass>(),
153+
static_assert(!internal::HasStrictnessModifier<StrictNessModifier>(),
154154
"Can't apply NiceMock to a class hierarchy that already has a "
155155
"strictness modifier. See "
156156
"https://google.github.io/googletest/"
157157
"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 using
164-
// declaration, which would preserve their visibility. However, many existing
165-
// tests rely on the fact that current implementation reexports protected
166-
// constructors as public. These tests would need to be cleaned up first.
167-
168-
// Single argument constructor is special-cased so that it can be
169-
// 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-
}
158+
StrictNessBase() = default;
183159

184160
private:
185-
NiceMock(const NiceMock&) = delete;
186-
NiceMock& operator=(const NiceMock&) = delete;
161+
StrictNessBase(const StrictNessBase&) = delete;
162+
StrictNessBase& operator=(const StrictNessBase&) = delete;
187163
};
188164

189165
template <class MockClass>
190-
class GTEST_INTERNAL_EMPTY_BASE_CLASS NaggyMock
191-
: 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");
166+
using NiceMockable =
167+
StrictNessBase<internal::NiceMockImpl<MockClass>, MockClass>;
198168

169+
template <class MockClass>
170+
using StrictMockable =
171+
StrictNessBase<internal::StrictMockImpl<MockClass>, MockClass>;
172+
173+
template <class MockClass>
174+
using NaggyMockable =
175+
StrictNessBase<internal::NaggyMockImpl<MockClass>, MockClass>;
176+
177+
template <class StrictNessModifier, class MockClass>
178+
class GTEST_INTERNAL_EMPTY_BASE_CLASS StrictNessMockImplBase
179+
: public StrictNessModifier,
180+
public MockClass {
199181
public:
200-
NaggyMock() : MockClass() {
182+
StrictNessMockImplBase() : MockClass() {
201183
static_assert(sizeof(*this) == sizeof(MockClass),
202184
"The impl subclass shouldn't introduce any padding");
203185
}
@@ -210,65 +192,31 @@ class GTEST_INTERNAL_EMPTY_BASE_CLASS NaggyMock
210192
// Single argument constructor is special-cased so that it can be
211193
// made explicit.
212194
template <typename A>
213-
explicit NaggyMock(A&& arg) : MockClass(std::forward<A>(arg)) {
195+
explicit StrictNessMockImplBase(A&& arg) : MockClass(std::forward<A>(arg)) {
214196
static_assert(sizeof(*this) == sizeof(MockClass),
215197
"The impl subclass shouldn't introduce any padding");
216198
}
217199

218200
template <typename TArg1, typename TArg2, typename... An>
219-
NaggyMock(TArg1&& arg1, TArg2&& arg2, An&&... args)
201+
StrictNessMockImplBase(TArg1&& arg1, TArg2&& arg2, An&&... args)
220202
: MockClass(std::forward<TArg1>(arg1), std::forward<TArg2>(arg2),
221203
std::forward<An>(args)...) {
222204
static_assert(sizeof(*this) == sizeof(MockClass),
223205
"The impl subclass shouldn't introduce any padding");
224206
}
225-
226-
private:
227-
NaggyMock(const NaggyMock&) = delete;
228-
NaggyMock& operator=(const NaggyMock&) = delete;
229207
};
230208

231209
template <class MockClass>
232-
class GTEST_INTERNAL_EMPTY_BASE_CLASS StrictMock
233-
: 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 using
248-
// declaration, which would preserve their visibility. However, many existing
249-
// tests rely on the fact that current implementation reexports protected
250-
// constructors as public. These tests would need to be cleaned up first.
251-
252-
// Single argument constructor is special-cased so that it can be
253-
// 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-
}
210+
using NiceMock =
211+
StrictNessMockImplBase<internal::NiceMockImpl<MockClass>, MockClass>;
259212

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-
}
213+
template <class MockClass>
214+
using StrictMock =
215+
StrictNessMockImplBase<internal::StrictMockImpl<MockClass>, MockClass>;
267216

268-
private:
269-
StrictMock(const StrictMock&) = delete;
270-
StrictMock& operator=(const StrictMock&) = delete;
271-
};
217+
template <class MockClass>
218+
using NaggyMock =
219+
StrictNessMockImplBase<internal::NaggyMockImpl<MockClass>, MockClass>;
272220

273221
#undef GTEST_INTERNAL_EMPTY_BASE_CLASS
274222

googlemock/test/gmock-nice-strict_test.cc

+35
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,21 @@ class MockBaz {
139139
MockBaz(MoveOnly) {}
140140
};
141141

142+
class NiceMockModifier : public NiceMockable<NiceMockModifier> {
143+
public:
144+
NiceMockModifier() = default;
145+
};
146+
147+
class NaggyMockModifier : public NaggyMockable<NaggyMockModifier> {
148+
public:
149+
NaggyMockModifier() = default;
150+
};
151+
152+
class StrictMockModifier : public StrictMockable<StrictMockModifier> {
153+
public:
154+
StrictMockModifier() = default;
155+
};
156+
142157
#if GTEST_HAS_STREAM_REDIRECTION
143158

144159
// Tests that a raw mock generates warnings for uninteresting calls.
@@ -324,6 +339,13 @@ TEST(NiceMockTest, IsNaggy_IsNice_IsStrict) {
324339
EXPECT_FALSE(Mock::IsStrict(&nice_foo));
325340
}
326341

342+
TEST(NiceMockTest, IsNaggy_IsNice_IsStrict_Class) {
343+
NiceMockModifier nice_foo;
344+
EXPECT_FALSE(Mock::IsNaggy(&nice_foo));
345+
EXPECT_TRUE(Mock::IsNice(&nice_foo));
346+
EXPECT_FALSE(Mock::IsStrict(&nice_foo));
347+
}
348+
327349
#if GTEST_HAS_STREAM_REDIRECTION
328350

329351
// Tests that a naggy mock generates warnings for uninteresting calls.
@@ -443,6 +465,13 @@ TEST(NaggyMockTest, IsNaggy_IsNice_IsStrict) {
443465
EXPECT_FALSE(Mock::IsStrict(&naggy_foo));
444466
}
445467

468+
TEST(NaggyMockTest, IsNaggy_IsNice_IsStrict_Class) {
469+
NaggyMockModifier naggy_foo;
470+
EXPECT_TRUE(Mock::IsNaggy(&naggy_foo));
471+
EXPECT_FALSE(Mock::IsNice(&naggy_foo));
472+
EXPECT_FALSE(Mock::IsStrict(&naggy_foo));
473+
}
474+
446475
// Tests that a strict mock allows expected calls.
447476
TEST(StrictMockTest, AllowsExpectedCall) {
448477
StrictMock<MockFoo> strict_foo;
@@ -537,5 +566,11 @@ TEST(StrictMockTest, IsNaggy_IsNice_IsStrict) {
537566
EXPECT_TRUE(Mock::IsStrict(&strict_foo));
538567
}
539568

569+
TEST(StrictMockTest, IsNaggy_IsNice_IsStrict_Class) {
570+
StrictMockModifier strict_foo;
571+
EXPECT_FALSE(Mock::IsNaggy(&strict_foo));
572+
EXPECT_FALSE(Mock::IsNice(&strict_foo));
573+
EXPECT_TRUE(Mock::IsStrict(&strict_foo));
574+
}
540575
} // namespace gmock_nice_strict_test
541576
} // namespace testing

0 commit comments

Comments
 (0)