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