Allows EXPECT_EQ to accept arguments that don't have operator << (by Zhanyong Wan).
Allows a user to customize how the universal printer prints a pointer of a specific type by overloading << (by Zhanyong Wan). Works around a bug in Cymbian's C++ compiler (by Vlad Losev).
This commit is contained in:
		| @@ -280,12 +280,23 @@ void DefaultPrintTo(IsNotContainer /* dummy */, | |||||||
|   if (p == NULL) { |   if (p == NULL) { | ||||||
|     *os << "NULL"; |     *os << "NULL"; | ||||||
|   } else { |   } else { | ||||||
|     // We want to print p as a const void*.  However, we cannot cast |     // C++ doesn't allow casting from a function pointer to any object | ||||||
|     // it to const void* directly, even using reinterpret_cast, as |     // pointer. | ||||||
|     // earlier versions of gcc (e.g. 3.4.5) cannot compile the cast |     if (ImplicitlyConvertible<T*, const void*>::value) { | ||||||
|     // when p is a function pointer.  Casting to UInt64 first solves |       // T is not a function type.  We just call << to print p, | ||||||
|     // the problem. |       // relying on ADL to pick up user-defined << for their pointer | ||||||
|     *os << reinterpret_cast<const void*>(reinterpret_cast<internal::UInt64>(p)); |       // types, if any. | ||||||
|  |       *os << p; | ||||||
|  |     } else { | ||||||
|  |       // T is a function type, so '*os << p' doesn't do what we want | ||||||
|  |       // (it just prints p as bool).  We want to print p as a const | ||||||
|  |       // void*.  However, we cannot cast it to const void* directly, | ||||||
|  |       // even using reinterpret_cast, as earlier versions of gcc | ||||||
|  |       // (e.g. 3.4.5) cannot compile the cast when p is a function | ||||||
|  |       // pointer.  Casting to UInt64 first solves the problem. | ||||||
|  |       *os << reinterpret_cast<const void*>( | ||||||
|  |           reinterpret_cast<internal::UInt64>(p)); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -341,13 +352,8 @@ void PrintTo(const T& value, ::std::ostream* os) { | |||||||
| // types, strings, plain arrays, and pointers). | // types, strings, plain arrays, and pointers). | ||||||
|  |  | ||||||
| // Overloads for various char types. | // Overloads for various char types. | ||||||
| GTEST_API_ void PrintCharTo(char c, int char_code, ::std::ostream* os); | GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os); | ||||||
| inline void PrintTo(unsigned char c, ::std::ostream* os) { | GTEST_API_ void PrintTo(signed char c, ::std::ostream* os); | ||||||
|   PrintCharTo(c, c, os); |  | ||||||
| } |  | ||||||
| inline void PrintTo(signed char c, ::std::ostream* os) { |  | ||||||
|   PrintCharTo(c, c, os); |  | ||||||
| } |  | ||||||
| inline void PrintTo(char c, ::std::ostream* os) { | inline void PrintTo(char c, ::std::ostream* os) { | ||||||
|   // When printing a plain char, we always treat it as unsigned.  This |   // When printing a plain char, we always treat it as unsigned.  This | ||||||
|   // way, the output won't be affected by whether the compiler thinks |   // way, the output won't be affected by whether the compiler thinks | ||||||
| @@ -375,6 +381,21 @@ inline void PrintTo(char* s, ::std::ostream* os) { | |||||||
|   PrintTo(implicit_cast<const char*>(s), os); |   PrintTo(implicit_cast<const char*>(s), os); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // signed/unsigned char is often used for representing binary data, so | ||||||
|  | // we print pointers to it as void* to be safe. | ||||||
|  | inline void PrintTo(const signed char* s, ::std::ostream* os) { | ||||||
|  |   PrintTo(implicit_cast<const void*>(s), os); | ||||||
|  | } | ||||||
|  | inline void PrintTo(signed char* s, ::std::ostream* os) { | ||||||
|  |   PrintTo(implicit_cast<const void*>(s), os); | ||||||
|  | } | ||||||
|  | inline void PrintTo(const unsigned char* s, ::std::ostream* os) { | ||||||
|  |   PrintTo(implicit_cast<const void*>(s), os); | ||||||
|  | } | ||||||
|  | inline void PrintTo(unsigned char* s, ::std::ostream* os) { | ||||||
|  |   PrintTo(implicit_cast<const void*>(s), os); | ||||||
|  | } | ||||||
|  |  | ||||||
| // MSVC can be configured to define wchar_t as a typedef of unsigned | // MSVC can be configured to define wchar_t as a typedef of unsigned | ||||||
| // short.  It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native | // short.  It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native | ||||||
| // type.  When wchar_t is a typedef, defining an overload for const | // type.  When wchar_t is a typedef, defining an overload for const | ||||||
|   | |||||||
| @@ -1207,30 +1207,6 @@ GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv); | |||||||
|  |  | ||||||
| namespace internal { | namespace internal { | ||||||
|  |  | ||||||
| // These overloaded versions handle ::std::string and ::std::wstring. |  | ||||||
| GTEST_API_ inline String FormatForFailureMessage(const ::std::string& str) { |  | ||||||
|   return (Message() << '"' << str << '"').GetString(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #if GTEST_HAS_STD_WSTRING |  | ||||||
| GTEST_API_ inline String FormatForFailureMessage(const ::std::wstring& wstr) { |  | ||||||
|   return (Message() << "L\"" << wstr << '"').GetString(); |  | ||||||
| } |  | ||||||
| #endif  // GTEST_HAS_STD_WSTRING |  | ||||||
|  |  | ||||||
| // These overloaded versions handle ::string and ::wstring. |  | ||||||
| #if GTEST_HAS_GLOBAL_STRING |  | ||||||
| GTEST_API_ inline String FormatForFailureMessage(const ::string& str) { |  | ||||||
|   return (Message() << '"' << str << '"').GetString(); |  | ||||||
| } |  | ||||||
| #endif  // GTEST_HAS_GLOBAL_STRING |  | ||||||
|  |  | ||||||
| #if GTEST_HAS_GLOBAL_WSTRING |  | ||||||
| GTEST_API_ inline String FormatForFailureMessage(const ::wstring& wstr) { |  | ||||||
|   return (Message() << "L\"" << wstr << '"').GetString(); |  | ||||||
| } |  | ||||||
| #endif  // GTEST_HAS_GLOBAL_WSTRING |  | ||||||
|  |  | ||||||
| // Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc) | // Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc) | ||||||
| // operand to be used in a failure message.  The type (but not value) | // operand to be used in a failure message.  The type (but not value) | ||||||
| // of the other operand may affect the format.  This allows us to | // of the other operand may affect the format.  This allows us to | ||||||
| @@ -1246,7 +1222,7 @@ GTEST_API_ inline String FormatForFailureMessage(const ::wstring& wstr) { | |||||||
| template <typename T1, typename T2> | template <typename T1, typename T2> | ||||||
| String FormatForComparisonFailureMessage(const T1& value, | String FormatForComparisonFailureMessage(const T1& value, | ||||||
|                                          const T2& /* other_operand */) { |                                          const T2& /* other_operand */) { | ||||||
|   return FormatForFailureMessage(value); |   return PrintToString(value); | ||||||
| } | } | ||||||
|  |  | ||||||
| // The helper function for {ASSERT|EXPECT}_EQ. | // The helper function for {ASSERT|EXPECT}_EQ. | ||||||
|   | |||||||
| @@ -102,7 +102,7 @@ namespace proto2 { class Message; } | |||||||
|  |  | ||||||
| namespace testing { | namespace testing { | ||||||
|  |  | ||||||
| // Forward declaration of classes. | // Forward declarations. | ||||||
|  |  | ||||||
| class AssertionResult;                 // Result of an assertion. | class AssertionResult;                 // Result of an assertion. | ||||||
| class Message;                         // Represents a failure message. | class Message;                         // Represents a failure message. | ||||||
| @@ -111,6 +111,9 @@ class TestInfo;                        // Information about a test. | |||||||
| class TestPartResult;                  // Result of a test part. | class TestPartResult;                  // Result of a test part. | ||||||
| class UnitTest;                        // A collection of test cases. | class UnitTest;                        // A collection of test cases. | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | ::std::string PrintToString(const T& value); | ||||||
|  |  | ||||||
| namespace internal { | namespace internal { | ||||||
|  |  | ||||||
| struct TraceInfo;                      // Information about a trace point. | struct TraceInfo;                      // Information about a trace point. | ||||||
| @@ -192,72 +195,23 @@ class GTEST_API_ ScopedTrace { | |||||||
| template <typename T> | template <typename T> | ||||||
| String StreamableToString(const T& streamable); | String StreamableToString(const T& streamable); | ||||||
|  |  | ||||||
| // Formats a value to be used in a failure message. | // When this operand is a const char* or char*, if the other operand | ||||||
|  |  | ||||||
| #ifdef GTEST_NEEDS_IS_POINTER_ |  | ||||||
|  |  | ||||||
| // These are needed as the Nokia Symbian and IBM XL C/C++ compilers |  | ||||||
| // cannot decide between const T& and const T* in a function template. |  | ||||||
| // These compilers _can_ decide between class template specializations |  | ||||||
| // for T and T*, so a tr1::type_traits-like is_pointer works, and we |  | ||||||
| // can overload on that. |  | ||||||
|  |  | ||||||
| // This overload makes sure that all pointers (including |  | ||||||
| // those to char or wchar_t) are printed as raw pointers. |  | ||||||
| template <typename T> |  | ||||||
| inline String FormatValueForFailureMessage(internal::true_type /*dummy*/, |  | ||||||
|                                            T* pointer) { |  | ||||||
|   return StreamableToString(static_cast<const void*>(pointer)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline String FormatValueForFailureMessage(internal::false_type /*dummy*/, |  | ||||||
|                                            const T& value) { |  | ||||||
|   return StreamableToString(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline String FormatForFailureMessage(const T& value) { |  | ||||||
|   return FormatValueForFailureMessage( |  | ||||||
|       typename internal::is_pointer<T>::type(), value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #else |  | ||||||
|  |  | ||||||
| // These are needed as the above solution using is_pointer has the |  | ||||||
| // limitation that T cannot be a type without external linkage, when |  | ||||||
| // compiled using MSVC. |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline String FormatForFailureMessage(const T& value) { |  | ||||||
|   return StreamableToString(value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // This overload makes sure that all pointers (including |  | ||||||
| // those to char or wchar_t) are printed as raw pointers. |  | ||||||
| template <typename T> |  | ||||||
| inline String FormatForFailureMessage(T* pointer) { |  | ||||||
|   return StreamableToString(static_cast<const void*>(pointer)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #endif  // GTEST_NEEDS_IS_POINTER_ |  | ||||||
|  |  | ||||||
| // These overloaded versions handle narrow and wide characters. |  | ||||||
| GTEST_API_ String FormatForFailureMessage(char ch); |  | ||||||
| GTEST_API_ String FormatForFailureMessage(wchar_t wchar); |  | ||||||
|  |  | ||||||
| // When this operand is a const char* or char*, and the other operand |  | ||||||
| // is a ::std::string or ::string, we print this operand as a C string | // is a ::std::string or ::string, we print this operand as a C string | ||||||
| // rather than a pointer.  We do the same for wide strings. | // rather than a pointer (we do the same for wide strings); otherwise | ||||||
|  | // we print it as a pointer to be safe. | ||||||
|  |  | ||||||
| // This internal macro is used to avoid duplicated code. | // This internal macro is used to avoid duplicated code. | ||||||
|  | // Making the first operand const reference works around a bug in the | ||||||
|  | // Symbian compiler which is unable to select the correct specialization of | ||||||
|  | // FormatForComparisonFailureMessage. | ||||||
| #define GTEST_FORMAT_IMPL_(operand2_type, operand1_printer)\ | #define GTEST_FORMAT_IMPL_(operand2_type, operand1_printer)\ | ||||||
| inline String FormatForComparisonFailureMessage(\ | inline String FormatForComparisonFailureMessage(\ | ||||||
|     operand2_type::value_type* str, const operand2_type& /*operand2*/) {\ |     operand2_type::value_type* const& str, const operand2_type& /*operand2*/) {\ | ||||||
|   return operand1_printer(str);\ |   return operand1_printer(str);\ | ||||||
| }\ | }\ | ||||||
| inline String FormatForComparisonFailureMessage(\ | inline String FormatForComparisonFailureMessage(\ | ||||||
|     const operand2_type::value_type* str, const operand2_type& /*operand2*/) {\ |     const operand2_type::value_type* const& str, \ | ||||||
|  |     const operand2_type& /*operand2*/) {\ | ||||||
|   return operand1_printer(str);\ |   return operand1_printer(str);\ | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -275,6 +229,27 @@ GTEST_FORMAT_IMPL_(::wstring, String::ShowWideCStringQuoted) | |||||||
|  |  | ||||||
| #undef GTEST_FORMAT_IMPL_ | #undef GTEST_FORMAT_IMPL_ | ||||||
|  |  | ||||||
|  | // The next four overloads handle the case where the operand being | ||||||
|  | // printed is a char/wchar_t pointer and the other operand is not a | ||||||
|  | // string/wstring object.  In such cases, we just print the operand as | ||||||
|  | // a pointer to be safe. | ||||||
|  | // | ||||||
|  | // Making the first operand const reference works around a bug in the | ||||||
|  | // Symbian compiler which is unable to select the correct specialization of | ||||||
|  | // FormatForComparisonFailureMessage. | ||||||
|  | #define GTEST_FORMAT_CHAR_PTR_IMPL_(CharType)                       \ | ||||||
|  |   template <typename T>                                             \ | ||||||
|  |   String FormatForComparisonFailureMessage(CharType* const& p, const T&) { \ | ||||||
|  |     return PrintToString(static_cast<const void*>(p));              \ | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | GTEST_FORMAT_CHAR_PTR_IMPL_(char) | ||||||
|  | GTEST_FORMAT_CHAR_PTR_IMPL_(const char) | ||||||
|  | GTEST_FORMAT_CHAR_PTR_IMPL_(wchar_t) | ||||||
|  | GTEST_FORMAT_CHAR_PTR_IMPL_(const wchar_t) | ||||||
|  |  | ||||||
|  | #undef GTEST_FORMAT_CHAR_PTR_IMPL_ | ||||||
|  |  | ||||||
| // Constructs and returns the message for an equality assertion | // Constructs and returns the message for an equality assertion | ||||||
| // (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. | // (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. | ||||||
| // | // | ||||||
|   | |||||||
| @@ -123,10 +123,31 @@ void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, | |||||||
|  |  | ||||||
| namespace internal { | namespace internal { | ||||||
|  |  | ||||||
| // Prints a wide char as a char literal without the quotes, escaping it | // Depending on the value of a char (or wchar_t), we print it in one | ||||||
| // when necessary. | // of three formats: | ||||||
| static void PrintAsWideCharLiteralTo(wchar_t c, ostream* os) { | //   - as is if it's a printable ASCII (e.g. 'a', '2', ' '), | ||||||
|   switch (c) { | //   - as a hexidecimal escape sequence (e.g. '\x7F'), or | ||||||
|  | //   - as a special escape sequence (e.g. '\r', '\n'). | ||||||
|  | enum CharFormat { | ||||||
|  |   kAsIs, | ||||||
|  |   kHexEscape, | ||||||
|  |   kSpecialEscape | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Returns true if c is a printable ASCII character.  We test the | ||||||
|  | // value of c directly instead of calling isprint(), which is buggy on | ||||||
|  | // Windows Mobile. | ||||||
|  | static inline bool IsPrintableAscii(wchar_t c) { | ||||||
|  |   return 0x20 <= c && c <= 0x7E; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Prints a wide or narrow char c as a character literal without the | ||||||
|  | // quotes, escaping it when necessary; returns how c was formatted. | ||||||
|  | // The template argument UnsignedChar is the unsigned version of Char, | ||||||
|  | // which is the type of c. | ||||||
|  | template <typename UnsignedChar, typename Char> | ||||||
|  | static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { | ||||||
|  |   switch (static_cast<wchar_t>(c)) { | ||||||
|     case L'\0': |     case L'\0': | ||||||
|       *os << "\\0"; |       *os << "\\0"; | ||||||
|       break; |       break; | ||||||
| @@ -161,19 +182,15 @@ static void PrintAsWideCharLiteralTo(wchar_t c, ostream* os) { | |||||||
|       *os << "\\v"; |       *os << "\\v"; | ||||||
|       break; |       break; | ||||||
|     default: |     default: | ||||||
|       // Checks whether c is printable or not. Printable characters are in |       if (IsPrintableAscii(c)) { | ||||||
|       // the range [0x20,0x7E]. |  | ||||||
|       // We test the value of c directly instead of calling isprint(), as |  | ||||||
|       // isprint() is buggy on Windows mobile. |  | ||||||
|       if (0x20 <= c && c <= 0x7E) { |  | ||||||
|         *os << static_cast<char>(c); |         *os << static_cast<char>(c); | ||||||
|  |         return kAsIs; | ||||||
|       } else { |       } else { | ||||||
|         // Buffer size enough for the maximum number of digits and \0. |         *os << String::Format("\\x%X", static_cast<UnsignedChar>(c)); | ||||||
|         char text[2 * sizeof(unsigned long) + 1] = ""; |         return kHexEscape; | ||||||
|         snprintf(text, sizeof(text), "%lX", static_cast<unsigned long>(c)); |  | ||||||
|         *os << "\\x" << text; |  | ||||||
|       } |       } | ||||||
|   } |   } | ||||||
|  |   return kSpecialEscape; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Prints a char as if it's part of a string literal, escaping it when | // Prints a char as if it's part of a string literal, escaping it when | ||||||
| @@ -187,50 +204,57 @@ static void PrintAsWideStringLiteralTo(wchar_t c, ostream* os) { | |||||||
|       *os << "\\\""; |       *os << "\\\""; | ||||||
|       break; |       break; | ||||||
|     default: |     default: | ||||||
|       PrintAsWideCharLiteralTo(c, os); |       PrintAsCharLiteralTo<wchar_t>(c, os); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| // Prints a char as a char literal without the quotes, escaping it |  | ||||||
| // when necessary. |  | ||||||
| static void PrintAsCharLiteralTo(char c, ostream* os) { |  | ||||||
|   PrintAsWideCharLiteralTo(static_cast<unsigned char>(c), os); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Prints a char as if it's part of a string literal, escaping it when | // Prints a char as if it's part of a string literal, escaping it when | ||||||
| // necessary. | // necessary. | ||||||
| static void PrintAsStringLiteralTo(char c, ostream* os) { | static void PrintAsNarrowStringLiteralTo(char c, ostream* os) { | ||||||
|   PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os); |   PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Prints a char and its code.  The '\0' char is printed as "'\\0'", | // Prints a wide or narrow character c and its code.  '\0' is printed | ||||||
| // other unprintable characters are also properly escaped using the | // as "'\\0'", other unprintable characters are also properly escaped | ||||||
| // standard C++ escape sequence. | // using the standard C++ escape sequence.  The template argument | ||||||
| void PrintCharTo(char c, int char_code, ostream* os) { | // UnsignedChar is the unsigned version of Char, which is the type of c. | ||||||
|  | template <typename UnsignedChar, typename Char> | ||||||
|  | void PrintCharAndCodeTo(Char c, ostream* os) { | ||||||
|  |   // First, print c as a literal in the most readable form we can find. | ||||||
|  |   *os << ((sizeof(c) > 1) ? "L'" : "'"); | ||||||
|  |   const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os); | ||||||
|   *os << "'"; |   *os << "'"; | ||||||
|   PrintAsCharLiteralTo(c, os); |  | ||||||
|   *os << "'"; |   // To aid user debugging, we also print c's code in decimal, unless | ||||||
|   if (c != '\0') |   // it's 0 (in which case c was printed as '\\0', making the code | ||||||
|     *os << " (" << char_code << ")"; |   // obvious). | ||||||
|  |   if (c == 0) | ||||||
|  |     return; | ||||||
|  |   *os << " (" << String::Format("%d", c).c_str(); | ||||||
|  |  | ||||||
|  |   // For more convenience, we print c's code again in hexidecimal, | ||||||
|  |   // unless c was already printed in the form '\x##' or the code is in | ||||||
|  |   // [1, 9]. | ||||||
|  |   if (format == kHexEscape || (1 <= c && c <= 9)) { | ||||||
|  |     // Do nothing. | ||||||
|  |   } else { | ||||||
|  |     *os << String::Format(", 0x%X", | ||||||
|  |                           static_cast<UnsignedChar>(c)).c_str(); | ||||||
|  |   } | ||||||
|  |   *os << ")"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void PrintTo(unsigned char c, ::std::ostream* os) { | ||||||
|  |   PrintCharAndCodeTo<unsigned char>(c, os); | ||||||
|  | } | ||||||
|  | void PrintTo(signed char c, ::std::ostream* os) { | ||||||
|  |   PrintCharAndCodeTo<unsigned char>(c, os); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Prints a wchar_t as a symbol if it is printable or as its internal | // Prints a wchar_t as a symbol if it is printable or as its internal | ||||||
| // code otherwise and also as its decimal code (except for L'\0'). | // code otherwise and also as its code.  L'\0' is printed as "L'\\0'". | ||||||
| // The L'\0' char is printed as "L'\\0'". The decimal code is printed |  | ||||||
| // as signed integer when wchar_t is implemented by the compiler |  | ||||||
| // as a signed type and is printed as an unsigned integer when wchar_t |  | ||||||
| // is implemented as an unsigned type. |  | ||||||
| void PrintTo(wchar_t wc, ostream* os) { | void PrintTo(wchar_t wc, ostream* os) { | ||||||
|   *os << "L'"; |   PrintCharAndCodeTo<wchar_t>(wc, os); | ||||||
|   PrintAsWideCharLiteralTo(wc, os); |  | ||||||
|   *os << "'"; |  | ||||||
|   if (wc != L'\0') { |  | ||||||
|     // Type Int64 is used because it provides more storage than wchar_t thus |  | ||||||
|     // when the compiler converts signed or unsigned implementation of wchar_t |  | ||||||
|     // to Int64 it fills higher bits with either zeros or the sign bit |  | ||||||
|     // passing it to operator <<() as either signed or unsigned integer. |  | ||||||
|     *os << " (" << static_cast<Int64>(wc) << ")"; |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // Prints the given array of characters to the ostream. | // Prints the given array of characters to the ostream. | ||||||
| @@ -239,7 +263,7 @@ void PrintTo(wchar_t wc, ostream* os) { | |||||||
| static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) { | static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) { | ||||||
|   *os << "\""; |   *os << "\""; | ||||||
|   for (size_t index = 0; index < len; ++index) { |   for (size_t index = 0; index < len; ++index) { | ||||||
|     PrintAsStringLiteralTo(begin[index], os); |     PrintAsNarrowStringLiteralTo(begin[index], os); | ||||||
|   } |   } | ||||||
|   *os << "\""; |   *os << "\""; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										42
									
								
								src/gtest.cc
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								src/gtest.cc
									
									
									
									
									
								
							| @@ -918,48 +918,6 @@ Message& Message::operator <<(const ::wstring& wstr) { | |||||||
| } | } | ||||||
| #endif  // GTEST_HAS_GLOBAL_WSTRING | #endif  // GTEST_HAS_GLOBAL_WSTRING | ||||||
|  |  | ||||||
| namespace internal { |  | ||||||
|  |  | ||||||
| // Formats a value to be used in a failure message. |  | ||||||
|  |  | ||||||
| // For a char value, we print it as a C++ char literal and as an |  | ||||||
| // unsigned integer (both in decimal and in hexadecimal). |  | ||||||
| String FormatForFailureMessage(char ch) { |  | ||||||
|   const unsigned int ch_as_uint = ch; |  | ||||||
|   // A String object cannot contain '\0', so we print "\\0" when ch is |  | ||||||
|   // '\0'. |  | ||||||
|   return String::Format("'%s' (%u, 0x%X)", |  | ||||||
|                         ch ? String::Format("%c", ch).c_str() : "\\0", |  | ||||||
|                         ch_as_uint, ch_as_uint); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // For a wchar_t value, we print it as a C++ wchar_t literal and as an |  | ||||||
| // unsigned integer (both in decimal and in hexidecimal). |  | ||||||
| String FormatForFailureMessage(wchar_t wchar) { |  | ||||||
|   // The C++ standard doesn't specify the exact size of the wchar_t |  | ||||||
|   // type.  It just says that it shall have the same size as another |  | ||||||
|   // integral type, called its underlying type. |  | ||||||
|   // |  | ||||||
|   // Therefore, in order to print a wchar_t value in the numeric form, |  | ||||||
|   // we first convert it to the largest integral type (UInt64) and |  | ||||||
|   // then print the converted value. |  | ||||||
|   // |  | ||||||
|   // We use streaming to print the value as "%llu" doesn't work |  | ||||||
|   // correctly with MSVC 7.1. |  | ||||||
|   const UInt64 wchar_as_uint64 = wchar; |  | ||||||
|   Message msg; |  | ||||||
|   // A String object cannot contain '\0', so we print "\\0" when wchar is |  | ||||||
|   // L'\0'. |  | ||||||
|   char buffer[32];  // CodePointToUtf8 requires a buffer that big. |  | ||||||
|   msg << "L'" |  | ||||||
|       << (wchar ? CodePointToUtf8(static_cast<UInt32>(wchar), buffer) : "\\0") |  | ||||||
|       << "' (" << wchar_as_uint64 << ", 0x" << ::std::setbase(16) |  | ||||||
|       << wchar_as_uint64 << ")"; |  | ||||||
|   return msg.GetString(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| }  // namespace internal |  | ||||||
|  |  | ||||||
| // AssertionResult constructors. | // AssertionResult constructors. | ||||||
| // Used in EXPECT_TRUE/FALSE(assertion_result). | // Used in EXPECT_TRUE/FALSE(assertion_result). | ||||||
| AssertionResult::AssertionResult(const AssertionResult& other) | AssertionResult::AssertionResult(const AssertionResult& other) | ||||||
|   | |||||||
| @@ -79,6 +79,10 @@ inline void operator<<(::std::ostream& os, const StreamableInGlobal& /* x */) { | |||||||
|   os << "StreamableInGlobal"; |   os << "StreamableInGlobal"; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void operator<<(::std::ostream& os, const StreamableInGlobal* /* x */) { | ||||||
|  |   os << "StreamableInGlobal*"; | ||||||
|  | } | ||||||
|  |  | ||||||
| namespace foo { | namespace foo { | ||||||
|  |  | ||||||
| // A user-defined unprintable type in a user namespace. | // A user-defined unprintable type in a user namespace. | ||||||
| @@ -100,6 +104,15 @@ void PrintTo(const PrintableViaPrintTo& x, ::std::ostream* os) { | |||||||
|   *os << "PrintableViaPrintTo: " << x.value; |   *os << "PrintableViaPrintTo: " << x.value; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // A type with a user-defined << for printing its pointer. | ||||||
|  | struct PointerPrintable { | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | ::std::ostream& operator<<(::std::ostream& os, | ||||||
|  |                            const PointerPrintable* /* x */) { | ||||||
|  |   return os << "PointerPrintable*"; | ||||||
|  | } | ||||||
|  |  | ||||||
| // A user-defined printable class template in a user-chosen namespace. | // A user-defined printable class template in a user-chosen namespace. | ||||||
| template <typename T> | template <typename T> | ||||||
| class PrintableViaPrintToTemplate { | class PrintableViaPrintToTemplate { | ||||||
| @@ -199,21 +212,21 @@ string PrintByRef(const T& value) { | |||||||
| // char. | // char. | ||||||
| TEST(PrintCharTest, PlainChar) { | TEST(PrintCharTest, PlainChar) { | ||||||
|   EXPECT_EQ("'\\0'", Print('\0')); |   EXPECT_EQ("'\\0'", Print('\0')); | ||||||
|   EXPECT_EQ("'\\'' (39)", Print('\'')); |   EXPECT_EQ("'\\'' (39, 0x27)", Print('\'')); | ||||||
|   EXPECT_EQ("'\"' (34)", Print('"')); |   EXPECT_EQ("'\"' (34, 0x22)", Print('"')); | ||||||
|   EXPECT_EQ("'\\?' (63)", Print('\?')); |   EXPECT_EQ("'\\?' (63, 0x3F)", Print('\?')); | ||||||
|   EXPECT_EQ("'\\\\' (92)", Print('\\')); |   EXPECT_EQ("'\\\\' (92, 0x5C)", Print('\\')); | ||||||
|   EXPECT_EQ("'\\a' (7)", Print('\a')); |   EXPECT_EQ("'\\a' (7)", Print('\a')); | ||||||
|   EXPECT_EQ("'\\b' (8)", Print('\b')); |   EXPECT_EQ("'\\b' (8)", Print('\b')); | ||||||
|   EXPECT_EQ("'\\f' (12)", Print('\f')); |   EXPECT_EQ("'\\f' (12, 0xC)", Print('\f')); | ||||||
|   EXPECT_EQ("'\\n' (10)", Print('\n')); |   EXPECT_EQ("'\\n' (10, 0xA)", Print('\n')); | ||||||
|   EXPECT_EQ("'\\r' (13)", Print('\r')); |   EXPECT_EQ("'\\r' (13, 0xD)", Print('\r')); | ||||||
|   EXPECT_EQ("'\\t' (9)", Print('\t')); |   EXPECT_EQ("'\\t' (9)", Print('\t')); | ||||||
|   EXPECT_EQ("'\\v' (11)", Print('\v')); |   EXPECT_EQ("'\\v' (11, 0xB)", Print('\v')); | ||||||
|   EXPECT_EQ("'\\x7F' (127)", Print('\x7F')); |   EXPECT_EQ("'\\x7F' (127)", Print('\x7F')); | ||||||
|   EXPECT_EQ("'\\xFF' (255)", Print('\xFF')); |   EXPECT_EQ("'\\xFF' (255)", Print('\xFF')); | ||||||
|   EXPECT_EQ("' ' (32)", Print(' ')); |   EXPECT_EQ("' ' (32, 0x20)", Print(' ')); | ||||||
|   EXPECT_EQ("'a' (97)", Print('a')); |   EXPECT_EQ("'a' (97, 0x61)", Print('a')); | ||||||
| } | } | ||||||
|  |  | ||||||
| // signed char. | // signed char. | ||||||
| @@ -226,7 +239,7 @@ TEST(PrintCharTest, SignedChar) { | |||||||
| // unsigned char. | // unsigned char. | ||||||
| TEST(PrintCharTest, UnsignedChar) { | TEST(PrintCharTest, UnsignedChar) { | ||||||
|   EXPECT_EQ("'\\0'", Print(static_cast<unsigned char>('\0'))); |   EXPECT_EQ("'\\0'", Print(static_cast<unsigned char>('\0'))); | ||||||
|   EXPECT_EQ("'b' (98)", |   EXPECT_EQ("'b' (98, 0x62)", | ||||||
|             Print(static_cast<unsigned char>('b'))); |             Print(static_cast<unsigned char>('b'))); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -241,21 +254,21 @@ TEST(PrintBuiltInTypeTest, Bool) { | |||||||
| // wchar_t. | // wchar_t. | ||||||
| TEST(PrintBuiltInTypeTest, Wchar_t) { | TEST(PrintBuiltInTypeTest, Wchar_t) { | ||||||
|   EXPECT_EQ("L'\\0'", Print(L'\0')); |   EXPECT_EQ("L'\\0'", Print(L'\0')); | ||||||
|   EXPECT_EQ("L'\\'' (39)", Print(L'\'')); |   EXPECT_EQ("L'\\'' (39, 0x27)", Print(L'\'')); | ||||||
|   EXPECT_EQ("L'\"' (34)", Print(L'"')); |   EXPECT_EQ("L'\"' (34, 0x22)", Print(L'"')); | ||||||
|   EXPECT_EQ("L'\\?' (63)", Print(L'\?')); |   EXPECT_EQ("L'\\?' (63, 0x3F)", Print(L'\?')); | ||||||
|   EXPECT_EQ("L'\\\\' (92)", Print(L'\\')); |   EXPECT_EQ("L'\\\\' (92, 0x5C)", Print(L'\\')); | ||||||
|   EXPECT_EQ("L'\\a' (7)", Print(L'\a')); |   EXPECT_EQ("L'\\a' (7)", Print(L'\a')); | ||||||
|   EXPECT_EQ("L'\\b' (8)", Print(L'\b')); |   EXPECT_EQ("L'\\b' (8)", Print(L'\b')); | ||||||
|   EXPECT_EQ("L'\\f' (12)", Print(L'\f')); |   EXPECT_EQ("L'\\f' (12, 0xC)", Print(L'\f')); | ||||||
|   EXPECT_EQ("L'\\n' (10)", Print(L'\n')); |   EXPECT_EQ("L'\\n' (10, 0xA)", Print(L'\n')); | ||||||
|   EXPECT_EQ("L'\\r' (13)", Print(L'\r')); |   EXPECT_EQ("L'\\r' (13, 0xD)", Print(L'\r')); | ||||||
|   EXPECT_EQ("L'\\t' (9)", Print(L'\t')); |   EXPECT_EQ("L'\\t' (9)", Print(L'\t')); | ||||||
|   EXPECT_EQ("L'\\v' (11)", Print(L'\v')); |   EXPECT_EQ("L'\\v' (11, 0xB)", Print(L'\v')); | ||||||
|   EXPECT_EQ("L'\\x7F' (127)", Print(L'\x7F')); |   EXPECT_EQ("L'\\x7F' (127)", Print(L'\x7F')); | ||||||
|   EXPECT_EQ("L'\\xFF' (255)", Print(L'\xFF')); |   EXPECT_EQ("L'\\xFF' (255)", Print(L'\xFF')); | ||||||
|   EXPECT_EQ("L' ' (32)", Print(L' ')); |   EXPECT_EQ("L' ' (32, 0x20)", Print(L' ')); | ||||||
|   EXPECT_EQ("L'a' (97)", Print(L'a')); |   EXPECT_EQ("L'a' (97, 0x61)", Print(L'a')); | ||||||
|   EXPECT_EQ("L'\\x576' (1398)", Print(L'\x576')); |   EXPECT_EQ("L'\\x576' (1398)", Print(L'\x576')); | ||||||
|   EXPECT_EQ("L'\\xC74D' (51021)", Print(L'\xC74D')); |   EXPECT_EQ("L'\\xC74D' (51021)", Print(L'\xC74D')); | ||||||
| } | } | ||||||
| @@ -700,7 +713,7 @@ TEST(PrintStlContainerTest, NonEmptyDeque) { | |||||||
| TEST(PrintStlContainerTest, OneElementHashMap) { | TEST(PrintStlContainerTest, OneElementHashMap) { | ||||||
|   hash_map<int, char> map1; |   hash_map<int, char> map1; | ||||||
|   map1[1] = 'a'; |   map1[1] = 'a'; | ||||||
|   EXPECT_EQ("{ (1, 'a' (97)) }", Print(map1)); |   EXPECT_EQ("{ (1, 'a' (97, 0x61)) }", Print(map1)); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(PrintStlContainerTest, HashMultiMap) { | TEST(PrintStlContainerTest, HashMultiMap) { | ||||||
| @@ -848,7 +861,7 @@ TEST(PrintTupleTest, VariousSizes) { | |||||||
|   EXPECT_EQ("(5)", Print(t1)); |   EXPECT_EQ("(5)", Print(t1)); | ||||||
|  |  | ||||||
|   tuple<char, bool> t2('a', true); |   tuple<char, bool> t2('a', true); | ||||||
|   EXPECT_EQ("('a' (97), true)", Print(t2)); |   EXPECT_EQ("('a' (97, 0x61), true)", Print(t2)); | ||||||
|  |  | ||||||
|   tuple<bool, int, int> t3(false, 2, 3); |   tuple<bool, int, int> t3(false, 2, 3); | ||||||
|   EXPECT_EQ("(false, 2, 3)", Print(t3)); |   EXPECT_EQ("(false, 2, 3)", Print(t3)); | ||||||
| @@ -877,7 +890,7 @@ TEST(PrintTupleTest, VariousSizes) { | |||||||
|   tuple<bool, char, short, testing::internal::Int32,  // NOLINT |   tuple<bool, char, short, testing::internal::Int32,  // NOLINT | ||||||
|       testing::internal::Int64, float, double, const char*, void*, string> |       testing::internal::Int64, float, double, const char*, void*, string> | ||||||
|       t10(false, 'a', 3, 4, 5, 1.5F, -2.5, str, NULL, "10"); |       t10(false, 'a', 3, 4, 5, 1.5F, -2.5, str, NULL, "10"); | ||||||
|   EXPECT_EQ("(false, 'a' (97), 3, 4, 5, 1.5, -2.5, " + PrintPointer(str) + |   EXPECT_EQ("(false, 'a' (97, 0x61), 3, 4, 5, 1.5, -2.5, " + PrintPointer(str) + | ||||||
|             " pointing to \"8\", NULL, \"10\")", |             " pointing to \"8\", NULL, \"10\")", | ||||||
|             Print(t10)); |             Print(t10)); | ||||||
| } | } | ||||||
| @@ -885,7 +898,7 @@ TEST(PrintTupleTest, VariousSizes) { | |||||||
| // Nested tuples. | // Nested tuples. | ||||||
| TEST(PrintTupleTest, NestedTuple) { | TEST(PrintTupleTest, NestedTuple) { | ||||||
|   tuple<tuple<int, bool>, char> nested(make_tuple(5, true), 'a'); |   tuple<tuple<int, bool>, char> nested(make_tuple(5, true), 'a'); | ||||||
|   EXPECT_EQ("((5, true), 'a' (97))", Print(nested)); |   EXPECT_EQ("((5, true), 'a' (97, 0x61))", Print(nested)); | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif  // GTEST_HAS_TR1_TUPLE | #endif  // GTEST_HAS_TR1_TUPLE | ||||||
| @@ -926,8 +939,9 @@ TEST(PrintUnpritableTypeTest, BigObject) { | |||||||
|  |  | ||||||
| // Streamable types in the global namespace. | // Streamable types in the global namespace. | ||||||
| TEST(PrintStreamableTypeTest, InGlobalNamespace) { | TEST(PrintStreamableTypeTest, InGlobalNamespace) { | ||||||
|   EXPECT_EQ("StreamableInGlobal", |   StreamableInGlobal x; | ||||||
|             Print(StreamableInGlobal())); |   EXPECT_EQ("StreamableInGlobal", Print(x)); | ||||||
|  |   EXPECT_EQ("StreamableInGlobal*", Print(&x)); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Printable template types in a user namespace. | // Printable template types in a user namespace. | ||||||
| @@ -942,6 +956,13 @@ TEST(PrintPrintableTypeTest, InUserNamespace) { | |||||||
|             Print(::foo::PrintableViaPrintTo())); |             Print(::foo::PrintableViaPrintTo())); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Tests printing a pointer to a user-defined type that has a << | ||||||
|  | // operator for its pointer. | ||||||
|  | TEST(PrintPrintableTypeTest, PointerInUserNamespace) { | ||||||
|  |   ::foo::PointerPrintable x; | ||||||
|  |   EXPECT_EQ("PointerPrintable*", Print(&x)); | ||||||
|  | } | ||||||
|  |  | ||||||
| // Tests printing user-defined class template that have a PrintTo() function. | // Tests printing user-defined class template that have a PrintTo() function. | ||||||
| TEST(PrintPrintableTypeTest, TemplateInUserNamespace) { | TEST(PrintPrintableTypeTest, TemplateInUserNamespace) { | ||||||
|   EXPECT_EQ("PrintableViaPrintToTemplate: 5", |   EXPECT_EQ("PrintableViaPrintToTemplate: 5", | ||||||
| @@ -1046,26 +1067,35 @@ TEST(PrintReferenceTest, HandlesMemberVariablePointer) { | |||||||
|       "@" + PrintPointer(&p) + " " + Print(sizeof(p)) + "-byte object ")); |       "@" + PrintPointer(&p) + " " + Print(sizeof(p)) + "-byte object ")); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Useful for testing PrintToString().  We cannot use EXPECT_EQ() | ||||||
|  | // there as its implementation uses PrintToString().  The caller must | ||||||
|  | // ensure that 'value' has no side effect. | ||||||
|  | #define EXPECT_PRINT_TO_STRING_(value, expected_string)         \ | ||||||
|  |   EXPECT_TRUE(PrintToString(value) == (expected_string))        \ | ||||||
|  |       << " where " #value " prints as " << (PrintToString(value)) | ||||||
|  |  | ||||||
| TEST(PrintToStringTest, WorksForScalar) { | TEST(PrintToStringTest, WorksForScalar) { | ||||||
|   EXPECT_EQ("123", PrintToString(123)); |   EXPECT_PRINT_TO_STRING_(123, "123"); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(PrintToStringTest, WorksForPointerToConstChar) { | TEST(PrintToStringTest, WorksForPointerToConstChar) { | ||||||
|   const char* p = "hello"; |   const char* p = "hello"; | ||||||
|   EXPECT_EQ("\"hello\"", PrintToString(p)); |   EXPECT_PRINT_TO_STRING_(p, "\"hello\""); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(PrintToStringTest, WorksForPointerToNonConstChar) { | TEST(PrintToStringTest, WorksForPointerToNonConstChar) { | ||||||
|   char s[] = "hello"; |   char s[] = "hello"; | ||||||
|   char* p = s; |   char* p = s; | ||||||
|   EXPECT_EQ("\"hello\"", PrintToString(p)); |   EXPECT_PRINT_TO_STRING_(p, "\"hello\""); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(PrintToStringTest, WorksForArray) { | TEST(PrintToStringTest, WorksForArray) { | ||||||
|   int n[3] = { 1, 2, 3 }; |   int n[3] = { 1, 2, 3 }; | ||||||
|   EXPECT_EQ("{ 1, 2, 3 }", PrintToString(n)); |   EXPECT_PRINT_TO_STRING_(n, "{ 1, 2, 3 }"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #undef EXPECT_PRINT_TO_STRING_ | ||||||
|  |  | ||||||
| TEST(UniversalTersePrintTest, WorksForNonReference) { | TEST(UniversalTersePrintTest, WorksForNonReference) { | ||||||
|   ::std::stringstream ss; |   ::std::stringstream ss; | ||||||
|   UniversalTersePrint(123, &ss); |   UniversalTersePrint(123, &ss); | ||||||
| @@ -1144,7 +1174,7 @@ TEST(UniversalTersePrintTupleFieldsToStringsTest, PrintsTwoTuple) { | |||||||
|   Strings result = UniversalTersePrintTupleFieldsToStrings(make_tuple(1, 'a')); |   Strings result = UniversalTersePrintTupleFieldsToStrings(make_tuple(1, 'a')); | ||||||
|   ASSERT_EQ(2u, result.size()); |   ASSERT_EQ(2u, result.size()); | ||||||
|   EXPECT_EQ("1", result[0]); |   EXPECT_EQ("1", result[0]); | ||||||
|   EXPECT_EQ("'a' (97)", result[1]); |   EXPECT_EQ("'a' (97, 0x61)", result[1]); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST(UniversalTersePrintTupleFieldsToStringsTest, PrintsTersely) { | TEST(UniversalTersePrintTupleFieldsToStringsTest, PrintsTersely) { | ||||||
|   | |||||||
| @@ -418,7 +418,7 @@ Expected failure | |||||||
| [0;32m[ RUN      ] [mUnsigned/TypedTestP/0.Failure | [0;32m[ RUN      ] [mUnsigned/TypedTestP/0.Failure | ||||||
| gtest_output_test_.cc:#: Failure | gtest_output_test_.cc:#: Failure | ||||||
| Value of: TypeParam() | Value of: TypeParam() | ||||||
|   Actual: \0 |   Actual: '\0' | ||||||
| Expected: 1U | Expected: 1U | ||||||
| Which is: 1 | Which is: 1 | ||||||
| Expected failure | Expected failure | ||||||
|   | |||||||
| @@ -375,7 +375,7 @@ Expected failure | |||||||
| [       OK ] Unsigned/TypedTestP/0.Success | [       OK ] Unsigned/TypedTestP/0.Success | ||||||
| [ RUN      ] Unsigned/TypedTestP/0.Failure | [ RUN      ] Unsigned/TypedTestP/0.Failure | ||||||
| gtest_output_test_.cc:#: error: Value of: TypeParam() | gtest_output_test_.cc:#: error: Value of: TypeParam() | ||||||
|   Actual: \0 |   Actual: '\0' | ||||||
| Expected: 1U | Expected: 1U | ||||||
| Which is: 1 | Which is: 1 | ||||||
| Expected failure | Expected failure | ||||||
|   | |||||||
| @@ -4652,6 +4652,65 @@ TEST(EqAssertionTest, OtherPointer) { | |||||||
|                        "0x1234"); |                        "0x1234"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // A class that supports binary comparison operators but not streaming. | ||||||
|  | class UnprintableChar { | ||||||
|  |  public: | ||||||
|  |   explicit UnprintableChar(char ch) : char_(ch) {} | ||||||
|  |  | ||||||
|  |   bool operator==(const UnprintableChar& rhs) const { | ||||||
|  |     return char_ == rhs.char_; | ||||||
|  |   } | ||||||
|  |   bool operator!=(const UnprintableChar& rhs) const { | ||||||
|  |     return char_ != rhs.char_; | ||||||
|  |   } | ||||||
|  |   bool operator<(const UnprintableChar& rhs) const { | ||||||
|  |     return char_ < rhs.char_; | ||||||
|  |   } | ||||||
|  |   bool operator<=(const UnprintableChar& rhs) const { | ||||||
|  |     return char_ <= rhs.char_; | ||||||
|  |   } | ||||||
|  |   bool operator>(const UnprintableChar& rhs) const { | ||||||
|  |     return char_ > rhs.char_; | ||||||
|  |   } | ||||||
|  |   bool operator>=(const UnprintableChar& rhs) const { | ||||||
|  |     return char_ >= rhs.char_; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   char char_; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Tests that ASSERT_EQ() and friends don't require the arguments to | ||||||
|  | // be printable. | ||||||
|  | TEST(ComparisonAssertionTest, AcceptsUnprintableArgs) { | ||||||
|  |   const UnprintableChar x('x'), y('y'); | ||||||
|  |   ASSERT_EQ(x, x); | ||||||
|  |   EXPECT_NE(x, y); | ||||||
|  |   ASSERT_LT(x, y); | ||||||
|  |   EXPECT_LE(x, y); | ||||||
|  |   ASSERT_GT(y, x); | ||||||
|  |   EXPECT_GE(x, x); | ||||||
|  |  | ||||||
|  |   EXPECT_NONFATAL_FAILURE(EXPECT_EQ(x, y), "1-byte object <78>"); | ||||||
|  |   EXPECT_NONFATAL_FAILURE(EXPECT_EQ(x, y), "1-byte object <79>"); | ||||||
|  |   EXPECT_NONFATAL_FAILURE(EXPECT_LT(y, y), "1-byte object <79>"); | ||||||
|  |   EXPECT_NONFATAL_FAILURE(EXPECT_GT(x, y), "1-byte object <78>"); | ||||||
|  |   EXPECT_NONFATAL_FAILURE(EXPECT_GT(x, y), "1-byte object <79>"); | ||||||
|  |  | ||||||
|  |   // Code tested by EXPECT_FATAL_FAILURE cannot reference local | ||||||
|  |   // variables, so we have to write UnprintableChar('x') instead of x. | ||||||
|  |   EXPECT_FATAL_FAILURE(ASSERT_NE(UnprintableChar('x'), UnprintableChar('x')), | ||||||
|  |                        "1-byte object <78>"); | ||||||
|  |   EXPECT_FATAL_FAILURE(ASSERT_LE(UnprintableChar('y'), UnprintableChar('x')), | ||||||
|  |                        "1-byte object <78>"); | ||||||
|  |   EXPECT_FATAL_FAILURE(ASSERT_LE(UnprintableChar('y'), UnprintableChar('x')), | ||||||
|  |                        "1-byte object <79>"); | ||||||
|  |   EXPECT_FATAL_FAILURE(ASSERT_GE(UnprintableChar('x'), UnprintableChar('y')), | ||||||
|  |                        "1-byte object <78>"); | ||||||
|  |   EXPECT_FATAL_FAILURE(ASSERT_GE(UnprintableChar('x'), UnprintableChar('y')), | ||||||
|  |                        "1-byte object <79>"); | ||||||
|  | } | ||||||
|  |  | ||||||
| // Tests the FRIEND_TEST macro. | // Tests the FRIEND_TEST macro. | ||||||
|  |  | ||||||
| // This class has a private member we want to test.  We will test it | // This class has a private member we want to test.  We will test it | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 zhanyong.wan
					zhanyong.wan