Source file
src/math/big/intconv_test.go
1
2
3
4
5 package big
6
7 import (
8 "bytes"
9 "fmt"
10 "math/rand/v2"
11 "testing"
12 )
13
14 var stringTests = []struct {
15 in string
16 out string
17 base int
18 val int64
19 ok bool
20 }{
21
22 {in: ""},
23 {in: "a"},
24 {in: "z"},
25 {in: "+"},
26 {in: "-"},
27 {in: "0b"},
28 {in: "0o"},
29 {in: "0x"},
30 {in: "0y"},
31 {in: "2", base: 2},
32 {in: "0b2", base: 0},
33 {in: "08"},
34 {in: "8", base: 8},
35 {in: "0xg", base: 0},
36 {in: "g", base: 16},
37
38
39
40 {in: "_"},
41 {in: "0_"},
42 {in: "_0"},
43 {in: "-1__0"},
44 {in: "0x10_"},
45 {in: "1_000", base: 10},
46 {in: "d_e_a_d", base: 16},
47
48
49 {"0", "0", 0, 0, true},
50 {"0", "0", 10, 0, true},
51 {"0", "0", 16, 0, true},
52 {"+0", "0", 0, 0, true},
53 {"-0", "0", 0, 0, true},
54 {"10", "10", 0, 10, true},
55 {"10", "10", 10, 10, true},
56 {"10", "10", 16, 16, true},
57 {"-10", "-10", 16, -16, true},
58 {"+10", "10", 16, 16, true},
59 {"0b10", "2", 0, 2, true},
60 {"0o10", "8", 0, 8, true},
61 {"0x10", "16", 0, 16, true},
62 {in: "0x10", base: 16},
63 {"-0x10", "-16", 0, -16, true},
64 {"+0x10", "16", 0, 16, true},
65 {"00", "0", 0, 0, true},
66 {"0", "0", 8, 0, true},
67 {"07", "7", 0, 7, true},
68 {"7", "7", 8, 7, true},
69 {"023", "19", 0, 19, true},
70 {"23", "23", 8, 19, true},
71 {"cafebabe", "cafebabe", 16, 0xcafebabe, true},
72 {"0b0", "0", 0, 0, true},
73 {"-111", "-111", 2, -7, true},
74 {"-0b111", "-7", 0, -7, true},
75 {"0b1001010111", "599", 0, 0x257, true},
76 {"1001010111", "1001010111", 2, 0x257, true},
77 {"A", "a", 36, 10, true},
78 {"A", "A", 37, 36, true},
79 {"ABCXYZ", "abcxyz", 36, 623741435, true},
80 {"ABCXYZ", "ABCXYZ", 62, 33536793425, true},
81
82
83
84 {"1_000", "1000", 0, 1000, true},
85 {"0b_1010", "10", 0, 10, true},
86 {"+0o_660", "432", 0, 0660, true},
87 {"-0xF00D_1E", "-15731998", 0, -0xf00d1e, true},
88 }
89
90 func TestIntText(t *testing.T) {
91 z := new(Int)
92 for _, test := range stringTests {
93 if !test.ok {
94 continue
95 }
96
97 _, ok := z.SetString(test.in, test.base)
98 if !ok {
99 t.Errorf("%v: failed to parse", test)
100 continue
101 }
102
103 base := test.base
104 if base == 0 {
105 base = 10
106 }
107
108 if got := z.Text(base); got != test.out {
109 t.Errorf("%v: got %s; want %s", test, got, test.out)
110 }
111 }
112 }
113
114 func TestAppendText(t *testing.T) {
115 z := new(Int)
116 var buf []byte
117 for _, test := range stringTests {
118 if !test.ok {
119 continue
120 }
121
122 _, ok := z.SetString(test.in, test.base)
123 if !ok {
124 t.Errorf("%v: failed to parse", test)
125 continue
126 }
127
128 base := test.base
129 if base == 0 {
130 base = 10
131 }
132
133 i := len(buf)
134 buf = z.Append(buf, base)
135 if got := string(buf[i:]); got != test.out {
136 t.Errorf("%v: got %s; want %s", test, got, test.out)
137 }
138 }
139 }
140
141 func format(base int) string {
142 switch base {
143 case 2:
144 return "%b"
145 case 8:
146 return "%o"
147 case 16:
148 return "%x"
149 }
150 return "%d"
151 }
152
153 func TestGetString(t *testing.T) {
154 z := new(Int)
155 for i, test := range stringTests {
156 if !test.ok {
157 continue
158 }
159 z.SetInt64(test.val)
160
161 if test.base == 10 {
162 if got := z.String(); got != test.out {
163 t.Errorf("#%da got %s; want %s", i, got, test.out)
164 }
165 }
166
167 f := format(test.base)
168 got := fmt.Sprintf(f, z)
169 if f == "%d" {
170 if got != fmt.Sprintf("%d", test.val) {
171 t.Errorf("#%db got %s; want %d", i, got, test.val)
172 }
173 } else {
174 if got != test.out {
175 t.Errorf("#%dc got %s; want %s", i, got, test.out)
176 }
177 }
178 }
179 }
180
181 func TestSetString(t *testing.T) {
182 tmp := new(Int)
183 for i, test := range stringTests {
184
185
186 tmp.SetInt64(1234567890)
187 n1, ok1 := new(Int).SetString(test.in, test.base)
188 n2, ok2 := tmp.SetString(test.in, test.base)
189 expected := NewInt(test.val)
190 if ok1 != test.ok || ok2 != test.ok {
191 t.Errorf("#%d (input '%s') ok incorrect (should be %t)", i, test.in, test.ok)
192 continue
193 }
194 if !ok1 {
195 if n1 != nil {
196 t.Errorf("#%d (input '%s') n1 != nil", i, test.in)
197 }
198 continue
199 }
200 if !ok2 {
201 if n2 != nil {
202 t.Errorf("#%d (input '%s') n2 != nil", i, test.in)
203 }
204 continue
205 }
206
207 if ok1 && !isNormalized(n1) {
208 t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n1)
209 }
210 if ok2 && !isNormalized(n2) {
211 t.Errorf("#%d (input '%s'): %v is not normalized", i, test.in, *n2)
212 }
213
214 if n1.Cmp(expected) != 0 {
215 t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n1, test.val)
216 }
217 if n2.Cmp(expected) != 0 {
218 t.Errorf("#%d (input '%s') got: %s want: %d", i, test.in, n2, test.val)
219 }
220 }
221 }
222
223 var formatTests = []struct {
224 input string
225 format string
226 output string
227 }{
228 {"<nil>", "%x", "<nil>"},
229 {"<nil>", "%#x", "<nil>"},
230 {"<nil>", "%#y", "%!y(big.Int=<nil>)"},
231
232 {"10", "%b", "1010"},
233 {"10", "%o", "12"},
234 {"10", "%d", "10"},
235 {"10", "%v", "10"},
236 {"10", "%x", "a"},
237 {"10", "%X", "A"},
238 {"-10", "%X", "-A"},
239 {"10", "%y", "%!y(big.Int=10)"},
240 {"-10", "%y", "%!y(big.Int=-10)"},
241
242 {"10", "%#b", "0b1010"},
243 {"10", "%#o", "012"},
244 {"10", "%O", "0o12"},
245 {"-10", "%#b", "-0b1010"},
246 {"-10", "%#o", "-012"},
247 {"-10", "%O", "-0o12"},
248 {"10", "%#d", "10"},
249 {"10", "%#v", "10"},
250 {"10", "%#x", "0xa"},
251 {"10", "%#X", "0XA"},
252 {"-10", "%#X", "-0XA"},
253 {"10", "%#y", "%!y(big.Int=10)"},
254 {"-10", "%#y", "%!y(big.Int=-10)"},
255
256 {"1234", "%d", "1234"},
257 {"1234", "%3d", "1234"},
258 {"1234", "%4d", "1234"},
259 {"-1234", "%d", "-1234"},
260 {"1234", "% 5d", " 1234"},
261 {"1234", "%+5d", "+1234"},
262 {"1234", "%-5d", "1234 "},
263 {"1234", "%x", "4d2"},
264 {"1234", "%X", "4D2"},
265 {"-1234", "%3x", "-4d2"},
266 {"-1234", "%4x", "-4d2"},
267 {"-1234", "%5x", " -4d2"},
268 {"-1234", "%-5x", "-4d2 "},
269 {"1234", "%03d", "1234"},
270 {"1234", "%04d", "1234"},
271 {"1234", "%05d", "01234"},
272 {"1234", "%06d", "001234"},
273 {"-1234", "%06d", "-01234"},
274 {"1234", "%+06d", "+01234"},
275 {"1234", "% 06d", " 01234"},
276 {"1234", "%-6d", "1234 "},
277 {"1234", "%-06d", "1234 "},
278 {"-1234", "%-06d", "-1234 "},
279
280 {"1234", "%.3d", "1234"},
281 {"1234", "%.4d", "1234"},
282 {"1234", "%.5d", "01234"},
283 {"1234", "%.6d", "001234"},
284 {"-1234", "%.3d", "-1234"},
285 {"-1234", "%.4d", "-1234"},
286 {"-1234", "%.5d", "-01234"},
287 {"-1234", "%.6d", "-001234"},
288
289 {"1234", "%8.3d", " 1234"},
290 {"1234", "%8.4d", " 1234"},
291 {"1234", "%8.5d", " 01234"},
292 {"1234", "%8.6d", " 001234"},
293 {"-1234", "%8.3d", " -1234"},
294 {"-1234", "%8.4d", " -1234"},
295 {"-1234", "%8.5d", " -01234"},
296 {"-1234", "%8.6d", " -001234"},
297
298 {"1234", "%+8.3d", " +1234"},
299 {"1234", "%+8.4d", " +1234"},
300 {"1234", "%+8.5d", " +01234"},
301 {"1234", "%+8.6d", " +001234"},
302 {"-1234", "%+8.3d", " -1234"},
303 {"-1234", "%+8.4d", " -1234"},
304 {"-1234", "%+8.5d", " -01234"},
305 {"-1234", "%+8.6d", " -001234"},
306
307 {"1234", "% 8.3d", " 1234"},
308 {"1234", "% 8.4d", " 1234"},
309 {"1234", "% 8.5d", " 01234"},
310 {"1234", "% 8.6d", " 001234"},
311 {"-1234", "% 8.3d", " -1234"},
312 {"-1234", "% 8.4d", " -1234"},
313 {"-1234", "% 8.5d", " -01234"},
314 {"-1234", "% 8.6d", " -001234"},
315
316 {"1234", "%.3x", "4d2"},
317 {"1234", "%.4x", "04d2"},
318 {"1234", "%.5x", "004d2"},
319 {"1234", "%.6x", "0004d2"},
320 {"-1234", "%.3x", "-4d2"},
321 {"-1234", "%.4x", "-04d2"},
322 {"-1234", "%.5x", "-004d2"},
323 {"-1234", "%.6x", "-0004d2"},
324
325 {"1234", "%8.3x", " 4d2"},
326 {"1234", "%8.4x", " 04d2"},
327 {"1234", "%8.5x", " 004d2"},
328 {"1234", "%8.6x", " 0004d2"},
329 {"-1234", "%8.3x", " -4d2"},
330 {"-1234", "%8.4x", " -04d2"},
331 {"-1234", "%8.5x", " -004d2"},
332 {"-1234", "%8.6x", " -0004d2"},
333
334 {"1234", "%+8.3x", " +4d2"},
335 {"1234", "%+8.4x", " +04d2"},
336 {"1234", "%+8.5x", " +004d2"},
337 {"1234", "%+8.6x", " +0004d2"},
338 {"-1234", "%+8.3x", " -4d2"},
339 {"-1234", "%+8.4x", " -04d2"},
340 {"-1234", "%+8.5x", " -004d2"},
341 {"-1234", "%+8.6x", " -0004d2"},
342
343 {"1234", "% 8.3x", " 4d2"},
344 {"1234", "% 8.4x", " 04d2"},
345 {"1234", "% 8.5x", " 004d2"},
346 {"1234", "% 8.6x", " 0004d2"},
347 {"1234", "% 8.7x", " 00004d2"},
348 {"1234", "% 8.8x", " 000004d2"},
349 {"-1234", "% 8.3x", " -4d2"},
350 {"-1234", "% 8.4x", " -04d2"},
351 {"-1234", "% 8.5x", " -004d2"},
352 {"-1234", "% 8.6x", " -0004d2"},
353 {"-1234", "% 8.7x", "-00004d2"},
354 {"-1234", "% 8.8x", "-000004d2"},
355
356 {"1234", "%-8.3d", "1234 "},
357 {"1234", "%-8.4d", "1234 "},
358 {"1234", "%-8.5d", "01234 "},
359 {"1234", "%-8.6d", "001234 "},
360 {"1234", "%-8.7d", "0001234 "},
361 {"1234", "%-8.8d", "00001234"},
362 {"-1234", "%-8.3d", "-1234 "},
363 {"-1234", "%-8.4d", "-1234 "},
364 {"-1234", "%-8.5d", "-01234 "},
365 {"-1234", "%-8.6d", "-001234 "},
366 {"-1234", "%-8.7d", "-0001234"},
367 {"-1234", "%-8.8d", "-00001234"},
368
369 {"16777215", "%b", "111111111111111111111111"},
370
371 {"0", "%.d", ""},
372 {"0", "%.0d", ""},
373 {"0", "%3.d", ""},
374 }
375
376 func TestFormat(t *testing.T) {
377 for i, test := range formatTests {
378 var x *Int
379 if test.input != "<nil>" {
380 var ok bool
381 x, ok = new(Int).SetString(test.input, 0)
382 if !ok {
383 t.Errorf("#%d failed reading input %s", i, test.input)
384 }
385 }
386 output := fmt.Sprintf(test.format, x)
387 if output != test.output {
388 t.Errorf("#%d got %q; want %q, {%q, %q, %q}", i, output, test.output, test.input, test.format, test.output)
389 }
390 }
391 }
392
393 type scanTest struct {
394 input string
395 format string
396 output string
397 remaining int
398 }
399
400 var scanTests = []scanTest{
401 {"1010", "%b", "10", 0},
402 {"0b1010", "%v", "10", 0},
403 {"12", "%o", "10", 0},
404 {"012", "%v", "10", 0},
405 {"10", "%d", "10", 0},
406 {"10", "%v", "10", 0},
407 {"a", "%x", "10", 0},
408 {"0xa", "%v", "10", 0},
409 {"A", "%X", "10", 0},
410 {"-A", "%X", "-10", 0},
411 {"+0b1011001", "%v", "89", 0},
412 {"0xA", "%v", "10", 0},
413 {"0 ", "%v", "0", 1},
414 {"2+3", "%v", "2", 2},
415 {"0XABC 12", "%v", "2748", 3},
416
417 {"10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000022222223333333333444444444", "%x", "72999049881955123498258745691204661198291656115976958889267080286388402675338838184094604981077942396458276955120179409196748346461468914795561487752253275293347599221664790586512596660792869956", 0},
418 {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1", "%x", "1167984798111281975972139931059274579172666497855631342228273284582214442805421410945513679697247078343332431249286160621687557589604464869034163736183926240549918956767671325412748661204059352801", 0},
419 {"5c0d52f451aec609b15da8e5e5626c4eaa88723bdeac9d25ca9b961269400410ca208a16af9c2fb07d7a11c7772cba02c22f9711078d51a3797eb18e691295293284d988e349fa6deba46b25a4ecd9f715", "%x", "419981998319789881681348172155240145539175961318447822049735313481433836043208347786919222066492311384432264836938599791362288343314139526391998172436831830624710446410781662672086936222288181013", 0},
420 {"92fcad4b5c0d52f451aec609b15da8e5e5626c4eaa88723bdeac9d25ca9b961269400410ca208a16af9c2fb07d799c32fe2f3cc5422f9711078d51a3797eb18e691295293284d8f5e69caf6decddfe1df6", "%x", "670619546945481998414061201992255225716434798957375727890607516800039934374391281275121813279544891602026798031004764406015624866771554937391445093144221697436880587924204655403711377861305572854", 0},
421 {"10000000000000000000000200000000000000000000003000000000000000000000040000000000000000000000500000000000000000000006", "%d", "10000000000000000000000200000000000000000000003000000000000000000000040000000000000000000000500000000000000000000006", 0},
422 }
423
424 func init() {
425 for i := range 200 {
426 d := make([]byte, i+1)
427 for j := range d {
428 d[j] = '0' + rand.N(byte(10))
429 }
430 if d[0] == '0' {
431 d[0] = '1'
432 }
433 scanTests = append(scanTests, scanTest{input: string(d), format: "%d", output: string(d)})
434 }
435 }
436
437 func TestScan(t *testing.T) {
438 var buf bytes.Buffer
439 for i, test := range scanTests {
440 x := new(Int)
441 buf.Reset()
442 buf.WriteString(test.input)
443 if _, err := fmt.Fscanf(&buf, test.format, x); err != nil {
444 t.Errorf("#%d error: %s", i, err)
445 }
446 if x.String() != test.output {
447 t.Errorf("#%d got %s; want %s", i, x.String(), test.output)
448 }
449 if buf.Len() != test.remaining {
450 t.Errorf("#%d got %d bytes remaining; want %d", i, buf.Len(), test.remaining)
451 }
452 }
453 }
454
View as plain text