Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2010 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 <math.h>
      6 
      7 #include <limits>
      8 
      9 #include "base/string_number_conversions.h"
     10 #include "base/utf_string_conversions.h"
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 
     13 namespace base {
     14 
     15 namespace {
     16 
     17 template <typename INT>
     18 struct IntToStringTest {
     19   INT num;
     20   const char* sexpected;
     21   const char* uexpected;
     22 };
     23 
     24 }  // namespace
     25 
     26 TEST(StringNumberConversionsTest, IntToString) {
     27   static const IntToStringTest<int> int_tests[] = {
     28       { 0, "0", "0" },
     29       { -1, "-1", "4294967295" },
     30       { std::numeric_limits<int>::max(), "2147483647", "2147483647" },
     31       { std::numeric_limits<int>::min(), "-2147483648", "2147483648" },
     32   };
     33   static const IntToStringTest<int64> int64_tests[] = {
     34       { 0, "0", "0" },
     35       { -1, "-1", "18446744073709551615" },
     36       { std::numeric_limits<int64>::max(),
     37         "9223372036854775807",
     38         "9223372036854775807", },
     39       { std::numeric_limits<int64>::min(),
     40         "-9223372036854775808",
     41         "9223372036854775808" },
     42   };
     43 
     44   for (size_t i = 0; i < arraysize(int_tests); ++i) {
     45     const IntToStringTest<int>* test = &int_tests[i];
     46     EXPECT_EQ(IntToString(test->num), test->sexpected);
     47     EXPECT_EQ(IntToString16(test->num), UTF8ToUTF16(test->sexpected));
     48     EXPECT_EQ(UintToString(test->num), test->uexpected);
     49     EXPECT_EQ(UintToString16(test->num), UTF8ToUTF16(test->uexpected));
     50   }
     51   for (size_t i = 0; i < arraysize(int64_tests); ++i) {
     52     const IntToStringTest<int64>* test = &int64_tests[i];
     53     EXPECT_EQ(Int64ToString(test->num), test->sexpected);
     54     EXPECT_EQ(Int64ToString16(test->num), UTF8ToUTF16(test->sexpected));
     55     EXPECT_EQ(Uint64ToString(test->num), test->uexpected);
     56     EXPECT_EQ(Uint64ToString16(test->num), UTF8ToUTF16(test->uexpected));
     57   }
     58 }
     59 
     60 TEST(StringNumberConversionsTest, Uint64ToString) {
     61   static const struct {
     62     uint64 input;
     63     std::string output;
     64   } cases[] = {
     65     {0, "0"},
     66     {42, "42"},
     67     {INT_MAX, "2147483647"},
     68     {kuint64max, "18446744073709551615"},
     69   };
     70 
     71   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i)
     72     EXPECT_EQ(cases[i].output, Uint64ToString(cases[i].input));
     73 }
     74 
     75 TEST(StringNumberConversionsTest, StringToInt) {
     76   static const struct {
     77     std::string input;
     78     int output;
     79     bool success;
     80   } cases[] = {
     81     {"0", 0, true},
     82     {"42", 42, true},
     83     {"42\x99", 42, false},
     84     {"\x99" "42\x99", 0, false},
     85     {"-2147483648", INT_MIN, true},
     86     {"2147483647", INT_MAX, true},
     87     {"", 0, false},
     88     {" 42", 42, false},
     89     {"42 ", 42, false},
     90     {"\t\n\v\f\r 42", 42, false},
     91     {"blah42", 0, false},
     92     {"42blah", 42, false},
     93     {"blah42blah", 0, false},
     94     {"-273.15", -273, false},
     95     {"+98.6", 98, false},
     96     {"--123", 0, false},
     97     {"++123", 0, false},
     98     {"-+123", 0, false},
     99     {"+-123", 0, false},
    100     {"-", 0, false},
    101     {"-2147483649", INT_MIN, false},
    102     {"-99999999999", INT_MIN, false},
    103     {"2147483648", INT_MAX, false},
    104     {"99999999999", INT_MAX, false},
    105   };
    106 
    107   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
    108     const char* ascii_chars = cases[i].input.c_str();
    109     int output = 0;
    110     EXPECT_EQ(cases[i].success, StringToInt(cases[i].input, &output));
    111     EXPECT_EQ(cases[i].output, output);
    112     output = 0;
    113     EXPECT_EQ(cases[i].success, StringToInt(cases[i].input.begin(),
    114                                             cases[i].input.end(),
    115                                             &output));
    116     EXPECT_EQ(cases[i].output, output);
    117     output = 0;
    118     EXPECT_EQ(cases[i].success, StringToInt(
    119         ascii_chars, ascii_chars + cases[i].input.length(), &output));
    120     EXPECT_EQ(cases[i].output, output);
    121 
    122     string16 utf16_input = UTF8ToUTF16(cases[i].input);
    123     const char16* utf16_chars = utf16_input.c_str();
    124     output = 0;
    125     EXPECT_EQ(cases[i].success, StringToInt(utf16_input, &output));
    126     EXPECT_EQ(cases[i].output, output);
    127     output = 0;
    128     EXPECT_EQ(cases[i].success, StringToInt(utf16_input.begin(),
    129                                             utf16_input.end(),
    130                                             &output));
    131     EXPECT_EQ(cases[i].output, output);
    132     output = 0;
    133     EXPECT_EQ(cases[i].success, StringToInt(
    134         utf16_chars, utf16_chars + utf16_input.length(), &output));
    135     EXPECT_EQ(cases[i].output, output);
    136   }
    137 
    138   // One additional test to verify that conversion of numbers in strings with
    139   // embedded NUL characters.  The NUL and extra data after it should be
    140   // interpreted as junk after the number.
    141   const char input[] = "6\06";
    142   std::string input_string(input, arraysize(input) - 1);
    143   int output;
    144   EXPECT_FALSE(StringToInt(input_string, &output));
    145   EXPECT_EQ(6, output);
    146   output = 0;
    147   EXPECT_FALSE(StringToInt(input_string.begin(), input_string.end(), &output));
    148   EXPECT_EQ(6, output);
    149   output = 0;
    150   EXPECT_FALSE(StringToInt(input, input + arraysize(input), &output));
    151   EXPECT_EQ(6, output);
    152 
    153   string16 utf16_input = UTF8ToUTF16(input_string);
    154   const char16* utf16_chars = utf16_input.c_str();
    155   output = 0;
    156   EXPECT_FALSE(StringToInt(utf16_input, &output));
    157   EXPECT_EQ(6, output);
    158   output = 0;
    159   EXPECT_FALSE(StringToInt(utf16_input.begin(), utf16_input.end(), &output));
    160   EXPECT_EQ(6, output);
    161   output = 0;
    162   EXPECT_FALSE(StringToInt(utf16_chars,
    163                            utf16_chars + utf16_input.length(),
    164                            &output));
    165   EXPECT_EQ(6, output);
    166 
    167   output = 0;
    168   const char16 negative_wide_input[] = { 0xFF4D, '4', '2', 0};
    169   EXPECT_FALSE(StringToInt(string16(negative_wide_input), &output));
    170   EXPECT_EQ(0, output);
    171 }
    172 
    173 TEST(StringNumberConversionsTest, StringToInt64) {
    174   static const struct {
    175     std::string input;
    176     int64 output;
    177     bool success;
    178   } cases[] = {
    179     {"0", 0, true},
    180     {"42", 42, true},
    181     {"-2147483648", INT_MIN, true},
    182     {"2147483647", INT_MAX, true},
    183     {"-2147483649", GG_INT64_C(-2147483649), true},
    184     {"-99999999999", GG_INT64_C(-99999999999), true},
    185     {"2147483648", GG_INT64_C(2147483648), true},
    186     {"99999999999", GG_INT64_C(99999999999), true},
    187     {"9223372036854775807", kint64max, true},
    188     {"-9223372036854775808", kint64min, true},
    189     {"09", 9, true},
    190     {"-09", -9, true},
    191     {"", 0, false},
    192     {" 42", 42, false},
    193     {"42 ", 42, false},
    194     {"0x42", 0, false},
    195     {"\t\n\v\f\r 42", 42, false},
    196     {"blah42", 0, false},
    197     {"42blah", 42, false},
    198     {"blah42blah", 0, false},
    199     {"-273.15", -273, false},
    200     {"+98.6", 98, false},
    201     {"--123", 0, false},
    202     {"++123", 0, false},
    203     {"-+123", 0, false},
    204     {"+-123", 0, false},
    205     {"-", 0, false},
    206     {"-9223372036854775809", kint64min, false},
    207     {"-99999999999999999999", kint64min, false},
    208     {"9223372036854775808", kint64max, false},
    209     {"99999999999999999999", kint64max, false},
    210   };
    211 
    212   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
    213     const char* ascii_chars = cases[i].input.c_str();
    214     int64 output = 0;
    215     EXPECT_EQ(cases[i].success, StringToInt64(cases[i].input, &output));
    216     EXPECT_EQ(cases[i].output, output);
    217     output = 0;
    218     EXPECT_EQ(cases[i].success, StringToInt64(cases[i].input.begin(),
    219                                               cases[i].input.end(),
    220                                               &output));
    221     EXPECT_EQ(cases[i].output, output);
    222     output = 0;
    223     EXPECT_EQ(cases[i].success, StringToInt64(
    224         ascii_chars, ascii_chars + cases[i].input.length(), &output));
    225     EXPECT_EQ(cases[i].output, output);
    226 
    227     string16 utf16_input = UTF8ToUTF16(cases[i].input);
    228     const char16* utf16_chars = utf16_input.c_str();
    229     output = 0;
    230     EXPECT_EQ(cases[i].success, StringToInt64(utf16_input, &output));
    231     EXPECT_EQ(cases[i].output, output);
    232     output = 0;
    233     EXPECT_EQ(cases[i].success, StringToInt64(utf16_input.begin(),
    234                                               utf16_input.end(),
    235                                               &output));
    236     EXPECT_EQ(cases[i].output, output);
    237     output = 0;
    238     EXPECT_EQ(cases[i].success, StringToInt64(
    239         utf16_chars, utf16_chars + utf16_input.length(), &output));
    240     EXPECT_EQ(cases[i].output, output);
    241   }
    242 
    243   // One additional test to verify that conversion of numbers in strings with
    244   // embedded NUL characters.  The NUL and extra data after it should be
    245   // interpreted as junk after the number.
    246   const char input[] = "6\06";
    247   std::string input_string(input, arraysize(input) - 1);
    248   int64 output;
    249   EXPECT_FALSE(StringToInt64(input_string, &output));
    250   EXPECT_EQ(6, output);
    251   output = 0;
    252   EXPECT_FALSE(StringToInt64(input_string.begin(),
    253                              input_string.end(),
    254                              &output));
    255   EXPECT_EQ(6, output);
    256   output = 0;
    257   EXPECT_FALSE(StringToInt64(input, input + arraysize(input), &output));
    258   EXPECT_EQ(6, output);
    259 
    260   string16 utf16_input = UTF8ToUTF16(input_string);
    261   const char16* utf16_chars = utf16_input.c_str();
    262   output = 0;
    263   EXPECT_FALSE(StringToInt64(utf16_input, &output));
    264   EXPECT_EQ(6, output);
    265   output = 0;
    266   EXPECT_FALSE(StringToInt64(utf16_input.begin(), utf16_input.end(), &output));
    267   EXPECT_EQ(6, output);
    268   output = 0;
    269   EXPECT_FALSE(StringToInt64(utf16_chars,
    270                              utf16_chars + utf16_input.length(),
    271                              &output));
    272   EXPECT_EQ(6, output);
    273 }
    274 
    275 TEST(StringNumberConversionsTest, HexStringToInt) {
    276   static const struct {
    277     std::string input;
    278     int output;
    279     bool success;
    280   } cases[] = {
    281     {"0", 0, true},
    282     {"42", 66, true},
    283     {"-42", -66, true},
    284     {"+42", 66, true},
    285     {"7fffffff", INT_MAX, true},
    286     {"80000000", INT_MIN, true},
    287     {"ffffffff", -1, true},
    288     {"DeadBeef", 0xdeadbeef, true},
    289     {"0x42", 66, true},
    290     {"-0x42", -66, true},
    291     {"+0x42", 66, true},
    292     {"0x7fffffff", INT_MAX, true},
    293     {"0x80000000", INT_MIN, true},
    294     {"0xffffffff", -1, true},
    295     {"0XDeadBeef", 0xdeadbeef, true},
    296     {"0x0f", 15, true},
    297     {"0f", 15, true},
    298     {" 45", 0x45, false},
    299     {"\t\n\v\f\r 0x45", 0x45, false},
    300     {" 45", 0x45, false},
    301     {"45 ", 0x45, false},
    302     {"45:", 0x45, false},
    303     {"efgh", 0xef, false},
    304     {"0xefgh", 0xef, false},
    305     {"hgfe", 0, false},
    306     {"100000000", -1, false},  // don't care about |output|, just |success|
    307     {"-", 0, false},
    308     {"", 0, false},
    309   };
    310 
    311   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
    312     const char* ascii_chars = cases[i].input.c_str();
    313     int output = 0;
    314     EXPECT_EQ(cases[i].success, HexStringToInt(cases[i].input, &output));
    315     EXPECT_EQ(cases[i].output, output);
    316     output = 0;
    317     EXPECT_EQ(cases[i].success, HexStringToInt(cases[i].input.begin(),
    318                                                cases[i].input.end(),
    319                                                &output));
    320     EXPECT_EQ(cases[i].output, output);
    321     output = 0;
    322     EXPECT_EQ(cases[i].success, HexStringToInt(
    323         ascii_chars, ascii_chars + cases[i].input.length(), &output));
    324     EXPECT_EQ(cases[i].output, output);
    325   }
    326   // One additional test to verify that conversion of numbers in strings with
    327   // embedded NUL characters.  The NUL and extra data after it should be
    328   // interpreted as junk after the number.
    329   const char input[] = "0xc0ffee\09";
    330   std::string input_string(input, arraysize(input) - 1);
    331   int output;
    332   EXPECT_FALSE(HexStringToInt(input_string, &output));
    333   EXPECT_EQ(0xc0ffee, output);
    334   output = 0;
    335   EXPECT_FALSE(HexStringToInt(input_string.begin(),
    336                               input_string.end(),
    337                               &output));
    338   EXPECT_EQ(0xc0ffee, output);
    339   output = 0;
    340   EXPECT_FALSE(HexStringToInt(input, input + arraysize(input), &output));
    341   EXPECT_EQ(0xc0ffee, output);
    342 }
    343 
    344 TEST(StringNumberConversionsTest, HexStringToBytes) {
    345   static const struct {
    346     const std::string input;
    347     const char* output;
    348     size_t output_len;
    349     bool success;
    350   } cases[] = {
    351     {"0", "", 0, false},  // odd number of characters fails
    352     {"00", "\0", 1, true},
    353     {"42", "\x42", 1, true},
    354     {"-42", "", 0, false},  // any non-hex value fails
    355     {"+42", "", 0, false},
    356     {"7fffffff", "\x7f\xff\xff\xff", 4, true},
    357     {"80000000", "\x80\0\0\0", 4, true},
    358     {"deadbeef", "\xde\xad\xbe\xef", 4, true},
    359     {"DeadBeef", "\xde\xad\xbe\xef", 4, true},
    360     {"0x42", "", 0, false},  // leading 0x fails (x is not hex)
    361     {"0f", "\xf", 1, true},
    362     {"45  ", "\x45", 1, false},
    363     {"efgh", "\xef", 1, false},
    364     {"", "", 0, false},
    365     {"0123456789ABCDEF", "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8, true},
    366     {"0123456789ABCDEF012345",
    367      "\x01\x23\x45\x67\x89\xAB\xCD\xEF\x01\x23\x45", 11, true},
    368   };
    369 
    370 
    371   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
    372     std::vector<uint8> output;
    373     std::vector<uint8> compare;
    374     EXPECT_EQ(cases[i].success, HexStringToBytes(cases[i].input, &output)) <<
    375         i << ": " << cases[i].input;
    376     for (size_t j = 0; j < cases[i].output_len; ++j)
    377       compare.push_back(static_cast<uint8>(cases[i].output[j]));
    378     ASSERT_EQ(output.size(), compare.size()) << i << ": " << cases[i].input;
    379     EXPECT_TRUE(std::equal(output.begin(), output.end(), compare.begin())) <<
    380         i << ": " << cases[i].input;
    381   }
    382 }
    383 
    384 TEST(StringNumberConversionsTest, StringToDouble) {
    385   static const struct {
    386     std::string input;
    387     double output;
    388     bool success;
    389   } cases[] = {
    390     {"0", 0.0, true},
    391     {"42", 42.0, true},
    392     {"-42", -42.0, true},
    393     {"123.45", 123.45, true},
    394     {"-123.45", -123.45, true},
    395     {"+123.45", 123.45, true},
    396     {"2.99792458e8", 299792458.0, true},
    397     {"149597870.691E+3", 149597870691.0, true},
    398     {"6.", 6.0, true},
    399     {"9e99999999999999999999", HUGE_VAL, false},
    400     {"-9e99999999999999999999", -HUGE_VAL, false},
    401     {"1e-2", 0.01, true},
    402     {"42 ", 42.0, false},
    403     {" 1e-2", 0.01, false},
    404     {"1e-2 ", 0.01, false},
    405     {"-1E-7", -0.0000001, true},
    406     {"01e02", 100, true},
    407     {"2.3e15", 2.3e15, true},
    408     {"\t\n\v\f\r -123.45e2", -12345.0, false},
    409     {"+123 e4", 123.0, false},
    410     {"123e ", 123.0, false},
    411     {"123e", 123.0, false},
    412     {" 2.99", 2.99, false},
    413     {"1e3.4", 1000.0, false},
    414     {"nothing", 0.0, false},
    415     {"-", 0.0, false},
    416     {"+", 0.0, false},
    417     {"", 0.0, false},
    418   };
    419 
    420   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
    421     double output;
    422     EXPECT_EQ(cases[i].success, StringToDouble(cases[i].input, &output));
    423     EXPECT_DOUBLE_EQ(cases[i].output, output);
    424   }
    425 
    426   // One additional test to verify that conversion of numbers in strings with
    427   // embedded NUL characters.  The NUL and extra data after it should be
    428   // interpreted as junk after the number.
    429   const char input[] = "3.14\0159";
    430   std::string input_string(input, arraysize(input) - 1);
    431   double output;
    432   EXPECT_FALSE(StringToDouble(input_string, &output));
    433   EXPECT_DOUBLE_EQ(3.14, output);
    434 }
    435 
    436 TEST(StringNumberConversionsTest, HexEncode) {
    437   std::string hex(HexEncode(NULL, 0));
    438   EXPECT_EQ(hex.length(), 0U);
    439   unsigned char bytes[] = {0x01, 0xff, 0x02, 0xfe, 0x03, 0x80, 0x81};
    440   hex = HexEncode(bytes, sizeof(bytes));
    441   EXPECT_EQ(hex.compare("01FF02FE038081"), 0);
    442 }
    443 
    444 }  // namespace base
    445