• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST(StringNumberConversionsTest,IntToString)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 
TEST(StringNumberConversionsTest,Uint64ToString)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 
TEST(StringNumberConversionsTest,StringToInt)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 
TEST(StringNumberConversionsTest,StringToInt64)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 
TEST(StringNumberConversionsTest,HexStringToInt)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 
TEST(StringNumberConversionsTest,HexStringToBytes)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 
TEST(StringNumberConversionsTest,StringToDouble)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 
TEST(StringNumberConversionsTest,HexEncode)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