gmock-internal-utils.h 18.9 KB
Newer Older
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
// 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.
Gennadiy Civil's avatar
 
Gennadiy Civil committed
29

30
31
32
33
34
35
// Google Mock - a framework for writing C++ mock classes.
//
// This file defines some utilities useful for implementing Google
// Mock.  They are subject to change without notice, so please DO NOT
// USE THEM IN USER CODE.

36
37
38
// IWYU pragma: private, include "gmock/gmock.h"
// IWYU pragma: friend gmock/.*

Abseil Team's avatar
Abseil Team committed
39
40
#ifndef GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
#define GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
41
42

#include <stdio.h>
43

44
45
#include <ostream>  // NOLINT
#include <string>
Abseil Team's avatar
Abseil Team committed
46
#include <type_traits>
47
48
#include <vector>

49
50
#include "gmock/internal/gmock-port.h"
#include "gtest/gtest.h"
51
52

namespace testing {
Abseil Team's avatar
Abseil Team committed
53
54
55
56

template <typename>
class Matcher;

57
58
namespace internal {

Gennadiy Civil's avatar
Gennadiy Civil committed
59
60
61
// Silence MSVC C4100 (unreferenced formal parameter) and
// C4805('==': unsafe mix of type 'const int' and type 'const bool')
#ifdef _MSC_VER
62
63
64
#pragma warning(push)
#pragma warning(disable : 4100)
#pragma warning(disable : 4805)
Gennadiy Civil's avatar
Gennadiy Civil committed
65
66
#endif

Gennadiy Civil's avatar
Gennadiy Civil committed
67
68
// Joins a vector of strings as if they are fields of a tuple; returns
// the joined string.
69
70
GTEST_API_ std::string JoinAsKeyValueTuple(
    const std::vector<const char*>& names, const Strings& values);
Gennadiy Civil's avatar
Gennadiy Civil committed
71

zhanyong.wan's avatar
zhanyong.wan committed
72
73
74
75
// Converts an identifier name to a space-separated list of lower-case
// words.  Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
// treated as one word.  For example, both "FooBar123" and
// "foo_bar_123" are converted to "foo bar 123".
Gennadiy Civil's avatar
Gennadiy Civil committed
76
GTEST_API_ std::string ConvertIdentifierNameToWords(const char* id_name);
zhanyong.wan's avatar
zhanyong.wan committed
77

78
79
80
81
// GetRawPointer(p) returns the raw pointer underlying p when p is a
// smart pointer, or returns p itself when p is already a raw pointer.
// The following default implementation is for the smart pointer case.
template <typename Pointer>
82
inline const typename Pointer::element_type* GetRawPointer(const Pointer& p) {
83
84
  return p.get();
}
85
86
87
88
89
90
91
// This overload version is for std::reference_wrapper, which does not work with
// the overload above, as it does not have an `element_type`.
template <typename Element>
inline const Element* GetRawPointer(const std::reference_wrapper<Element>& r) {
  return &r.get();
}

92
93
// This overloaded version is for the raw pointer case.
template <typename Element>
94
95
96
inline Element* GetRawPointer(Element* p) {
  return p;
}
97

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Default definitions for all compilers.
// NOTE: If you implement support for other compilers, make sure to avoid
// unexpected overlaps.
// (e.g., Clang also processes #pragma GCC, and clang-cl also handles _MSC_VER.)
#define GMOCK_INTERNAL_WARNING_PUSH()
#define GMOCK_INTERNAL_WARNING_CLANG(Level, Name)
#define GMOCK_INTERNAL_WARNING_POP()

#if defined(__clang__)
#undef GMOCK_INTERNAL_WARNING_PUSH
#define GMOCK_INTERNAL_WARNING_PUSH() _Pragma("clang diagnostic push")
#undef GMOCK_INTERNAL_WARNING_CLANG
#define GMOCK_INTERNAL_WARNING_CLANG(Level, Warning) \
  _Pragma(GMOCK_PP_INTERNAL_STRINGIZE(clang diagnostic Level Warning))
#undef GMOCK_INTERNAL_WARNING_POP
#define GMOCK_INTERNAL_WARNING_POP() _Pragma("clang diagnostic pop")
#endif

116
117
118
119
// MSVC treats wchar_t as a native type usually, but treats it as the
// same as unsigned short when the compiler option /Zc:wchar_t- is
// specified.  It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t
// is a native type.
Abseil Team's avatar
Abseil Team committed
120
#if defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED)
121
122
// wchar_t is a typedef.
#else
123
#define GMOCK_WCHAR_T_IS_NATIVE_ 1
124
125
#endif

126
127
128
129
130
// In what follows, we use the term "kind" to indicate whether a type
// is bool, an integer type (excluding bool), a floating-point type,
// or none of them.  This categorization is useful for determining
// when a matcher argument type can be safely converted to another
// type in the implementation of SafeMatcherCast.
131
enum TypeKind { kBool, kInteger, kFloatingPoint, kOther };
132
133

// KindOf<T>::value is the kind of type T.
134
135
template <typename T>
struct KindOf {
136
137
138
139
140
  enum { value = kOther };  // The default kind.
};

// This macro declares that the kind of 'type' is 'kind'.
#define GMOCK_DECLARE_KIND_(type, kind) \
141
142
143
144
  template <>                           \
  struct KindOf<type> {                 \
    enum { value = kind };              \
  }
145
146
147
148
149
150
151

GMOCK_DECLARE_KIND_(bool, kBool);

// All standard integer types.
GMOCK_DECLARE_KIND_(char, kInteger);
GMOCK_DECLARE_KIND_(signed char, kInteger);
GMOCK_DECLARE_KIND_(unsigned char, kInteger);
152
GMOCK_DECLARE_KIND_(short, kInteger);           // NOLINT
153
154
155
GMOCK_DECLARE_KIND_(unsigned short, kInteger);  // NOLINT
GMOCK_DECLARE_KIND_(int, kInteger);
GMOCK_DECLARE_KIND_(unsigned int, kInteger);
156
157
158
GMOCK_DECLARE_KIND_(long, kInteger);                // NOLINT
GMOCK_DECLARE_KIND_(unsigned long, kInteger);       // NOLINT
GMOCK_DECLARE_KIND_(long long, kInteger);           // NOLINT
Abseil Team's avatar
Abseil Team committed
159
GMOCK_DECLARE_KIND_(unsigned long long, kInteger);  // NOLINT
160

161
#if GMOCK_WCHAR_T_IS_NATIVE_
162
163
164
165
166
167
168
169
170
171
172
GMOCK_DECLARE_KIND_(wchar_t, kInteger);
#endif

// All standard floating-point types.
GMOCK_DECLARE_KIND_(float, kFloatingPoint);
GMOCK_DECLARE_KIND_(double, kFloatingPoint);
GMOCK_DECLARE_KIND_(long double, kFloatingPoint);

#undef GMOCK_DECLARE_KIND_

// Evaluates to the kind of 'type'.
173
#define GMOCK_KIND_OF_(type)                   \
174
175
176
177
  static_cast< ::testing::internal::TypeKind>( \
      ::testing::internal::KindOf<type>::value)

// LosslessArithmeticConvertibleImpl<kFromKind, From, kToKind, To>::value
178
// is true if and only if arithmetic type From can be losslessly converted to
179
180
181
182
183
184
185
186
// arithmetic type To.
//
// It's the user's responsibility to ensure that both From and To are
// raw (i.e. has no CV modifier, is not a pointer, and is not a
// reference) built-in arithmetic types, kFromKind is the kind of
// From, and kToKind is the kind of To; the value is
// implementation-defined when the above pre-condition is violated.
template <TypeKind kFromKind, typename From, TypeKind kToKind, typename To>
Abseil Team's avatar
Abseil Team committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
using LosslessArithmeticConvertibleImpl = std::integral_constant<
    bool,
    // clang-format off
      // Converting from bool is always lossless
      (kFromKind == kBool) ? true
      // Converting between any other type kinds will be lossy if the type
      // kinds are not the same.
    : (kFromKind != kToKind) ? false
    : (kFromKind == kInteger &&
       // Converting between integers of different widths is allowed so long
       // as the conversion does not go from signed to unsigned.
      (((sizeof(From) < sizeof(To)) &&
        !(std::is_signed<From>::value && !std::is_signed<To>::value)) ||
       // Converting between integers of the same width only requires the
       // two types to have the same signedness.
       ((sizeof(From) == sizeof(To)) &&
        (std::is_signed<From>::value == std::is_signed<To>::value)))
       ) ? true
      // Floating point conversions are lossless if and only if `To` is at least
      // as wide as `From`.
    : (kFromKind == kFloatingPoint && (sizeof(From) <= sizeof(To))) ? true
    : false
    // clang-format on
    >;
211

212
213
// LosslessArithmeticConvertible<From, To>::value is true if and only if
// arithmetic type From can be losslessly converted to arithmetic type To.
214
215
216
217
218
219
//
// It's the user's responsibility to ensure that both From and To are
// raw (i.e. has no CV modifier, is not a pointer, and is not a
// reference) built-in arithmetic types; the value is
// implementation-defined when the above pre-condition is violated.
template <typename From, typename To>
Abseil Team's avatar
Abseil Team committed
220
221
222
using LosslessArithmeticConvertible =
    LosslessArithmeticConvertibleImpl<GMOCK_KIND_OF_(From), From,
                                      GMOCK_KIND_OF_(To), To>;
223

224
225
226
227
228
// This interface knows how to report a Google Mock failure (either
// non-fatal or fatal).
class FailureReporterInterface {
 public:
  // The type of a failure (either non-fatal or fatal).
229
  enum FailureType { kNonfatal, kFatal };
230
231
232
233
234

  virtual ~FailureReporterInterface() {}

  // Reports a failure that occurred at the given source file location.
  virtual void ReportFailure(FailureType type, const char* file, int line,
235
                             const std::string& message) = 0;
236
237
238
};

// Returns the failure reporter used by Google Mock.
239
GTEST_API_ FailureReporterInterface* GetFailureReporter();
240
241
242
243
244
245
246

// Asserts that condition is true; aborts the process with the given
// message if condition is false.  We cannot use LOG(FATAL) or CHECK()
// as Google Mock might be used to mock the log sink itself.  We
// inline this function to prevent it from showing up in the stack
// trace.
inline void Assert(bool condition, const char* file, int line,
247
                   const std::string& msg) {
248
  if (!condition) {
249
250
    GetFailureReporter()->ReportFailure(FailureReporterInterface::kFatal, file,
                                        line, msg);
251
252
253
254
255
256
257
258
259
  }
}
inline void Assert(bool condition, const char* file, int line) {
  Assert(condition, file, line, "Assertion failed.");
}

// Verifies that condition is true; generates a non-fatal failure if
// condition is false.
inline void Expect(bool condition, const char* file, int line,
260
                   const std::string& msg) {
261
  if (!condition) {
zhanyong.wan's avatar
zhanyong.wan committed
262
    GetFailureReporter()->ReportFailure(FailureReporterInterface::kNonfatal,
263
264
265
266
267
268
269
270
                                        file, line, msg);
  }
}
inline void Expect(bool condition, const char* file, int line) {
  Expect(condition, file, line, "Expectation failed.");
}

// Severity level of a log.
271
enum LogSeverity { kInfo = 0, kWarning = 1 };
272
273
274
275
276
277
278
279
280
281

// Valid values for the --gmock_verbose flag.

// All logs (informational and warnings) are printed.
const char kInfoVerbosity[] = "info";
// Only warnings are printed.
const char kWarningVerbosity[] = "warning";
// No logs are printed.
const char kErrorVerbosity[] = "error";

282
283
// Returns true if and only if a log with the given severity is visible
// according to the --gmock_verbose flag.
284
GTEST_API_ bool LogIsVisible(LogSeverity severity);
285

286
// Prints the given message to stdout if and only if 'severity' >= the level
287
288
289
290
291
292
// specified by the --gmock_verbose flag.  If stack_frames_to_skip >=
// 0, also prints the stack trace excluding the top
// stack_frames_to_skip frames.  In opt mode, any positive
// stack_frames_to_skip is treated as 0, since we don't know which
// function calls will be inlined by the compiler and need to be
// conservative.
293
GTEST_API_ void Log(LogSeverity severity, const std::string& message,
294
                    int stack_frames_to_skip);
295

296
297
298
299
// A marker class that is used to resolve parameterless expectations to the
// correct overload. This must not be instantiable, to prevent client code from
// accidentally resolving to the overload; for example:
//
300
//    ON_CALL(mock, Method({}, nullptr))...
301
//
302
class WithoutMatchers {
303
304
 private:
  WithoutMatchers() {}
305
  friend GTEST_API_ WithoutMatchers GetWithoutMatchers();
306
307
308
};

// Internal use only: access the singleton instance of WithoutMatchers.
309
GTEST_API_ WithoutMatchers GetWithoutMatchers();
310

311
312
// Invalid<T>() is usable as an expression of type T, but will terminate
// the program with an assertion failure if actually run.  This is useful
313
314
315
316
317
// when a value of type T is needed for compilation, but the statement
// will not really be executed (or we don't care if the statement
// crashes).
template <typename T>
inline T Invalid() {
318
  Assert(false, "", -1, "Internal error: attempt to return invalid value");
319
320
321
322
323
#if defined(__GNUC__) || defined(__clang__)
  __builtin_unreachable();
#elif defined(_MSC_VER)
  __assume(0);
#else
324
  return Invalid<T>();
325
#endif
326
}
327

328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
// Given a raw type (i.e. having no top-level reference or const
// modifier) RawContainer that's either an STL-style container or a
// native array, class StlContainerView<RawContainer> has the
// following members:
//
//   - type is a type that provides an STL-style container view to
//     (i.e. implements the STL container concept for) RawContainer;
//   - const_reference is a type that provides a reference to a const
//     RawContainer;
//   - ConstReference(raw_container) returns a const reference to an STL-style
//     container view to raw_container, which is a RawContainer.
//   - Copy(raw_container) returns an STL-style container view of a
//     copy of raw_container, which is a RawContainer.
//
// This generic version is used when RawContainer itself is already an
// STL-style container.
template <class RawContainer>
class StlContainerView {
 public:
  typedef RawContainer type;
  typedef const type& const_reference;

  static const_reference ConstReference(const RawContainer& container) {
kuzkry's avatar
kuzkry committed
351
352
    static_assert(!std::is_const<RawContainer>::value,
                  "RawContainer type must not be const");
353
354
355
356
357
358
359
360
361
    return container;
  }
  static type Copy(const RawContainer& container) { return container; }
};

// This specialization is used when RawContainer is a native array type.
template <typename Element, size_t N>
class StlContainerView<Element[N]> {
 public:
362
  typedef typename std::remove_const<Element>::type RawElement;
363
364
365
366
367
368
369
370
371
  typedef internal::NativeArray<RawElement> type;
  // NativeArray<T> can represent a native array either by value or by
  // reference (selected by a constructor argument), so 'const type'
  // can be used to reference a const native array.  We cannot
  // 'typedef const type& const_reference' here, as that would mean
  // ConstReference() has to return a reference to a local variable.
  typedef const type const_reference;

  static const_reference ConstReference(const Element (&array)[N]) {
kuzkry's avatar
kuzkry committed
372
373
    static_assert(std::is_same<Element, RawElement>::value,
                  "Element type must not be const");
billydonahue's avatar
billydonahue committed
374
    return type(array, N, RelationToSourceReference());
375
376
  }
  static type Copy(const Element (&array)[N]) {
billydonahue's avatar
billydonahue committed
377
    return type(array, N, RelationToSourceCopy());
378
379
380
381
382
383
  }
};

// This specialization is used when RawContainer is a native array
// represented as a (pointer, size) tuple.
template <typename ElementPointer, typename Size>
Abseil Team's avatar
Abseil Team committed
384
class StlContainerView< ::std::tuple<ElementPointer, Size> > {
385
 public:
386
  typedef typename std::remove_const<
Abseil Team's avatar
Abseil Team committed
387
388
      typename std::pointer_traits<ElementPointer>::element_type>::type
      RawElement;
389
390
391
392
  typedef internal::NativeArray<RawElement> type;
  typedef const type const_reference;

  static const_reference ConstReference(
Abseil Team's avatar
Abseil Team committed
393
394
395
      const ::std::tuple<ElementPointer, Size>& array) {
    return type(std::get<0>(array), std::get<1>(array),
                RelationToSourceReference());
396
  }
Abseil Team's avatar
Abseil Team committed
397
398
  static type Copy(const ::std::tuple<ElementPointer, Size>& array) {
    return type(std::get<0>(array), std::get<1>(array), RelationToSourceCopy());
399
400
401
402
403
  }
};

// The following specialization prevents the user from instantiating
// StlContainer with a reference type.
404
405
template <typename T>
class StlContainerView<T&>;
406

407
408
409
410
411
412
413
414
415
416
417
418
419
420
// A type transform to remove constness from the first part of a pair.
// Pairs like that are used as the value_type of associative containers,
// and this transform produces a similar but assignable pair.
template <typename T>
struct RemoveConstFromKey {
  typedef T type;
};

// Partially specialized to remove constness from std::pair<const K, V>.
template <typename K, typename V>
struct RemoveConstFromKey<std::pair<const K, V> > {
  typedef std::pair<K, V> type;
};

Gennadiy Civil's avatar
Gennadiy Civil committed
421
422
// Emit an assertion failure due to incorrect DoDefault() usage. Out-of-lined to
// reduce code size.
Gennadiy Civil's avatar
Gennadiy Civil committed
423
GTEST_API_ void IllegalDoDefault(const char* file, int line);
Gennadiy Civil's avatar
Gennadiy Civil committed
424
425

template <typename F, typename Tuple, size_t... Idx>
426
427
428
auto ApplyImpl(F&& f, Tuple&& args, IndexSequence<Idx...>)
    -> decltype(std::forward<F>(f)(
        std::get<Idx>(std::forward<Tuple>(args))...)) {
Gennadiy Civil's avatar
Gennadiy Civil committed
429
430
431
432
433
  return std::forward<F>(f)(std::get<Idx>(std::forward<Tuple>(args))...);
}

// Apply the function to a tuple of arguments.
template <typename F, typename Tuple>
434
435
436
437
auto Apply(F&& f, Tuple&& args) -> decltype(ApplyImpl(
    std::forward<F>(f), std::forward<Tuple>(args),
    MakeIndexSequence<std::tuple_size<
        typename std::remove_reference<Tuple>::type>::value>())) {
Gennadiy Civil's avatar
Gennadiy Civil committed
438
  return ApplyImpl(std::forward<F>(f), std::forward<Tuple>(args),
Abseil Team's avatar
Abseil Team committed
439
440
                   MakeIndexSequence<std::tuple_size<
                       typename std::remove_reference<Tuple>::type>::value>());
Gennadiy Civil's avatar
Gennadiy Civil committed
441
}
Gennadiy Civil's avatar
Gennadiy Civil committed
442

Abseil Team's avatar
Abseil Team committed
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
// Template struct Function<F>, where F must be a function type, contains
// the following typedefs:
//
//   Result:               the function's return type.
//   Arg<N>:               the type of the N-th argument, where N starts with 0.
//   ArgumentTuple:        the tuple type consisting of all parameters of F.
//   ArgumentMatcherTuple: the tuple type consisting of Matchers for all
//                         parameters of F.
//   MakeResultVoid:       the function type obtained by substituting void
//                         for the return type of F.
//   MakeResultIgnoredValue:
//                         the function type obtained by substituting Something
//                         for the return type of F.
template <typename T>
struct Function;

template <typename R, typename... Args>
struct Function<R(Args...)> {
  using Result = R;
  static constexpr size_t ArgumentCount = sizeof...(Args);
  template <size_t I>
Abseil Team's avatar
Abseil Team committed
464
  using Arg = ElemFromList<I, Args...>;
Abseil Team's avatar
Abseil Team committed
465
466
467
468
469
470
471
472
  using ArgumentTuple = std::tuple<Args...>;
  using ArgumentMatcherTuple = std::tuple<Matcher<Args>...>;
  using MakeResultVoid = void(Args...);
  using MakeResultIgnoredValue = IgnoredValue(Args...);
};

template <typename R, typename... Args>
constexpr size_t Function<R(Args...)>::ArgumentCount;
Gennadiy Civil's avatar
Gennadiy Civil committed
473

474
475
476
477
478
479
480
// Workaround for MSVC error C2039: 'type': is not a member of 'std'
// when std::tuple_element is used.
// See: https://github.com/google/googletest/issues/3931
// Can be replaced with std::tuple_element_t in C++14.
template <size_t I, typename T>
using TupleElement = typename std::tuple_element<I, T>::type;

Abseil Team's avatar
Abseil Team committed
481
482
bool Base64Unescape(const std::string& encoded, std::string* decoded);

Gennadiy Civil's avatar
Gennadiy Civil committed
483
#ifdef _MSC_VER
484
#pragma warning(pop)
Gennadiy Civil's avatar
Gennadiy Civil committed
485
486
#endif

487
488
489
}  // namespace internal
}  // namespace testing

Abseil Team's avatar
Abseil Team committed
490
#endif  // GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_