summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2021-03-20 01:24:27 -0400
committerDerek Mauro <dmauro@google.com>2021-03-22 15:18:50 -0400
commit1a8ecf1813d022cc7914e04564b92decff6161fc (patch)
tree3ff9941b412d6470e3a37ffc102bd166a4100171
parent3ff1e8b98a3d1d3abc24a5bacb7651c9b32faedd (diff)
downloadgoogletest-1a8ecf1813d022cc7914e04564b92decff6161fc.tar.gz
googletest-1a8ecf1813d022cc7914e04564b92decff6161fc.zip
Googletest export
Print std::u8string, std::u16string, and std::u32string as string literals Previously, these types were printed as "{ U+123, U+456, U+789 }". However, printed output in that form is difficult to compare against any literals that might be defined in code. Instead, just treat these types like std::string and std::wstring, escaping non-ASCII characters with a hexadecimal escape sequence. The tests have also been updated to cover the new functionality: as a bonus, the tests now also pass with the MSVC toolchain. Internally, the code has been reorganized to primarily operate in terms of char32_t, under the assumption that char32_t will always be at least as big as wchar_t. While that assumption is currently true, perhaps it won't be in the future... PiperOrigin-RevId: 364033132
-rw-r--r--BUILD.bazel8
-rw-r--r--googletest/cmake/internal_utils.cmake2
-rw-r--r--googletest/include/gtest/gtest-printers.h104
-rw-r--r--googletest/include/gtest/internal/gtest-port.h13
-rw-r--r--googletest/src/gtest-printers.cc187
-rw-r--r--googletest/test/BUILD.bazel4
-rw-r--r--googletest/test/googletest-printers-test.cc257
7 files changed, 394 insertions, 181 deletions
diff --git a/BUILD.bazel b/BUILD.bazel
index 35986610..965c518d 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -44,6 +44,14 @@ config_setting(
)
config_setting(
+ name = "msvc_compiler",
+ flag_values = {
+ "@bazel_tools//tools/cpp:compiler": "msvc-cl",
+ },
+ visibility = [":__subpackages__"],
+)
+
+config_setting(
name = "has_absl",
values = {"define": "absl=1"},
)
diff --git a/googletest/cmake/internal_utils.cmake b/googletest/cmake/internal_utils.cmake
index aadbab47..dc2b685c 100644
--- a/googletest/cmake/internal_utils.cmake
+++ b/googletest/cmake/internal_utils.cmake
@@ -81,6 +81,8 @@ macro(config_compiler_and_linker)
# Suppress "unreachable code" warning
# http://stackoverflow.com/questions/3232669 explains the issue.
set(cxx_base_flags "${cxx_base_flags} -wd4702")
+ # Ensure MSVC treats source files as UTF-8 encoded.
+ set(cxx_base_flags "${cxx_base_flags} -utf-8")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(cxx_base_flags "-Wall -Wshadow -Werror -Wconversion")
set(cxx_exception_flags "-fexceptions")
diff --git a/googletest/include/gtest/gtest-printers.h b/googletest/include/gtest/gtest-printers.h
index a7e0a3c9..46fe8950 100644
--- a/googletest/include/gtest/gtest-printers.h
+++ b/googletest/include/gtest/gtest-printers.h
@@ -505,24 +505,21 @@ inline void PrintTo(unsigned char* s, ::std::ostream* os) {
PrintTo(ImplicitCast_<const void*>(s), os);
}
#ifdef __cpp_char8_t
-inline void PrintTo(const char8_t* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
-}
+// Overloads for u8 strings.
+void PrintTo(const char8_t* s, ::std::ostream* os);
inline void PrintTo(char8_t* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
+ PrintTo(ImplicitCast_<const char8_t*>(s), os);
}
#endif
-inline void PrintTo(const char16_t* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
-}
+// Overloads for u16 strings.
+void PrintTo(const char16_t* s, ::std::ostream* os);
inline void PrintTo(char16_t* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
-}
-inline void PrintTo(const char32_t* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
+ PrintTo(ImplicitCast_<const char16_t*>(s), os);
}
+// Overloads for u32 strings.
+void PrintTo(const char32_t* s, ::std::ostream* os);
inline void PrintTo(char32_t* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
+ PrintTo(ImplicitCast_<const char32_t*>(s), os);
}
// MSVC can be configured to define wchar_t as a typedef of unsigned
@@ -558,6 +555,26 @@ inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
PrintStringTo(s, os);
}
+// Overloads for ::std::u8string
+#ifdef __cpp_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);
+}
+#endif
+
+// Overloads for ::std::u16string
+GTEST_API_ void PrintU16StringTo(const ::std::u16string& s, ::std::ostream* os);
+inline void PrintTo(const ::std::u16string& s, ::std::ostream* os) {
+ PrintU16StringTo(s, os);
+}
+
+// Overloads for ::std::u32string
+GTEST_API_ void PrintU32StringTo(const ::std::u32string& s, ::std::ostream* os);
+inline void PrintTo(const ::std::u32string& s, ::std::ostream* os) {
+ PrintU32StringTo(s, os);
+}
+
// Overloads for ::std::wstring.
#if GTEST_HAS_STD_WSTRING
GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
@@ -805,6 +822,20 @@ void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
GTEST_API_ void UniversalPrintArray(
const char* begin, size_t len, ::std::ostream* os);
+#ifdef __cpp_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);
+#endif
+
+// This overload prints a (const) char16_t array compactly.
+GTEST_API_ void UniversalPrintArray(const char16_t* begin, size_t len,
+ ::std::ostream* os);
+
+// This overload prints a (const) char32_t array compactly.
+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);
@@ -877,12 +908,55 @@ class UniversalTersePrinter<const char*> {
}
};
template <>
-class UniversalTersePrinter<char*> {
+class UniversalTersePrinter<char*> : public UniversalTersePrinter<const char*> {
+};
+
+#ifdef __cpp_char8_t
+template <>
+class UniversalTersePrinter<const char8_t*> {
+ public:
+ static void Print(const char8_t* str, ::std::ostream* os) {
+ if (str == nullptr) {
+ *os << "NULL";
+ } else {
+ UniversalPrint(::std::u8string(str), os);
+ }
+ }
+};
+template <>
+class UniversalTersePrinter<char8_t*>
+ : public UniversalTersePrinter<const char8_t*> {};
+#endif
+
+template <>
+class UniversalTersePrinter<const char16_t*> {
+ public:
+ static void Print(const char16_t* str, ::std::ostream* os) {
+ if (str == nullptr) {
+ *os << "NULL";
+ } else {
+ UniversalPrint(::std::u16string(str), os);
+ }
+ }
+};
+template <>
+class UniversalTersePrinter<char16_t*>
+ : public UniversalTersePrinter<const char16_t*> {};
+
+template <>
+class UniversalTersePrinter<const char32_t*> {
public:
- static void Print(char* str, ::std::ostream* os) {
- UniversalTersePrinter<const char*>::Print(str, os);
+ static void Print(const char32_t* str, ::std::ostream* os) {
+ if (str == nullptr) {
+ *os << "NULL";
+ } else {
+ UniversalPrint(::std::u32string(str), os);
+ }
}
};
+template <>
+class UniversalTersePrinter<char32_t*>
+ : public UniversalTersePrinter<const char32_t*> {};
#if GTEST_HAS_STD_WSTRING
template <>
diff --git a/googletest/include/gtest/internal/gtest-port.h b/googletest/include/gtest/internal/gtest-port.h
index f3b1c8c8..1c0deddd 100644
--- a/googletest/include/gtest/internal/gtest-port.h
+++ b/googletest/include/gtest/internal/gtest-port.h
@@ -1936,6 +1936,19 @@ inline bool IsUpper(char ch) {
inline bool IsXDigit(char ch) {
return isxdigit(static_cast<unsigned char>(ch)) != 0;
}
+#ifdef __cpp_char8_t
+inline bool IsXDigit(char8_t ch) {
+ return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+#endif
+inline bool IsXDigit(char16_t ch) {
+ const unsigned char low_byte = static_cast<unsigned char>(ch);
+ return ch == low_byte && isxdigit(low_byte) != 0;
+}
+inline bool IsXDigit(char32_t ch) {
+ const unsigned char low_byte = static_cast<unsigned char>(ch);
+ return ch == low_byte && isxdigit(low_byte) != 0;
+}
inline bool IsXDigit(wchar_t ch) {
const unsigned char low_byte = static_cast<unsigned char>(ch);
return ch == low_byte && isxdigit(low_byte) != 0;
diff --git a/googletest/src/gtest-printers.cc b/googletest/src/gtest-printers.cc
index 20ce1b86..1b68fcb5 100644
--- a/googletest/src/gtest-printers.cc
+++ b/googletest/src/gtest-printers.cc
@@ -42,12 +42,16 @@
// defines Foo.
#include "gtest/gtest-printers.h"
+
#include <stdio.h>
+
#include <cctype>
#include <cstdint>
#include <cwchar>
#include <ostream> // NOLINT
#include <string>
+#include <type_traits>
+
#include "gtest/internal/gtest-port.h"
#include "src/gtest-internal-inl.h"
@@ -103,6 +107,16 @@ void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
*os << ">";
}
+// Helpers for widening a character to char32_t. Since the standard does not
+// specify if char / wchar_t is signed or unsigned, it is important to first
+// convert it to the unsigned type of the same width before widening it to
+// char32_t.
+template <typename CharType>
+char32_t ToChar32(CharType in) {
+ return static_cast<char32_t>(
+ static_cast<typename std::make_unsigned<CharType>::type>(in));
+}
+
} // namespace
namespace internal {
@@ -131,18 +145,15 @@ enum CharFormat {
// 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.
-inline bool IsPrintableAscii(wchar_t c) {
- return 0x20 <= c && c <= 0x7E;
-}
+inline bool IsPrintableAscii(char32_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>
+// Prints c (of type char, char8_t, char16_t, char32_t, or wchar_t) as a
+// character literal without the quotes, escaping it when necessary; returns how
+// c was formatted.
+template <typename Char>
static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
- wchar_t w_c = static_cast<wchar_t>(c);
- switch (w_c) {
+ const char32_t u_c = ToChar32(c);
+ switch (u_c) {
case L'\0':
*os << "\\0";
break;
@@ -174,13 +185,12 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
*os << "\\v";
break;
default:
- if (IsPrintableAscii(w_c)) {
+ if (IsPrintableAscii(u_c)) {
*os << static_cast<char>(c);
return kAsIs;
} else {
ostream::fmtflags flags = os->flags();
- *os << "\\x" << std::hex << std::uppercase
- << static_cast<int>(static_cast<UnsignedChar>(c));
+ *os << "\\x" << std::hex << std::uppercase << static_cast<int>(u_c);
os->flags(flags);
return kHexEscape;
}
@@ -188,9 +198,9 @@ static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
return kSpecialEscape;
}
-// Prints a wchar_t c as if it's part of a string literal, escaping it when
+// Prints a char32_t c as if it's part of a string literal, escaping it when
// necessary; returns how c was formatted.
-static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
+static CharFormat PrintAsStringLiteralTo(char32_t c, ostream* os) {
switch (c) {
case L'\'':
*os << "'";
@@ -199,26 +209,68 @@ static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
*os << "\\\"";
return kSpecialEscape;
default:
- return PrintAsCharLiteralTo<wchar_t>(c, os);
+ return PrintAsCharLiteralTo(c, os);
}
}
+static const char* GetCharWidthPrefix(char) {
+ return "";
+}
+
+static const char* GetCharWidthPrefix(signed char) {
+ return "";
+}
+
+static const char* GetCharWidthPrefix(unsigned char) {
+ return "";
+}
+
+#ifdef __cpp_char8_t
+static const char* GetCharWidthPrefix(char8_t) {
+ return "u8";
+}
+#endif
+
+static const char* GetCharWidthPrefix(char16_t) {
+ return "u";
+}
+
+static const char* GetCharWidthPrefix(char32_t) {
+ return "U";
+}
+
+static const char* GetCharWidthPrefix(wchar_t) {
+ return "L";
+}
+
// Prints a char c as if it's part of a string literal, escaping it when
// necessary; returns how c was formatted.
static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
- return PrintAsStringLiteralTo(
- static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
+ return PrintAsStringLiteralTo(ToChar32(c), os);
+}
+
+#ifdef __cpp_char8_t
+static CharFormat PrintAsStringLiteralTo(char8_t c, ostream* os) {
+ return PrintAsStringLiteralTo(ToChar32(c), os);
+}
+#endif
+
+static CharFormat PrintAsStringLiteralTo(char16_t c, ostream* os) {
+ return PrintAsStringLiteralTo(ToChar32(c), os);
}
-// Prints a wide or narrow character c and its code. '\0' is printed
-// as "'\\0'", other unprintable characters are also properly escaped
-// using the standard C++ escape sequence. The template argument
-// UnsignedChar is the unsigned version of Char, which is the type of c.
-template <typename UnsignedChar, typename Char>
+static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
+ return PrintAsStringLiteralTo(ToChar32(c), os);
+}
+
+// Prints a character c (of type char, char8_t, char16_t, char32_t, or wchar_t)
+// and its code. '\0' is printed as "'\\0'", other unprintable characters are
+// also properly escaped using the standard C++ escape sequence.
+template <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 << GetCharWidthPrefix(c) << "'";
+ const CharFormat format = PrintAsCharLiteralTo(c, os);
*os << "'";
// To aid user debugging, we also print c's code in decimal, unless
@@ -239,26 +291,21 @@ void PrintCharAndCodeTo(Char c, ostream* os) {
*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);
-}
+void PrintTo(unsigned char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
+void PrintTo(signed char c, ::std::ostream* os) { PrintCharAndCodeTo(c, os); }
// Prints a wchar_t as a symbol if it is printable or as its internal
// code otherwise and also as its code. L'\0' is printed as "L'\\0'".
-void PrintTo(wchar_t wc, ostream* os) {
- PrintCharAndCodeTo<wchar_t>(wc, os);
-}
+void PrintTo(wchar_t wc, ostream* os) { PrintCharAndCodeTo(wc, os); }
+// TODO(dcheng): Consider making this delegate to PrintCharAndCodeTo() as well.
void PrintTo(char32_t c, ::std::ostream* os) {
*os << std::hex << "U+" << std::uppercase << std::setfill('0') << std::setw(4)
<< static_cast<uint32_t>(c);
}
// Prints the given array of characters to the ostream. CharType must be either
-// char or wchar_t.
+// char, char8_t, char16_t, char32_t, or wchar_t.
// The array starts at begin, the length is len, it may include '\0' characters
// and may not be NUL-terminated.
template <typename CharType>
@@ -268,8 +315,8 @@ GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
static CharFormat PrintCharsAsStringTo(
const CharType* begin, size_t len, ostream* os) {
- const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
- *os << kQuoteBegin;
+ const char* const quote_prefix = GetCharWidthPrefix(*begin);
+ *os << quote_prefix << "\"";
bool is_previous_hex = false;
CharFormat print_format = kAsIs;
for (size_t index = 0; index < len; ++index) {
@@ -278,7 +325,7 @@ static CharFormat PrintCharsAsStringTo(
// Previous character is of '\x..' form and this character can be
// interpreted as another hexadecimal digit in its number. Break string to
// disambiguate.
- *os << "\" " << kQuoteBegin;
+ *os << "\" " << quote_prefix << "\"";
}
is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
// Remember if any characters required hex escaping.
@@ -324,22 +371,57 @@ void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
UniversalPrintCharArray(begin, len, os);
}
+#ifdef __cpp_char8_t
+// Prints a (const) char8_t array of 'len' elements, starting at address
+// 'begin'.
+void UniversalPrintArray(const char8_t* begin, size_t len, ostream* os) {
+ UniversalPrintCharArray(begin, len, os);
+}
+#endif
+
+// Prints a (const) char16_t array of 'len' elements, starting at address
+// 'begin'.
+void UniversalPrintArray(const char16_t* begin, size_t len, ostream* os) {
+ UniversalPrintCharArray(begin, len, os);
+}
+
+// Prints a (const) char32_t array of 'len' elements, starting at address
+// 'begin'.
+void UniversalPrintArray(const char32_t* begin, size_t len, ostream* os) {
+ UniversalPrintCharArray(begin, len, os);
+}
+
// Prints a (const) wchar_t array of 'len' elements, starting at address
// 'begin'.
void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
UniversalPrintCharArray(begin, len, os);
}
-// Prints the given C string to the ostream.
-void PrintTo(const char* s, ostream* os) {
+namespace {
+
+// Prints a null-terminated C-style string to the ostream.
+template <typename Char>
+void PrintCStringTo(const Char* s, ostream* os) {
if (s == nullptr) {
*os << "NULL";
} else {
*os << ImplicitCast_<const void*>(s) << " pointing to ";
- PrintCharsAsStringTo(s, strlen(s), os);
+ PrintCharsAsStringTo(s, std::char_traits<Char>::length(s), os);
}
}
+} // anonymous namespace
+
+void PrintTo(const char* s, ostream* os) { PrintCStringTo(s, os); }
+
+#ifdef __cpp_char8_t
+void PrintTo(const char8_t* s, ostream* os) { PrintCStringTo(s, os); }
+#endif
+
+void PrintTo(const char16_t* s, ostream* os) { PrintCStringTo(s, os); }
+
+void PrintTo(const char32_t* s, ostream* os) { PrintCStringTo(s, os); }
+
// MSVC compiler can be configured to define whar_t as a typedef
// of unsigned short. Defining an overload for const wchar_t* in that case
// would cause pointers to unsigned shorts be printed as wide strings,
@@ -348,14 +430,7 @@ void PrintTo(const char* s, ostream* os) {
// wchar_t is implemented as a native type.
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
// Prints the given wide C string to the ostream.
-void PrintTo(const wchar_t* s, ostream* os) {
- if (s == nullptr) {
- *os << "NULL";
- } else {
- *os << ImplicitCast_<const void*>(s) << " pointing to ";
- PrintCharsAsStringTo(s, wcslen(s), os);
- }
-}
+void PrintTo(const wchar_t* s, ostream* os) { PrintCStringTo(s, os); }
#endif // wchar_t is native
namespace {
@@ -433,6 +508,20 @@ void PrintStringTo(const ::std::string& s, ostream* os) {
}
}
+#ifdef __cpp_char8_t
+void PrintU8StringTo(const ::std::u8string& s, ostream* os) {
+ PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif
+
+void PrintU16StringTo(const ::std::u16string& s, ostream* os) {
+ PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
+void PrintU32StringTo(const ::std::u32string& s, ostream* os) {
+ PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
#if GTEST_HAS_STD_WSTRING
void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
PrintCharsAsStringTo(s.data(), s.size(), os);
diff --git a/googletest/test/BUILD.bazel b/googletest/test/BUILD.bazel
index 8f24988a..e79b875c 100644
--- a/googletest/test/BUILD.bazel
+++ b/googletest/test/BUILD.bazel
@@ -83,6 +83,10 @@ cc_test(
copts = select({
"//:windows": ["-DGTEST_USE_OWN_TR1_TUPLE=0"],
"//conditions:default": ["-DGTEST_USE_OWN_TR1_TUPLE=1"],
+ }) + select({
+ # Ensure MSVC treats source files as UTF-8 encoded.
+ "//:msvc_compiler": ["-utf-8"],
+ "//conditions:default": [],
}),
includes = [
"googletest",
diff --git a/googletest/test/googletest-printers-test.cc b/googletest/test/googletest-printers-test.cc
index f037480b..04635e58 100644
--- a/googletest/test/googletest-printers-test.cc
+++ b/googletest/test/googletest-printers-test.cc
@@ -493,6 +493,92 @@ TEST(PrintCStringTest, EscapesProperly) {
Print(p));
}
+#ifdef __cpp_char8_t
+// const char8_t*.
+TEST(PrintU8StringTest, Const) {
+ const char8_t* p = u8"界";
+ EXPECT_EQ(PrintPointer(p) + " pointing to u8\"\\xE7\\x95\\x8C\"", Print(p));
+}
+
+// char8_t*.
+TEST(PrintU8StringTest, NonConst) {
+ char8_t p[] = u8"世";
+ EXPECT_EQ(PrintPointer(p) + " pointing to u8\"\\xE4\\xB8\\x96\"",
+ Print(static_cast<char8_t*>(p)));
+}
+
+// NULL u8 string.
+TEST(PrintU8StringTest, Null) {
+ const char8_t* p = nullptr;
+ EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests that u8 strings are escaped properly.
+TEST(PrintU8StringTest, EscapesProperly) {
+ const char8_t* p = u8"'\"?\\\a\b\f\n\r\t\v\x7F\xFF hello 世界";
+ EXPECT_EQ(PrintPointer(p) +
+ " pointing to u8\"'\\\"?\\\\\\a\\b\\f\\n\\r\\t\\v\\x7F\\xFF "
+ "hello \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"",
+ Print(p));
+}
+#endif
+
+// const char16_t*.
+TEST(PrintU16StringTest, Const) {
+ const char16_t* p = u"界";
+ EXPECT_EQ(PrintPointer(p) + " pointing to u\"\\x754C\"", Print(p));
+}
+
+// char16_t*.
+TEST(PrintU16StringTest, NonConst) {
+ char16_t p[] = u"世";
+ EXPECT_EQ(PrintPointer(p) + " pointing to u\"\\x4E16\"",
+ Print(static_cast<char16_t*>(p)));
+}
+
+// NULL u16 string.
+TEST(PrintU16StringTest, Null) {
+ const char16_t* p = nullptr;
+ EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests that u16 strings are escaped properly.
+TEST(PrintU16StringTest, EscapesProperly) {
+ const char16_t* p = u"'\"?\\\a\b\f\n\r\t\v\x7F\xFF hello 世界";
+ EXPECT_EQ(PrintPointer(p) +
+ " pointing to u\"'\\\"?\\\\\\a\\b\\f\\n\\r\\t\\v\\x7F\\xFF "
+ "hello \\x4E16\\x754C\"",
+ Print(p));
+}
+
+// const char32_t*.
+TEST(PrintU32StringTest, Const) {
+ const char32_t* p = U"🗺️";
+ EXPECT_EQ(PrintPointer(p) + " pointing to U\"\\x1F5FA\\xFE0F\"", Print(p));
+}
+
+// char32_t*.
+TEST(PrintU32StringTest, NonConst) {
+ char32_t p[] = U"🌌";
+ EXPECT_EQ(PrintPointer(p) + " pointing to U\"\\x1F30C\"",
+ Print(static_cast<char32_t*>(p)));
+}
+
+// NULL u32 string.
+TEST(PrintU32StringTest, Null) {
+ const char32_t* p = nullptr;
+ EXPECT_EQ("NULL", Print(p));
+}
+
+// Tests that u32 strings are escaped properly.
+TEST(PrintU32StringTest, EscapesProperly) {
+ const char32_t* p = U"'\"?\\\a\b\f\n\r\t\v\x7F\xFF hello 🗺️";
+ EXPECT_EQ(PrintPointer(p) +
+ " pointing to U\"'\\\"?\\\\\\a\\b\\f\\n\\r\\t\\v\\x7F\\xFF "
+ "hello \\x1F5FA\\xFE0F\"",
+ Print(p));
+}
+
// MSVC compiler can be configured to define whar_t as a typedef
// of unsigned short. Defining an overload for const wchar_t* in that case
// would cause pointers to unsigned shorts be printed as wide strings,
@@ -564,56 +650,6 @@ TEST(PrintCharPointerTest, ConstUnsignedChar) {
EXPECT_EQ("NULL", Print(p));
}
-#ifdef __cpp_char8_t
-// char8_t*
-TEST(PrintCharPointerTest, Char8) {
- char8_t* p = reinterpret_cast<char8_t*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// const char8_t*
-TEST(PrintCharPointerTest, ConstChar8) {
- const char8_t* p = reinterpret_cast<const char8_t*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-#endif
-
-// char16_t*
-TEST(PrintCharPointerTest, Char16) {
- char16_t* p = reinterpret_cast<char16_t*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// const char16_t*
-TEST(PrintCharPointerTest, ConstChar16) {
- const char16_t* p = reinterpret_cast<const char16_t*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// char32_t*
-TEST(PrintCharPointerTest, Char32) {
- char32_t* p = reinterpret_cast<char32_t*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// const char32_t*
-TEST(PrintCharPointerTest, ConstChar32) {
- const char32_t* p = reinterpret_cast<const char32_t*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
// Tests printing pointers to simple, built-in types.
// bool*.
@@ -753,62 +789,68 @@ TEST(PrintArrayTest, CharArrayWithNoTerminatingNul) {
EXPECT_EQ("\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a));
}
-// const char array with terminating NUL.
-TEST(PrintArrayTest, ConstCharArrayWithTerminatingNul) {
+// char array with terminating NUL.
+TEST(PrintArrayTest, CharArrayWithTerminatingNul) {
const char a[] = "\0Hi";
EXPECT_EQ("\"\\0Hi\"", PrintArrayHelper(a));
}
-// const wchar_t array without terminating NUL.
-TEST(PrintArrayTest, WCharArrayWithNoTerminatingNul) {
+#ifdef __cpp_char8_t
+// char_t array without terminating NUL.
+TEST(PrintArrayTest, Char8ArrayWithNoTerminatingNul) {
// Array a contains '\0' in the middle and doesn't end with '\0'.
- const wchar_t a[] = { L'H', L'\0', L'i' };
- EXPECT_EQ("L\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a));
+ const char8_t a[] = {u8'H', u8'\0', u8'i'};
+ EXPECT_EQ("u8\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a));
}
-// wchar_t array with terminating NUL.
-TEST(PrintArrayTest, WConstCharArrayWithTerminatingNul) {
- const wchar_t a[] = L"\0Hi";
- EXPECT_EQ("L\"\\0Hi\"", PrintArrayHelper(a));
-}
-
-#ifdef __cpp_char8_t
-// char8_t array.
-TEST(PrintArrayTest, Char8Array) {
- const char8_t a[] = u8"Hello, world!";
+// char8_t array with terminating NUL.
+TEST(PrintArrayTest, Char8ArrayWithTerminatingNul) {
+ const char8_t a[] = u8"\0世界";
EXPECT_EQ(
- "{ U+0048, U+0065, U+006C, U+006C, U+006F, U+002C, U+0020, U+0077, "
- "U+006F, U+0072, U+006C, U+0064, U+0021, U+0000 }",
+ "u8\"\\0\\xE4\\xB8\\x96\\xE7\\x95\\x8C\"",
PrintArrayHelper(a));
}
#endif
-// char16_t array.
-#ifdef _MSC_VER
-// TODO(b/173029407): Figure out why this doesn't work under MSVC.
-TEST(PrintArrayTest, DISABLED_Char16Array) {
-#else
-TEST(PrintArrayTest, Char16Array) {
-#endif
- const char16_t a[] = u"Hello, 世界";
- EXPECT_EQ(
- "{ U+0048, U+0065, U+006C, U+006C, U+006F, U+002C, U+0020, U+4E16, "
- "U+754C, U+0000 }",
- PrintArrayHelper(a));
+// const char16_t array without terminating NUL.
+TEST(PrintArrayTest, Char16ArrayWithNoTerminatingNul) {
+ // Array a contains '\0' in the middle and doesn't end with '\0'.
+ const char16_t a[] = {u'こ', u'\0', u'ん', u'に', u'ち', u'は'};
+ EXPECT_EQ("u\"\\x3053\\0\\x3093\\x306B\\x3061\\x306F\" (no terminating NUL)",
+ PrintArrayHelper(a));
}
-// char32_t array.
-#ifdef _MSC_VER
-// TODO(b/173029407): Figure out why this doesn't work under MSVC.
-TEST(PrintArrayTest, DISABLED_Char32Array) {
-#else
-TEST(PrintArrayTest, Char32Array) {
-#endif
- const char32_t a[] = U"Hello, 世界";
- EXPECT_EQ(
- "{ U+0048, U+0065, U+006C, U+006C, U+006F, U+002C, U+0020, U+4E16, "
- "U+754C, U+0000 }",
- PrintArrayHelper(a));
+// char16_t array with terminating NUL.
+TEST(PrintArrayTest, Char16ArrayWithTerminatingNul) {
+ const char16_t a[] = u"\0こんにちは";
+ EXPECT_EQ("u\"\\0\\x3053\\x3093\\x306B\\x3061\\x306F\"", PrintArrayHelper(a));
+}
+
+// char32_t array without terminating NUL.
+TEST(PrintArrayTest, Char32ArrayWithNoTerminatingNul) {
+ // Array a contains '\0' in the middle and doesn't end with '\0'.
+ const char32_t a[] = {U'👋', U'\0', U'🌌'};
+ EXPECT_EQ("U\"\\x1F44B\\0\\x1F30C\" (no terminating NUL)",
+ PrintArrayHelper(a));
+}
+
+// char32_t array with terminating NUL.
+TEST(PrintArrayTest, Char32ArrayWithTerminatingNul) {
+ const char32_t a[] = U"\0👋🌌";
+ EXPECT_EQ("U\"\\0\\x1F44B\\x1F30C\"", PrintArrayHelper(a));
+}
+
+// wchar_t array without terminating NUL.
+TEST(PrintArrayTest, WCharArrayWithNoTerminatingNul) {
+ // Array a contains '\0' in the middle and doesn't end with '\0'.
+ const wchar_t a[] = {L'H', L'\0', L'i'};
+ EXPECT_EQ("L\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a));
+}
+
+// wchar_t array with terminating NUL.
+TEST(PrintArrayTest, WCharArrayWithTerminatingNul) {
+ const wchar_t a[] = L"\0Hi";
+ EXPECT_EQ("L\"\\0Hi\"", PrintArrayHelper(a));
}
// Array of objects.
@@ -872,41 +914,22 @@ TEST(PrintWideStringTest, StringAmbiguousHex) {
#ifdef __cpp_char8_t
TEST(PrintStringTest, U8String) {
- std::u8string str = u8"Hello, world!";
+ std::u8string str = u8"Hello, 世界";
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type.
- EXPECT_EQ(
- "{ U+0048, U+0065, U+006C, U+006C, U+006F, U+002C, U+0020, U+0077, "
- "U+006F, U+0072, U+006C, U+0064, U+0021 }",
- Print(str));
+ EXPECT_EQ("u8\"Hello, \\xE4\\xB8\\x96\\xE7\\x95\\x8C\"", Print(str));
}
#endif
-#ifdef _MSC_VER
-// TODO(b/173029407): Figure out why this doesn't work under MSVC.
-TEST(PrintStringTest, DISABLED_U16String) {
-#else
TEST(PrintStringTest, U16String) {
-#endif
std::u16string str = u"Hello, 世界";
EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type.
- EXPECT_EQ(
- "{ U+0048, U+0065, U+006C, U+006C, U+006F, U+002C, U+0020, U+4E16, "
- "U+754C }",
- Print(str));
+ EXPECT_EQ("u\"Hello, \\x4E16\\x754C\"", Print(str));
}
-#ifdef _MSC_VER
-// TODO(b/173029407): Figure out why this doesn't work under MSVC.
-TEST(PrintStringTest, DISABLED_U32String) {
-#else
TEST(PrintStringTest, U32String) {
-#endif
- std::u32string str = U"Hello, 世界";
- EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type.
- EXPECT_EQ(
- "{ U+0048, U+0065, U+006C, U+006C, U+006F, U+002C, U+0020, U+4E16, "
- "U+754C }",
- Print(str));
+ std::u32string str = U"Hello, 🗺️";
+ EXPECT_EQ(str, str); // Verify EXPECT_EQ compiles with this type
+ EXPECT_EQ("U\"Hello, \\x1F5FA\\xFE0F\"", Print(str));
}
// Tests printing types that support generic streaming (i.e. streaming
OpenPOWER on IntegriCloud