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