str_cat_test.cc (24160B)
1 // Copyright 2017 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Unit tests for all str_cat.h functions 16 17 #include "absl/strings/str_cat.h" 18 19 #include <cstddef> 20 #include <cstdint> 21 #include <cstdlib> 22 #include <limits> 23 #include <string> 24 #include <vector> 25 26 #include "gtest/gtest.h" 27 #include "absl/base/config.h" 28 #include "absl/strings/str_format.h" 29 #include "absl/strings/string_view.h" 30 31 #if defined(ABSL_HAVE_STD_STRING_VIEW) 32 #include <string_view> 33 #endif 34 35 #ifdef __ANDROID__ 36 // Android assert messages only go to system log, so death tests cannot inspect 37 // the message for matching. 38 #define ABSL_EXPECT_DEBUG_DEATH(statement, regex) \ 39 EXPECT_DEBUG_DEATH(statement, ".*") 40 #else 41 #define ABSL_EXPECT_DEBUG_DEATH(statement, regex) \ 42 EXPECT_DEBUG_DEATH(statement, regex) 43 #endif 44 45 namespace { 46 47 // Test absl::StrCat of ints and longs of various sizes and signdedness. 48 TEST(StrCat, Ints) { 49 const short s = -1; // NOLINT(runtime/int) 50 const uint16_t us = 2; 51 const int i = -3; 52 const unsigned int ui = 4; 53 const long l = -5; // NOLINT(runtime/int) 54 const unsigned long ul = 6; // NOLINT(runtime/int) 55 const long long ll = -7; // NOLINT(runtime/int) 56 const unsigned long long ull = 8; // NOLINT(runtime/int) 57 const ptrdiff_t ptrdiff = -9; 58 const size_t size = 10; 59 const intptr_t intptr = -12; 60 const uintptr_t uintptr = 13; 61 std::string answer; 62 answer = absl::StrCat(s, us); 63 EXPECT_EQ(answer, "-12"); 64 answer = absl::StrCat(i, ui); 65 EXPECT_EQ(answer, "-34"); 66 answer = absl::StrCat(l, ul); 67 EXPECT_EQ(answer, "-56"); 68 answer = absl::StrCat(ll, ull); 69 EXPECT_EQ(answer, "-78"); 70 answer = absl::StrCat(ptrdiff, size); 71 EXPECT_EQ(answer, "-910"); 72 answer = absl::StrCat(ptrdiff, intptr); 73 EXPECT_EQ(answer, "-9-12"); 74 answer = absl::StrCat(uintptr, 0); 75 EXPECT_EQ(answer, "130"); 76 } 77 78 TEST(StrCat, Enums) { 79 enum SmallNumbers { One = 1, Ten = 10 } e = Ten; 80 EXPECT_EQ("10", absl::StrCat(e)); 81 EXPECT_EQ("1", absl::StrCat(One)); 82 83 enum class Option { Boxers = 1, Briefs = -1 }; 84 85 EXPECT_EQ("-1", absl::StrCat(Option::Briefs)); 86 87 enum class Airplane : uint64_t { 88 Airbus = 1, 89 Boeing = 1000, 90 Canary = 10000000000 // too big for "int" 91 }; 92 93 EXPECT_EQ("10000000000", absl::StrCat(Airplane::Canary)); 94 95 enum class TwoGig : int32_t { 96 TwoToTheZero = 1, 97 TwoToTheSixteenth = 1 << 16, 98 TwoToTheThirtyFirst = INT32_MIN 99 }; 100 EXPECT_EQ("65536", absl::StrCat(TwoGig::TwoToTheSixteenth)); 101 EXPECT_EQ("-2147483648", absl::StrCat(TwoGig::TwoToTheThirtyFirst)); 102 EXPECT_EQ("-1", absl::StrCat(static_cast<TwoGig>(-1))); 103 104 enum class FourGig : uint32_t { 105 TwoToTheZero = 1, 106 TwoToTheSixteenth = 1 << 16, 107 TwoToTheThirtyFirst = 1U << 31 // too big for "int" 108 }; 109 EXPECT_EQ("65536", absl::StrCat(FourGig::TwoToTheSixteenth)); 110 EXPECT_EQ("2147483648", absl::StrCat(FourGig::TwoToTheThirtyFirst)); 111 EXPECT_EQ("4294967295", absl::StrCat(static_cast<FourGig>(-1))); 112 113 EXPECT_EQ("10000000000", absl::StrCat(Airplane::Canary)); 114 } 115 116 TEST(StrCat, Basics) { 117 std::string result; 118 119 std::string strs[] = {"Hello", "Cruel", "World"}; 120 121 std::string stdstrs[] = { 122 "std::Hello", 123 "std::Cruel", 124 "std::World" 125 }; 126 127 absl::string_view pieces[] = {"Hello", "Cruel", "World"}; 128 129 const char* c_strs[] = { 130 "Hello", 131 "Cruel", 132 "World" 133 }; 134 135 int32_t i32s[] = {'H', 'C', 'W'}; 136 uint64_t ui64s[] = {12345678910LL, 10987654321LL}; 137 138 EXPECT_EQ(absl::StrCat(), ""); 139 140 result = absl::StrCat(false, true, 2, 3); 141 EXPECT_EQ(result, "0123"); 142 143 result = absl::StrCat(-1); 144 EXPECT_EQ(result, "-1"); 145 146 result = absl::StrCat(absl::SixDigits(0.5)); 147 EXPECT_EQ(result, "0.5"); 148 149 result = absl::StrCat(strs[1], pieces[2]); 150 EXPECT_EQ(result, "CruelWorld"); 151 152 result = absl::StrCat(stdstrs[1], " ", stdstrs[2]); 153 EXPECT_EQ(result, "std::Cruel std::World"); 154 155 result = absl::StrCat(strs[0], ", ", pieces[2]); 156 EXPECT_EQ(result, "Hello, World"); 157 158 result = absl::StrCat(strs[0], ", ", strs[1], " ", strs[2], "!"); 159 EXPECT_EQ(result, "Hello, Cruel World!"); 160 161 result = absl::StrCat(pieces[0], ", ", pieces[1], " ", pieces[2]); 162 EXPECT_EQ(result, "Hello, Cruel World"); 163 164 result = absl::StrCat(c_strs[0], ", ", c_strs[1], " ", c_strs[2]); 165 EXPECT_EQ(result, "Hello, Cruel World"); 166 167 result = absl::StrCat("ASCII ", i32s[0], ", ", i32s[1], " ", i32s[2], "!"); 168 EXPECT_EQ(result, "ASCII 72, 67 87!"); 169 170 result = absl::StrCat(ui64s[0], ", ", ui64s[1], "!"); 171 EXPECT_EQ(result, "12345678910, 10987654321!"); 172 173 std::string one = 174 "1"; // Actually, it's the size of this string that we want; a 175 // 64-bit build distinguishes between size_t and uint64_t, 176 // even though they're both unsigned 64-bit values. 177 result = absl::StrCat("And a ", one.size(), " and a ", 178 &result[2] - &result[0], " and a ", one, " 2 3 4", "!"); 179 EXPECT_EQ(result, "And a 1 and a 2 and a 1 2 3 4!"); 180 181 // result = absl::StrCat("Single chars won't compile", '!'); 182 // result = absl::StrCat("Neither will nullptrs", nullptr); 183 result = 184 absl::StrCat("To output a char by ASCII/numeric value, use +: ", '!' + 0); 185 EXPECT_EQ(result, "To output a char by ASCII/numeric value, use +: 33"); 186 187 float f = 100000.5; 188 result = absl::StrCat("A hundred K and a half is ", absl::SixDigits(f)); 189 EXPECT_EQ(result, "A hundred K and a half is 100000"); 190 191 f = 100001.5; 192 result = 193 absl::StrCat("A hundred K and one and a half is ", absl::SixDigits(f)); 194 EXPECT_EQ(result, "A hundred K and one and a half is 100002"); 195 196 double d = 100000.5; 197 d *= d; 198 result = 199 absl::StrCat("A hundred K and a half squared is ", absl::SixDigits(d)); 200 EXPECT_EQ(result, "A hundred K and a half squared is 1.00001e+10"); 201 202 result = absl::StrCat(1, 2, 333, 4444, 55555, 666666, 7777777, 88888888, 203 999999999); 204 EXPECT_EQ(result, "12333444455555666666777777788888888999999999"); 205 } 206 207 TEST(StrCat, CornerCases) { 208 std::string result; 209 210 result = absl::StrCat(""); // NOLINT 211 EXPECT_EQ(result, ""); 212 result = absl::StrCat("", ""); 213 EXPECT_EQ(result, ""); 214 result = absl::StrCat("", "", ""); 215 EXPECT_EQ(result, ""); 216 result = absl::StrCat("", "", "", ""); 217 EXPECT_EQ(result, ""); 218 result = absl::StrCat("", "", "", "", ""); 219 EXPECT_EQ(result, ""); 220 } 221 222 #if defined(ABSL_HAVE_STD_STRING_VIEW) 223 TEST(StrCat, StdStringView) { 224 std::string_view pieces[] = {"Hello", ", ", "World", "!"}; 225 EXPECT_EQ(absl::StrCat(pieces[0], pieces[1], pieces[2], pieces[3]), 226 "Hello, World!"); 227 } 228 #endif // ABSL_HAVE_STD_STRING_VIEW 229 230 TEST(StrCat, NullConstCharPtr) { 231 const char* null = nullptr; 232 EXPECT_EQ(absl::StrCat("mon", null, "key"), "monkey"); 233 } 234 235 // A minimal allocator that uses malloc(). 236 template <typename T> 237 struct Mallocator { 238 typedef T value_type; 239 typedef size_t size_type; 240 typedef ptrdiff_t difference_type; 241 typedef T* pointer; 242 typedef const T* const_pointer; 243 typedef T& reference; 244 typedef const T& const_reference; 245 246 size_type max_size() const { 247 return size_t(std::numeric_limits<size_type>::max()) / sizeof(value_type); 248 } 249 template <typename U> 250 struct rebind { 251 typedef Mallocator<U> other; 252 }; 253 Mallocator() = default; 254 template <class U> 255 Mallocator(const Mallocator<U>&) {} // NOLINT(runtime/explicit) 256 257 T* allocate(size_t n) { return static_cast<T*>(std::malloc(n * sizeof(T))); } 258 void deallocate(T* p, size_t) { std::free(p); } 259 }; 260 template <typename T, typename U> 261 bool operator==(const Mallocator<T>&, const Mallocator<U>&) { 262 return true; 263 } 264 template <typename T, typename U> 265 bool operator!=(const Mallocator<T>&, const Mallocator<U>&) { 266 return false; 267 } 268 269 TEST(StrCat, CustomAllocator) { 270 using mstring = 271 std::basic_string<char, std::char_traits<char>, Mallocator<char>>; 272 const mstring str1("PARACHUTE OFF A BLIMP INTO MOSCONE!!"); 273 274 const mstring str2("Read this book about coffee tables"); 275 276 std::string result = absl::StrCat(str1, str2); 277 EXPECT_EQ(result, 278 "PARACHUTE OFF A BLIMP INTO MOSCONE!!" 279 "Read this book about coffee tables"); 280 } 281 282 TEST(StrCat, MaxArgs) { 283 std::string result; 284 // Test 10 up to 26 arguments, the old maximum 285 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a"); 286 EXPECT_EQ(result, "123456789a"); 287 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b"); 288 EXPECT_EQ(result, "123456789ab"); 289 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c"); 290 EXPECT_EQ(result, "123456789abc"); 291 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d"); 292 EXPECT_EQ(result, "123456789abcd"); 293 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e"); 294 EXPECT_EQ(result, "123456789abcde"); 295 result = 296 absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f"); 297 EXPECT_EQ(result, "123456789abcdef"); 298 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", 299 "g"); 300 EXPECT_EQ(result, "123456789abcdefg"); 301 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", 302 "g", "h"); 303 EXPECT_EQ(result, "123456789abcdefgh"); 304 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", 305 "g", "h", "i"); 306 EXPECT_EQ(result, "123456789abcdefghi"); 307 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", 308 "g", "h", "i", "j"); 309 EXPECT_EQ(result, "123456789abcdefghij"); 310 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", 311 "g", "h", "i", "j", "k"); 312 EXPECT_EQ(result, "123456789abcdefghijk"); 313 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", 314 "g", "h", "i", "j", "k", "l"); 315 EXPECT_EQ(result, "123456789abcdefghijkl"); 316 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", 317 "g", "h", "i", "j", "k", "l", "m"); 318 EXPECT_EQ(result, "123456789abcdefghijklm"); 319 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", 320 "g", "h", "i", "j", "k", "l", "m", "n"); 321 EXPECT_EQ(result, "123456789abcdefghijklmn"); 322 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", 323 "g", "h", "i", "j", "k", "l", "m", "n", "o"); 324 EXPECT_EQ(result, "123456789abcdefghijklmno"); 325 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", 326 "g", "h", "i", "j", "k", "l", "m", "n", "o", "p"); 327 EXPECT_EQ(result, "123456789abcdefghijklmnop"); 328 result = absl::StrCat(1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", 329 "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q"); 330 EXPECT_EQ(result, "123456789abcdefghijklmnopq"); 331 // No limit thanks to C++11's variadic templates 332 result = absl::StrCat( 333 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "a", "b", "c", "d", "e", "f", "g", "h", 334 "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", 335 "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", 336 "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"); 337 EXPECT_EQ(result, 338 "12345678910abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); 339 } 340 341 TEST(StrAppend, Basics) { 342 std::string result = "existing text"; 343 344 std::string strs[] = {"Hello", "Cruel", "World"}; 345 346 std::string stdstrs[] = { 347 "std::Hello", 348 "std::Cruel", 349 "std::World" 350 }; 351 352 absl::string_view pieces[] = {"Hello", "Cruel", "World"}; 353 354 const char* c_strs[] = { 355 "Hello", 356 "Cruel", 357 "World" 358 }; 359 360 int32_t i32s[] = {'H', 'C', 'W'}; 361 uint64_t ui64s[] = {12345678910LL, 10987654321LL}; 362 363 std::string::size_type old_size = result.size(); 364 absl::StrAppend(&result); 365 EXPECT_EQ(result.size(), old_size); 366 367 old_size = result.size(); 368 absl::StrAppend(&result, strs[0]); 369 EXPECT_EQ(result.substr(old_size), "Hello"); 370 371 old_size = result.size(); 372 absl::StrAppend(&result, strs[1], pieces[2]); 373 EXPECT_EQ(result.substr(old_size), "CruelWorld"); 374 375 old_size = result.size(); 376 absl::StrAppend(&result, stdstrs[0], ", ", pieces[2]); 377 EXPECT_EQ(result.substr(old_size), "std::Hello, World"); 378 379 old_size = result.size(); 380 absl::StrAppend(&result, strs[0], ", ", stdstrs[1], " ", strs[2], "!"); 381 EXPECT_EQ(result.substr(old_size), "Hello, std::Cruel World!"); 382 383 old_size = result.size(); 384 absl::StrAppend(&result, pieces[0], ", ", pieces[1], " ", pieces[2]); 385 EXPECT_EQ(result.substr(old_size), "Hello, Cruel World"); 386 387 old_size = result.size(); 388 absl::StrAppend(&result, c_strs[0], ", ", c_strs[1], " ", c_strs[2]); 389 EXPECT_EQ(result.substr(old_size), "Hello, Cruel World"); 390 391 old_size = result.size(); 392 absl::StrAppend(&result, "ASCII ", i32s[0], ", ", i32s[1], " ", i32s[2], "!"); 393 EXPECT_EQ(result.substr(old_size), "ASCII 72, 67 87!"); 394 395 old_size = result.size(); 396 absl::StrAppend(&result, ui64s[0], ", ", ui64s[1], "!"); 397 EXPECT_EQ(result.substr(old_size), "12345678910, 10987654321!"); 398 399 std::string one = 400 "1"; // Actually, it's the size of this string that we want; a 401 // 64-bit build distinguishes between size_t and uint64_t, 402 // even though they're both unsigned 64-bit values. 403 old_size = result.size(); 404 absl::StrAppend(&result, "And a ", one.size(), " and a ", 405 &result[2] - &result[0], " and a ", one, " 2 3 4", "!"); 406 EXPECT_EQ(result.substr(old_size), "And a 1 and a 2 and a 1 2 3 4!"); 407 408 // result = absl::StrCat("Single chars won't compile", '!'); 409 // result = absl::StrCat("Neither will nullptrs", nullptr); 410 old_size = result.size(); 411 absl::StrAppend(&result, 412 "To output a char by ASCII/numeric value, use +: ", '!' + 0); 413 EXPECT_EQ(result.substr(old_size), 414 "To output a char by ASCII/numeric value, use +: 33"); 415 416 // Test 9 arguments, the old maximum 417 old_size = result.size(); 418 absl::StrAppend(&result, 1, 22, 333, 4444, 55555, 666666, 7777777, 88888888, 419 9); 420 EXPECT_EQ(result.substr(old_size), "1223334444555556666667777777888888889"); 421 422 // No limit thanks to C++11's variadic templates 423 old_size = result.size(); 424 absl::StrAppend( 425 &result, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // 426 "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", // 427 "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", // 428 "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", // 429 "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", // 430 "No limit thanks to C++11's variadic templates"); 431 EXPECT_EQ(result.substr(old_size), 432 "12345678910abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 433 "No limit thanks to C++11's variadic templates"); 434 } 435 436 TEST(StrCat, VectorBoolReferenceTypes) { 437 std::vector<bool> v; 438 v.push_back(true); 439 v.push_back(false); 440 std::vector<bool> const& cv = v; 441 // Test that vector<bool>::reference and vector<bool>::const_reference 442 // are handled as if the were really bool types and not the proxy types 443 // they really are. 444 std::string result = absl::StrCat(v[0], v[1], cv[0], cv[1]); // NOLINT 445 EXPECT_EQ(result, "1010"); 446 } 447 448 // Passing nullptr to memcpy is undefined behavior and this test 449 // provides coverage of codepaths that handle empty strings with nullptrs. 450 TEST(StrCat, AvoidsMemcpyWithNullptr) { 451 EXPECT_EQ(absl::StrCat(42, absl::string_view{}), "42"); 452 453 // Cover CatPieces code. 454 EXPECT_EQ(absl::StrCat(1, 2, 3, 4, 5, absl::string_view{}), "12345"); 455 456 // Cover AppendPieces. 457 std::string result; 458 absl::StrAppend(&result, 1, 2, 3, 4, 5, absl::string_view{}); 459 EXPECT_EQ(result, "12345"); 460 } 461 462 #if GTEST_HAS_DEATH_TEST 463 TEST(StrAppend, Death) { 464 std::string s = "self"; 465 // on linux it's "assertion", on mac it's "Assertion", 466 // on chromiumos it's "Assertion ... failed". 467 ABSL_EXPECT_DEBUG_DEATH(absl::StrAppend(&s, s.c_str() + 1), 468 "ssertion.*failed"); 469 ABSL_EXPECT_DEBUG_DEATH(absl::StrAppend(&s, s), "ssertion.*failed"); 470 } 471 #endif // GTEST_HAS_DEATH_TEST 472 473 TEST(StrAppend, CornerCases) { 474 std::string result; 475 absl::StrAppend(&result, ""); 476 EXPECT_EQ(result, ""); 477 absl::StrAppend(&result, "", ""); 478 EXPECT_EQ(result, ""); 479 absl::StrAppend(&result, "", "", ""); 480 EXPECT_EQ(result, ""); 481 absl::StrAppend(&result, "", "", "", ""); 482 EXPECT_EQ(result, ""); 483 absl::StrAppend(&result, "", "", "", "", ""); 484 EXPECT_EQ(result, ""); 485 } 486 487 TEST(StrAppend, CornerCasesNonEmptyAppend) { 488 for (std::string result : {"hello", "a string too long to fit in the SSO"}) { 489 const std::string expected = result; 490 absl::StrAppend(&result, ""); 491 EXPECT_EQ(result, expected); 492 absl::StrAppend(&result, "", ""); 493 EXPECT_EQ(result, expected); 494 absl::StrAppend(&result, "", "", ""); 495 EXPECT_EQ(result, expected); 496 absl::StrAppend(&result, "", "", "", ""); 497 EXPECT_EQ(result, expected); 498 absl::StrAppend(&result, "", "", "", "", ""); 499 EXPECT_EQ(result, expected); 500 } 501 } 502 503 template <typename IntType> 504 void CheckHex(IntType v, const char* nopad_format, const char* zeropad_format, 505 const char* spacepad_format) { 506 char expected[256]; 507 508 std::string actual = absl::StrCat(absl::Hex(v, absl::kNoPad)); 509 snprintf(expected, sizeof(expected), nopad_format, v); 510 EXPECT_EQ(expected, actual) << " decimal value " << v; 511 512 for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad20; ++spec) { 513 std::string actual = 514 absl::StrCat(absl::Hex(v, static_cast<absl::PadSpec>(spec))); 515 snprintf(expected, sizeof(expected), zeropad_format, 516 spec - absl::kZeroPad2 + 2, v); 517 EXPECT_EQ(expected, actual) << " decimal value " << v; 518 } 519 520 for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad20; ++spec) { 521 std::string actual = 522 absl::StrCat(absl::Hex(v, static_cast<absl::PadSpec>(spec))); 523 snprintf(expected, sizeof(expected), spacepad_format, 524 spec - absl::kSpacePad2 + 2, v); 525 EXPECT_EQ(expected, actual) << " decimal value " << v; 526 } 527 } 528 529 template <typename IntType> 530 void CheckDec(IntType v, const char* nopad_format, const char* zeropad_format, 531 const char* spacepad_format) { 532 char expected[256]; 533 534 std::string actual = absl::StrCat(absl::Dec(v, absl::kNoPad)); 535 snprintf(expected, sizeof(expected), nopad_format, v); 536 EXPECT_EQ(expected, actual) << " decimal value " << v; 537 538 for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad20; ++spec) { 539 std::string actual = 540 absl::StrCat(absl::Dec(v, static_cast<absl::PadSpec>(spec))); 541 snprintf(expected, sizeof(expected), zeropad_format, 542 spec - absl::kZeroPad2 + 2, v); 543 EXPECT_EQ(expected, actual) 544 << " decimal value " << v << " format '" << zeropad_format 545 << "' digits " << (spec - absl::kZeroPad2 + 2); 546 } 547 548 for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad20; ++spec) { 549 std::string actual = 550 absl::StrCat(absl::Dec(v, static_cast<absl::PadSpec>(spec))); 551 snprintf(expected, sizeof(expected), spacepad_format, 552 spec - absl::kSpacePad2 + 2, v); 553 EXPECT_EQ(expected, actual) 554 << " decimal value " << v << " format '" << spacepad_format 555 << "' digits " << (spec - absl::kSpacePad2 + 2); 556 } 557 } 558 559 void CheckHexDec64(uint64_t v) { 560 unsigned long long ullv = v; // NOLINT(runtime/int) 561 562 CheckHex(ullv, "%llx", "%0*llx", "%*llx"); 563 CheckDec(ullv, "%llu", "%0*llu", "%*llu"); 564 565 long long llv = static_cast<long long>(ullv); // NOLINT(runtime/int) 566 CheckDec(llv, "%lld", "%0*lld", "%*lld"); 567 568 if (sizeof(v) == sizeof(&v)) { 569 auto uintptr = static_cast<uintptr_t>(v); 570 void* ptr = reinterpret_cast<void*>(uintptr); 571 CheckHex(ptr, "%llx", "%0*llx", "%*llx"); 572 } 573 } 574 575 void CheckHexDec32(uint32_t uv) { 576 CheckHex(uv, "%x", "%0*x", "%*x"); 577 CheckDec(uv, "%u", "%0*u", "%*u"); 578 int32_t v = static_cast<int32_t>(uv); 579 CheckDec(v, "%d", "%0*d", "%*d"); 580 581 if (sizeof(v) == sizeof(&v)) { 582 auto uintptr = static_cast<uintptr_t>(v); 583 void* ptr = reinterpret_cast<void*>(uintptr); 584 CheckHex(ptr, "%x", "%0*x", "%*x"); 585 } 586 } 587 588 void CheckAll(uint64_t v) { 589 CheckHexDec64(v); 590 CheckHexDec32(static_cast<uint32_t>(v)); 591 } 592 593 void TestFastPrints() { 594 // Test all small ints; there aren't many and they're common. 595 for (int i = 0; i < 10000; i++) { 596 CheckAll(i); 597 } 598 599 CheckAll(std::numeric_limits<uint64_t>::max()); 600 CheckAll(std::numeric_limits<uint64_t>::max() - 1); 601 CheckAll(std::numeric_limits<int64_t>::min()); 602 CheckAll(std::numeric_limits<int64_t>::min() + 1); 603 CheckAll(std::numeric_limits<uint32_t>::max()); 604 CheckAll(std::numeric_limits<uint32_t>::max() - 1); 605 CheckAll(std::numeric_limits<int32_t>::min()); 606 CheckAll(std::numeric_limits<int32_t>::min() + 1); 607 CheckAll(999999999); // fits in 32 bits 608 CheckAll(1000000000); // fits in 32 bits 609 CheckAll(9999999999); // doesn't fit in 32 bits 610 CheckAll(10000000000); // doesn't fit in 32 bits 611 CheckAll(999999999999999999); // fits in signed 64-bit 612 CheckAll(9999999999999999999u); // fits in unsigned 64-bit, but not signed. 613 CheckAll(1000000000000000000); // fits in signed 64-bit 614 CheckAll(10000000000000000000u); // fits in unsigned 64-bit, but not signed. 615 616 CheckAll(999999999876543210); // check all decimal digits, signed 617 CheckAll(9999999999876543210u); // check all decimal digits, unsigned. 618 CheckAll(0x123456789abcdef0); // check all hex digits 619 CheckAll(0x12345678); 620 621 int8_t minus_one_8bit = -1; 622 EXPECT_EQ("ff", absl::StrCat(absl::Hex(minus_one_8bit))); 623 624 int16_t minus_one_16bit = -1; 625 EXPECT_EQ("ffff", absl::StrCat(absl::Hex(minus_one_16bit))); 626 } 627 628 TEST(Numbers, TestFunctionsMovedOverFromNumbersMain) { 629 TestFastPrints(); 630 } 631 632 struct PointStringify { 633 template <typename FormatSink> 634 friend void AbslStringify(FormatSink& sink, const PointStringify& p) { 635 sink.Append("("); 636 sink.Append(absl::StrCat(p.x)); 637 sink.Append(", "); 638 sink.Append(absl::StrCat(p.y)); 639 sink.Append(")"); 640 } 641 642 double x = 10.0; 643 double y = 20.0; 644 }; 645 646 TEST(StrCat, AbslStringifyExample) { 647 PointStringify p; 648 EXPECT_EQ(absl::StrCat(p), "(10, 20)"); 649 EXPECT_EQ(absl::StrCat("a ", p, " z"), "a (10, 20) z"); 650 } 651 652 struct PointStringifyUsingFormat { 653 template <typename FormatSink> 654 friend void AbslStringify(FormatSink& sink, 655 const PointStringifyUsingFormat& p) { 656 absl::Format(&sink, "(%g, %g)", p.x, p.y); 657 } 658 659 double x = 10.0; 660 double y = 20.0; 661 }; 662 663 TEST(StrCat, AbslStringifyExampleUsingFormat) { 664 PointStringifyUsingFormat p; 665 EXPECT_EQ(absl::StrCat(p), "(10, 20)"); 666 EXPECT_EQ(absl::StrCat("a ", p, " z"), "a (10, 20) z"); 667 } 668 669 enum class EnumWithStringify { Many = 0, Choices = 1 }; 670 671 template <typename Sink> 672 void AbslStringify(Sink& sink, EnumWithStringify e) { 673 absl::Format(&sink, "%s", e == EnumWithStringify::Many ? "Many" : "Choices"); 674 } 675 676 TEST(StrCat, AbslStringifyWithEnum) { 677 const auto e = EnumWithStringify::Choices; 678 EXPECT_EQ(absl::StrCat(e), "Choices"); 679 } 680 681 template <typename Integer> 682 void CheckSingleArgumentIntegerLimits() { 683 Integer max = std::numeric_limits<Integer>::max(); 684 Integer min = std::numeric_limits<Integer>::min(); 685 686 EXPECT_EQ(absl::StrCat(max), std::to_string(max)); 687 EXPECT_EQ(absl::StrCat(min), std::to_string(min)); 688 } 689 690 TEST(StrCat, SingleArgumentLimits) { 691 CheckSingleArgumentIntegerLimits<int32_t>(); 692 CheckSingleArgumentIntegerLimits<uint32_t>(); 693 CheckSingleArgumentIntegerLimits<int64_t>(); 694 CheckSingleArgumentIntegerLimits<uint64_t>(); 695 } 696 697 } // namespace