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