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