1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/strings/string_number_conversions.h"
6
7 #include <errno.h>
8 #include <limits.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 #include <stdio.h>
12
13 #include <cmath>
14 #include <limits>
15
16 #include <gtest/gtest.h>
17
18 #include "base/macros.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversion_utils.h"
21
22 namespace base {
23
24 namespace {
25
26 template <typename INT>
27 struct IntToStringTest {
28 INT num;
29 const char* sexpected;
30 const char* uexpected;
31 };
32
33 } // namespace
34
TEST(StringNumberConversionsTest,IntToString)35 TEST(StringNumberConversionsTest, IntToString) {
36 static const IntToStringTest<int> int_tests[] = {
37 { 0, "0", "0" },
38 { -1, "-1", "4294967295" },
39 { std::numeric_limits<int>::max(), "2147483647", "2147483647" },
40 { std::numeric_limits<int>::min(), "-2147483648", "2147483648" },
41 };
42 static const IntToStringTest<int64_t> int64_tests[] = {
43 {0, "0", "0"},
44 {-1, "-1", "18446744073709551615"},
45 {
46 std::numeric_limits<int64_t>::max(), "9223372036854775807",
47 "9223372036854775807",
48 },
49 {std::numeric_limits<int64_t>::min(), "-9223372036854775808",
50 "9223372036854775808"},
51 };
52
53 for (size_t i = 0; i < arraysize(int_tests); ++i) {
54 const IntToStringTest<int>* test = &int_tests[i];
55 EXPECT_EQ(IntToString(test->num), test->sexpected);
56 EXPECT_EQ(UintToString(test->num), test->uexpected);
57 }
58 for (size_t i = 0; i < arraysize(int64_tests); ++i) {
59 const IntToStringTest<int64_t>* test = &int64_tests[i];
60 EXPECT_EQ(Int64ToString(test->num), test->sexpected);
61 EXPECT_EQ(Uint64ToString(test->num), test->uexpected);
62 }
63 }
64
TEST(StringNumberConversionsTest,Uint64ToString)65 TEST(StringNumberConversionsTest, Uint64ToString) {
66 static const struct {
67 uint64_t input;
68 std::string output;
69 } cases[] = {
70 {0, "0"},
71 {42, "42"},
72 {INT_MAX, "2147483647"},
73 {std::numeric_limits<uint64_t>::max(), "18446744073709551615"},
74 };
75
76 for (size_t i = 0; i < arraysize(cases); ++i)
77 EXPECT_EQ(cases[i].output, Uint64ToString(cases[i].input));
78 }
79
TEST(StringNumberConversionsTest,SizeTToString)80 TEST(StringNumberConversionsTest, SizeTToString) {
81 size_t size_t_max = std::numeric_limits<size_t>::max();
82 std::string size_t_max_string = std::to_string(size_t_max);
83
84 static const struct {
85 size_t input;
86 std::string output;
87 } cases[] = {
88 {0, "0"},
89 {9, "9"},
90 {42, "42"},
91 {INT_MAX, "2147483647"},
92 {2147483648U, "2147483648"},
93 #if SIZE_MAX > 4294967295U
94 {99999999999U, "99999999999"},
95 #endif
96 {size_t_max, size_t_max_string},
97 };
98
99 for (size_t i = 0; i < arraysize(cases); ++i)
100 EXPECT_EQ(cases[i].output, Uint64ToString(cases[i].input));
101 }
102
TEST(StringNumberConversionsTest,StringToInt)103 TEST(StringNumberConversionsTest, StringToInt) {
104 static const struct {
105 std::string input;
106 int output;
107 bool success;
108 } cases[] = {
109 {"0", 0, true},
110 {"42", 42, true},
111 {"42\x99", 42, false},
112 {"\x99" "42\x99", 0, false},
113 {"-2147483648", INT_MIN, true},
114 {"2147483647", INT_MAX, true},
115 {"", 0, false},
116 {" 42", 42, false},
117 {"42 ", 42, false},
118 {"\t\n\v\f\r 42", 42, false},
119 {"blah42", 0, false},
120 {"42blah", 42, false},
121 {"blah42blah", 0, false},
122 {"-273.15", -273, false},
123 {"+98.6", 98, false},
124 {"--123", 0, false},
125 {"++123", 0, false},
126 {"-+123", 0, false},
127 {"+-123", 0, false},
128 {"-", 0, false},
129 {"-2147483649", INT_MIN, false},
130 {"-99999999999", INT_MIN, false},
131 {"2147483648", INT_MAX, false},
132 {"99999999999", INT_MAX, false},
133 };
134
135 for (size_t i = 0; i < arraysize(cases); ++i) {
136 int output = 0;
137 EXPECT_EQ(cases[i].success, StringToInt(cases[i].input, &output));
138 EXPECT_EQ(cases[i].output, output);
139 }
140
141 // One additional test to verify that conversion of numbers in strings with
142 // embedded NUL characters. The NUL and extra data after it should be
143 // interpreted as junk after the number.
144 const char input[] = "6\06";
145 std::string input_string(input, arraysize(input) - 1);
146 int output;
147 EXPECT_FALSE(StringToInt(input_string, &output));
148 EXPECT_EQ(6, output);
149 }
150
TEST(StringNumberConversionsTest,StringToUint)151 TEST(StringNumberConversionsTest, StringToUint) {
152 static const struct {
153 std::string input;
154 unsigned output;
155 bool success;
156 } cases[] = {
157 {"0", 0, true},
158 {"42", 42, true},
159 {"42\x99", 42, false},
160 {"\x99" "42\x99", 0, false},
161 {"-2147483648", 0, false},
162 {"2147483647", INT_MAX, true},
163 {"", 0, false},
164 {" 42", 42, false},
165 {"42 ", 42, false},
166 {"\t\n\v\f\r 42", 42, false},
167 {"blah42", 0, false},
168 {"42blah", 42, false},
169 {"blah42blah", 0, false},
170 {"-273.15", 0, false},
171 {"+98.6", 98, false},
172 {"--123", 0, false},
173 {"++123", 0, false},
174 {"-+123", 0, false},
175 {"+-123", 0, false},
176 {"-", 0, false},
177 {"-2147483649", 0, false},
178 {"-99999999999", 0, false},
179 {"4294967295", UINT_MAX, true},
180 {"4294967296", UINT_MAX, false},
181 {"99999999999", UINT_MAX, false},
182 };
183
184 for (size_t i = 0; i < arraysize(cases); ++i) {
185 unsigned output = 0;
186 EXPECT_EQ(cases[i].success, StringToUint(cases[i].input, &output));
187 EXPECT_EQ(cases[i].output, output);
188 }
189
190 // One additional test to verify that conversion of numbers in strings with
191 // embedded NUL characters. The NUL and extra data after it should be
192 // interpreted as junk after the number.
193 const char input[] = "6\06";
194 std::string input_string(input, arraysize(input) - 1);
195 unsigned output;
196 EXPECT_FALSE(StringToUint(input_string, &output));
197 EXPECT_EQ(6U, output);
198 }
199
TEST(StringNumberConversionsTest,StringToInt64)200 TEST(StringNumberConversionsTest, StringToInt64) {
201 static const struct {
202 std::string input;
203 int64_t output;
204 bool success;
205 } cases[] = {
206 {"0", 0, true},
207 {"42", 42, true},
208 {"-2147483648", INT_MIN, true},
209 {"2147483647", INT_MAX, true},
210 {"-2147483649", INT64_C(-2147483649), true},
211 {"-99999999999", INT64_C(-99999999999), true},
212 {"2147483648", INT64_C(2147483648), true},
213 {"99999999999", INT64_C(99999999999), true},
214 {"9223372036854775807", std::numeric_limits<int64_t>::max(), true},
215 {"-9223372036854775808", std::numeric_limits<int64_t>::min(), true},
216 {"09", 9, true},
217 {"-09", -9, true},
218 {"", 0, false},
219 {" 42", 42, false},
220 {"42 ", 42, false},
221 {"0x42", 0, false},
222 {"\t\n\v\f\r 42", 42, false},
223 {"blah42", 0, false},
224 {"42blah", 42, false},
225 {"blah42blah", 0, false},
226 {"-273.15", -273, false},
227 {"+98.6", 98, false},
228 {"--123", 0, false},
229 {"++123", 0, false},
230 {"-+123", 0, false},
231 {"+-123", 0, false},
232 {"-", 0, false},
233 {"-9223372036854775809", std::numeric_limits<int64_t>::min(), false},
234 {"-99999999999999999999", std::numeric_limits<int64_t>::min(), false},
235 {"9223372036854775808", std::numeric_limits<int64_t>::max(), false},
236 {"99999999999999999999", std::numeric_limits<int64_t>::max(), false},
237 };
238
239 for (size_t i = 0; i < arraysize(cases); ++i) {
240 int64_t output = 0;
241 EXPECT_EQ(cases[i].success, StringToInt64(cases[i].input, &output));
242 EXPECT_EQ(cases[i].output, output);
243 }
244
245 // One additional test to verify that conversion of numbers in strings with
246 // embedded NUL characters. The NUL and extra data after it should be
247 // interpreted as junk after the number.
248 const char input[] = "6\06";
249 std::string input_string(input, arraysize(input) - 1);
250 int64_t output;
251 EXPECT_FALSE(StringToInt64(input_string, &output));
252 EXPECT_EQ(6, output);
253 }
254
TEST(StringNumberConversionsTest,StringToUint64)255 TEST(StringNumberConversionsTest, StringToUint64) {
256 static const struct {
257 std::string input;
258 uint64_t output;
259 bool success;
260 } cases[] = {
261 {"0", 0, true},
262 {"42", 42, true},
263 {"-2147483648", 0, false},
264 {"2147483647", INT_MAX, true},
265 {"-2147483649", 0, false},
266 {"-99999999999", 0, false},
267 {"2147483648", UINT64_C(2147483648), true},
268 {"99999999999", UINT64_C(99999999999), true},
269 {"9223372036854775807", std::numeric_limits<int64_t>::max(), true},
270 {"-9223372036854775808", 0, false},
271 {"09", 9, true},
272 {"-09", 0, false},
273 {"", 0, false},
274 {" 42", 42, false},
275 {"42 ", 42, false},
276 {"0x42", 0, false},
277 {"\t\n\v\f\r 42", 42, false},
278 {"blah42", 0, false},
279 {"42blah", 42, false},
280 {"blah42blah", 0, false},
281 {"-273.15", 0, false},
282 {"+98.6", 98, false},
283 {"--123", 0, false},
284 {"++123", 0, false},
285 {"-+123", 0, false},
286 {"+-123", 0, false},
287 {"-", 0, false},
288 {"-9223372036854775809", 0, false},
289 {"-99999999999999999999", 0, false},
290 {"9223372036854775808", UINT64_C(9223372036854775808), true},
291 {"99999999999999999999", std::numeric_limits<uint64_t>::max(), false},
292 {"18446744073709551615", std::numeric_limits<uint64_t>::max(), true},
293 {"18446744073709551616", std::numeric_limits<uint64_t>::max(), false},
294 };
295
296 for (size_t i = 0; i < arraysize(cases); ++i) {
297 uint64_t output = 0;
298 EXPECT_EQ(cases[i].success, StringToUint64(cases[i].input, &output));
299 EXPECT_EQ(cases[i].output, output);
300 }
301
302 // One additional test to verify that conversion of numbers in strings with
303 // embedded NUL characters. The NUL and extra data after it should be
304 // interpreted as junk after the number.
305 const char input[] = "6\06";
306 std::string input_string(input, arraysize(input) - 1);
307 uint64_t output;
308 EXPECT_FALSE(StringToUint64(input_string, &output));
309 EXPECT_EQ(6U, output);
310 }
311
TEST(StringNumberConversionsTest,StringToSizeT)312 TEST(StringNumberConversionsTest, StringToSizeT) {
313 size_t size_t_max = std::numeric_limits<size_t>::max();
314 std::string size_t_max_string = std::to_string(size_t_max);
315
316 static const struct {
317 std::string input;
318 size_t output;
319 bool success;
320 } cases[] = {
321 {"0", 0, true},
322 {"42", 42, true},
323 {"-2147483648", 0, false},
324 {"2147483647", INT_MAX, true},
325 {"-2147483649", 0, false},
326 {"-99999999999", 0, false},
327 {"2147483648", 2147483648U, true},
328 #if SIZE_MAX > 4294967295U
329 {"99999999999", 99999999999U, true},
330 #endif
331 {"-9223372036854775808", 0, false},
332 {"09", 9, true},
333 {"-09", 0, false},
334 {"", 0, false},
335 {" 42", 42, false},
336 {"42 ", 42, false},
337 {"0x42", 0, false},
338 {"\t\n\v\f\r 42", 42, false},
339 {"blah42", 0, false},
340 {"42blah", 42, false},
341 {"blah42blah", 0, false},
342 {"-273.15", 0, false},
343 {"+98.6", 98, false},
344 {"--123", 0, false},
345 {"++123", 0, false},
346 {"-+123", 0, false},
347 {"+-123", 0, false},
348 {"-", 0, false},
349 {"-9223372036854775809", 0, false},
350 {"-99999999999999999999", 0, false},
351 {"999999999999999999999999", size_t_max, false},
352 {size_t_max_string, size_t_max, true},
353 };
354
355 for (size_t i = 0; i < arraysize(cases); ++i) {
356 size_t output = 0;
357 EXPECT_EQ(cases[i].success, StringToSizeT(cases[i].input, &output));
358 EXPECT_EQ(cases[i].output, output);
359 }
360
361 // One additional test to verify that conversion of numbers in strings with
362 // embedded NUL characters. The NUL and extra data after it should be
363 // interpreted as junk after the number.
364 const char input[] = "6\06";
365 std::string input_string(input, arraysize(input) - 1);
366 size_t output;
367 EXPECT_FALSE(StringToSizeT(input_string, &output));
368 EXPECT_EQ(6U, output);
369 }
370
TEST(StringNumberConversionsTest,HexStringToInt)371 TEST(StringNumberConversionsTest, HexStringToInt) {
372 static const struct {
373 std::string input;
374 int64_t output;
375 bool success;
376 } cases[] = {
377 {"0", 0, true},
378 {"42", 66, true},
379 {"-42", -66, true},
380 {"+42", 66, true},
381 {"7fffffff", INT_MAX, true},
382 {"-80000000", INT_MIN, true},
383 {"80000000", INT_MAX, false}, // Overflow test.
384 {"-80000001", INT_MIN, false}, // Underflow test.
385 {"0x42", 66, true},
386 {"-0x42", -66, true},
387 {"+0x42", 66, true},
388 {"0x7fffffff", INT_MAX, true},
389 {"-0x80000000", INT_MIN, true},
390 {"-80000000", INT_MIN, true},
391 {"80000000", INT_MAX, false}, // Overflow test.
392 {"-80000001", INT_MIN, false}, // Underflow test.
393 {"0x0f", 15, true},
394 {"0f", 15, true},
395 {" 45", 0x45, false},
396 {"\t\n\v\f\r 0x45", 0x45, false},
397 {" 45", 0x45, false},
398 {"45 ", 0x45, false},
399 {"45:", 0x45, false},
400 {"efgh", 0xef, false},
401 {"0xefgh", 0xef, false},
402 {"hgfe", 0, false},
403 {"-", 0, false},
404 {"", 0, false},
405 {"0x", 0, false},
406 };
407
408 for (size_t i = 0; i < arraysize(cases); ++i) {
409 int output = 0;
410 EXPECT_EQ(cases[i].success, HexStringToInt(cases[i].input, &output));
411 EXPECT_EQ(cases[i].output, output);
412 }
413 // One additional test to verify that conversion of numbers in strings with
414 // embedded NUL characters. The NUL and extra data after it should be
415 // interpreted as junk after the number.
416 const char input[] = "0xc0ffee\0" "9";
417 std::string input_string(input, arraysize(input) - 1);
418 int output;
419 EXPECT_FALSE(HexStringToInt(input_string, &output));
420 EXPECT_EQ(0xc0ffee, output);
421 }
422
TEST(StringNumberConversionsTest,HexStringToUInt)423 TEST(StringNumberConversionsTest, HexStringToUInt) {
424 static const struct {
425 std::string input;
426 uint32_t output;
427 bool success;
428 } cases[] = {
429 {"0", 0, true},
430 {"42", 0x42, true},
431 {"-42", 0, false},
432 {"+42", 0x42, true},
433 {"7fffffff", INT_MAX, true},
434 {"-80000000", 0, false},
435 {"ffffffff", 0xffffffff, true},
436 {"DeadBeef", 0xdeadbeef, true},
437 {"0x42", 0x42, true},
438 {"-0x42", 0, false},
439 {"+0x42", 0x42, true},
440 {"0x7fffffff", INT_MAX, true},
441 {"-0x80000000", 0, false},
442 {"0xffffffff", std::numeric_limits<uint32_t>::max(), true},
443 {"0XDeadBeef", 0xdeadbeef, true},
444 {"0x7fffffffffffffff", std::numeric_limits<uint32_t>::max(),
445 false}, // Overflow test.
446 {"-0x8000000000000000", 0, false},
447 {"0x8000000000000000", std::numeric_limits<uint32_t>::max(),
448 false}, // Overflow test.
449 {"-0x8000000000000001", 0, false},
450 {"0xFFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(),
451 false}, // Overflow test.
452 {"FFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(),
453 false}, // Overflow test.
454 {"0x0000000000000000", 0, true},
455 {"0000000000000000", 0, true},
456 {"1FFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(),
457 false}, // Overflow test.
458 {"0x0f", 0x0f, true},
459 {"0f", 0x0f, true},
460 {" 45", 0x45, false},
461 {"\t\n\v\f\r 0x45", 0x45, false},
462 {" 45", 0x45, false},
463 {"45 ", 0x45, false},
464 {"45:", 0x45, false},
465 {"efgh", 0xef, false},
466 {"0xefgh", 0xef, false},
467 {"hgfe", 0, false},
468 {"-", 0, false},
469 {"", 0, false},
470 {"0x", 0, false},
471 };
472
473 for (size_t i = 0; i < arraysize(cases); ++i) {
474 uint32_t output = 0;
475 EXPECT_EQ(cases[i].success, HexStringToUInt(cases[i].input, &output));
476 EXPECT_EQ(cases[i].output, output);
477 }
478 // One additional test to verify that conversion of numbers in strings with
479 // embedded NUL characters. The NUL and extra data after it should be
480 // interpreted as junk after the number.
481 const char input[] = "0xc0ffee\0" "9";
482 std::string input_string(input, arraysize(input) - 1);
483 uint32_t output;
484 EXPECT_FALSE(HexStringToUInt(input_string, &output));
485 EXPECT_EQ(0xc0ffeeU, output);
486 }
487
TEST(StringNumberConversionsTest,HexStringToInt64)488 TEST(StringNumberConversionsTest, HexStringToInt64) {
489 static const struct {
490 std::string input;
491 int64_t output;
492 bool success;
493 } cases[] = {
494 {"0", 0, true},
495 {"42", 66, true},
496 {"-42", -66, true},
497 {"+42", 66, true},
498 {"40acd88557b", INT64_C(4444444448123), true},
499 {"7fffffff", INT_MAX, true},
500 {"-80000000", INT_MIN, true},
501 {"ffffffff", 0xffffffff, true},
502 {"DeadBeef", 0xdeadbeef, true},
503 {"0x42", 66, true},
504 {"-0x42", -66, true},
505 {"+0x42", 66, true},
506 {"0x40acd88557b", INT64_C(4444444448123), true},
507 {"0x7fffffff", INT_MAX, true},
508 {"-0x80000000", INT_MIN, true},
509 {"0xffffffff", 0xffffffff, true},
510 {"0XDeadBeef", 0xdeadbeef, true},
511 {"0x7fffffffffffffff", std::numeric_limits<int64_t>::max(), true},
512 {"-0x8000000000000000", std::numeric_limits<int64_t>::min(), true},
513 {"0x8000000000000000", std::numeric_limits<int64_t>::max(),
514 false}, // Overflow test.
515 {"-0x8000000000000001", std::numeric_limits<int64_t>::min(),
516 false}, // Underflow test.
517 {"0x0f", 15, true},
518 {"0f", 15, true},
519 {" 45", 0x45, false},
520 {"\t\n\v\f\r 0x45", 0x45, false},
521 {" 45", 0x45, false},
522 {"45 ", 0x45, false},
523 {"45:", 0x45, false},
524 {"efgh", 0xef, false},
525 {"0xefgh", 0xef, false},
526 {"hgfe", 0, false},
527 {"-", 0, false},
528 {"", 0, false},
529 {"0x", 0, false},
530 };
531
532 for (size_t i = 0; i < arraysize(cases); ++i) {
533 int64_t output = 0;
534 EXPECT_EQ(cases[i].success, HexStringToInt64(cases[i].input, &output));
535 EXPECT_EQ(cases[i].output, output);
536 }
537 // One additional test to verify that conversion of numbers in strings with
538 // embedded NUL characters. The NUL and extra data after it should be
539 // interpreted as junk after the number.
540 const char input[] = "0xc0ffee\0" "9";
541 std::string input_string(input, arraysize(input) - 1);
542 int64_t output;
543 EXPECT_FALSE(HexStringToInt64(input_string, &output));
544 EXPECT_EQ(0xc0ffee, output);
545 }
546
TEST(StringNumberConversionsTest,HexStringToUInt64)547 TEST(StringNumberConversionsTest, HexStringToUInt64) {
548 static const struct {
549 std::string input;
550 uint64_t output;
551 bool success;
552 } cases[] = {
553 {"0", 0, true},
554 {"42", 66, true},
555 {"-42", 0, false},
556 {"+42", 66, true},
557 {"40acd88557b", INT64_C(4444444448123), true},
558 {"7fffffff", INT_MAX, true},
559 {"-80000000", 0, false},
560 {"ffffffff", 0xffffffff, true},
561 {"DeadBeef", 0xdeadbeef, true},
562 {"0x42", 66, true},
563 {"-0x42", 0, false},
564 {"+0x42", 66, true},
565 {"0x40acd88557b", INT64_C(4444444448123), true},
566 {"0x7fffffff", INT_MAX, true},
567 {"-0x80000000", 0, false},
568 {"0xffffffff", 0xffffffff, true},
569 {"0XDeadBeef", 0xdeadbeef, true},
570 {"0x7fffffffffffffff", std::numeric_limits<int64_t>::max(), true},
571 {"-0x8000000000000000", 0, false},
572 {"0x8000000000000000", UINT64_C(0x8000000000000000), true},
573 {"-0x8000000000000001", 0, false},
574 {"0xFFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(), true},
575 {"FFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(), true},
576 {"0x0000000000000000", 0, true},
577 {"0000000000000000", 0, true},
578 {"1FFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(),
579 false}, // Overflow test.
580 {"0x0f", 15, true},
581 {"0f", 15, true},
582 {" 45", 0x45, false},
583 {"\t\n\v\f\r 0x45", 0x45, false},
584 {" 45", 0x45, false},
585 {"45 ", 0x45, false},
586 {"45:", 0x45, false},
587 {"efgh", 0xef, false},
588 {"0xefgh", 0xef, false},
589 {"hgfe", 0, false},
590 {"-", 0, false},
591 {"", 0, false},
592 {"0x", 0, false},
593 };
594
595 for (size_t i = 0; i < arraysize(cases); ++i) {
596 uint64_t output = 0;
597 EXPECT_EQ(cases[i].success, HexStringToUInt64(cases[i].input, &output));
598 EXPECT_EQ(cases[i].output, output);
599 }
600 // One additional test to verify that conversion of numbers in strings with
601 // embedded NUL characters. The NUL and extra data after it should be
602 // interpreted as junk after the number.
603 const char input[] = "0xc0ffee\0" "9";
604 std::string input_string(input, arraysize(input) - 1);
605 uint64_t output;
606 EXPECT_FALSE(HexStringToUInt64(input_string, &output));
607 EXPECT_EQ(0xc0ffeeU, output);
608 }
609
TEST(StringNumberConversionsTest,HexStringToBytes)610 TEST(StringNumberConversionsTest, HexStringToBytes) {
611 static const struct {
612 const std::string input;
613 const char* output;
614 size_t output_len;
615 bool success;
616 } cases[] = {
617 {"0", "", 0, false}, // odd number of characters fails
618 {"00", "\0", 1, true},
619 {"42", "\x42", 1, true},
620 {"-42", "", 0, false}, // any non-hex value fails
621 {"+42", "", 0, false},
622 {"7fffffff", "\x7f\xff\xff\xff", 4, true},
623 {"80000000", "\x80\0\0\0", 4, true},
624 {"deadbeef", "\xde\xad\xbe\xef", 4, true},
625 {"DeadBeef", "\xde\xad\xbe\xef", 4, true},
626 {"0x42", "", 0, false}, // leading 0x fails (x is not hex)
627 {"0f", "\xf", 1, true},
628 {"45 ", "\x45", 1, false},
629 {"efgh", "\xef", 1, false},
630 {"", "", 0, false},
631 {"0123456789ABCDEF", "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8, true},
632 {"0123456789ABCDEF012345",
633 "\x01\x23\x45\x67\x89\xAB\xCD\xEF\x01\x23\x45", 11, true},
634 };
635
636
637 for (size_t i = 0; i < arraysize(cases); ++i) {
638 std::vector<uint8_t> output;
639 std::vector<uint8_t> compare;
640 EXPECT_EQ(cases[i].success, HexStringToBytes(cases[i].input, &output)) <<
641 i << ": " << cases[i].input;
642 for (size_t j = 0; j < cases[i].output_len; ++j)
643 compare.push_back(static_cast<uint8_t>(cases[i].output[j]));
644 ASSERT_EQ(output.size(), compare.size()) << i << ": " << cases[i].input;
645 EXPECT_TRUE(std::equal(output.begin(), output.end(), compare.begin())) <<
646 i << ": " << cases[i].input;
647 }
648 }
649
TEST(StringNumberConversionsTest,StringToDouble)650 TEST(StringNumberConversionsTest, StringToDouble) {
651 static const struct {
652 std::string input;
653 double output;
654 bool success;
655 } cases[] = {
656 {"0", 0.0, true},
657 {"42", 42.0, true},
658 {"-42", -42.0, true},
659 {"123.45", 123.45, true},
660 {"-123.45", -123.45, true},
661 {"+123.45", 123.45, true},
662 {"2.99792458e8", 299792458.0, true},
663 {"149597870.691E+3", 149597870691.0, true},
664 {"6.", 6.0, true},
665 {"9e99999999999999999999", std::numeric_limits<double>::infinity(),
666 false},
667 {"-9e99999999999999999999", -std::numeric_limits<double>::infinity(),
668 false},
669 {"1e-2", 0.01, true},
670 {"42 ", 42.0, false},
671 {" 1e-2", 0.01, false},
672 {"1e-2 ", 0.01, false},
673 {"-1E-7", -0.0000001, true},
674 {"01e02", 100, true},
675 {"2.3e15", 2.3e15, true},
676 {"\t\n\v\f\r -123.45e2", -12345.0, false},
677 {"+123 e4", 123.0, false},
678 {"123e ", 123.0, false},
679 {"123e", 123.0, false},
680 {" 2.99", 2.99, false},
681 {"1e3.4", 1000.0, false},
682 {"nothing", 0.0, false},
683 {"-", 0.0, false},
684 {"+", 0.0, false},
685 {"", 0.0, false},
686 };
687
688 for (size_t i = 0; i < arraysize(cases); ++i) {
689 double output;
690 errno = 1;
691 EXPECT_EQ(cases[i].success, StringToDouble(cases[i].input, &output))
692 << "for input=" << cases[i].input << "got output=" << output;
693 if (cases[i].success)
694 EXPECT_EQ(1, errno) << i; // confirm that errno is unchanged.
695 EXPECT_DOUBLE_EQ(cases[i].output, output);
696 }
697
698 // One additional test to verify that conversion of numbers in strings with
699 // embedded NUL characters. The NUL and extra data after it should be
700 // interpreted as junk after the number.
701 const char input[] = "3.14\0" "159";
702 std::string input_string(input, arraysize(input) - 1);
703 double output;
704 EXPECT_FALSE(StringToDouble(input_string, &output));
705 EXPECT_DOUBLE_EQ(3.14, output);
706 }
707
TEST(StringNumberConversionsTest,DoubleToString)708 TEST(StringNumberConversionsTest, DoubleToString) {
709 static const struct {
710 double input;
711 const char* expected;
712 } cases[] = {
713 {0.0, "0.0"},
714 {1.25, "1.25"},
715 {1.33518e+012, "1335180000000.0"},
716 {1.33489e+012, "1334890000000.0"},
717 {1.33505e+012, "1335050000000.0"},
718 {1.33545e+009, "1335450000.0"},
719 {1.33503e+009, "1335030000.0"},
720 };
721
722 for (size_t i = 0; i < arraysize(cases); ++i) {
723 EXPECT_EQ(cases[i].expected, DoubleToString(cases[i].input));
724 }
725
726 // The following two values were seen in crashes in the wild.
727 const char input_bytes[8] = {0, 0, 0, 0, '\xee', '\x6d', '\x73', '\x42'};
728 double input = 0;
729 memcpy(&input, input_bytes, arraysize(input_bytes));
730 EXPECT_EQ("1335179083776.0", DoubleToString(input));
731 const char input_bytes2[8] =
732 {0, 0, 0, '\xa0', '\xda', '\x6c', '\x73', '\x42'};
733 input = 0;
734 memcpy(&input, input_bytes2, arraysize(input_bytes2));
735 EXPECT_EQ("1334890332160.0", DoubleToString(input));
736 }
737
TEST(StringNumberConversionsTest,HexEncode)738 TEST(StringNumberConversionsTest, HexEncode) {
739 std::string hex(HexEncode(NULL, 0));
740 EXPECT_EQ(hex.length(), 0U);
741 unsigned char bytes[] = {0x01, 0xff, 0x02, 0xfe, 0x03, 0x80, 0x81};
742 hex = HexEncode(bytes, sizeof(bytes));
743 EXPECT_EQ(hex.compare("01FF02FE038081"), 0);
744 }
745
746 } // namespace base
747