OLD | NEW |
| (Empty) |
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 <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 int output = 0; | |
109 EXPECT_EQ(cases[i].success, StringToInt(cases[i].input, &output)); | |
110 EXPECT_EQ(cases[i].output, output); | |
111 | |
112 string16 utf16_input = UTF8ToUTF16(cases[i].input); | |
113 output = 0; | |
114 EXPECT_EQ(cases[i].success, StringToInt(utf16_input, &output)); | |
115 EXPECT_EQ(cases[i].output, output); | |
116 } | |
117 | |
118 // One additional test to verify that conversion of numbers in strings with | |
119 // embedded NUL characters. The NUL and extra data after it should be | |
120 // interpreted as junk after the number. | |
121 const char input[] = "6\06"; | |
122 std::string input_string(input, arraysize(input) - 1); | |
123 int output; | |
124 EXPECT_FALSE(StringToInt(input_string, &output)); | |
125 EXPECT_EQ(6, output); | |
126 | |
127 string16 utf16_input = UTF8ToUTF16(input_string); | |
128 output = 0; | |
129 EXPECT_FALSE(StringToInt(utf16_input, &output)); | |
130 EXPECT_EQ(6, output); | |
131 | |
132 output = 0; | |
133 const char16 negative_wide_input[] = { 0xFF4D, '4', '2', 0}; | |
134 EXPECT_FALSE(StringToInt(string16(negative_wide_input), &output)); | |
135 EXPECT_EQ(0, output); | |
136 } | |
137 | |
138 TEST(StringNumberConversionsTest, StringToInt64) { | |
139 static const struct { | |
140 std::string input; | |
141 int64 output; | |
142 bool success; | |
143 } cases[] = { | |
144 {"0", 0, true}, | |
145 {"42", 42, true}, | |
146 {"-2147483648", INT_MIN, true}, | |
147 {"2147483647", INT_MAX, true}, | |
148 {"-2147483649", GG_INT64_C(-2147483649), true}, | |
149 {"-99999999999", GG_INT64_C(-99999999999), true}, | |
150 {"2147483648", GG_INT64_C(2147483648), true}, | |
151 {"99999999999", GG_INT64_C(99999999999), true}, | |
152 {"9223372036854775807", kint64max, true}, | |
153 {"-9223372036854775808", kint64min, true}, | |
154 {"09", 9, true}, | |
155 {"-09", -9, true}, | |
156 {"", 0, false}, | |
157 {" 42", 42, false}, | |
158 {"42 ", 42, false}, | |
159 {"0x42", 0, false}, | |
160 {"\t\n\v\f\r 42", 42, false}, | |
161 {"blah42", 0, false}, | |
162 {"42blah", 42, false}, | |
163 {"blah42blah", 0, false}, | |
164 {"-273.15", -273, false}, | |
165 {"+98.6", 98, false}, | |
166 {"--123", 0, false}, | |
167 {"++123", 0, false}, | |
168 {"-+123", 0, false}, | |
169 {"+-123", 0, false}, | |
170 {"-", 0, false}, | |
171 {"-9223372036854775809", kint64min, false}, | |
172 {"-99999999999999999999", kint64min, false}, | |
173 {"9223372036854775808", kint64max, false}, | |
174 {"99999999999999999999", kint64max, false}, | |
175 }; | |
176 | |
177 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
178 int64 output = 0; | |
179 EXPECT_EQ(cases[i].success, StringToInt64(cases[i].input, &output)); | |
180 EXPECT_EQ(cases[i].output, output); | |
181 | |
182 string16 utf16_input = UTF8ToUTF16(cases[i].input); | |
183 output = 0; | |
184 EXPECT_EQ(cases[i].success, StringToInt64(utf16_input, &output)); | |
185 EXPECT_EQ(cases[i].output, output); | |
186 } | |
187 | |
188 // One additional test to verify that conversion of numbers in strings with | |
189 // embedded NUL characters. The NUL and extra data after it should be | |
190 // interpreted as junk after the number. | |
191 const char input[] = "6\06"; | |
192 std::string input_string(input, arraysize(input) - 1); | |
193 int64 output; | |
194 EXPECT_FALSE(StringToInt64(input_string, &output)); | |
195 EXPECT_EQ(6, output); | |
196 | |
197 string16 utf16_input = UTF8ToUTF16(input_string); | |
198 output = 0; | |
199 EXPECT_FALSE(StringToInt64(utf16_input, &output)); | |
200 EXPECT_EQ(6, output); | |
201 } | |
202 | |
203 TEST(StringNumberConversionsTest, HexStringToInt) { | |
204 static const struct { | |
205 std::string input; | |
206 int64 output; | |
207 bool success; | |
208 } cases[] = { | |
209 {"0", 0, true}, | |
210 {"42", 66, true}, | |
211 {"-42", -66, true}, | |
212 {"+42", 66, true}, | |
213 {"7fffffff", INT_MAX, true}, | |
214 {"-80000000", INT_MIN, true}, | |
215 {"80000000", INT_MAX, false}, // Overflow test. | |
216 {"-80000001", INT_MIN, false}, // Underflow test. | |
217 {"0x42", 66, true}, | |
218 {"-0x42", -66, true}, | |
219 {"+0x42", 66, true}, | |
220 {"0x7fffffff", INT_MAX, true}, | |
221 {"-0x80000000", INT_MIN, true}, | |
222 {"-80000000", INT_MIN, true}, | |
223 {"80000000", INT_MAX, false}, // Overflow test. | |
224 {"-80000001", INT_MIN, false}, // Underflow test. | |
225 {"0x0f", 15, true}, | |
226 {"0f", 15, true}, | |
227 {" 45", 0x45, false}, | |
228 {"\t\n\v\f\r 0x45", 0x45, false}, | |
229 {" 45", 0x45, false}, | |
230 {"45 ", 0x45, false}, | |
231 {"45:", 0x45, false}, | |
232 {"efgh", 0xef, false}, | |
233 {"0xefgh", 0xef, false}, | |
234 {"hgfe", 0, false}, | |
235 {"-", 0, false}, | |
236 {"", 0, false}, | |
237 {"0x", 0, false}, | |
238 }; | |
239 | |
240 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
241 int output = 0; | |
242 EXPECT_EQ(cases[i].success, HexStringToInt(cases[i].input, &output)); | |
243 EXPECT_EQ(cases[i].output, output); | |
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[] = "0xc0ffee\09"; | |
249 std::string input_string(input, arraysize(input) - 1); | |
250 int output; | |
251 EXPECT_FALSE(HexStringToInt(input_string, &output)); | |
252 EXPECT_EQ(0xc0ffee, output); | |
253 } | |
254 | |
255 TEST(StringNumberConversionsTest, HexStringToInt64) { | |
256 static const struct { | |
257 std::string input; | |
258 int64 output; | |
259 bool success; | |
260 } cases[] = { | |
261 {"0", 0, true}, | |
262 {"42", 66, true}, | |
263 {"-42", -66, true}, | |
264 {"+42", 66, true}, | |
265 {"40acd88557b", GG_INT64_C(4444444448123), true}, | |
266 {"7fffffff", INT_MAX, true}, | |
267 {"-80000000", INT_MIN, true}, | |
268 {"ffffffff", 0xffffffff, true}, | |
269 {"DeadBeef", 0xdeadbeef, true}, | |
270 {"0x42", 66, true}, | |
271 {"-0x42", -66, true}, | |
272 {"+0x42", 66, true}, | |
273 {"0x40acd88557b", GG_INT64_C(4444444448123), true}, | |
274 {"0x7fffffff", INT_MAX, true}, | |
275 {"-0x80000000", INT_MIN, true}, | |
276 {"0xffffffff", 0xffffffff, true}, | |
277 {"0XDeadBeef", 0xdeadbeef, true}, | |
278 {"0x7fffffffffffffff", kint64max, true}, | |
279 {"-0x8000000000000000", kint64min, true}, | |
280 {"0x8000000000000000", kint64max, false}, // Overflow test. | |
281 {"-0x8000000000000001", kint64min, false}, // Underflow test. | |
282 {"0x0f", 15, true}, | |
283 {"0f", 15, true}, | |
284 {" 45", 0x45, false}, | |
285 {"\t\n\v\f\r 0x45", 0x45, false}, | |
286 {" 45", 0x45, false}, | |
287 {"45 ", 0x45, false}, | |
288 {"45:", 0x45, false}, | |
289 {"efgh", 0xef, false}, | |
290 {"0xefgh", 0xef, false}, | |
291 {"hgfe", 0, false}, | |
292 {"-", 0, false}, | |
293 {"", 0, false}, | |
294 {"0x", 0, false}, | |
295 }; | |
296 | |
297 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
298 int64 output = 0; | |
299 EXPECT_EQ(cases[i].success, HexStringToInt64(cases[i].input, &output)); | |
300 EXPECT_EQ(cases[i].output, output); | |
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[] = "0xc0ffee\09"; | |
306 std::string input_string(input, arraysize(input) - 1); | |
307 int64 output; | |
308 EXPECT_FALSE(HexStringToInt64(input_string, &output)); | |
309 EXPECT_EQ(0xc0ffee, output); | |
310 } | |
311 | |
312 TEST(StringNumberConversionsTest, HexStringToBytes) { | |
313 static const struct { | |
314 const std::string input; | |
315 const char* output; | |
316 size_t output_len; | |
317 bool success; | |
318 } cases[] = { | |
319 {"0", "", 0, false}, // odd number of characters fails | |
320 {"00", "\0", 1, true}, | |
321 {"42", "\x42", 1, true}, | |
322 {"-42", "", 0, false}, // any non-hex value fails | |
323 {"+42", "", 0, false}, | |
324 {"7fffffff", "\x7f\xff\xff\xff", 4, true}, | |
325 {"80000000", "\x80\0\0\0", 4, true}, | |
326 {"deadbeef", "\xde\xad\xbe\xef", 4, true}, | |
327 {"DeadBeef", "\xde\xad\xbe\xef", 4, true}, | |
328 {"0x42", "", 0, false}, // leading 0x fails (x is not hex) | |
329 {"0f", "\xf", 1, true}, | |
330 {"45 ", "\x45", 1, false}, | |
331 {"efgh", "\xef", 1, false}, | |
332 {"", "", 0, false}, | |
333 {"0123456789ABCDEF", "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8, true}, | |
334 {"0123456789ABCDEF012345", | |
335 "\x01\x23\x45\x67\x89\xAB\xCD\xEF\x01\x23\x45", 11, true}, | |
336 }; | |
337 | |
338 | |
339 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
340 std::vector<uint8> output; | |
341 std::vector<uint8> compare; | |
342 EXPECT_EQ(cases[i].success, HexStringToBytes(cases[i].input, &output)) << | |
343 i << ": " << cases[i].input; | |
344 for (size_t j = 0; j < cases[i].output_len; ++j) | |
345 compare.push_back(static_cast<uint8>(cases[i].output[j])); | |
346 ASSERT_EQ(output.size(), compare.size()) << i << ": " << cases[i].input; | |
347 EXPECT_TRUE(std::equal(output.begin(), output.end(), compare.begin())) << | |
348 i << ": " << cases[i].input; | |
349 } | |
350 } | |
351 | |
352 TEST(StringNumberConversionsTest, StringToDouble) { | |
353 static const struct { | |
354 std::string input; | |
355 double output; | |
356 bool success; | |
357 } cases[] = { | |
358 {"0", 0.0, true}, | |
359 {"42", 42.0, true}, | |
360 {"-42", -42.0, true}, | |
361 {"123.45", 123.45, true}, | |
362 {"-123.45", -123.45, true}, | |
363 {"+123.45", 123.45, true}, | |
364 {"2.99792458e8", 299792458.0, true}, | |
365 {"149597870.691E+3", 149597870691.0, true}, | |
366 {"6.", 6.0, true}, | |
367 {"9e99999999999999999999", HUGE_VAL, false}, | |
368 {"-9e99999999999999999999", -HUGE_VAL, false}, | |
369 {"1e-2", 0.01, true}, | |
370 {"42 ", 42.0, false}, | |
371 {" 1e-2", 0.01, false}, | |
372 {"1e-2 ", 0.01, false}, | |
373 {"-1E-7", -0.0000001, true}, | |
374 {"01e02", 100, true}, | |
375 {"2.3e15", 2.3e15, true}, | |
376 {"\t\n\v\f\r -123.45e2", -12345.0, false}, | |
377 {"+123 e4", 123.0, false}, | |
378 {"123e ", 123.0, false}, | |
379 {"123e", 123.0, false}, | |
380 {" 2.99", 2.99, false}, | |
381 {"1e3.4", 1000.0, false}, | |
382 {"nothing", 0.0, false}, | |
383 {"-", 0.0, false}, | |
384 {"+", 0.0, false}, | |
385 {"", 0.0, false}, | |
386 }; | |
387 | |
388 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
389 double output; | |
390 EXPECT_EQ(cases[i].success, StringToDouble(cases[i].input, &output)); | |
391 EXPECT_DOUBLE_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[] = "3.14\0159"; | |
398 std::string input_string(input, arraysize(input) - 1); | |
399 double output; | |
400 EXPECT_FALSE(StringToDouble(input_string, &output)); | |
401 EXPECT_DOUBLE_EQ(3.14, output); | |
402 } | |
403 | |
404 TEST(StringNumberConversionsTest, DoubleToString) { | |
405 static const struct { | |
406 double input; | |
407 const char* expected; | |
408 } cases[] = { | |
409 {0.0, "0"}, | |
410 {1.25, "1.25"}, | |
411 {1.33518e+012, "1.33518e+12"}, | |
412 {1.33489e+012, "1.33489e+12"}, | |
413 {1.33505e+012, "1.33505e+12"}, | |
414 {1.33545e+009, "1335450000"}, | |
415 {1.33503e+009, "1335030000"}, | |
416 }; | |
417 | |
418 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { | |
419 EXPECT_EQ(cases[i].expected, DoubleToString(cases[i].input)); | |
420 } | |
421 | |
422 // The following two values were seen in crashes in the wild. | |
423 const char input_bytes[8] = {0, 0, 0, 0, '\xee', '\x6d', '\x73', '\x42'}; | |
424 double input = 0; | |
425 memcpy(&input, input_bytes, arraysize(input_bytes)); | |
426 EXPECT_EQ("1335179083776", DoubleToString(input)); | |
427 const char input_bytes2[8] = | |
428 {0, 0, 0, '\xa0', '\xda', '\x6c', '\x73', '\x42'}; | |
429 input = 0; | |
430 memcpy(&input, input_bytes2, arraysize(input_bytes2)); | |
431 EXPECT_EQ("1334890332160", DoubleToString(input)); | |
432 } | |
433 | |
434 TEST(StringNumberConversionsTest, HexEncode) { | |
435 std::string hex(HexEncode(NULL, 0)); | |
436 EXPECT_EQ(hex.length(), 0U); | |
437 unsigned char bytes[] = {0x01, 0xff, 0x02, 0xfe, 0x03, 0x80, 0x81}; | |
438 hex = HexEncode(bytes, sizeof(bytes)); | |
439 EXPECT_EQ(hex.compare("01FF02FE038081"), 0); | |
440 } | |
441 | |
442 } // namespace base | |
OLD | NEW |