• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST(StringNumberConversionsTest,IntToString)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 
TEST(StringNumberConversionsTest,Uint64ToString)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 
TEST(StringNumberConversionsTest,SizeTToString)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 
TEST(StringNumberConversionsTest,StringToInt)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 
TEST(StringNumberConversionsTest,StringToUint)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 
TEST(StringNumberConversionsTest,StringToInt64)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 
TEST(StringNumberConversionsTest,StringToUint64)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 
TEST(StringNumberConversionsTest,StringToSizeT)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 
TEST(StringNumberConversionsTest,HexStringToInt)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 
TEST(StringNumberConversionsTest,HexStringToUInt)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 
TEST(StringNumberConversionsTest,HexStringToInt64)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 
TEST(StringNumberConversionsTest,HexStringToUInt64)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 
TEST(StringNumberConversionsTest,HexStringToBytes)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 
TEST(StringNumberConversionsTest,StringToDouble)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 
TEST(StringNumberConversionsTest,DoubleToString)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 
TEST(StringNumberConversionsTest,HexEncode)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