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