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