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