Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_string / type_to_string_test.cc
1 // Copyright 2019 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // 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, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_string/type_to_string.h"
16
17 #include <cmath>
18 #include <cstring>
19 #include <limits>
20 #include <string_view>
21
22 #include "gtest/gtest.h"
23
24 namespace pw::string {
25 namespace {
26
27 TEST(Digits, DecimalDigits_AllOneDigit) {
28   for (uint64_t i = 0; i < 10; ++i) {
29     ASSERT_EQ(1u, DecimalDigitCount(i));
30   }
31 }
32
33 TEST(Digits, DecimalDigits_AllTwoDigit) {
34   for (uint64_t i = 10; i < 100u; ++i) {
35     ASSERT_EQ(2u, DecimalDigitCount(i));
36   }
37 }
38
39 TEST(Digits, DecimalDigits_1To19Digits) {
40   uint64_t value = 1;
41   for (unsigned digits = 1; digits <= 19u; ++digits) {
42     ASSERT_EQ(digits, DecimalDigitCount(value));
43     ASSERT_EQ(digits, DecimalDigitCount(value + 1));
44
45     value *= 10;
46     ASSERT_EQ(digits, DecimalDigitCount(value - 1));
47   }
48 }
49
50 TEST(Digits, DecimalDigits_20) {
51   for (uint64_t i : {
52            10'000'000'000'000'000'000llu,
53            10'000'000'000'000'000'001llu,
54            std::numeric_limits<unsigned long long>::max(),
55        }) {
56     ASSERT_EQ(20u, DecimalDigitCount(i));
57   }
58 }
59
60 TEST(Digits, HexDigits_AllOneDigit) {
61   for (uint64_t i = 0; i < 0x10; ++i) {
62     ASSERT_EQ(1u, HexDigitCount(i));
63   }
64 }
65
66 TEST(Digits, HexDigits_AllTwoDigit) {
67   for (uint64_t i = 0x10; i < 0x100u; ++i) {
68     ASSERT_EQ(2u, HexDigitCount(i));
69   }
70 }
71
72 TEST(Digits, HexDigits_1To15Digits) {
73   uint64_t value = 1;
74   for (unsigned digits = 1; digits <= 15u; ++digits) {
75     ASSERT_EQ(digits, HexDigitCount(value));
76     ASSERT_EQ(digits, HexDigitCount(value + 1));
77
78     value *= 0x10;
79     ASSERT_EQ(digits, HexDigitCount(value - 1));
80   }
81 }
82
83 TEST(Digits, HexDigits_16) {
84   for (uint64_t i : {
85            0x1000000000000000llu,
86            0x1000000000000001llu,
87            std::numeric_limits<unsigned long long>::max(),
88        }) {
89     ASSERT_EQ(16u, HexDigitCount(i));
90   }
91 }
92
93 class TestWithBuffer : public ::testing::Test {
94  protected:
95   static constexpr char kStartingString[] = "!@#$%^&*()!@#$%^&*()";
96   static constexpr char kUint64Max[] = "18446744073709551615";
97   static constexpr char kInt64Min[] = "-9223372036854775808";
98   static constexpr char kInt64Max[] = "9223372036854775807";
99
100   static_assert(sizeof(kStartingString) == sizeof(kUint64Max));
101
102   TestWithBuffer() { std::memcpy(buffer_, kStartingString, sizeof(buffer_)); }
103
104   char buffer_[sizeof(kUint64Max)];
105 };
106
107 class IntToStringTest : public TestWithBuffer {};
108
109 TEST_F(IntToStringTest, Unsigned_EmptyBuffer_WritesNothing) {
110   auto result = IntToString(9u, std::span(buffer_, 0));
111   EXPECT_EQ(0u, result.size());
112   EXPECT_FALSE(result.ok());
113   EXPECT_STREQ(kStartingString, buffer_);
114 }
115
116 TEST_F(IntToStringTest, Unsigned_TooSmall_1Char_OnlyNullTerminates) {
117   auto result = IntToString(9u, std::span(buffer_, 1));
118   EXPECT_EQ(0u, result.size());
119   EXPECT_FALSE(result.ok());
120   EXPECT_STREQ("", buffer_);
121 }
122
123 TEST_F(IntToStringTest, Unsigned_TooSmall_2Chars_OnlyNullTerminates) {
124   auto result = IntToString(10u, std::span(buffer_, 2));
125   EXPECT_EQ(0u, result.size());
126   EXPECT_FALSE(result.ok());
127   EXPECT_STREQ("", buffer_);
128 }
129
130 TEST_F(IntToStringTest, Unsigned_TooSmall_3Chars_OnlyNullTerminates) {
131   auto result = IntToString(123u, std::span(buffer_, 3));
132   EXPECT_EQ(0u, result.size());
133   EXPECT_FALSE(result.ok());
134   EXPECT_STREQ("", buffer_);
135 }
136
137 TEST_F(IntToStringTest, Unsigned_1Char_FitsExactly) {
138   auto result = IntToString(0u, std::span(buffer_, 2));
139   EXPECT_EQ(1u, result.size());
140   EXPECT_TRUE(result.ok());
141   EXPECT_STREQ("0", buffer_);
142
143   result = IntToString(9u, std::span(buffer_, 2));
144   EXPECT_EQ(1u, result.size());
145   EXPECT_TRUE(result.ok());
146   EXPECT_STREQ("9", buffer_);
147 }
148
149 TEST_F(IntToStringTest, Unsigned_2Chars_FitsExactly) {
150   auto result = IntToString(10u, std::span(buffer_, 3));
151   EXPECT_EQ(2u, result.size());
152   EXPECT_STREQ("10", buffer_);
153 }
154
155 TEST_F(IntToStringTest, Unsigned_MaxFitsExactly) {
156   EXPECT_EQ(20u,
157             IntToString(std::numeric_limits<uint64_t>::max(),
158                         std::span(buffer_, sizeof(kUint64Max)))
159                 .size());
160   EXPECT_STREQ(kUint64Max, buffer_);
161 }
162
163 TEST_F(IntToStringTest, SignedPositive_EmptyBuffer_WritesNothing) {
164   auto result = IntToString(9, std::span(buffer_, 0));
165   EXPECT_EQ(0u, result.size());
166   EXPECT_FALSE(result.ok());
167   EXPECT_STREQ(kStartingString, buffer_);
168 }
169
170 TEST_F(IntToStringTest, SignedPositive_TooSmall_NullTerminates) {
171   auto result = IntToString(9, std::span(buffer_, 1));
172   EXPECT_EQ(0u, result.size());
173   EXPECT_FALSE(result.ok());
174   EXPECT_STREQ("", buffer_);
175 }
176
177 TEST_F(IntToStringTest, SignedPositive_TooSmall_DoesNotWritePastEnd) {
178   EXPECT_EQ(0u, IntToString(9, std::span(buffer_, 1)).size());
179   EXPECT_EQ(0, std::memcmp("\0@#$%^&*()!@#$%^&*()", buffer_, sizeof(buffer_)));
180 }
181
182 TEST_F(IntToStringTest, SignedPositive_1Char_FitsExactly) {
183   auto result = IntToString(0, std::span(buffer_, 2));
184   EXPECT_EQ(1u, result.size());
185   EXPECT_TRUE(result.ok());
186   EXPECT_STREQ("0", buffer_);
187
188   result = IntToString(9, std::span(buffer_, 2));
189   EXPECT_EQ(1u, result.size());
190   EXPECT_TRUE(result.ok());
191   EXPECT_STREQ("9", buffer_);
192 }
193
194 TEST_F(IntToStringTest, SignedPositive_2Chars_FitsExactly) {
195   auto result = IntToString(10, std::span(buffer_, 4));
196   EXPECT_EQ(2u, result.size());
197   EXPECT_TRUE(result.ok());
198   EXPECT_STREQ("10", buffer_);
199 }
200
201 TEST_F(IntToStringTest, SignedPositive_MaxFitsExactly) {
202   auto result = IntToString(std::numeric_limits<int64_t>::max(),
203                             std::span(buffer_, sizeof(kInt64Min)));
204   EXPECT_EQ(19u, result.size());
205   EXPECT_STREQ(kInt64Max, buffer_);
206 }
207
208 TEST_F(IntToStringTest, SignedNegative_EmptyBuffer_WritesNothing) {
209   auto result = IntToString(-9, std::span(buffer_, 0));
210   EXPECT_EQ(0u, result.size());
211   EXPECT_FALSE(result.ok());
212   EXPECT_STREQ(kStartingString, buffer_);
213 }
214
215 TEST_F(IntToStringTest, SignedNegative_TooSmall_NullTerminates) {
216   auto result = IntToString(-9, std::span(buffer_, 1));
217   EXPECT_EQ(0u, result.size());
218   EXPECT_FALSE(result.ok());
219   EXPECT_STREQ("", buffer_);
220 }
221
222 TEST_F(IntToStringTest, SignedNegative_TooSmall_DoesNotWritePastEnd) {
223   // Note that two \0 are written due to the unsigned IntToString call.
224   EXPECT_EQ(0u, IntToString(-9, std::span(buffer_, 2)).size());
225   EXPECT_EQ(0, std::memcmp("\0\0#$%^&*()!@#$%^&*()", buffer_, sizeof(buffer_)));
226 }
227
228 TEST_F(IntToStringTest, SignedNegative_FitsExactly) {
229   auto result = IntToString(-9, std::span(buffer_, 3));
230   EXPECT_EQ(2u, result.size());
231   EXPECT_STREQ("-9", buffer_);
232   result = IntToString(-99, std::span(buffer_, 4));
233   EXPECT_EQ(3u, result.size());
234   EXPECT_STREQ("-99", buffer_);
235   result = IntToString(-123, std::span(buffer_, 5));
236   EXPECT_EQ(4u, result.size());
237   EXPECT_STREQ("-123", buffer_);
238 }
239
240 TEST_F(IntToStringTest, SignedNegative_MinFitsExactly) {
241   auto result = IntToString(std::numeric_limits<int64_t>::min(),
242                             std::span(buffer_, sizeof(kInt64Min)));
243   EXPECT_EQ(20u, result.size());
244   EXPECT_STREQ(kInt64Min, buffer_);
245 }
246
247 TEST(IntToString, SignedSweep) {
248   for (int i = -1002; i <= 1002; ++i) {
249     char buffer[6];
250     char printf_buffer[6];
251     int written = std::snprintf(printf_buffer, sizeof(printf_buffer), "%d", i);
252     auto result = IntToString(i, buffer);
253     ASSERT_EQ(static_cast<size_t>(written), result.size());
254     ASSERT_STREQ(printf_buffer, buffer);
255   }
256 }
257
258 TEST(IntToString, UnsignedSweep) {
259   for (unsigned i = 0; i <= 1002u; ++i) {
260     char buffer[5];
261     char printf_buffer[5];
262     int written = std::snprintf(printf_buffer, sizeof(printf_buffer), "%u", i);
263     auto result = IntToString(i, buffer);
264     ASSERT_EQ(static_cast<size_t>(written), result.size());
265     ASSERT_STREQ(printf_buffer, buffer);
266   }
267 }
268
269 class IntToHexStringTest : public TestWithBuffer {};
270
271 TEST_F(IntToHexStringTest, Sweep) {
272   for (unsigned i = 0; i < 1030; ++i) {
273     char hex[16];
274     int bytes = std::snprintf(hex, sizeof(hex), "%x", static_cast<unsigned>(i));
275
276     auto result = IntToHexString(i, buffer_);
277     EXPECT_EQ(static_cast<size_t>(bytes), result.size());
278     EXPECT_TRUE(result.ok());
279     EXPECT_STREQ(hex, buffer_);
280   }
281 }
282
283 TEST_F(IntToHexStringTest, MinWidth) {
284   unsigned val = 0xbeef;
285   EXPECT_TRUE(IntToHexString(val, buffer_, 8).ok());
286   EXPECT_STREQ("0000beef", buffer_);
287 }
288
289 TEST_F(IntToHexStringTest, Uint32Max) {
290   EXPECT_EQ(
291       8u,
292       IntToHexString(std::numeric_limits<uint32_t>::max() - 1, buffer_).size());
293   EXPECT_STREQ("fffffffe", buffer_);
294
295   EXPECT_EQ(
296       8u, IntToHexString(std::numeric_limits<uint32_t>::max(), buffer_).size());
297   EXPECT_STREQ("ffffffff", buffer_);
298 }
299
300 TEST_F(IntToHexStringTest, Uint64Max) {
301   EXPECT_EQ(
302       16u,
303       IntToHexString(std::numeric_limits<uint64_t>::max() - 1, buffer_).size());
304   EXPECT_STREQ("fffffffffffffffe", buffer_);
305
306   EXPECT_EQ(
307       16u,
308       IntToHexString(std::numeric_limits<uint64_t>::max(), buffer_).size());
309   EXPECT_STREQ("ffffffffffffffff", buffer_);
310 }
311
312 TEST_F(IntToHexStringTest, EmptyBuffer_WritesNothing) {
313   auto result = IntToHexString(0xbeef, std::span(buffer_, 0));
314   EXPECT_EQ(0u, result.size());
315   EXPECT_FALSE(result.ok());
316   EXPECT_STREQ(kStartingString, buffer_);
317 }
318
319 TEST_F(IntToHexStringTest, TooSmall_Truncates) {
320   auto result = IntToHexString(0xbeef, std::span(buffer_, 3));
321   EXPECT_EQ(0u, result.size());
322   EXPECT_FALSE(result.ok());
323   EXPECT_STREQ("", buffer_);
324 }
325
326 class FloatAsIntToStringTest : public TestWithBuffer {};
327
328 TEST_F(FloatAsIntToStringTest, PositiveInfinity) {
329   EXPECT_EQ(3u, FloatAsIntToString(INFINITY, buffer_).size());
330   EXPECT_STREQ("inf", buffer_);
331 }
332
333 TEST_F(FloatAsIntToStringTest, NegativeInfinity) {
334   EXPECT_EQ(4u, FloatAsIntToString(-INFINITY, buffer_).size());
335   EXPECT_STREQ("-inf", buffer_);
336 }
337
338 TEST_F(FloatAsIntToStringTest, PositiveNan) {
339   EXPECT_EQ(3u, FloatAsIntToString(NAN, buffer_).size());
340   EXPECT_STREQ("NaN", buffer_);
341 }
342
343 TEST_F(FloatAsIntToStringTest, NegativeNan) {
344   EXPECT_EQ(4u, FloatAsIntToString(-NAN, buffer_).size());
345   EXPECT_STREQ("-NaN", buffer_);
346 }
347
348 TEST_F(FloatAsIntToStringTest, RoundDown_PrintsNearestInt) {
349   EXPECT_EQ(1u, FloatAsIntToString(1.23, buffer_).size());
350   EXPECT_STREQ("1", buffer_);
351 }
352
353 TEST_F(FloatAsIntToStringTest, RoundUp_PrintsNearestInt) {
354   EXPECT_EQ(4u, FloatAsIntToString(1234.5, buffer_).size());
355   EXPECT_STREQ("1235", buffer_);
356 }
357
358 TEST_F(FloatAsIntToStringTest, RoundsToNegativeZero_PrintsZero) {
359   EXPECT_EQ(1u, FloatAsIntToString(-3.14e-20f, buffer_).size());
360   EXPECT_STREQ("0", buffer_);
361 }
362
363 TEST_F(FloatAsIntToStringTest, RoundsToPositiveZero_PrintsZero) {
364   EXPECT_EQ(1u, FloatAsIntToString(3.14e-20f, buffer_).size());
365   EXPECT_STREQ("0", buffer_);
366 }
367
368 TEST_F(FloatAsIntToStringTest, RoundDownNegative_PrintsNearestInt) {
369   volatile float x = -5.9;
370   EXPECT_EQ(2u, FloatAsIntToString(x, buffer_).size());
371   EXPECT_STREQ("-6", buffer_);
372 }
373
374 TEST_F(FloatAsIntToStringTest, RoundUpNegative_PrintsNearestInt) {
375   EXPECT_EQ(9u, FloatAsIntToString(-50000000.1, buffer_).size());
376   EXPECT_STREQ("-50000000", buffer_);
377 }
378
379 TEST_F(FloatAsIntToStringTest, LargerThanInteger) {
380   EXPECT_EQ(3u, FloatAsIntToString(3.14e20f, buffer_).size());
381   EXPECT_STREQ("inf", buffer_);
382 }
383
384 TEST_F(FloatAsIntToStringTest, SmallerThanInteger) {
385   EXPECT_EQ(4u, FloatAsIntToString(-3.14e20f, buffer_).size());
386   EXPECT_STREQ("-inf", buffer_);
387 }
388
389 TEST_F(FloatAsIntToStringTest, TooSmall_Numeric_NullTerminates) {
390   auto result = FloatAsIntToString(-3.14e20f, std::span(buffer_, 1));
391   EXPECT_EQ(0u, result.size());
392   EXPECT_FALSE(result.ok());
393   EXPECT_STREQ("", buffer_);
394 }
395
396 TEST_F(FloatAsIntToStringTest, TooSmall_Infinity_NullTerminates) {
397   auto result = FloatAsIntToString(-INFINITY, std::span(buffer_, 3));
398   EXPECT_EQ(0u, result.size());
399   EXPECT_FALSE(result.ok());
400   EXPECT_STREQ("", buffer_);
401 }
402
403 TEST_F(FloatAsIntToStringTest, TooSmall_NaN_NullTerminates) {
404   auto result = FloatAsIntToString(NAN, std::span(buffer_, 2));
405   EXPECT_EQ(0u, result.size());
406   EXPECT_FALSE(result.ok());
407   EXPECT_STREQ("", buffer_);
408 }
409
410 class CopyStringTest : public TestWithBuffer {};
411
412 using namespace std::literals::string_view_literals;
413
414 TEST_F(CopyStringTest, EmptyStringView_WritesNullTerminator) {
415   EXPECT_EQ(0u, CopyString("", buffer_).size());
416   EXPECT_EQ('\0', buffer_[0]);
417 }
418
419 TEST_F(CopyStringTest, EmptyBuffer_WritesNothing) {
420   auto result = CopyString("Hello", std::span(buffer_, 0));
421   EXPECT_EQ(0u, result.size());
422   EXPECT_FALSE(result.ok());
423   EXPECT_STREQ(kStartingString, buffer_);
424 }
425
426 TEST_F(CopyStringTest, TooSmall_Truncates) {
427   auto result = CopyString("Hi!", std::span(buffer_, 3));
428   EXPECT_EQ(2u, result.size());
429   EXPECT_FALSE(result.ok());
430   EXPECT_STREQ("Hi", buffer_);
431 }
432
433 TEST_F(CopyStringTest, ExactFit) {
434   auto result = CopyString("Hi!", std::span(buffer_, 4));
435   EXPECT_EQ(3u, result.size());
436   EXPECT_TRUE(result.ok());
437   EXPECT_STREQ("Hi!", buffer_);
438 }
439
440 TEST_F(CopyStringTest, NullTerminatorsInString) {
441   ASSERT_EQ(4u, CopyString("\0!\0\0"sv, std::span(buffer_, 5)).size());
442   EXPECT_EQ("\0!\0\0"sv, std::string_view(buffer_, 4));
443 }
444
445 class CopyEntireStringTest : public TestWithBuffer {};
446
447 TEST_F(CopyEntireStringTest, EmptyStringView_WritesNullTerminator) {
448   EXPECT_EQ(0u, CopyEntireString("", buffer_).size());
449   EXPECT_EQ('\0', buffer_[0]);
450 }
451
452 TEST_F(CopyEntireStringTest, EmptyBuffer_WritesNothing) {
453   auto result = CopyEntireString("Hello", std::span(buffer_, 0));
454   EXPECT_EQ(0u, result.size());
455   EXPECT_FALSE(result.ok());
456   EXPECT_STREQ(kStartingString, buffer_);
457 }
458
459 TEST_F(CopyEntireStringTest, TooSmall_WritesNothing) {
460   auto result = CopyEntireString("Hi!", std::span(buffer_, 3));
461   EXPECT_EQ(0u, result.size());
462   EXPECT_FALSE(result.ok());
463   EXPECT_STREQ("", buffer_);
464 }
465
466 TEST_F(CopyEntireStringTest, ExactFit) {
467   auto result = CopyEntireString("Hi!", std::span(buffer_, 4));
468   EXPECT_EQ(3u, result.size());
469   EXPECT_TRUE(result.ok());
470   EXPECT_STREQ("Hi!", buffer_);
471 }
472
473 TEST_F(CopyEntireStringTest, NullTerminatorsInString) {
474   ASSERT_EQ(4u, CopyEntireString("\0!\0\0"sv, std::span(buffer_, 5)).size());
475   EXPECT_EQ("\0!\0\0"sv, std::string_view(buffer_, 4));
476 }
477
478 class PointerToStringTest : public TestWithBuffer {};
479
480 TEST_F(PointerToStringTest, Nullptr_WritesNull) {
481   EXPECT_EQ(6u, PointerToString(nullptr, std::span(buffer_, 7)).size());
482   EXPECT_STREQ("(null)", buffer_);
483 }
484
485 TEST_F(PointerToStringTest, WritesAddress) {
486   const void* pointer = reinterpret_cast<void*>(0xbeef);
487   EXPECT_EQ(4u, PointerToString(pointer, buffer_).size());
488   EXPECT_STREQ("beef", buffer_);
489 }
490
491 class BoolToStringTest : public TestWithBuffer {};
492
493 TEST_F(BoolToStringTest, ExactFit) {
494   EXPECT_EQ(4u, BoolToString(true, std::span(buffer_, 5)).size());
495   EXPECT_STREQ("true", buffer_);
496
497   EXPECT_EQ(5u, BoolToString(false, std::span(buffer_, 6)).size());
498   EXPECT_STREQ("false", buffer_);
499 }
500
501 TEST_F(BoolToStringTest, True_TooSmall_WritesNullTerminator) {
502   auto result = BoolToString(true, std::span(buffer_, 4));
503   EXPECT_EQ(0u, result.size());
504   EXPECT_FALSE(result.ok());
505   EXPECT_STREQ("", buffer_);
506 }
507
508 TEST_F(BoolToStringTest, False_TooSmall_WritesNullTerminator) {
509   auto result = BoolToString(false, std::span(buffer_, 5));
510   EXPECT_EQ(0u, result.size());
511   EXPECT_FALSE(result.ok());
512   EXPECT_STREQ("", buffer_);
513 }
514
515 TEST_F(BoolToStringTest, EmptyBuffer_WritesNothing) {
516   EXPECT_EQ(0u, BoolToString(true, std::span(buffer_, 0)).size());
517   EXPECT_STREQ(kStartingString, buffer_);
518
519   EXPECT_EQ(0u, BoolToString(false, std::span(buffer_, 0)).size());
520   EXPECT_STREQ(kStartingString, buffer_);
521 }
522
523 }  // namespace
524 }  // namespace pw::string