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