diff options
Diffstat (limited to 'googletest/include/gtest/gtest-printers.h')
-rw-r--r-- | googletest/include/gtest/gtest-printers.h | 258 |
1 files changed, 215 insertions, 43 deletions
diff --git a/googletest/include/gtest/gtest-printers.h b/googletest/include/gtest/gtest-printers.h index 978420e8..59286815 100644 --- a/googletest/include/gtest/gtest-printers.h +++ b/googletest/include/gtest/gtest-printers.h @@ -27,7 +27,6 @@ // (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 Test - The Google C++ Testing and Mocking Framework // // This file implements a universal value printer that can print a @@ -44,6 +43,9 @@ // 1. foo::PrintTo(const T&, ostream*) // 2. operator<<(ostream&, const T&) defined in either foo or the // global namespace. +// * Prefer AbslStringify(..) to operator<<(..), per https://abseil.io/tips/215. +// * Define foo::PrintTo(..) if the type already has AbslStringify(..), but an +// alternative presentation in test results is of interest. // // However if T is an STL-style container then it is printed element-wise // unless foo::PrintTo(const T&, ostream*) is defined. Note that @@ -95,7 +97,9 @@ // being defined as many user-defined container types don't have // value_type. -// GOOGLETEST_CM0001 DO NOT DELETE +// IWYU pragma: private, include "gtest/gtest.h" +// IWYU pragma: friend gtest/.* +// IWYU pragma: friend gmock/.* #ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ #define GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ @@ -107,12 +111,21 @@ #include <string> #include <tuple> #include <type_traits> +#include <typeinfo> #include <utility> #include <vector> +#ifdef GTEST_HAS_ABSL +#include "absl/strings/has_absl_stringify.h" +#include "absl/strings/str_cat.h" +#endif // GTEST_HAS_ABSL #include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-port.h" +#if GTEST_INTERNAL_HAS_STD_SPAN +#include <span> // NOLINT +#endif // GTEST_INTERNAL_HAS_STD_SPAN + namespace testing { // Definitions in the internal* namespaces are subject to change without notice. @@ -122,13 +135,32 @@ namespace internal { template <typename T> void UniversalPrint(const T& value, ::std::ostream* os); +template <typename T> +struct IsStdSpan { + static constexpr bool value = false; +}; + +#if GTEST_INTERNAL_HAS_STD_SPAN +template <typename E> +struct IsStdSpan<std::span<E>> { + static constexpr bool value = true; +}; +#endif // GTEST_INTERNAL_HAS_STD_SPAN + // Used to print an STL-style container when the user doesn't define // a PrintTo() for it. +// +// NOTE: Since std::span does not have const_iterator until C++23, it would +// fail IsContainerTest before C++23. However, IsContainerTest only uses +// the presence of const_iterator to avoid treating iterators as containers +// because of iterator::iterator. Which means std::span satisfies the *intended* +// condition of IsContainerTest. struct ContainerPrinter { template <typename T, typename = typename std::enable_if< - (sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) && - !IsRecursiveContainer<T>::value>::type> + ((sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) && + !IsRecursiveContainer<T>::value) || + IsStdSpan<T>::value>::type> static void PrintValue(const T& container, std::ostream* os) { const size_t kMaxCount = 32; // The maximum number of elements to print. *os << '{'; @@ -176,6 +208,13 @@ struct FunctionPointerPrinter { } }; +// Android local change: There is a non-standard hack in android-base/logging.h +// which emits a warning when a string pointer is printed. Ignore the warning +// in this generic printer. +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wuser-defined-warnings" +#endif struct PointerPrinter { template <typename T> static void PrintValue(T* p, ::std::ostream* os) { @@ -189,6 +228,9 @@ struct PointerPrinter { } } }; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif namespace internal_stream_operator_without_lexical_name_lookup { @@ -204,12 +246,13 @@ struct StreamPrinter { // Don't accept member pointers here. We'd print them via implicit // conversion to bool, which isn't useful. typename = typename std::enable_if< - !std::is_member_pointer<T>::value>::type, - // Only accept types for which we can find a streaming operator via - // ADL (possibly involving implicit conversions). - typename = decltype(std::declval<std::ostream&>() - << std::declval<const T&>())> - static void PrintValue(const T& value, ::std::ostream* os) { + !std::is_member_pointer<T>::value>::type> + // Only accept types for which we can find a streaming operator via + // ADL (possibly involving implicit conversions). + // (Use SFINAE via return type, because it seems GCC < 12 doesn't handle name + // lookup properly when we do it in the template parameter list.) + static auto PrintValue(const T& value, ::std::ostream* os) + -> decltype((void)(*os << value)) { // Call streaming operator found by ADL, possibly with implicit conversions // of the arguments. *os << value; @@ -257,12 +300,21 @@ struct ConvertibleToStringViewPrinter { #endif }; +#ifdef GTEST_HAS_ABSL +struct ConvertibleToAbslStringifyPrinter { + template <typename T, + typename = typename std::enable_if< + absl::HasAbslStringify<T>::value>::type> // NOLINT + static void PrintValue(const T& value, ::std::ostream* os) { + *os << absl::StrCat(value); + } +}; +#endif // GTEST_HAS_ABSL // Prints the given number of bytes in the given object to the given // ostream. GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, - size_t count, - ::std::ostream* os); + size_t count, ::std::ostream* os); struct RawBytesPrinter { // SFINAE on `sizeof` to make sure we have a complete type. template <typename T, size_t = sizeof(T)> @@ -297,8 +349,8 @@ struct FindFirstPrinter< // - Print containers (they have begin/end/etc). // - Print function pointers. // - Print object pointers. -// - Use the stream operator, if available. // - Print protocol buffers. +// - Use the stream operator, if available. // - Print types convertible to BiggestInt. // - Print types convertible to StringView, if available. // - Fallback to printing the raw bytes of the object. @@ -306,9 +358,13 @@ template <typename T> void PrintWithFallback(const T& value, ::std::ostream* os) { using Printer = typename FindFirstPrinter< T, void, ContainerPrinter, FunctionPointerPrinter, PointerPrinter, + ProtobufPrinter, +#ifdef GTEST_HAS_ABSL + ConvertibleToAbslStringifyPrinter, +#endif // GTEST_HAS_ABSL internal_stream_operator_without_lexical_name_lookup::StreamPrinter, - ProtobufPrinter, ConvertibleToIntegerPrinter, - ConvertibleToStringViewPrinter, RawBytesPrinter, FallbackPrinter>::type; + ConvertibleToIntegerPrinter, ConvertibleToStringViewPrinter, + RawBytesPrinter, FallbackPrinter>::type; Printer::PrintValue(value, os); } @@ -360,7 +416,7 @@ GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char); GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char); GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t); GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); -#ifdef __cpp_char8_t +#ifdef __cpp_lib_char8_t GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char8_t); GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char8_t); #endif @@ -375,17 +431,17 @@ GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char32_t); // to point to a NUL-terminated string, and thus can print it as a string. #define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \ - template <> \ - class FormatForComparison<CharType*, OtherStringType> { \ - public: \ - static ::std::string Format(CharType* value) { \ - return ::testing::PrintToString(value); \ - } \ + template <> \ + class FormatForComparison<CharType*, OtherStringType> { \ + public: \ + static ::std::string Format(CharType* value) { \ + return ::testing::PrintToString(value); \ + } \ } GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string); GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string); -#ifdef __cpp_char8_t +#ifdef __cpp_lib_char8_t GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char8_t, ::std::u8string); GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char8_t, ::std::u8string); #endif @@ -410,8 +466,8 @@ GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring); // // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. template <typename T1, typename T2> -std::string FormatForComparisonFailureMessage( - const T1& value, const T2& /* other_operand */) { +std::string FormatForComparisonFailureMessage(const T1& value, + const T2& /* other_operand */) { return FormatForComparison<T1, T2>::Format(value); } @@ -473,12 +529,107 @@ GTEST_API_ void PrintTo(char32_t c, ::std::ostream* os); inline void PrintTo(char16_t c, ::std::ostream* os) { PrintTo(ImplicitCast_<char32_t>(c), os); } -#ifdef __cpp_char8_t +#ifdef __cpp_lib_char8_t inline void PrintTo(char8_t c, ::std::ostream* os) { PrintTo(ImplicitCast_<char32_t>(c), os); } #endif +// gcc/clang __{u,}int128_t +#if defined(__SIZEOF_INT128__) +GTEST_API_ void PrintTo(__uint128_t v, ::std::ostream* os); +GTEST_API_ void PrintTo(__int128_t v, ::std::ostream* os); +#endif // __SIZEOF_INT128__ + +// The default resolution used to print floating-point values uses only +// 6 digits, which can be confusing if a test compares two values whose +// difference lies in the 7th digit. So we'd like to print out numbers +// in full precision. +// However if the value is something simple like 1.1, full will print a +// long string like 1.100000001 due to floating-point numbers not using +// a base of 10. This routiune returns an appropriate resolution for a +// given floating-point number, that is, 6 if it will be accurate, or a +// max_digits10 value (full precision) if it won't, for values between +// 0.0001 and one million. +// It does this by computing what those digits would be (by multiplying +// by an appropriate power of 10), then dividing by that power again to +// see if gets the original value back. +// A similar algorithm applies for values larger than one million; note +// that for those values, we must divide to get a six-digit number, and +// then multiply to possibly get the original value again. +template <typename FloatType> +int AppropriateResolution(FloatType val) { + int full = std::numeric_limits<FloatType>::max_digits10; + if (val < 0) val = -val; + + // Android local change: do not warn about exact float comparison. +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + if (val < 1000000) { + FloatType mulfor6 = 1e10; + if (val >= 100000.0) { // 100,000 to 999,999 + mulfor6 = 1.0; + } else if (val >= 10000.0) { + mulfor6 = 1e1; + } else if (val >= 1000.0) { + mulfor6 = 1e2; + } else if (val >= 100.0) { + mulfor6 = 1e3; + } else if (val >= 10.0) { + mulfor6 = 1e4; + } else if (val >= 1.0) { + mulfor6 = 1e5; + } else if (val >= 0.1) { + mulfor6 = 1e6; + } else if (val >= 0.01) { + mulfor6 = 1e7; + } else if (val >= 0.001) { + mulfor6 = 1e8; + } else if (val >= 0.0001) { + mulfor6 = 1e9; + } + if (static_cast<FloatType>(static_cast<int32_t>(val * mulfor6 + 0.5)) / + mulfor6 == + val) + return 6; + } else if (val < 1e10) { + FloatType divfor6 = 1.0; + if (val >= 1e9) { // 1,000,000,000 to 9,999,999,999 + divfor6 = 10000; + } else if (val >= 1e8) { // 100,000,000 to 999,999,999 + divfor6 = 1000; + } else if (val >= 1e7) { // 10,000,000 to 99,999,999 + divfor6 = 100; + } else if (val >= 1e6) { // 1,000,000 to 9,999,999 + divfor6 = 10; + } + if (static_cast<FloatType>(static_cast<int32_t>(val / divfor6 + 0.5)) * + divfor6 == + val) + return 6; + } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + return full; +} + +inline void PrintTo(float f, ::std::ostream* os) { + auto old_precision = os->precision(); + os->precision(AppropriateResolution(f)); + *os << f; + os->precision(old_precision); +} + +inline void PrintTo(double d, ::std::ostream* os) { + auto old_precision = os->precision(); + os->precision(AppropriateResolution(d)); + *os << d; + os->precision(old_precision); +} + // Overloads for C strings. GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); inline void PrintTo(char* s, ::std::ostream* os) { @@ -499,20 +650,20 @@ inline void PrintTo(const unsigned char* s, ::std::ostream* os) { inline void PrintTo(unsigned char* s, ::std::ostream* os) { PrintTo(ImplicitCast_<const void*>(s), os); } -#ifdef __cpp_char8_t +#ifdef __cpp_lib_char8_t // Overloads for u8 strings. -void PrintTo(const char8_t* s, ::std::ostream* os); +GTEST_API_ void PrintTo(const char8_t* s, ::std::ostream* os); inline void PrintTo(char8_t* s, ::std::ostream* os) { PrintTo(ImplicitCast_<const char8_t*>(s), os); } #endif // Overloads for u16 strings. -void PrintTo(const char16_t* s, ::std::ostream* os); +GTEST_API_ void PrintTo(const char16_t* s, ::std::ostream* os); inline void PrintTo(char16_t* s, ::std::ostream* os) { PrintTo(ImplicitCast_<const char16_t*>(s), os); } // Overloads for u32 strings. -void PrintTo(const char32_t* s, ::std::ostream* os); +GTEST_API_ void PrintTo(const char32_t* s, ::std::ostream* os); inline void PrintTo(char32_t* s, ::std::ostream* os) { PrintTo(ImplicitCast_<const char32_t*>(s), os); } @@ -545,13 +696,13 @@ void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) { } // Overloads for ::std::string. -GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os); +GTEST_API_ void PrintStringTo(const ::std::string& s, ::std::ostream* os); inline void PrintTo(const ::std::string& s, ::std::ostream* os) { PrintStringTo(s, os); } // Overloads for ::std::u8string -#ifdef __cpp_char8_t +#ifdef __cpp_lib_char8_t GTEST_API_ void PrintU8StringTo(const ::std::u8string& s, ::std::ostream* os); inline void PrintTo(const ::std::u8string& s, ::std::ostream* os) { PrintU8StringTo(s, os); @@ -572,7 +723,7 @@ inline void PrintTo(const ::std::u32string& s, ::std::ostream* os) { // Overloads for ::std::wstring. #if GTEST_HAS_STD_WSTRING -GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); +GTEST_API_ void PrintWideStringTo(const ::std::wstring& s, ::std::ostream* os); inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { PrintWideStringTo(s, os); } @@ -587,6 +738,12 @@ inline void PrintTo(internal::StringView sp, ::std::ostream* os) { inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; } +#if GTEST_HAS_RTTI +inline void PrintTo(const std::type_info& info, std::ostream* os) { + *os << internal::GetTypeName(info); +} +#endif // GTEST_HAS_RTTI + template <typename T> void PrintTo(std::reference_wrapper<T> ref, ::std::ostream* os) { UniversalPrinter<T&>::Print(ref.get(), os); @@ -744,6 +901,14 @@ class UniversalPrinter<Optional<T>> { } }; +template <> +class UniversalPrinter<decltype(Nullopt())> { + public: + static void Print(decltype(Nullopt()), ::std::ostream* os) { + *os << "(nullopt)"; + } +}; + #endif // GTEST_INTERNAL_HAS_OPTIONAL #if GTEST_INTERNAL_HAS_VARIANT @@ -755,7 +920,7 @@ class UniversalPrinter<Variant<T...>> { public: static void Print(const Variant<T...>& value, ::std::ostream* os) { *os << '('; -#if GTEST_HAS_ABSL +#ifdef GTEST_HAS_ABSL absl::visit(Visitor{os, value.index()}, value); #else std::visit(Visitor{os, value.index()}, value); @@ -802,10 +967,10 @@ void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { } } // This overload prints a (const) char array compactly. -GTEST_API_ void UniversalPrintArray( - const char* begin, size_t len, ::std::ostream* os); +GTEST_API_ void UniversalPrintArray(const char* begin, size_t len, + ::std::ostream* os); -#ifdef __cpp_char8_t +#ifdef __cpp_lib_char8_t // This overload prints a (const) char8_t array compactly. GTEST_API_ void UniversalPrintArray(const char8_t* begin, size_t len, ::std::ostream* os); @@ -820,8 +985,8 @@ GTEST_API_ void UniversalPrintArray(const char32_t* begin, size_t len, ::std::ostream* os); // This overload prints a (const) wchar_t array compactly. -GTEST_API_ void UniversalPrintArray( - const wchar_t* begin, size_t len, ::std::ostream* os); +GTEST_API_ void UniversalPrintArray(const wchar_t* begin, size_t len, + ::std::ostream* os); // Implements printing an array type T[N]. template <typename T, size_t N> @@ -872,6 +1037,13 @@ class UniversalTersePrinter<T&> { UniversalPrint(value, os); } }; +template <typename T> +class UniversalTersePrinter<std::reference_wrapper<T>> { + public: + static void Print(std::reference_wrapper<T> value, ::std::ostream* os) { + UniversalTersePrinter<T>::Print(value.get(), os); + } +}; template <typename T, size_t N> class UniversalTersePrinter<T[N]> { public: @@ -894,7 +1066,7 @@ template <> class UniversalTersePrinter<char*> : public UniversalTersePrinter<const char*> { }; -#ifdef __cpp_char8_t +#ifdef __cpp_lib_char8_t template <> class UniversalTersePrinter<const char8_t*> { public: @@ -980,10 +1152,10 @@ void UniversalPrint(const T& value, ::std::ostream* os) { UniversalPrinter<T1>::Print(value, os); } -typedef ::std::vector< ::std::string> Strings; +typedef ::std::vector<::std::string> Strings; - // Tersely prints the first N fields of a tuple to a string vector, - // one element for each field. +// Tersely prints the first N fields of a tuple to a string vector, +// one element for each field. template <typename Tuple> void TersePrintPrefixToStrings(const Tuple&, std::integral_constant<size_t, 0>, Strings*) {} |