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	. "strconv"
9	"testing"
10)
11
12type itob64Test struct {
13	in   int64
14	base int
15	out  string
16}
17
18var itob64tests = []itob64Test{
19	{0, 10, "0"},
20	{1, 10, "1"},
21	{-1, 10, "-1"},
22	{12345678, 10, "12345678"},
23	{-987654321, 10, "-987654321"},
24	{1<<31 - 1, 10, "2147483647"},
25	{-1<<31 + 1, 10, "-2147483647"},
26	{1 << 31, 10, "2147483648"},
27	{-1 << 31, 10, "-2147483648"},
28	{1<<31 + 1, 10, "2147483649"},
29	{-1<<31 - 1, 10, "-2147483649"},
30	{1<<32 - 1, 10, "4294967295"},
31	{-1<<32 + 1, 10, "-4294967295"},
32	{1 << 32, 10, "4294967296"},
33	{-1 << 32, 10, "-4294967296"},
34	{1<<32 + 1, 10, "4294967297"},
35	{-1<<32 - 1, 10, "-4294967297"},
36	{1 << 50, 10, "1125899906842624"},
37	{1<<63 - 1, 10, "9223372036854775807"},
38	{-1<<63 + 1, 10, "-9223372036854775807"},
39	{-1 << 63, 10, "-9223372036854775808"},
40
41	{0, 2, "0"},
42	{10, 2, "1010"},
43	{-1, 2, "-1"},
44	{1 << 15, 2, "1000000000000000"},
45
46	{-8, 8, "-10"},
47	{057635436545, 8, "57635436545"},
48	{1 << 24, 8, "100000000"},
49
50	{16, 16, "10"},
51	{-0x123456789abcdef, 16, "-123456789abcdef"},
52	{1<<63 - 1, 16, "7fffffffffffffff"},
53	{1<<63 - 1, 2, "111111111111111111111111111111111111111111111111111111111111111"},
54	{-1 << 63, 2, "-1000000000000000000000000000000000000000000000000000000000000000"},
55
56	{16, 17, "g"},
57	{25, 25, "10"},
58	{(((((17*35+24)*35+21)*35+34)*35+12)*35+24)*35 + 32, 35, "holycow"},
59	{(((((17*36+24)*36+21)*36+34)*36+12)*36+24)*36 + 32, 36, "holycow"},
60}
61
62func TestItoa(t *testing.T) {
63	for _, test := range itob64tests {
64		s := FormatInt(test.in, test.base)
65		if s != test.out {
66			t.Errorf("FormatInt(%v, %v) = %v want %v",
67				test.in, test.base, s, test.out)
68		}
69		x := AppendInt([]byte("abc"), test.in, test.base)
70		if string(x) != "abc"+test.out {
71			t.Errorf("AppendInt(%q, %v, %v) = %q want %v",
72				"abc", test.in, test.base, x, test.out)
73		}
74
75		if test.in >= 0 {
76			s := FormatUint(uint64(test.in), test.base)
77			if s != test.out {
78				t.Errorf("FormatUint(%v, %v) = %v want %v",
79					test.in, test.base, s, test.out)
80			}
81			x := AppendUint(nil, uint64(test.in), test.base)
82			if string(x) != test.out {
83				t.Errorf("AppendUint(%q, %v, %v) = %q want %v",
84					"abc", uint64(test.in), test.base, x, test.out)
85			}
86		}
87
88		if test.base == 10 && int64(int(test.in)) == test.in {
89			s := Itoa(int(test.in))
90			if s != test.out {
91				t.Errorf("Itoa(%v) = %v want %v",
92					test.in, s, test.out)
93			}
94		}
95	}
96
97	// Override when base is illegal
98	defer func() {
99		if r := recover(); r == nil {
100			t.Fatalf("expected panic due to illegal base")
101		}
102	}()
103	FormatUint(12345678, 1)
104}
105
106type uitob64Test struct {
107	in   uint64
108	base int
109	out  string
110}
111
112var uitob64tests = []uitob64Test{
113	{1<<63 - 1, 10, "9223372036854775807"},
114	{1 << 63, 10, "9223372036854775808"},
115	{1<<63 + 1, 10, "9223372036854775809"},
116	{1<<64 - 2, 10, "18446744073709551614"},
117	{1<<64 - 1, 10, "18446744073709551615"},
118	{1<<64 - 1, 2, "1111111111111111111111111111111111111111111111111111111111111111"},
119}
120
121func TestUitoa(t *testing.T) {
122	for _, test := range uitob64tests {
123		s := FormatUint(test.in, test.base)
124		if s != test.out {
125			t.Errorf("FormatUint(%v, %v) = %v want %v",
126				test.in, test.base, s, test.out)
127		}
128		x := AppendUint([]byte("abc"), test.in, test.base)
129		if string(x) != "abc"+test.out {
130			t.Errorf("AppendUint(%q, %v, %v) = %q want %v",
131				"abc", test.in, test.base, x, test.out)
132		}
133
134	}
135}
136
137var varlenUints = []struct {
138	in  uint64
139	out string
140}{
141	{1, "1"},
142	{12, "12"},
143	{123, "123"},
144	{1234, "1234"},
145	{12345, "12345"},
146	{123456, "123456"},
147	{1234567, "1234567"},
148	{12345678, "12345678"},
149	{123456789, "123456789"},
150	{1234567890, "1234567890"},
151	{12345678901, "12345678901"},
152	{123456789012, "123456789012"},
153	{1234567890123, "1234567890123"},
154	{12345678901234, "12345678901234"},
155	{123456789012345, "123456789012345"},
156	{1234567890123456, "1234567890123456"},
157	{12345678901234567, "12345678901234567"},
158	{123456789012345678, "123456789012345678"},
159	{1234567890123456789, "1234567890123456789"},
160	{12345678901234567890, "12345678901234567890"},
161}
162
163func TestFormatUintVarlen(t *testing.T) {
164	for _, test := range varlenUints {
165		s := FormatUint(test.in, 10)
166		if s != test.out {
167			t.Errorf("FormatUint(%v, 10) = %v want %v", test.in, s, test.out)
168		}
169	}
170}
171
172func BenchmarkFormatInt(b *testing.B) {
173	for i := 0; i < b.N; i++ {
174		for _, test := range itob64tests {
175			s := FormatInt(test.in, test.base)
176			BenchSink += len(s)
177		}
178	}
179}
180
181func BenchmarkAppendInt(b *testing.B) {
182	dst := make([]byte, 0, 30)
183	for i := 0; i < b.N; i++ {
184		for _, test := range itob64tests {
185			dst = AppendInt(dst[:0], test.in, test.base)
186			BenchSink += len(dst)
187		}
188	}
189}
190
191func BenchmarkFormatUint(b *testing.B) {
192	for i := 0; i < b.N; i++ {
193		for _, test := range uitob64tests {
194			s := FormatUint(test.in, test.base)
195			BenchSink += len(s)
196		}
197	}
198}
199
200func BenchmarkAppendUint(b *testing.B) {
201	dst := make([]byte, 0, 30)
202	for i := 0; i < b.N; i++ {
203		for _, test := range uitob64tests {
204			dst = AppendUint(dst[:0], test.in, test.base)
205			BenchSink += len(dst)
206		}
207	}
208}
209
210func BenchmarkFormatIntSmall(b *testing.B) {
211	smallInts := []int64{7, 42}
212	for _, smallInt := range smallInts {
213		b.Run(Itoa(int(smallInt)), func(b *testing.B) {
214			for i := 0; i < b.N; i++ {
215				s := FormatInt(smallInt, 10)
216				BenchSink += len(s)
217			}
218		})
219	}
220}
221
222func BenchmarkAppendIntSmall(b *testing.B) {
223	dst := make([]byte, 0, 30)
224	const smallInt = 42
225	for i := 0; i < b.N; i++ {
226		dst = AppendInt(dst[:0], smallInt, 10)
227		BenchSink += len(dst)
228	}
229}
230
231func BenchmarkAppendUintVarlen(b *testing.B) {
232	for _, test := range varlenUints {
233		b.Run(test.out, func(b *testing.B) {
234			dst := make([]byte, 0, 30)
235			for j := 0; j < b.N; j++ {
236				dst = AppendUint(dst[:0], test.in, 10)
237				BenchSink += len(dst)
238			}
239		})
240	}
241}
242
243var BenchSink int // make sure compiler cannot optimize away benchmarks
244