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, 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
143TEST(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
207TEST(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
272TEST(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
339TEST(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
409TEST(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
461TEST(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
521TEST(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
578TEST(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
640TEST(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
680TEST(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
735TEST(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
765TEST(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