blob: be39880be78ef70d2282c3cc8654a01628e1c9c8 [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001// 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
36namespace {
37
38// Test absl::StrCat of ints and longs of various sizes and signdedness.
39TEST(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
69TEST(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
107TEST(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 std::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
198TEST(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().
214template <typename T>
215struct 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
224 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>
233 Mallocator(const Mallocator<U>&) {} // NOLINT(runtime/explicit)
234
235 T* allocate(size_t n) { return static_cast<T*>(std::malloc(n * sizeof(T))); }
236 void deallocate(T* p, size_t) { std::free(p); }
237};
238template <typename T, typename U>
239bool operator==(const Mallocator<T>&, const Mallocator<U>&) {
240 return true;
241}
242template <typename T, typename U>
243bool operator!=(const Mallocator<T>&, const Mallocator<U>&) {
244 return false;
245}
246
247TEST(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
260TEST(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
319TEST(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 std::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
414TEST(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.
428TEST(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
441TEST(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
451TEST(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
465TEST(StrAppend, CornerCasesNonEmptyAppend) {
466 for (std::string result : {"hello", "a std::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
481template <typename IntType>
482void 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
507template <typename IntType>
508void 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
537void 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
553void 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
566void CheckAll(uint64_t v) {
567 CheckHexDec64(v);
568 CheckHexDec32(static_cast<uint32_t>(v));
569}
570
571void 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
606TEST(Numbers, TestFunctionsMovedOverFromNumbersMain) {
607 TestFastPrints();
608}
609
610} // namespace