1
2
3
4
5 package strconv_test
6
7 import (
8 "fmt"
9 . "internal/strconv"
10 "reflect"
11 "testing"
12 )
13
14 type parseUint64Test struct {
15 in string
16 out uint64
17 err error
18 }
19
20 var parseUint64Tests = []parseUint64Test{
21 {"", 0, ErrSyntax},
22 {"0", 0, nil},
23 {"1", 1, nil},
24 {"12345", 12345, nil},
25 {"012345", 12345, nil},
26 {"12345x", 0, ErrSyntax},
27 {"98765432100", 98765432100, nil},
28 {"18446744073709551615", 1<<64 - 1, nil},
29 {"18446744073709551616", 1<<64 - 1, ErrRange},
30 {"18446744073709551620", 1<<64 - 1, ErrRange},
31 {"1_2_3_4_5", 0, ErrSyntax},
32 {"_12345", 0, ErrSyntax},
33 {"1__2345", 0, ErrSyntax},
34 {"12345_", 0, ErrSyntax},
35 {"-0", 0, ErrSyntax},
36 {"-1", 0, ErrSyntax},
37 {"+1", 0, ErrSyntax},
38 }
39
40 type parseUint64BaseTest struct {
41 in string
42 base int
43 out uint64
44 err error
45 }
46
47 var parseUint64BaseTests = []parseUint64BaseTest{
48 {"", 0, 0, ErrSyntax},
49 {"0", 0, 0, nil},
50 {"0x", 0, 0, ErrSyntax},
51 {"0X", 0, 0, ErrSyntax},
52 {"1", 0, 1, nil},
53 {"12345", 0, 12345, nil},
54 {"012345", 0, 012345, nil},
55 {"0x12345", 0, 0x12345, nil},
56 {"0X12345", 0, 0x12345, nil},
57 {"12345x", 0, 0, ErrSyntax},
58 {"0xabcdefg123", 0, 0, ErrSyntax},
59 {"123456789abc", 0, 0, ErrSyntax},
60 {"98765432100", 0, 98765432100, nil},
61 {"18446744073709551615", 0, 1<<64 - 1, nil},
62 {"18446744073709551616", 0, 1<<64 - 1, ErrRange},
63 {"18446744073709551620", 0, 1<<64 - 1, ErrRange},
64 {"0xFFFFFFFFFFFFFFFF", 0, 1<<64 - 1, nil},
65 {"0x10000000000000000", 0, 1<<64 - 1, ErrRange},
66 {"01777777777777777777777", 0, 1<<64 - 1, nil},
67 {"01777777777777777777778", 0, 0, ErrSyntax},
68 {"02000000000000000000000", 0, 1<<64 - 1, ErrRange},
69 {"0200000000000000000000", 0, 1 << 61, nil},
70 {"0b", 0, 0, ErrSyntax},
71 {"0B", 0, 0, ErrSyntax},
72 {"0b101", 0, 5, nil},
73 {"0B101", 0, 5, nil},
74 {"0o", 0, 0, ErrSyntax},
75 {"0O", 0, 0, ErrSyntax},
76 {"0o377", 0, 255, nil},
77 {"0O377", 0, 255, nil},
78
79
80 {"1_2_3_4_5", 0, 12345, nil},
81 {"_12345", 0, 0, ErrSyntax},
82 {"1__2345", 0, 0, ErrSyntax},
83 {"12345_", 0, 0, ErrSyntax},
84
85 {"1_2_3_4_5", 10, 0, ErrSyntax},
86 {"_12345", 10, 0, ErrSyntax},
87 {"1__2345", 10, 0, ErrSyntax},
88 {"12345_", 10, 0, ErrSyntax},
89
90 {"0x_1_2_3_4_5", 0, 0x12345, nil},
91 {"_0x12345", 0, 0, ErrSyntax},
92 {"0x__12345", 0, 0, ErrSyntax},
93 {"0x1__2345", 0, 0, ErrSyntax},
94 {"0x1234__5", 0, 0, ErrSyntax},
95 {"0x12345_", 0, 0, ErrSyntax},
96
97 {"1_2_3_4_5", 16, 0, ErrSyntax},
98 {"_12345", 16, 0, ErrSyntax},
99 {"1__2345", 16, 0, ErrSyntax},
100 {"1234__5", 16, 0, ErrSyntax},
101 {"12345_", 16, 0, ErrSyntax},
102
103 {"0_1_2_3_4_5", 0, 012345, nil},
104 {"_012345", 0, 0, ErrSyntax},
105 {"0__12345", 0, 0, ErrSyntax},
106 {"01234__5", 0, 0, ErrSyntax},
107 {"012345_", 0, 0, ErrSyntax},
108
109 {"0o_1_2_3_4_5", 0, 012345, nil},
110 {"_0o12345", 0, 0, ErrSyntax},
111 {"0o__12345", 0, 0, ErrSyntax},
112 {"0o1234__5", 0, 0, ErrSyntax},
113 {"0o12345_", 0, 0, ErrSyntax},
114
115 {"0_1_2_3_4_5", 8, 0, ErrSyntax},
116 {"_012345", 8, 0, ErrSyntax},
117 {"0__12345", 8, 0, ErrSyntax},
118 {"01234__5", 8, 0, ErrSyntax},
119 {"012345_", 8, 0, ErrSyntax},
120
121 {"0b_1_0_1", 0, 5, nil},
122 {"_0b101", 0, 0, ErrSyntax},
123 {"0b__101", 0, 0, ErrSyntax},
124 {"0b1__01", 0, 0, ErrSyntax},
125 {"0b10__1", 0, 0, ErrSyntax},
126 {"0b101_", 0, 0, ErrSyntax},
127
128 {"1_0_1", 2, 0, ErrSyntax},
129 {"_101", 2, 0, ErrSyntax},
130 {"1_01", 2, 0, ErrSyntax},
131 {"10_1", 2, 0, ErrSyntax},
132 {"101_", 2, 0, ErrSyntax},
133 }
134
135 type parseInt64Test struct {
136 in string
137 out int64
138 err error
139 }
140
141 var parseInt64Tests = []parseInt64Test{
142 {"", 0, ErrSyntax},
143 {"0", 0, nil},
144 {"-0", 0, nil},
145 {"+0", 0, nil},
146 {"1", 1, nil},
147 {"-1", -1, nil},
148 {"+1", 1, nil},
149 {"12345", 12345, nil},
150 {"-12345", -12345, nil},
151 {"012345", 12345, nil},
152 {"-012345", -12345, nil},
153 {"98765432100", 98765432100, nil},
154 {"-98765432100", -98765432100, nil},
155 {"9223372036854775807", 1<<63 - 1, nil},
156 {"-9223372036854775807", -(1<<63 - 1), nil},
157 {"9223372036854775808", 1<<63 - 1, ErrRange},
158 {"-9223372036854775808", -1 << 63, nil},
159 {"9223372036854775809", 1<<63 - 1, ErrRange},
160 {"-9223372036854775809", -1 << 63, ErrRange},
161 {"-1_2_3_4_5", 0, ErrSyntax},
162 {"-_12345", 0, ErrSyntax},
163 {"_12345", 0, ErrSyntax},
164 {"1__2345", 0, ErrSyntax},
165 {"12345_", 0, ErrSyntax},
166 {"123%45", 0, ErrSyntax},
167 }
168
169 type parseInt64BaseTest struct {
170 in string
171 base int
172 out int64
173 err error
174 }
175
176 var parseInt64BaseTests = []parseInt64BaseTest{
177 {"", 0, 0, ErrSyntax},
178 {"0", 0, 0, nil},
179 {"-0", 0, 0, nil},
180 {"1", 0, 1, nil},
181 {"-1", 0, -1, nil},
182 {"12345", 0, 12345, nil},
183 {"-12345", 0, -12345, nil},
184 {"012345", 0, 012345, nil},
185 {"-012345", 0, -012345, nil},
186 {"0x12345", 0, 0x12345, nil},
187 {"-0X12345", 0, -0x12345, nil},
188 {"12345x", 0, 0, ErrSyntax},
189 {"-12345x", 0, 0, ErrSyntax},
190 {"98765432100", 0, 98765432100, nil},
191 {"-98765432100", 0, -98765432100, nil},
192 {"9223372036854775807", 0, 1<<63 - 1, nil},
193 {"-9223372036854775807", 0, -(1<<63 - 1), nil},
194 {"9223372036854775808", 0, 1<<63 - 1, ErrRange},
195 {"-9223372036854775808", 0, -1 << 63, nil},
196 {"9223372036854775809", 0, 1<<63 - 1, ErrRange},
197 {"-9223372036854775809", 0, -1 << 63, ErrRange},
198
199
200 {"g", 17, 16, nil},
201 {"10", 25, 25, nil},
202 {"holycow", 35, (((((17*35+24)*35+21)*35+34)*35+12)*35+24)*35 + 32, nil},
203 {"holycow", 36, (((((17*36+24)*36+21)*36+34)*36+12)*36+24)*36 + 32, nil},
204
205
206 {"0", 2, 0, nil},
207 {"-1", 2, -1, nil},
208 {"1010", 2, 10, nil},
209 {"1000000000000000", 2, 1 << 15, nil},
210 {"111111111111111111111111111111111111111111111111111111111111111", 2, 1<<63 - 1, nil},
211 {"1000000000000000000000000000000000000000000000000000000000000000", 2, 1<<63 - 1, ErrRange},
212 {"-1000000000000000000000000000000000000000000000000000000000000000", 2, -1 << 63, nil},
213 {"-1000000000000000000000000000000000000000000000000000000000000001", 2, -1 << 63, ErrRange},
214
215
216 {"-10", 8, -8, nil},
217 {"57635436545", 8, 057635436545, nil},
218 {"100000000", 8, 1 << 24, nil},
219
220
221 {"10", 16, 16, nil},
222 {"-123456789abcdef", 16, -0x123456789abcdef, nil},
223 {"7fffffffffffffff", 16, 1<<63 - 1, nil},
224
225
226 {"-0x_1_2_3_4_5", 0, -0x12345, nil},
227 {"0x_1_2_3_4_5", 0, 0x12345, nil},
228 {"-_0x12345", 0, 0, ErrSyntax},
229 {"_-0x12345", 0, 0, ErrSyntax},
230 {"_0x12345", 0, 0, ErrSyntax},
231 {"0x__12345", 0, 0, ErrSyntax},
232 {"0x1__2345", 0, 0, ErrSyntax},
233 {"0x1234__5", 0, 0, ErrSyntax},
234 {"0x12345_", 0, 0, ErrSyntax},
235
236 {"-0_1_2_3_4_5", 0, -012345, nil},
237 {"0_1_2_3_4_5", 0, 012345, nil},
238 {"-_012345", 0, 0, ErrSyntax},
239 {"_-012345", 0, 0, ErrSyntax},
240 {"_012345", 0, 0, ErrSyntax},
241 {"0__12345", 0, 0, ErrSyntax},
242 {"01234__5", 0, 0, ErrSyntax},
243 {"012345_", 0, 0, ErrSyntax},
244
245 {"+0xf", 0, 0xf, nil},
246 {"-0xf", 0, -0xf, nil},
247 {"0x+f", 0, 0, ErrSyntax},
248 {"0x-f", 0, 0, ErrSyntax},
249 }
250
251 type parseUint32Test struct {
252 in string
253 out uint32
254 err error
255 }
256
257 var parseUint32Tests = []parseUint32Test{
258 {"", 0, ErrSyntax},
259 {"0", 0, nil},
260 {"1", 1, nil},
261 {"12345", 12345, nil},
262 {"012345", 12345, nil},
263 {"12345x", 0, ErrSyntax},
264 {"987654321", 987654321, nil},
265 {"4294967295", 1<<32 - 1, nil},
266 {"4294967296", 1<<32 - 1, ErrRange},
267 {"1_2_3_4_5", 0, ErrSyntax},
268 {"_12345", 0, ErrSyntax},
269 {"_12345", 0, ErrSyntax},
270 {"1__2345", 0, ErrSyntax},
271 {"12345_", 0, ErrSyntax},
272 }
273
274 type parseInt32Test struct {
275 in string
276 out int32
277 err error
278 }
279
280 var parseInt32Tests = []parseInt32Test{
281 {"", 0, ErrSyntax},
282 {"0", 0, nil},
283 {"-0", 0, nil},
284 {"1", 1, nil},
285 {"-1", -1, nil},
286 {"12345", 12345, nil},
287 {"-12345", -12345, nil},
288 {"012345", 12345, nil},
289 {"-012345", -12345, nil},
290 {"12345x", 0, ErrSyntax},
291 {"-12345x", 0, ErrSyntax},
292 {"987654321", 987654321, nil},
293 {"-987654321", -987654321, nil},
294 {"2147483647", 1<<31 - 1, nil},
295 {"-2147483647", -(1<<31 - 1), nil},
296 {"2147483648", 1<<31 - 1, ErrRange},
297 {"-2147483648", -1 << 31, nil},
298 {"2147483649", 1<<31 - 1, ErrRange},
299 {"-2147483649", -1 << 31, ErrRange},
300 {"-1_2_3_4_5", 0, ErrSyntax},
301 {"-_12345", 0, ErrSyntax},
302 {"_12345", 0, ErrSyntax},
303 {"1__2345", 0, ErrSyntax},
304 {"12345_", 0, ErrSyntax},
305 {"123%45", 0, ErrSyntax},
306 }
307
308 type numErrorTest struct {
309 num, want string
310 }
311
312 var numErrorTests = []numErrorTest{
313 {"0", `strconv.ParseFloat: parsing "0": failed`},
314 {"`", "strconv.ParseFloat: parsing \"`\": failed"},
315 {"1\x00.2", `strconv.ParseFloat: parsing "1\x00.2": failed`},
316 }
317
318 func TestParseUint32(t *testing.T) {
319 for i := range parseUint32Tests {
320 test := &parseUint32Tests[i]
321 out, err := ParseUint(test.in, 10, 32)
322 if uint64(test.out) != out || !reflect.DeepEqual(test.err, err) {
323 t.Errorf("ParseUint(%q, 10, 32) = %v, %v want %v, %v",
324 test.in, out, err, test.out, test.err)
325 }
326 }
327 }
328
329 func TestParseUint64(t *testing.T) {
330 for i := range parseUint64Tests {
331 test := &parseUint64Tests[i]
332 out, err := ParseUint(test.in, 10, 64)
333 if test.out != out || !reflect.DeepEqual(test.err, err) {
334 t.Errorf("ParseUint(%q, 10, 64) = %v, %v want %v, %v",
335 test.in, out, err, test.out, test.err)
336 }
337 }
338 }
339
340 func TestParseUint64Base(t *testing.T) {
341 for i := range parseUint64BaseTests {
342 test := &parseUint64BaseTests[i]
343 out, err := ParseUint(test.in, test.base, 64)
344 if test.out != out || !reflect.DeepEqual(test.err, err) {
345 t.Errorf("ParseUint(%q, %v, 64) = %v, %v want %v, %v",
346 test.in, test.base, out, err, test.out, test.err)
347 }
348 }
349 }
350
351 func TestParseInt32(t *testing.T) {
352 for i := range parseInt32Tests {
353 test := &parseInt32Tests[i]
354 out, err := ParseInt(test.in, 10, 32)
355 if int64(test.out) != out || !reflect.DeepEqual(test.err, err) {
356 t.Errorf("ParseInt(%q, 10 ,32) = %v, %v want %v, %v",
357 test.in, out, err, test.out, test.err)
358 }
359 }
360 }
361
362 func TestParseInt64(t *testing.T) {
363 for i := range parseInt64Tests {
364 test := &parseInt64Tests[i]
365 out, err := ParseInt(test.in, 10, 64)
366 if test.out != out || !reflect.DeepEqual(test.err, err) {
367 t.Errorf("ParseInt(%q, 10, 64) = %v, %v want %v, %v",
368 test.in, out, err, test.out, test.err)
369 }
370 }
371 }
372
373 func TestParseInt64Base(t *testing.T) {
374 for i := range parseInt64BaseTests {
375 test := &parseInt64BaseTests[i]
376 out, err := ParseInt(test.in, test.base, 64)
377 if test.out != out || !reflect.DeepEqual(test.err, err) {
378 t.Errorf("ParseInt(%q, %v, 64) = %v, %v want %v, %v",
379 test.in, test.base, out, err, test.out, test.err)
380 }
381 }
382 }
383
384 func TestParseUint(t *testing.T) {
385 switch IntSize {
386 case 32:
387 for i := range parseUint32Tests {
388 test := &parseUint32Tests[i]
389 out, err := ParseUint(test.in, 10, 0)
390 if uint64(test.out) != out || !reflect.DeepEqual(test.err, err) {
391 t.Errorf("ParseUint(%q, 10, 0) = %v, %v want %v, %v",
392 test.in, out, err, test.out, test.err)
393 }
394 }
395 case 64:
396 for i := range parseUint64Tests {
397 test := &parseUint64Tests[i]
398 out, err := ParseUint(test.in, 10, 0)
399 if test.out != out || !reflect.DeepEqual(test.err, err) {
400 t.Errorf("ParseUint(%q, 10, 0) = %v, %v want %v, %v",
401 test.in, out, err, test.out, test.err)
402 }
403 }
404 }
405 }
406
407 func TestParseInt(t *testing.T) {
408 switch IntSize {
409 case 32:
410 for i := range parseInt32Tests {
411 test := &parseInt32Tests[i]
412 out, err := ParseInt(test.in, 10, 0)
413 if int64(test.out) != out || !reflect.DeepEqual(test.err, err) {
414 t.Errorf("ParseInt(%q, 10, 0) = %v, %v want %v, %v",
415 test.in, out, err, test.out, test.err)
416 }
417 }
418 case 64:
419 for i := range parseInt64Tests {
420 test := &parseInt64Tests[i]
421 out, err := ParseInt(test.in, 10, 0)
422 if test.out != out || !reflect.DeepEqual(test.err, err) {
423 t.Errorf("ParseInt(%q, 10, 0) = %v, %v want %v, %v",
424 test.in, out, err, test.out, test.err)
425 }
426 }
427 }
428 }
429
430 func TestAtoi(t *testing.T) {
431 switch IntSize {
432 case 32:
433 for i := range parseInt32Tests {
434 test := &parseInt32Tests[i]
435 out, err := Atoi(test.in)
436 if out != int(test.out) || err != test.err {
437 t.Errorf("Atoi(%q) = %v, %v, want %v, %v", test.in, out, err, test.out, test.err)
438 }
439 }
440 case 64:
441 for i := range parseInt64Tests {
442 test := &parseInt64Tests[i]
443 out, err := Atoi(test.in)
444 if int64(out) != test.out || err != test.err {
445 t.Errorf("Atoi(%q) = %v, %v, want %v, %v", test.in, out, err, test.out, test.err)
446 }
447 }
448 }
449 }
450
451 type parseErrorTest struct {
452 arg int
453 err error
454 }
455
456 var parseBitSizeTests = []parseErrorTest{
457 {-1, ErrBitSize},
458 {0, nil},
459 {64, nil},
460 {65, ErrBitSize},
461 }
462
463 var parseBaseTests = []parseErrorTest{
464 {-1, ErrBase},
465 {0, nil},
466 {1, ErrBase},
467 {2, nil},
468 {36, nil},
469 {37, ErrBase},
470 }
471
472 func equalError(a, b error) bool {
473 if a == nil {
474 return b == nil
475 }
476 if b == nil {
477 return a == nil
478 }
479 return a.Error() == b.Error()
480 }
481
482 func TestParseIntBitSize(t *testing.T) {
483 for i := range parseBitSizeTests {
484 test := &parseBitSizeTests[i]
485 _, err := ParseInt("0", 0, test.arg)
486 if err != test.err {
487 t.Errorf("ParseInt(\"0\", 0, %v) = 0, %v want 0, %v",
488 test.arg, err, test.err)
489 }
490 }
491 }
492
493 func TestParseUintBitSize(t *testing.T) {
494 for i := range parseBitSizeTests {
495 test := &parseBitSizeTests[i]
496 _, err := ParseUint("0", 0, test.arg)
497 if err != test.err {
498 t.Errorf("ParseUint(\"0\", 0, %v) = 0, %v want 0, %v",
499 test.arg, err, test.err)
500 }
501 }
502 }
503
504 func TestParseIntBase(t *testing.T) {
505 for i := range parseBaseTests {
506 test := &parseBaseTests[i]
507 _, err := ParseInt("0", test.arg, 0)
508 if err != test.err {
509 t.Errorf("ParseInt(\"0\", %v, 0) = 0, %v want 0, %v",
510 test.arg, err, test.err)
511 }
512 }
513 }
514
515 func TestParseUintBase(t *testing.T) {
516 for i := range parseBaseTests {
517 test := &parseBaseTests[i]
518 _, err := ParseUint("0", test.arg, 0)
519 if err != test.err {
520 t.Errorf("ParseUint(\"0\", %v, 0) = 0, %v want 0, %v",
521 test.arg, err, test.err)
522 }
523 }
524 }
525
526 func BenchmarkParseInt(b *testing.B) {
527 b.Run("Pos", func(b *testing.B) {
528 benchmarkParseInt(b, 1)
529 })
530 b.Run("Neg", func(b *testing.B) {
531 benchmarkParseInt(b, -1)
532 })
533 }
534
535 type benchCase struct {
536 name string
537 num int64
538 }
539
540 func benchmarkParseInt(b *testing.B, neg int) {
541 cases := []benchCase{
542 {"7bit", 1<<7 - 1},
543 {"26bit", 1<<26 - 1},
544 {"31bit", 1<<31 - 1},
545 {"56bit", 1<<56 - 1},
546 {"63bit", 1<<63 - 1},
547 }
548 for _, cs := range cases {
549 b.Run(cs.name, func(b *testing.B) {
550 s := fmt.Sprintf("%d", cs.num*int64(neg))
551 for i := 0; i < b.N; i++ {
552 out, _ := ParseInt(s, 10, 64)
553 BenchSink += int(out)
554 }
555 })
556 }
557 }
558
559 func BenchmarkAtoi(b *testing.B) {
560 b.Run("Pos", func(b *testing.B) {
561 benchmarkAtoi(b, 1)
562 })
563 b.Run("Neg", func(b *testing.B) {
564 benchmarkAtoi(b, -1)
565 })
566 }
567
568 func benchmarkAtoi(b *testing.B, neg int) {
569 cases := []benchCase{
570 {"7bit", 1<<7 - 1},
571 {"26bit", 1<<26 - 1},
572 {"31bit", 1<<31 - 1},
573 }
574 if IntSize == 64 {
575 cases = append(cases, []benchCase{
576 {"56bit", 1<<56 - 1},
577 {"63bit", 1<<63 - 1},
578 }...)
579 }
580 for _, cs := range cases {
581 b.Run(cs.name, func(b *testing.B) {
582 s := fmt.Sprintf("%d", cs.num*int64(neg))
583 for i := 0; i < b.N; i++ {
584 out, _ := Atoi(s)
585 BenchSink += out
586 }
587 })
588 }
589 }
590
View as plain text