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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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