/home/arjun/llvm-project/llvm/utils/unittest/googletest/src/gtest-printers.cc
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | // Copyright 2007, Google Inc. | 
| 2 |  | // All rights reserved. | 
| 3 |  | // | 
| 4 |  | // Redistribution and use in source and binary forms, with or without | 
| 5 |  | // modification, are permitted provided that the following conditions are | 
| 6 |  | // met: | 
| 7 |  | // | 
| 8 |  | //     * Redistributions of source code must retain the above copyright | 
| 9 |  | // notice, this list of conditions and the following disclaimer. | 
| 10 |  | //     * Redistributions in binary form must reproduce the above | 
| 11 |  | // copyright notice, this list of conditions and the following disclaimer | 
| 12 |  | // in the documentation and/or other materials provided with the | 
| 13 |  | // distribution. | 
| 14 |  | //     * Neither the name of Google Inc. nor the names of its | 
| 15 |  | // contributors may be used to endorse or promote products derived from | 
| 16 |  | // this software without specific prior written permission. | 
| 17 |  | // | 
| 18 |  | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
| 19 |  | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
| 20 |  | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
| 21 |  | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
| 22 |  | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
| 23 |  | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
| 24 |  | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
| 25 |  | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
| 26 |  | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| 27 |  | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
| 28 |  | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 29 |  | // | 
| 30 |  | // Author: wan@google.com (Zhanyong Wan) | 
| 31 |  |  | 
| 32 |  | // Google Test - The Google C++ Testing Framework | 
| 33 |  | // | 
| 34 |  | // This file implements a universal value printer that can print a | 
| 35 |  | // value of any type T: | 
| 36 |  | // | 
| 37 |  | //   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr); | 
| 38 |  | // | 
| 39 |  | // It uses the << operator when possible, and prints the bytes in the | 
| 40 |  | // object otherwise.  A user can override its behavior for a class | 
| 41 |  | // type Foo by defining either operator<<(::std::ostream&, const Foo&) | 
| 42 |  | // or void PrintTo(const Foo&, ::std::ostream*) in the namespace that | 
| 43 |  | // defines Foo. | 
| 44 |  |  | 
| 45 |  | #include "gtest/gtest-printers.h" | 
| 46 |  | #include <ctype.h> | 
| 47 |  | #include <stdio.h> | 
| 48 |  | #include <cwchar> | 
| 49 |  | #include <ostream>  // NOLINT | 
| 50 |  | #include <string> | 
| 51 |  | #include "gtest/internal/gtest-port.h" | 
| 52 |  |  | 
| 53 |  | namespace testing { | 
| 54 |  |  | 
| 55 |  | namespace { | 
| 56 |  |  | 
| 57 |  | using ::std::ostream; | 
| 58 |  |  | 
| 59 |  | // Prints a segment of bytes in the given object. | 
| 60 |  | GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ | 
| 61 |  | GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ | 
| 62 |  | GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ | 
| 63 |  | void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, | 
| 64 | 0 |                                 size_t count, ostream* os) { | 
| 65 | 0 |   char text[5] = ""; | 
| 66 | 0 |   for (size_t i = 0; i != count; i++) { | 
| 67 | 0 |     const size_t j = start + i; | 
| 68 | 0 |     if (i != 0) { | 
| 69 | 0 |       // Organizes the bytes into groups of 2 for easy parsing by | 
| 70 | 0 |       // human. | 
| 71 | 0 |       if ((j % 2) == 0) | 
| 72 | 0 |         *os << ' '; | 
| 73 | 0 |       else | 
| 74 | 0 |         *os << '-'; | 
| 75 | 0 |     } | 
| 76 | 0 |     GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]); | 
| 77 | 0 |     *os << text; | 
| 78 | 0 |   } | 
| 79 | 0 | } | 
| 80 |  |  | 
| 81 |  | // Prints the bytes in the given value to the given ostream. | 
| 82 |  | void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count, | 
| 83 | 0 |                               ostream* os) { | 
| 84 | 0 |   // Tells the user how big the object is. | 
| 85 | 0 |   *os << count << "-byte object <"; | 
| 86 | 0 | 
 | 
| 87 | 0 |   const size_t kThreshold = 132; | 
| 88 | 0 |   const size_t kChunkSize = 64; | 
| 89 | 0 |   // If the object size is bigger than kThreshold, we'll have to omit | 
| 90 | 0 |   // some details by printing only the first and the last kChunkSize | 
| 91 | 0 |   // bytes. | 
| 92 | 0 |   // TODO(wan): let the user control the threshold using a flag. | 
| 93 | 0 |   if (count < kThreshold) { | 
| 94 | 0 |     PrintByteSegmentInObjectTo(obj_bytes, 0, count, os); | 
| 95 | 0 |   } else { | 
| 96 | 0 |     PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os); | 
| 97 | 0 |     *os << " ... "; | 
| 98 | 0 |     // Rounds up to 2-byte boundary. | 
| 99 | 0 |     const size_t resume_pos = (count - kChunkSize + 1)/2*2; | 
| 100 | 0 |     PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os); | 
| 101 | 0 |   } | 
| 102 | 0 |   *os << ">"; | 
| 103 | 0 | } | 
| 104 |  |  | 
| 105 |  | }  // namespace | 
| 106 |  |  | 
| 107 |  | namespace internal2 { | 
| 108 |  |  | 
| 109 |  | // Delegates to PrintBytesInObjectToImpl() to print the bytes in the | 
| 110 |  | // given object.  The delegation simplifies the implementation, which | 
| 111 |  | // uses the << operator and thus is easier done outside of the | 
| 112 |  | // ::testing::internal namespace, which contains a << operator that | 
| 113 |  | // sometimes conflicts with the one in STL. | 
| 114 |  | void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count, | 
| 115 | 0 |                           ostream* os) { | 
| 116 | 0 |   PrintBytesInObjectToImpl(obj_bytes, count, os); | 
| 117 | 0 | } | 
| 118 |  |  | 
| 119 |  | }  // namespace internal2 | 
| 120 |  |  | 
| 121 |  | namespace internal { | 
| 122 |  |  | 
| 123 |  | // Depending on the value of a char (or wchar_t), we print it in one | 
| 124 |  | // of three formats: | 
| 125 |  | //   - as is if it's a printable ASCII (e.g. 'a', '2', ' '), | 
| 126 |  | //   - as a hexidecimal escape sequence (e.g. '\x7F'), or | 
| 127 |  | //   - as a special escape sequence (e.g. '\r', '\n'). | 
| 128 |  | enum CharFormat { | 
| 129 |  |   kAsIs, | 
| 130 |  |   kHexEscape, | 
| 131 |  |   kSpecialEscape | 
| 132 |  | }; | 
| 133 |  |  | 
| 134 |  | // Returns true if c is a printable ASCII character.  We test the | 
| 135 |  | // value of c directly instead of calling isprint(), which is buggy on | 
| 136 |  | // Windows Mobile. | 
| 137 | 0 | inline bool IsPrintableAscii(wchar_t c) { | 
| 138 | 0 |   return 0x20 <= c && c <= 0x7E; | 
| 139 | 0 | } | 
| 140 |  |  | 
| 141 |  | // Prints a wide or narrow char c as a character literal without the | 
| 142 |  | // quotes, escaping it when necessary; returns how c was formatted. | 
| 143 |  | // The template argument UnsignedChar is the unsigned version of Char, | 
| 144 |  | // which is the type of c. | 
| 145 |  | template <typename UnsignedChar, typename Char> | 
| 146 | 0 | static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) { | 
| 147 | 0 |   switch (static_cast<wchar_t>(c)) { | 
| 148 | 0 |     case L'\0': | 
| 149 | 0 |       *os << "\\0"; | 
| 150 | 0 |       break; | 
| 151 | 0 |     case L'\'': | 
| 152 | 0 |       *os << "\\'"; | 
| 153 | 0 |       break; | 
| 154 | 0 |     case L'\\': | 
| 155 | 0 |       *os << "\\\\"; | 
| 156 | 0 |       break; | 
| 157 | 0 |     case L'\a': | 
| 158 | 0 |       *os << "\\a"; | 
| 159 | 0 |       break; | 
| 160 | 0 |     case L'\b': | 
| 161 | 0 |       *os << "\\b"; | 
| 162 | 0 |       break; | 
| 163 | 0 |     case L'\f': | 
| 164 | 0 |       *os << "\\f"; | 
| 165 | 0 |       break; | 
| 166 | 0 |     case L'\n': | 
| 167 | 0 |       *os << "\\n"; | 
| 168 | 0 |       break; | 
| 169 | 0 |     case L'\r': | 
| 170 | 0 |       *os << "\\r"; | 
| 171 | 0 |       break; | 
| 172 | 0 |     case L'\t': | 
| 173 | 0 |       *os << "\\t"; | 
| 174 | 0 |       break; | 
| 175 | 0 |     case L'\v': | 
| 176 | 0 |       *os << "\\v"; | 
| 177 | 0 |       break; | 
| 178 | 0 |     default: | 
| 179 | 0 |       if (IsPrintableAscii(c)) { | 
| 180 | 0 |         *os << static_cast<char>(c); | 
| 181 | 0 |         return kAsIs; | 
| 182 | 0 |       } else { | 
| 183 | 0 |         *os << "\\x" + String::FormatHexInt(static_cast<UnsignedChar>(c)); | 
| 184 | 0 |         return kHexEscape; | 
| 185 | 0 |       } | 
| 186 | 0 |   } | 
| 187 | 0 |   return kSpecialEscape; | 
| 188 | 0 | } Unexecuted instantiation: gtest-all.cc:_ZN7testing8internalL20PrintAsCharLiteralToIhhEENS0_10CharFormatET0_PSoUnexecuted instantiation: gtest-all.cc:_ZN7testing8internalL20PrintAsCharLiteralToIhaEENS0_10CharFormatET0_PSoUnexecuted instantiation: gtest-all.cc:_ZN7testing8internalL20PrintAsCharLiteralToIwwEENS0_10CharFormatET0_PSo | 
| 189 |  |  | 
| 190 |  | // Prints a wchar_t c as if it's part of a string literal, escaping it when | 
| 191 |  | // necessary; returns how c was formatted. | 
| 192 |  | static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) { | 
| 193 |  |   switch (c) { | 
| 194 |  |     case L'\'': | 
| 195 |  |       *os << "'"; | 
| 196 |  |       return kAsIs; | 
| 197 |  |     case L'"': | 
| 198 |  |       *os << "\\\""; | 
| 199 |  |       return kSpecialEscape; | 
| 200 |  |     default: | 
| 201 |  |       return PrintAsCharLiteralTo<wchar_t>(c, os); | 
| 202 |  |   } | 
| 203 |  | } | 
| 204 |  |  | 
| 205 |  | // Prints a char c as if it's part of a string literal, escaping it when | 
| 206 |  | // necessary; returns how c was formatted. | 
| 207 | 0 | static CharFormat PrintAsStringLiteralTo(char c, ostream* os) { | 
| 208 | 0 |   return PrintAsStringLiteralTo( | 
| 209 | 0 |       static_cast<wchar_t>(static_cast<unsigned char>(c)), os); | 
| 210 | 0 | } | 
| 211 |  |  | 
| 212 |  | // Prints a wide or narrow character c and its code.  '\0' is printed | 
| 213 |  | // as "'\\0'", other unprintable characters are also properly escaped | 
| 214 |  | // using the standard C++ escape sequence.  The template argument | 
| 215 |  | // UnsignedChar is the unsigned version of Char, which is the type of c. | 
| 216 |  | template <typename UnsignedChar, typename Char> | 
| 217 | 0 | void PrintCharAndCodeTo(Char c, ostream* os) { | 
| 218 | 0 |   // First, print c as a literal in the most readable form we can find. | 
| 219 | 0 |   *os << ((sizeof(c) > 1) ? "L'" : "'"); | 
| 220 | 0 |   const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os); | 
| 221 | 0 |   *os << "'"; | 
| 222 | 0 | 
 | 
| 223 | 0 |   // To aid user debugging, we also print c's code in decimal, unless | 
| 224 | 0 |   // it's 0 (in which case c was printed as '\\0', making the code | 
| 225 | 0 |   // obvious). | 
| 226 | 0 |   if (c == 0) | 
| 227 | 0 |     return; | 
| 228 | 0 |   *os << " (" << static_cast<int>(c); | 
| 229 | 0 | 
 | 
| 230 | 0 |   // For more convenience, we print c's code again in hexidecimal, | 
| 231 | 0 |   // unless c was already printed in the form '\x##' or the code is in | 
| 232 | 0 |   // [1, 9]. | 
| 233 | 0 |   if (format == kHexEscape || (1 <= c && c <= 9)) { | 
| 234 | 0 |     // Do nothing. | 
| 235 | 0 |   } else { | 
| 236 | 0 |     *os << ", 0x" << String::FormatHexInt(static_cast<UnsignedChar>(c)); | 
| 237 | 0 |   } | 
| 238 | 0 |   *os << ")"; | 
| 239 | 0 | } Unexecuted instantiation: _ZN7testing8internal18PrintCharAndCodeToIhhEEvT0_PSoUnexecuted instantiation: _ZN7testing8internal18PrintCharAndCodeToIhaEEvT0_PSoUnexecuted instantiation: _ZN7testing8internal18PrintCharAndCodeToIwwEEvT0_PSo | 
| 240 |  |  | 
| 241 | 0 | void PrintTo(unsigned char c, ::std::ostream* os) { | 
| 242 | 0 |   PrintCharAndCodeTo<unsigned char>(c, os); | 
| 243 | 0 | } | 
| 244 | 0 | void PrintTo(signed char c, ::std::ostream* os) { | 
| 245 | 0 |   PrintCharAndCodeTo<unsigned char>(c, os); | 
| 246 | 0 | } | 
| 247 |  |  | 
| 248 |  | // Prints a wchar_t as a symbol if it is printable or as its internal | 
| 249 |  | // code otherwise and also as its code.  L'\0' is printed as "L'\\0'". | 
| 250 | 0 | void PrintTo(wchar_t wc, ostream* os) { | 
| 251 | 0 |   PrintCharAndCodeTo<wchar_t>(wc, os); | 
| 252 | 0 | } | 
| 253 |  |  | 
| 254 |  | // Prints the given array of characters to the ostream.  CharType must be either | 
| 255 |  | // char or wchar_t. | 
| 256 |  | // The array starts at begin, the length is len, it may include '\0' characters | 
| 257 |  | // and may not be NUL-terminated. | 
| 258 |  | template <typename CharType> | 
| 259 |  | GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ | 
| 260 |  | GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ | 
| 261 |  | GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ | 
| 262 |  | static void PrintCharsAsStringTo( | 
| 263 | 0 |     const CharType* begin, size_t len, ostream* os) { | 
| 264 | 0 |   const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\""; | 
| 265 | 0 |   *os << kQuoteBegin; | 
| 266 | 0 |   bool is_previous_hex = false; | 
| 267 | 0 |   for (size_t index = 0; index < len; ++index) { | 
| 268 | 0 |     const CharType cur = begin[index]; | 
| 269 | 0 |     if (is_previous_hex && IsXDigit(cur)) { | 
| 270 | 0 |       // Previous character is of '\x..' form and this character can be | 
| 271 | 0 |       // interpreted as another hexadecimal digit in its number. Break string to | 
| 272 | 0 |       // disambiguate. | 
| 273 | 0 |       *os << "\" " << kQuoteBegin; | 
| 274 | 0 |     } | 
| 275 | 0 |     is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape; | 
| 276 | 0 |   } | 
| 277 | 0 |   *os << "\""; | 
| 278 | 0 | } Unexecuted instantiation: gtest-all.cc:_ZN7testing8internalL20PrintCharsAsStringToIcEEvPKT_mPSoUnexecuted instantiation: gtest-all.cc:_ZN7testing8internalL20PrintCharsAsStringToIwEEvPKT_mPSo | 
| 279 |  |  | 
| 280 |  | // Prints a (const) char/wchar_t array of 'len' elements, starting at address | 
| 281 |  | // 'begin'.  CharType must be either char or wchar_t. | 
| 282 |  | template <typename CharType> | 
| 283 |  | GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ | 
| 284 |  | GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ | 
| 285 |  | GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ | 
| 286 |  | static void UniversalPrintCharArray( | 
| 287 | 0 |     const CharType* begin, size_t len, ostream* os) { | 
| 288 | 0 |   // The code | 
| 289 | 0 |   //   const char kFoo[] = "foo"; | 
| 290 | 0 |   // generates an array of 4, not 3, elements, with the last one being '\0'. | 
| 291 | 0 |   // | 
| 292 | 0 |   // Therefore when printing a char array, we don't print the last element if | 
| 293 | 0 |   // it's '\0', such that the output matches the string literal as it's | 
| 294 | 0 |   // written in the source code. | 
| 295 | 0 |   if (len > 0 && begin[len - 1] == '\0') { | 
| 296 | 0 |     PrintCharsAsStringTo(begin, len - 1, os); | 
| 297 | 0 |     return; | 
| 298 | 0 |   } | 
| 299 | 0 |  | 
| 300 | 0 |   // If, however, the last element in the array is not '\0', e.g. | 
| 301 | 0 |   //    const char kFoo[] = { 'f', 'o', 'o' }; | 
| 302 | 0 |   // we must print the entire array.  We also print a message to indicate | 
| 303 | 0 |   // that the array is not NUL-terminated. | 
| 304 | 0 |   PrintCharsAsStringTo(begin, len, os); | 
| 305 | 0 |   *os << " (no terminating NUL)"; | 
| 306 | 0 | } Unexecuted instantiation: gtest-all.cc:_ZN7testing8internalL23UniversalPrintCharArrayIcEEvPKT_mPSoUnexecuted instantiation: gtest-all.cc:_ZN7testing8internalL23UniversalPrintCharArrayIwEEvPKT_mPSo | 
| 307 |  |  | 
| 308 |  | // Prints a (const) char array of 'len' elements, starting at address 'begin'. | 
| 309 | 0 | void UniversalPrintArray(const char* begin, size_t len, ostream* os) { | 
| 310 | 0 |   UniversalPrintCharArray(begin, len, os); | 
| 311 | 0 | } | 
| 312 |  |  | 
| 313 |  | // Prints a (const) wchar_t array of 'len' elements, starting at address | 
| 314 |  | // 'begin'. | 
| 315 | 0 | void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) { | 
| 316 | 0 |   UniversalPrintCharArray(begin, len, os); | 
| 317 | 0 | } | 
| 318 |  |  | 
| 319 |  | // Prints the given C string to the ostream. | 
| 320 | 0 | void PrintTo(const char* s, ostream* os) { | 
| 321 | 0 |   if (s == NULL) { | 
| 322 | 0 |     *os << "NULL"; | 
| 323 | 0 |   } else { | 
| 324 | 0 |     *os << ImplicitCast_<const void*>(s) << " pointing to "; | 
| 325 | 0 |     PrintCharsAsStringTo(s, strlen(s), os); | 
| 326 | 0 |   } | 
| 327 | 0 | } | 
| 328 |  |  | 
| 329 |  | // MSVC compiler can be configured to define whar_t as a typedef | 
| 330 |  | // of unsigned short. Defining an overload for const wchar_t* in that case | 
| 331 |  | // would cause pointers to unsigned shorts be printed as wide strings, | 
| 332 |  | // possibly accessing more memory than intended and causing invalid | 
| 333 |  | // memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when | 
| 334 |  | // wchar_t is implemented as a native type. | 
| 335 |  | #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) | 
| 336 |  | // Prints the given wide C string to the ostream. | 
| 337 | 0 | void PrintTo(const wchar_t* s, ostream* os) { | 
| 338 | 0 |   if (s == NULL) { | 
| 339 | 0 |     *os << "NULL"; | 
| 340 | 0 |   } else { | 
| 341 | 0 |     *os << ImplicitCast_<const void*>(s) << " pointing to "; | 
| 342 | 0 |     PrintCharsAsStringTo(s, std::wcslen(s), os); | 
| 343 | 0 |   } | 
| 344 | 0 | } | 
| 345 |  | #endif  // wchar_t is native | 
| 346 |  |  | 
| 347 |  | // Prints a ::string object. | 
| 348 |  | #if GTEST_HAS_GLOBAL_STRING | 
| 349 |  | void PrintStringTo(const ::string& s, ostream* os) { | 
| 350 |  |   PrintCharsAsStringTo(s.data(), s.size(), os); | 
| 351 |  | } | 
| 352 |  | #endif  // GTEST_HAS_GLOBAL_STRING | 
| 353 |  |  | 
| 354 | 0 | void PrintStringTo(const ::std::string& s, ostream* os) { | 
| 355 | 0 |   PrintCharsAsStringTo(s.data(), s.size(), os); | 
| 356 | 0 | } | 
| 357 |  |  | 
| 358 |  | // Prints a ::wstring object. | 
| 359 |  | #if GTEST_HAS_GLOBAL_WSTRING | 
| 360 |  | void PrintWideStringTo(const ::wstring& s, ostream* os) { | 
| 361 |  |   PrintCharsAsStringTo(s.data(), s.size(), os); | 
| 362 |  | } | 
| 363 |  | #endif  // GTEST_HAS_GLOBAL_WSTRING | 
| 364 |  |  | 
| 365 |  | #if GTEST_HAS_STD_WSTRING | 
| 366 | 0 | void PrintWideStringTo(const ::std::wstring& s, ostream* os) { | 
| 367 | 0 |   PrintCharsAsStringTo(s.data(), s.size(), os); | 
| 368 | 0 | } | 
| 369 |  | #endif  // GTEST_HAS_STD_WSTRING | 
| 370 |  |  | 
| 371 |  | }  // namespace internal | 
| 372 |  |  | 
| 373 |  | }  // namespace testing |