// 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 defines some utilities useful for implementing Google // Mock. They are subject to change without notice, so please DO NOT // USE THEM IN USER CODE. // GOOGLETEST_CM0002 DO NOT DELETE #ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_ #define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_ #include #include // NOLINT #include #include #include "gmock/internal/gmock-port.h" #include "gtest/gtest.h" namespace testing { template class Matcher; namespace internal { // Silence MSVC C4100 (unreferenced formal parameter) and // C4805('==': unsafe mix of type 'const int' and type 'const bool') #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable:4100) # pragma warning(disable:4805) #endif // Joins a vector of strings as if they are fields of a tuple; returns // the joined string. GTEST_API_ std::string JoinAsTuple(const Strings& fields); // 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". GTEST_API_ std::string ConvertIdentifierNameToWords(const char* id_name); // PointeeOf::type is the type of a value pointed to by a // Pointer, which can be either a smart pointer or a raw pointer. The // following default implementation is for the case where Pointer is a // smart pointer. template struct PointeeOf { // Smart pointer classes define type element_type as the type of // their pointees. typedef typename Pointer::element_type type; }; // This specialization is for the raw pointer case. template struct PointeeOf { typedef T type; }; // NOLINT // 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 inline const typename Pointer::element_type* GetRawPointer(const Pointer& p) { return p.get(); } // This overloaded version is for the raw pointer case. template inline Element* GetRawPointer(Element* p) { return p; } // 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. #if defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED) // wchar_t is a typedef. #else # define GMOCK_WCHAR_T_IS_NATIVE_ 1 #endif // 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. enum TypeKind { kBool, kInteger, kFloatingPoint, kOther }; // KindOf::value is the kind of type T. template struct KindOf { enum { value = kOther }; // The default kind. }; // This macro declares that the kind of 'type' is 'kind'. #define GMOCK_DECLARE_KIND_(type, kind) \ template <> struct KindOf { enum { value = kind }; } 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); GMOCK_DECLARE_KIND_(short, kInteger); // NOLINT GMOCK_DECLARE_KIND_(unsigned short, kInteger); // NOLINT GMOCK_DECLARE_KIND_(int, kInteger); GMOCK_DECLARE_KIND_(unsigned int, kInteger); GMOCK_DECLARE_KIND_(long, kInteger); // NOLINT GMOCK_DECLARE_KIND_(unsigned long, kInteger); // NOLINT GMOCK_DECLARE_KIND_(long long, kInteger); // NOLINT GMOCK_DECLARE_KIND_(unsigned long long, kInteger); // NOLINT #if GMOCK_WCHAR_T_IS_NATIVE_ 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'. #define GMOCK_KIND_OF_(type) \ static_cast< ::testing::internal::TypeKind>( \ ::testing::internal::KindOf::value) // LosslessArithmeticConvertibleImpl::value // is true if and only if arithmetic type From can be losslessly converted to // 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 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::value && !std::is_signed::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::value == std::is_signed::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 >; // LosslessArithmeticConvertible::value is true if and only if // arithmetic type From can be losslessly converted to 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; the value is // implementation-defined when the above pre-condition is violated. template using LosslessArithmeticConvertible = LosslessArithmeticConvertibleImpl; // 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). enum FailureType { kNonfatal, kFatal }; virtual ~FailureReporterInterface() {} // Reports a failure that occurred at the given source file location. virtual void ReportFailure(FailureType type, const char* file, int line, const std::string& message) = 0; }; // Returns the failure reporter used by Google Mock. GTEST_API_ FailureReporterInterface* GetFailureReporter(); // 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, const std::string& msg) { if (!condition) { GetFailureReporter()->ReportFailure(FailureReporterInterface::kFatal, file, line, msg); } } 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, const std::string& msg) { if (!condition) { GetFailureReporter()->ReportFailure(FailureReporterInterface::kNonfatal, file, line, msg); } } inline void Expect(bool condition, const char* file, int line) { Expect(condition, file, line, "Expectation failed."); } // Severity level of a log. enum LogSeverity { kInfo = 0, kWarning = 1 }; // 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"; // Returns true if and only if a log with the given severity is visible // according to the --gmock_verbose flag. GTEST_API_ bool LogIsVisible(LogSeverity severity); // Prints the given message to stdout if and only if 'severity' >= the level // 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. GTEST_API_ void Log(LogSeverity severity, const std::string& message, int stack_frames_to_skip); // 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: // // ON_CALL(mock, Method({}, nullptr))... // class WithoutMatchers { private: WithoutMatchers() {} friend GTEST_API_ WithoutMatchers GetWithoutMatchers(); }; // Internal use only: access the singleton instance of WithoutMatchers. GTEST_API_ WithoutMatchers GetWithoutMatchers(); // Disable MSVC warnings for infinite recursion, since in this case the // the recursion is unreachable. #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable:4717) #endif // Invalid() is usable as an expression of type T, but will terminate // the program with an assertion failure if actually run. This is useful // 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 inline T Invalid() { Assert(false, "", -1, "Internal error: attempt to return invalid value"); // This statement is unreachable, and would never terminate even if it // could be reached. It is provided only to placate compiler warnings // about missing return statements. return Invalid(); } #ifdef _MSC_VER # pragma warning(pop) #endif // 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 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 StlContainerView { public: typedef RawContainer type; typedef const type& const_reference; static const_reference ConstReference(const RawContainer& container) { static_assert(!std::is_const::value, "RawContainer type must not be const"); return container; } static type Copy(const RawContainer& container) { return container; } }; // This specialization is used when RawContainer is a native array type. template class StlContainerView { public: typedef typename std::remove_const::type RawElement; typedef internal::NativeArray type; // NativeArray 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]) { static_assert(std::is_same::value, "Element type must not be const"); return type(array, N, RelationToSourceReference()); } static type Copy(const Element (&array)[N]) { return type(array, N, RelationToSourceCopy()); } }; // This specialization is used when RawContainer is a native array // represented as a (pointer, size) tuple. template class StlContainerView< ::std::tuple > { public: typedef typename std::remove_const< typename internal::PointeeOf::type>::type RawElement; typedef internal::NativeArray type; typedef const type const_reference; static const_reference ConstReference( const ::std::tuple& array) { return type(std::get<0>(array), std::get<1>(array), RelationToSourceReference()); } static type Copy(const ::std::tuple& array) { return type(std::get<0>(array), std::get<1>(array), RelationToSourceCopy()); } }; // The following specialization prevents the user from instantiating // StlContainer with a reference type. template class StlContainerView; // 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 struct RemoveConstFromKey { typedef T type; }; // Partially specialized to remove constness from std::pair. template struct RemoveConstFromKey > { typedef std::pair type; }; // Emit an assertion failure due to incorrect DoDefault() usage. Out-of-lined to // reduce code size. GTEST_API_ void IllegalDoDefault(const char* file, int line); template auto ApplyImpl(F&& f, Tuple&& args, IndexSequence) -> decltype( std::forward(f)(std::get(std::forward(args))...)) { return std::forward(f)(std::get(std::forward(args))...); } // Apply the function to a tuple of arguments. template auto Apply(F&& f, Tuple&& args) -> decltype(ApplyImpl(std::forward(f), std::forward(args), MakeIndexSequence::value>())) { return ApplyImpl(std::forward(f), std::forward(args), MakeIndexSequence::value>()); } // Template struct Function, where F must be a function type, contains // the following typedefs: // // Result: the function's return type. // Arg: 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 struct Function; template struct Function { using Result = R; static constexpr size_t ArgumentCount = sizeof...(Args); template using Arg = ElemFromList; using ArgumentTuple = std::tuple; using ArgumentMatcherTuple = std::tuple...>; using MakeResultVoid = void(Args...); using MakeResultIgnoredValue = IgnoredValue(Args...); }; template constexpr size_t Function::ArgumentCount; #ifdef _MSC_VER # pragma warning(pop) #endif } // namespace internal } // namespace testing #endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_