gmock-function-mocker_test.cc 27.9 KB
Newer Older
Abseil Team's avatar
Abseil Team committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Copyright 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


// Google Mock - a framework for writing C++ mock classes.
//
// This file tests the function mocker classes.
Abseil Team's avatar
Abseil Team committed
34
#include "gmock/gmock-function-mocker.h"
Abseil Team's avatar
Abseil Team committed
35
36
37
38
39
40
41
42
43
44

#if GTEST_OS_WINDOWS
// MSDN says the header file to be included for STDMETHOD is BaseTyps.h but
// we are getting compiler errors if we use basetyps.h, hence including
// objbase.h for definition of STDMETHOD.
# include <objbase.h>
#endif  // GTEST_OS_WINDOWS

#include <map>
#include <string>
45
46
#include <type_traits>

Abseil Team's avatar
Abseil Team committed
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace testing {
namespace gmock_function_mocker_test {

using testing::_;
using testing::A;
using testing::An;
using testing::AnyNumber;
using testing::Const;
using testing::DoDefault;
using testing::Eq;
using testing::Lt;
using testing::MockFunction;
using testing::Ref;
using testing::Return;
using testing::ReturnRef;
using testing::TypedEq;

Abseil Team's avatar
Abseil Team committed
67
68
69
70
71
72
73
74
75
template<typename T>
class TemplatedCopyable {
 public:
  TemplatedCopyable() {}

  template <typename U>
  TemplatedCopyable(const U& other) {}  // NOLINT
};

Abseil Team's avatar
Abseil Team committed
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
class FooInterface {
 public:
  virtual ~FooInterface() {}

  virtual void VoidReturning(int x) = 0;

  virtual int Nullary() = 0;
  virtual bool Unary(int x) = 0;
  virtual long Binary(short x, int y) = 0;  // NOLINT
  virtual int Decimal(bool b, char c, short d, int e, long f,  // NOLINT
                      float g, double h, unsigned i, char* j,
                      const std::string& k) = 0;

  virtual bool TakesNonConstReference(int& n) = 0;  // NOLINT
  virtual std::string TakesConstReference(const int& n) = 0;
  virtual bool TakesConst(const int x) = 0;

  virtual int OverloadedOnArgumentNumber() = 0;
  virtual int OverloadedOnArgumentNumber(int n) = 0;

  virtual int OverloadedOnArgumentType(int n) = 0;
  virtual char OverloadedOnArgumentType(char c) = 0;

  virtual int OverloadedOnConstness() = 0;
  virtual char OverloadedOnConstness() const = 0;

  virtual int TypeWithHole(int (*func)()) = 0;
  virtual int TypeWithComma(const std::map<int, std::string>& a_map) = 0;
Abseil Team's avatar
Abseil Team committed
104
  virtual int TypeWithTemplatedCopyCtor(const TemplatedCopyable<int>&) = 0;
Abseil Team's avatar
Abseil Team committed
105

Abseil Team's avatar
Abseil Team committed
106
107
108
109
  virtual int (*ReturnsFunctionPointer1(int))(bool) = 0;
  using fn_ptr = int (*)(bool);
  virtual fn_ptr ReturnsFunctionPointer2(int) = 0;

Abseil Team's avatar
Abseil Team committed
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#if GTEST_OS_WINDOWS
  STDMETHOD_(int, CTNullary)() = 0;
  STDMETHOD_(bool, CTUnary)(int x) = 0;
  STDMETHOD_(int, CTDecimal)
  (bool b, char c, short d, int e, long f,  // NOLINT
   float g, double h, unsigned i, char* j, const std::string& k) = 0;
  STDMETHOD_(char, CTConst)(int x) const = 0;
#endif  // GTEST_OS_WINDOWS
};

// Const qualifiers on arguments were once (incorrectly) considered
// significant in determining whether two virtual functions had the same
// signature. This was fixed in Visual Studio 2008. However, the compiler
// still emits a warning that alerts about this change in behavior.
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable : 4373)
#endif
class MockFoo : public FooInterface {
 public:
  MockFoo() {}

  // Makes sure that a mock function parameter can be named.
  MOCK_METHOD(void, VoidReturning, (int n));  // NOLINT

  MOCK_METHOD(int, Nullary, ());  // NOLINT

  // Makes sure that a mock function parameter can be unnamed.
  MOCK_METHOD(bool, Unary, (int));          // NOLINT
  MOCK_METHOD(long, Binary, (short, int));  // NOLINT
  MOCK_METHOD(int, Decimal,
              (bool, char, short, int, long, float,  // NOLINT
               double, unsigned, char*, const std::string& str),
              (override));

  MOCK_METHOD(bool, TakesNonConstReference, (int&));  // NOLINT
  MOCK_METHOD(std::string, TakesConstReference, (const int&));
  MOCK_METHOD(bool, TakesConst, (const int));  // NOLINT

  // Tests that the function return type can contain unprotected comma.
  MOCK_METHOD((std::map<int, std::string>), ReturnTypeWithComma, (), ());
  MOCK_METHOD((std::map<int, std::string>), ReturnTypeWithComma, (int),
              (const));  // NOLINT

  MOCK_METHOD(int, OverloadedOnArgumentNumber, ());     // NOLINT
  MOCK_METHOD(int, OverloadedOnArgumentNumber, (int));  // NOLINT

  MOCK_METHOD(int, OverloadedOnArgumentType, (int));    // NOLINT
  MOCK_METHOD(char, OverloadedOnArgumentType, (char));  // NOLINT

  MOCK_METHOD(int, OverloadedOnConstness, (), (override));          // NOLINT
  MOCK_METHOD(char, OverloadedOnConstness, (), (override, const));  // NOLINT

  MOCK_METHOD(int, TypeWithHole, (int (*)()), ());  // NOLINT
  MOCK_METHOD(int, TypeWithComma, ((const std::map<int, std::string>&)));
Abseil Team's avatar
Abseil Team committed
165
166
  MOCK_METHOD(int, TypeWithTemplatedCopyCtor,
              (const TemplatedCopyable<int>&));  // NOLINT
Abseil Team's avatar
Abseil Team committed
167

Abseil Team's avatar
Abseil Team committed
168
169
170
  MOCK_METHOD(int (*)(bool), ReturnsFunctionPointer1, (int), ());
  MOCK_METHOD(fn_ptr, ReturnsFunctionPointer2, (int), ());

Abseil Team's avatar
Abseil Team committed
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#if GTEST_OS_WINDOWS
  MOCK_METHOD(int, CTNullary, (), (Calltype(STDMETHODCALLTYPE)));
  MOCK_METHOD(bool, CTUnary, (int), (Calltype(STDMETHODCALLTYPE)));
  MOCK_METHOD(int, CTDecimal,
              (bool b, char c, short d, int e, long f, float g, double h,
               unsigned i, char* j, const std::string& k),
              (Calltype(STDMETHODCALLTYPE)));
  MOCK_METHOD(char, CTConst, (int), (const, Calltype(STDMETHODCALLTYPE)));
  MOCK_METHOD((std::map<int, std::string>), CTReturnTypeWithComma, (),
              (Calltype(STDMETHODCALLTYPE)));
#endif  // GTEST_OS_WINDOWS

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo);
};
Abseil Team's avatar
Abseil Team committed
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

class LegacyMockFoo : public FooInterface {
 public:
  LegacyMockFoo() {}

  // Makes sure that a mock function parameter can be named.
  MOCK_METHOD1(VoidReturning, void(int n));  // NOLINT

  MOCK_METHOD0(Nullary, int());  // NOLINT

  // Makes sure that a mock function parameter can be unnamed.
  MOCK_METHOD1(Unary, bool(int));                                  // NOLINT
  MOCK_METHOD2(Binary, long(short, int));                          // NOLINT
  MOCK_METHOD10(Decimal, int(bool, char, short, int, long, float,  // NOLINT
                             double, unsigned, char*, const std::string& str));

  MOCK_METHOD1(TakesNonConstReference, bool(int&));  // NOLINT
  MOCK_METHOD1(TakesConstReference, std::string(const int&));
  MOCK_METHOD1(TakesConst, bool(const int));  // NOLINT

  // Tests that the function return type can contain unprotected comma.
  MOCK_METHOD0(ReturnTypeWithComma, std::map<int, std::string>());
  MOCK_CONST_METHOD1(ReturnTypeWithComma,
                     std::map<int, std::string>(int));  // NOLINT

  MOCK_METHOD0(OverloadedOnArgumentNumber, int());     // NOLINT
  MOCK_METHOD1(OverloadedOnArgumentNumber, int(int));  // NOLINT

  MOCK_METHOD1(OverloadedOnArgumentType, int(int));    // NOLINT
  MOCK_METHOD1(OverloadedOnArgumentType, char(char));  // NOLINT

  MOCK_METHOD0(OverloadedOnConstness, int());         // NOLINT
  MOCK_CONST_METHOD0(OverloadedOnConstness, char());  // NOLINT

  MOCK_METHOD1(TypeWithHole, int(int (*)()));  // NOLINT
  MOCK_METHOD1(TypeWithComma,
               int(const std::map<int, std::string>&));  // NOLINT
  MOCK_METHOD1(TypeWithTemplatedCopyCtor,
               int(const TemplatedCopyable<int>&));  // NOLINT

  MOCK_METHOD1(ReturnsFunctionPointer1, int (*(int))(bool));
  MOCK_METHOD1(ReturnsFunctionPointer2, fn_ptr(int));

#if GTEST_OS_WINDOWS
  MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTNullary, int());
  MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTUnary, bool(int));  // NOLINT
  MOCK_METHOD10_WITH_CALLTYPE(STDMETHODCALLTYPE, CTDecimal,
                              int(bool b, char c, short d, int e,  // NOLINT
                                  long f, float g, double h,       // NOLINT
                                  unsigned i, char* j, const std::string& k));
  MOCK_CONST_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTConst,
                                   char(int));  // NOLINT

  // Tests that the function return type can contain unprotected comma.
  MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTReturnTypeWithComma,
                             std::map<int, std::string>());
#endif  // GTEST_OS_WINDOWS

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockFoo);
};

Abseil Team's avatar
Abseil Team committed
248
249
250
251
#ifdef _MSC_VER
# pragma warning(pop)
#endif

Abseil Team's avatar
Abseil Team committed
252
253
template <class T>
class FunctionMockerTest : public testing::Test {
Abseil Team's avatar
Abseil Team committed
254
 protected:
Abseil Team's avatar
Abseil Team committed
255
  FunctionMockerTest() : foo_(&mock_foo_) {}
Abseil Team's avatar
Abseil Team committed
256
257

  FooInterface* const foo_;
Abseil Team's avatar
Abseil Team committed
258
  T mock_foo_;
Abseil Team's avatar
Abseil Team committed
259
};
Abseil Team's avatar
Abseil Team committed
260
261
using FunctionMockerTestTypes = ::testing::Types<MockFoo, LegacyMockFoo>;
TYPED_TEST_SUITE(FunctionMockerTest, FunctionMockerTestTypes);
Abseil Team's avatar
Abseil Team committed
262
263

// Tests mocking a void-returning function.
Abseil Team's avatar
Abseil Team committed
264
265
266
TYPED_TEST(FunctionMockerTest, MocksVoidFunction) {
  EXPECT_CALL(this->mock_foo_, VoidReturning(Lt(100)));
  this->foo_->VoidReturning(0);
Abseil Team's avatar
Abseil Team committed
267
268
269
}

// Tests mocking a nullary function.
Abseil Team's avatar
Abseil Team committed
270
271
TYPED_TEST(FunctionMockerTest, MocksNullaryFunction) {
  EXPECT_CALL(this->mock_foo_, Nullary())
Abseil Team's avatar
Abseil Team committed
272
273
274
      .WillOnce(DoDefault())
      .WillOnce(Return(1));

Abseil Team's avatar
Abseil Team committed
275
276
  EXPECT_EQ(0, this->foo_->Nullary());
  EXPECT_EQ(1, this->foo_->Nullary());
Abseil Team's avatar
Abseil Team committed
277
278
279
}

// Tests mocking a unary function.
Abseil Team's avatar
Abseil Team committed
280
281
TYPED_TEST(FunctionMockerTest, MocksUnaryFunction) {
  EXPECT_CALL(this->mock_foo_, Unary(Eq(2))).Times(2).WillOnce(Return(true));
Abseil Team's avatar
Abseil Team committed
282

Abseil Team's avatar
Abseil Team committed
283
284
  EXPECT_TRUE(this->foo_->Unary(2));
  EXPECT_FALSE(this->foo_->Unary(2));
Abseil Team's avatar
Abseil Team committed
285
286
287
}

// Tests mocking a binary function.
Abseil Team's avatar
Abseil Team committed
288
289
TYPED_TEST(FunctionMockerTest, MocksBinaryFunction) {
  EXPECT_CALL(this->mock_foo_, Binary(2, _)).WillOnce(Return(3));
Abseil Team's avatar
Abseil Team committed
290

Abseil Team's avatar
Abseil Team committed
291
  EXPECT_EQ(3, this->foo_->Binary(2, 1));
Abseil Team's avatar
Abseil Team committed
292
293
294
}

// Tests mocking a decimal function.
Abseil Team's avatar
Abseil Team committed
295
296
297
TYPED_TEST(FunctionMockerTest, MocksDecimalFunction) {
  EXPECT_CALL(this->mock_foo_,
              Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U, NULL, "hi"))
Abseil Team's avatar
Abseil Team committed
298
299
      .WillOnce(Return(5));

Abseil Team's avatar
Abseil Team committed
300
  EXPECT_EQ(5, this->foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi"));
Abseil Team's avatar
Abseil Team committed
301
302
303
}

// Tests mocking a function that takes a non-const reference.
Abseil Team's avatar
Abseil Team committed
304
TYPED_TEST(FunctionMockerTest, MocksFunctionWithNonConstReferenceArgument) {
Abseil Team's avatar
Abseil Team committed
305
  int a = 0;
Abseil Team's avatar
Abseil Team committed
306
  EXPECT_CALL(this->mock_foo_, TakesNonConstReference(Ref(a)))
Abseil Team's avatar
Abseil Team committed
307
308
      .WillOnce(Return(true));

Abseil Team's avatar
Abseil Team committed
309
  EXPECT_TRUE(this->foo_->TakesNonConstReference(a));
Abseil Team's avatar
Abseil Team committed
310
311
312
}

// Tests mocking a function that takes a const reference.
Abseil Team's avatar
Abseil Team committed
313
TYPED_TEST(FunctionMockerTest, MocksFunctionWithConstReferenceArgument) {
Abseil Team's avatar
Abseil Team committed
314
  int a = 0;
Abseil Team's avatar
Abseil Team committed
315
  EXPECT_CALL(this->mock_foo_, TakesConstReference(Ref(a)))
Abseil Team's avatar
Abseil Team committed
316
317
      .WillOnce(Return("Hello"));

Abseil Team's avatar
Abseil Team committed
318
  EXPECT_EQ("Hello", this->foo_->TakesConstReference(a));
Abseil Team's avatar
Abseil Team committed
319
320
321
}

// Tests mocking a function that takes a const variable.
Abseil Team's avatar
Abseil Team committed
322
323
TYPED_TEST(FunctionMockerTest, MocksFunctionWithConstArgument) {
  EXPECT_CALL(this->mock_foo_, TakesConst(Lt(10))).WillOnce(DoDefault());
Abseil Team's avatar
Abseil Team committed
324

Abseil Team's avatar
Abseil Team committed
325
  EXPECT_FALSE(this->foo_->TakesConst(5));
Abseil Team's avatar
Abseil Team committed
326
327
328
}

// Tests mocking functions overloaded on the number of arguments.
Abseil Team's avatar
Abseil Team committed
329
330
TYPED_TEST(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentNumber) {
  EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentNumber())
Abseil Team's avatar
Abseil Team committed
331
      .WillOnce(Return(1));
Abseil Team's avatar
Abseil Team committed
332
  EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentNumber(_))
Abseil Team's avatar
Abseil Team committed
333
334
      .WillOnce(Return(2));

Abseil Team's avatar
Abseil Team committed
335
336
  EXPECT_EQ(2, this->foo_->OverloadedOnArgumentNumber(1));
  EXPECT_EQ(1, this->foo_->OverloadedOnArgumentNumber());
Abseil Team's avatar
Abseil Team committed
337
338
339
}

// Tests mocking functions overloaded on the types of argument.
Abseil Team's avatar
Abseil Team committed
340
341
TYPED_TEST(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentType) {
  EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentType(An<int>()))
Abseil Team's avatar
Abseil Team committed
342
      .WillOnce(Return(1));
Abseil Team's avatar
Abseil Team committed
343
  EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentType(TypedEq<char>('a')))
Abseil Team's avatar
Abseil Team committed
344
345
      .WillOnce(Return('b'));

Abseil Team's avatar
Abseil Team committed
346
347
  EXPECT_EQ(1, this->foo_->OverloadedOnArgumentType(0));
  EXPECT_EQ('b', this->foo_->OverloadedOnArgumentType('a'));
Abseil Team's avatar
Abseil Team committed
348
349
350
}

// Tests mocking functions overloaded on the const-ness of this object.
Abseil Team's avatar
Abseil Team committed
351
352
353
TYPED_TEST(FunctionMockerTest, MocksFunctionsOverloadedOnConstnessOfThis) {
  EXPECT_CALL(this->mock_foo_, OverloadedOnConstness());
  EXPECT_CALL(Const(this->mock_foo_), OverloadedOnConstness())
Abseil Team's avatar
Abseil Team committed
354
355
      .WillOnce(Return('a'));

Abseil Team's avatar
Abseil Team committed
356
357
  EXPECT_EQ(0, this->foo_->OverloadedOnConstness());
  EXPECT_EQ('a', Const(*this->foo_).OverloadedOnConstness());
Abseil Team's avatar
Abseil Team committed
358
359
}

Abseil Team's avatar
Abseil Team committed
360
TYPED_TEST(FunctionMockerTest, MocksReturnTypeWithComma) {
Abseil Team's avatar
Abseil Team committed
361
  const std::map<int, std::string> a_map;
Abseil Team's avatar
Abseil Team committed
362
363
  EXPECT_CALL(this->mock_foo_, ReturnTypeWithComma()).WillOnce(Return(a_map));
  EXPECT_CALL(this->mock_foo_, ReturnTypeWithComma(42)).WillOnce(Return(a_map));
Abseil Team's avatar
Abseil Team committed
364

Abseil Team's avatar
Abseil Team committed
365
366
  EXPECT_EQ(a_map, this->mock_foo_.ReturnTypeWithComma());
  EXPECT_EQ(a_map, this->mock_foo_.ReturnTypeWithComma(42));
Abseil Team's avatar
Abseil Team committed
367
368
}

Abseil Team's avatar
Abseil Team committed
369
370
371
372
TYPED_TEST(FunctionMockerTest, MocksTypeWithTemplatedCopyCtor) {
  EXPECT_CALL(this->mock_foo_, TypeWithTemplatedCopyCtor(_))
      .WillOnce(Return(true));
  EXPECT_TRUE(this->foo_->TypeWithTemplatedCopyCtor(TemplatedCopyable<int>()));
Abseil Team's avatar
Abseil Team committed
373
374
}

Abseil Team's avatar
Abseil Team committed
375
376
#if GTEST_OS_WINDOWS
// Tests mocking a nullary function with calltype.
Abseil Team's avatar
Abseil Team committed
377
378
TYPED_TEST(FunctionMockerTest, MocksNullaryFunctionWithCallType) {
  EXPECT_CALL(this->mock_foo_, CTNullary())
Abseil Team's avatar
Abseil Team committed
379
380
381
      .WillOnce(Return(-1))
      .WillOnce(Return(0));

Abseil Team's avatar
Abseil Team committed
382
383
  EXPECT_EQ(-1, this->foo_->CTNullary());
  EXPECT_EQ(0, this->foo_->CTNullary());
Abseil Team's avatar
Abseil Team committed
384
385
386
}

// Tests mocking a unary function with calltype.
Abseil Team's avatar
Abseil Team committed
387
388
TYPED_TEST(FunctionMockerTest, MocksUnaryFunctionWithCallType) {
  EXPECT_CALL(this->mock_foo_, CTUnary(Eq(2)))
Abseil Team's avatar
Abseil Team committed
389
390
391
392
      .Times(2)
      .WillOnce(Return(true))
      .WillOnce(Return(false));

Abseil Team's avatar
Abseil Team committed
393
394
  EXPECT_TRUE(this->foo_->CTUnary(2));
  EXPECT_FALSE(this->foo_->CTUnary(2));
Abseil Team's avatar
Abseil Team committed
395
396
397
}

// Tests mocking a decimal function with calltype.
Abseil Team's avatar
Abseil Team committed
398
399
400
TYPED_TEST(FunctionMockerTest, MocksDecimalFunctionWithCallType) {
  EXPECT_CALL(this->mock_foo_, CTDecimal(true, 'a', 0, 0, 1L, A<float>(),
                                         Lt(100), 5U, NULL, "hi"))
Abseil Team's avatar
Abseil Team committed
401
402
      .WillOnce(Return(10));

Abseil Team's avatar
Abseil Team committed
403
  EXPECT_EQ(10, this->foo_->CTDecimal(true, 'a', 0, 0, 1, 0, 0, 5, NULL, "hi"));
Abseil Team's avatar
Abseil Team committed
404
405
406
}

// Tests mocking functions overloaded on the const-ness of this object.
Abseil Team's avatar
Abseil Team committed
407
408
TYPED_TEST(FunctionMockerTest, MocksFunctionsConstFunctionWithCallType) {
  EXPECT_CALL(Const(this->mock_foo_), CTConst(_)).WillOnce(Return('a'));
Abseil Team's avatar
Abseil Team committed
409

Abseil Team's avatar
Abseil Team committed
410
  EXPECT_EQ('a', Const(*this->foo_).CTConst(0));
Abseil Team's avatar
Abseil Team committed
411
412
}

Abseil Team's avatar
Abseil Team committed
413
TYPED_TEST(FunctionMockerTest, MocksReturnTypeWithCommaAndCallType) {
Abseil Team's avatar
Abseil Team committed
414
  const std::map<int, std::string> a_map;
Abseil Team's avatar
Abseil Team committed
415
  EXPECT_CALL(this->mock_foo_, CTReturnTypeWithComma()).WillOnce(Return(a_map));
Abseil Team's avatar
Abseil Team committed
416

Abseil Team's avatar
Abseil Team committed
417
  EXPECT_EQ(a_map, this->mock_foo_.CTReturnTypeWithComma());
Abseil Team's avatar
Abseil Team committed
418
419
420
421
422
423
424
425
426
427
428
429
430
431
}

#endif  // GTEST_OS_WINDOWS

class MockB {
 public:
  MockB() {}

  MOCK_METHOD(void, DoB, ());

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockB);
};

Abseil Team's avatar
Abseil Team committed
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
class LegacyMockB {
 public:
  LegacyMockB() {}

  MOCK_METHOD0(DoB, void());

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockB);
};

template <typename T>
class ExpectCallTest : public ::testing::Test {};
using ExpectCallTestTypes = ::testing::Types<MockB, LegacyMockB>;
TYPED_TEST_SUITE(ExpectCallTest, ExpectCallTestTypes);

Abseil Team's avatar
Abseil Team committed
447
448
// Tests that functions with no EXPECT_CALL() rules can be called any
// number of times.
Abseil Team's avatar
Abseil Team committed
449
450
TYPED_TEST(ExpectCallTest, UnmentionedFunctionCanBeCalledAnyNumberOfTimes) {
  { TypeParam b; }
Abseil Team's avatar
Abseil Team committed
451
452

  {
Abseil Team's avatar
Abseil Team committed
453
    TypeParam b;
Abseil Team's avatar
Abseil Team committed
454
455
456
457
    b.DoB();
  }

  {
Abseil Team's avatar
Abseil Team committed
458
    TypeParam b;
Abseil Team's avatar
Abseil Team committed
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
    b.DoB();
    b.DoB();
  }
}

// Tests mocking template interfaces.

template <typename T>
class StackInterface {
 public:
  virtual ~StackInterface() {}

  // Template parameter appears in function parameter.
  virtual void Push(const T& value) = 0;
  virtual void Pop() = 0;
  virtual int GetSize() const = 0;
  // Template parameter appears in function return type.
  virtual const T& GetTop() const = 0;
};

template <typename T>
class MockStack : public StackInterface<T> {
 public:
  MockStack() {}

  MOCK_METHOD(void, Push, (const T& elem), ());
  MOCK_METHOD(void, Pop, (), (final));
  MOCK_METHOD(int, GetSize, (), (const, override));
  MOCK_METHOD(const T&, GetTop, (), (const));

  // Tests that the function return type can contain unprotected comma.
  MOCK_METHOD((std::map<int, int>), ReturnTypeWithComma, (), ());
  MOCK_METHOD((std::map<int, int>), ReturnTypeWithComma, (int), (const));

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStack);
};

Abseil Team's avatar
Abseil Team committed
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
template <typename T>
class LegacyMockStack : public StackInterface<T> {
 public:
  LegacyMockStack() {}

  MOCK_METHOD1_T(Push, void(const T& elem));
  MOCK_METHOD0_T(Pop, void());
  MOCK_CONST_METHOD0_T(GetSize, int());  // NOLINT
  MOCK_CONST_METHOD0_T(GetTop, const T&());

  // Tests that the function return type can contain unprotected comma.
  MOCK_METHOD0_T(ReturnTypeWithComma, std::map<int, int>());
  MOCK_CONST_METHOD1_T(ReturnTypeWithComma, std::map<int, int>(int));  // NOLINT

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockStack);
};

template <typename T>
class TemplateMockTest : public ::testing::Test {};
using TemplateMockTestTypes =
    ::testing::Types<MockStack<int>, LegacyMockStack<int>>;
TYPED_TEST_SUITE(TemplateMockTest, TemplateMockTestTypes);

Abseil Team's avatar
Abseil Team committed
521
// Tests that template mock works.
Abseil Team's avatar
Abseil Team committed
522
523
TYPED_TEST(TemplateMockTest, Works) {
  TypeParam mock;
Abseil Team's avatar
Abseil Team committed
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543

  EXPECT_CALL(mock, GetSize())
      .WillOnce(Return(0))
      .WillOnce(Return(1))
      .WillOnce(Return(0));
  EXPECT_CALL(mock, Push(_));
  int n = 5;
  EXPECT_CALL(mock, GetTop())
      .WillOnce(ReturnRef(n));
  EXPECT_CALL(mock, Pop())
      .Times(AnyNumber());

  EXPECT_EQ(0, mock.GetSize());
  mock.Push(5);
  EXPECT_EQ(1, mock.GetSize());
  EXPECT_EQ(5, mock.GetTop());
  mock.Pop();
  EXPECT_EQ(0, mock.GetSize());
}

Abseil Team's avatar
Abseil Team committed
544
545
TYPED_TEST(TemplateMockTest, MethodWithCommaInReturnTypeWorks) {
  TypeParam mock;
Abseil Team's avatar
Abseil Team committed
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588

  const std::map<int, int> a_map;
  EXPECT_CALL(mock, ReturnTypeWithComma())
      .WillOnce(Return(a_map));
  EXPECT_CALL(mock, ReturnTypeWithComma(1))
      .WillOnce(Return(a_map));

  EXPECT_EQ(a_map, mock.ReturnTypeWithComma());
  EXPECT_EQ(a_map, mock.ReturnTypeWithComma(1));
}

#if GTEST_OS_WINDOWS
// Tests mocking template interfaces with calltype.

template <typename T>
class StackInterfaceWithCallType {
 public:
  virtual ~StackInterfaceWithCallType() {}

  // Template parameter appears in function parameter.
  STDMETHOD_(void, Push)(const T& value) = 0;
  STDMETHOD_(void, Pop)() = 0;
  STDMETHOD_(int, GetSize)() const = 0;
  // Template parameter appears in function return type.
  STDMETHOD_(const T&, GetTop)() const = 0;
};

template <typename T>
class MockStackWithCallType : public StackInterfaceWithCallType<T> {
 public:
  MockStackWithCallType() {}

  MOCK_METHOD(void, Push, (const T& elem),
              (Calltype(STDMETHODCALLTYPE), override));
  MOCK_METHOD(void, Pop, (), (Calltype(STDMETHODCALLTYPE), override));
  MOCK_METHOD(int, GetSize, (), (Calltype(STDMETHODCALLTYPE), override, const));
  MOCK_METHOD(const T&, GetTop, (),
              (Calltype(STDMETHODCALLTYPE), override, const));

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStackWithCallType);
};

Abseil Team's avatar
Abseil Team committed
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
template <typename T>
class LegacyMockStackWithCallType : public StackInterfaceWithCallType<T> {
 public:
  LegacyMockStackWithCallType() {}

  MOCK_METHOD1_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Push, void(const T& elem));
  MOCK_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Pop, void());
  MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetSize, int());
  MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTop, const T&());

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockStackWithCallType);
};

template <typename T>
class TemplateMockTestWithCallType : public ::testing::Test {};
using TemplateMockTestWithCallTypeTypes =
    ::testing::Types<MockStackWithCallType<int>,
                     LegacyMockStackWithCallType<int>>;
TYPED_TEST_SUITE(TemplateMockTestWithCallType,
                 TemplateMockTestWithCallTypeTypes);

Abseil Team's avatar
Abseil Team committed
611
// Tests that template mock with calltype works.
Abseil Team's avatar
Abseil Team committed
612
613
TYPED_TEST(TemplateMockTestWithCallType, Works) {
  TypeParam mock;
Abseil Team's avatar
Abseil Team committed
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639

  EXPECT_CALL(mock, GetSize())
      .WillOnce(Return(0))
      .WillOnce(Return(1))
      .WillOnce(Return(0));
  EXPECT_CALL(mock, Push(_));
  int n = 5;
  EXPECT_CALL(mock, GetTop())
      .WillOnce(ReturnRef(n));
  EXPECT_CALL(mock, Pop())
      .Times(AnyNumber());

  EXPECT_EQ(0, mock.GetSize());
  mock.Push(5);
  EXPECT_EQ(1, mock.GetSize());
  EXPECT_EQ(5, mock.GetTop());
  mock.Pop();
  EXPECT_EQ(0, mock.GetSize());
}
#endif  // GTEST_OS_WINDOWS

#define MY_MOCK_METHODS1_                       \
  MOCK_METHOD(void, Overloaded, ());            \
  MOCK_METHOD(int, Overloaded, (int), (const)); \
  MOCK_METHOD(bool, Overloaded, (bool f, int n))

Abseil Team's avatar
Abseil Team committed
640
641
642
643
644
#define LEGACY_MY_MOCK_METHODS1_              \
  MOCK_METHOD0(Overloaded, void());           \
  MOCK_CONST_METHOD1(Overloaded, int(int n)); \
  MOCK_METHOD2(Overloaded, bool(bool f, int n))

Abseil Team's avatar
Abseil Team committed
645
646
647
648
649
650
651
652
653
654
class MockOverloadedOnArgNumber {
 public:
  MockOverloadedOnArgNumber() {}

  MY_MOCK_METHODS1_;

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockOverloadedOnArgNumber);
};

Abseil Team's avatar
Abseil Team committed
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
class LegacyMockOverloadedOnArgNumber {
 public:
  LegacyMockOverloadedOnArgNumber() {}

  LEGACY_MY_MOCK_METHODS1_;

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockOverloadedOnArgNumber);
};

template <typename T>
class OverloadedMockMethodTest : public ::testing::Test {};
using OverloadedMockMethodTestTypes =
    ::testing::Types<MockOverloadedOnArgNumber,
                     LegacyMockOverloadedOnArgNumber>;
TYPED_TEST_SUITE(OverloadedMockMethodTest, OverloadedMockMethodTestTypes);

TYPED_TEST(OverloadedMockMethodTest, CanOverloadOnArgNumberInMacroBody) {
  TypeParam mock;
Abseil Team's avatar
Abseil Team committed
674
675
676
677
678
679
680
681
682
683
684
  EXPECT_CALL(mock, Overloaded());
  EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2));
  EXPECT_CALL(mock, Overloaded(true, 1)).WillOnce(Return(true));

  mock.Overloaded();
  EXPECT_EQ(2, mock.Overloaded(1));
  EXPECT_TRUE(mock.Overloaded(true, 1));
}

#define MY_MOCK_METHODS2_ \
    MOCK_CONST_METHOD1(Overloaded, int(int n)); \
Abseil Team's avatar
Abseil Team committed
685
    MOCK_METHOD1(Overloaded, int(int n))
Abseil Team's avatar
Abseil Team committed
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797

class MockOverloadedOnConstness {
 public:
  MockOverloadedOnConstness() {}

  MY_MOCK_METHODS2_;

 private:
  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockOverloadedOnConstness);
};

TEST(MockMethodOverloadedMockMethodTest, CanOverloadOnConstnessInMacroBody) {
  MockOverloadedOnConstness mock;
  const MockOverloadedOnConstness* const_mock = &mock;
  EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2));
  EXPECT_CALL(*const_mock, Overloaded(1)).WillOnce(Return(3));

  EXPECT_EQ(2, mock.Overloaded(1));
  EXPECT_EQ(3, const_mock->Overloaded(1));
}

TEST(MockMethodMockFunctionTest, WorksForVoidNullary) {
  MockFunction<void()> foo;
  EXPECT_CALL(foo, Call());
  foo.Call();
}

TEST(MockMethodMockFunctionTest, WorksForNonVoidNullary) {
  MockFunction<int()> foo;
  EXPECT_CALL(foo, Call())
      .WillOnce(Return(1))
      .WillOnce(Return(2));
  EXPECT_EQ(1, foo.Call());
  EXPECT_EQ(2, foo.Call());
}

TEST(MockMethodMockFunctionTest, WorksForVoidUnary) {
  MockFunction<void(int)> foo;
  EXPECT_CALL(foo, Call(1));
  foo.Call(1);
}

TEST(MockMethodMockFunctionTest, WorksForNonVoidBinary) {
  MockFunction<int(bool, int)> foo;
  EXPECT_CALL(foo, Call(false, 42))
      .WillOnce(Return(1))
      .WillOnce(Return(2));
  EXPECT_CALL(foo, Call(true, Ge(100)))
      .WillOnce(Return(3));
  EXPECT_EQ(1, foo.Call(false, 42));
  EXPECT_EQ(2, foo.Call(false, 42));
  EXPECT_EQ(3, foo.Call(true, 120));
}

TEST(MockMethodMockFunctionTest, WorksFor10Arguments) {
  MockFunction<int(bool a0, char a1, int a2, int a3, int a4,
                   int a5, int a6, char a7, int a8, bool a9)> foo;
  EXPECT_CALL(foo, Call(_, 'a', _, _, _, _, _, _, _, _))
      .WillOnce(Return(1))
      .WillOnce(Return(2));
  EXPECT_EQ(1, foo.Call(false, 'a', 0, 0, 0, 0, 0, 'b', 0, true));
  EXPECT_EQ(2, foo.Call(true, 'a', 0, 0, 0, 0, 0, 'b', 1, false));
}

TEST(MockMethodMockFunctionTest, AsStdFunction) {
  MockFunction<int(int)> foo;
  auto call = [](const std::function<int(int)> &f, int i) {
    return f(i);
  };
  EXPECT_CALL(foo, Call(1)).WillOnce(Return(-1));
  EXPECT_CALL(foo, Call(2)).WillOnce(Return(-2));
  EXPECT_EQ(-1, call(foo.AsStdFunction(), 1));
  EXPECT_EQ(-2, call(foo.AsStdFunction(), 2));
}

TEST(MockMethodMockFunctionTest, AsStdFunctionReturnsReference) {
  MockFunction<int&()> foo;
  int value = 1;
  EXPECT_CALL(foo, Call()).WillOnce(ReturnRef(value));
  int& ref = foo.AsStdFunction()();
  EXPECT_EQ(1, ref);
  value = 2;
  EXPECT_EQ(2, ref);
}

TEST(MockMethodMockFunctionTest, AsStdFunctionWithReferenceParameter) {
  MockFunction<int(int &)> foo;
  auto call = [](const std::function<int(int& )> &f, int &i) {
    return f(i);
  };
  int i = 42;
  EXPECT_CALL(foo, Call(i)).WillOnce(Return(-1));
  EXPECT_EQ(-1, call(foo.AsStdFunction(), i));
}


struct MockMethodSizes0 {
  MOCK_METHOD(void, func, ());
};
struct MockMethodSizes1 {
  MOCK_METHOD(void, func, (int));
};
struct MockMethodSizes2 {
  MOCK_METHOD(void, func, (int, int));
};
struct MockMethodSizes3 {
  MOCK_METHOD(void, func, (int, int, int));
};
struct MockMethodSizes4 {
  MOCK_METHOD(void, func, (int, int, int, int));
};

Abseil Team's avatar
Abseil Team committed
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
struct LegacyMockMethodSizes0 {
    MOCK_METHOD0(func, void());
};
struct LegacyMockMethodSizes1 {
    MOCK_METHOD1(func, void(int));
};
struct LegacyMockMethodSizes2 {
    MOCK_METHOD2(func, void(int, int));
};
struct LegacyMockMethodSizes3 {
    MOCK_METHOD3(func, void(int, int, int));
};
struct LegacyMockMethodSizes4 {
    MOCK_METHOD4(func, void(int, int, int, int));
};


Abseil Team's avatar
Abseil Team committed
815
816
817
818
819
TEST(MockMethodMockFunctionTest, MockMethodSizeOverhead) {
  EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes1));
  EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes2));
  EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes3));
  EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes4));
Abseil Team's avatar
Abseil Team committed
820
821
822
823
824
825
826

  EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes1));
  EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes2));
  EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes3));
  EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes4));

  EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(MockMethodSizes0));
Abseil Team's avatar
Abseil Team committed
827
828
}

829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
void hasTwoParams(int, int);
void MaybeThrows();
void DoesntThrow() noexcept;
struct MockMethodNoexceptSpecifier {
  MOCK_METHOD(void, func1, (), (noexcept));
  MOCK_METHOD(void, func2, (), (noexcept(true)));
  MOCK_METHOD(void, func3, (), (noexcept(false)));
  MOCK_METHOD(void, func4, (), (noexcept(noexcept(MaybeThrows()))));
  MOCK_METHOD(void, func5, (), (noexcept(noexcept(DoesntThrow()))));
  MOCK_METHOD(void, func6, (), (noexcept(noexcept(DoesntThrow())), const));
  MOCK_METHOD(void, func7, (), (const, noexcept(noexcept(DoesntThrow()))));
  // Put commas in the noexcept expression
  MOCK_METHOD(void, func8, (), (noexcept(noexcept(hasTwoParams(1, 2))), const));
};

TEST(MockMethodMockFunctionTest, NoexceptSpecifierPreserved) {
  EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func1()));
  EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func2()));
  EXPECT_FALSE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func3()));
  EXPECT_FALSE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func4()));
  EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func5()));
  EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func6()));
  EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func7()));
  EXPECT_EQ(noexcept(std::declval<MockMethodNoexceptSpecifier>().func8()),
            noexcept(hasTwoParams(1, 2)));
}

Abseil Team's avatar
Abseil Team committed
856
857
}  // namespace gmock_function_mocker_test
}  // namespace testing