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