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