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 "reflect" 10 . "strconv" 11 "testing" 12 ) 13 14 type atoui64Test struct { 15 in string 16 out uint64 17 err error 18 } 19 20 var atoui64tests = []atoui64Test{ 21 {"", 0, ErrSyntax}, 22 {"0", 0, nil}, 23 {"1", 1, nil}, 24 {"12345", 12345, nil}, 25 {"012345", 12345, nil}, 26 {"12345x", 0, ErrSyntax}, 27 {"98765432100", 98765432100, nil}, 28 {"18446744073709551615", 1<<64 - 1, nil}, 29 {"18446744073709551616", 1<<64 - 1, ErrRange}, 30 {"18446744073709551620", 1<<64 - 1, ErrRange}, 31 } 32 33 var btoui64tests = []atoui64Test{ 34 {"", 0, ErrSyntax}, 35 {"0", 0, nil}, 36 {"0x", 0, ErrSyntax}, 37 {"0X", 0, ErrSyntax}, 38 {"1", 1, nil}, 39 {"12345", 12345, nil}, 40 {"012345", 012345, nil}, 41 {"0x12345", 0x12345, nil}, 42 {"0X12345", 0x12345, nil}, 43 {"12345x", 0, ErrSyntax}, 44 {"0xabcdefg123", 0, ErrSyntax}, 45 {"123456789abc", 0, ErrSyntax}, 46 {"98765432100", 98765432100, nil}, 47 {"18446744073709551615", 1<<64 - 1, nil}, 48 {"18446744073709551616", 1<<64 - 1, ErrRange}, 49 {"18446744073709551620", 1<<64 - 1, ErrRange}, 50 {"0xFFFFFFFFFFFFFFFF", 1<<64 - 1, nil}, 51 {"0x10000000000000000", 1<<64 - 1, ErrRange}, 52 {"01777777777777777777777", 1<<64 - 1, nil}, 53 {"01777777777777777777778", 0, ErrSyntax}, 54 {"02000000000000000000000", 1<<64 - 1, ErrRange}, 55 {"0200000000000000000000", 1 << 61, nil}, 56 } 57 58 type atoi64Test struct { 59 in string 60 out int64 61 err error 62 } 63 64 var atoi64tests = []atoi64Test{ 65 {"", 0, ErrSyntax}, 66 {"0", 0, nil}, 67 {"-0", 0, nil}, 68 {"1", 1, nil}, 69 {"-1", -1, nil}, 70 {"12345", 12345, nil}, 71 {"-12345", -12345, nil}, 72 {"012345", 12345, nil}, 73 {"-012345", -12345, nil}, 74 {"98765432100", 98765432100, nil}, 75 {"-98765432100", -98765432100, nil}, 76 {"9223372036854775807", 1<<63 - 1, nil}, 77 {"-9223372036854775807", -(1<<63 - 1), nil}, 78 {"9223372036854775808", 1<<63 - 1, ErrRange}, 79 {"-9223372036854775808", -1 << 63, nil}, 80 {"9223372036854775809", 1<<63 - 1, ErrRange}, 81 {"-9223372036854775809", -1 << 63, ErrRange}, 82 } 83 84 type btoi64Test struct { 85 in string 86 base int 87 out int64 88 err error 89 } 90 91 var btoi64tests = []btoi64Test{ 92 {"", 0, 0, ErrSyntax}, 93 {"0", 0, 0, nil}, 94 {"-0", 0, 0, nil}, 95 {"1", 0, 1, nil}, 96 {"-1", 0, -1, nil}, 97 {"12345", 0, 12345, nil}, 98 {"-12345", 0, -12345, nil}, 99 {"012345", 0, 012345, nil}, 100 {"-012345", 0, -012345, nil}, 101 {"0x12345", 0, 0x12345, nil}, 102 {"-0X12345", 0, -0x12345, nil}, 103 {"12345x", 0, 0, ErrSyntax}, 104 {"-12345x", 0, 0, ErrSyntax}, 105 {"98765432100", 0, 98765432100, nil}, 106 {"-98765432100", 0, -98765432100, nil}, 107 {"9223372036854775807", 0, 1<<63 - 1, nil}, 108 {"-9223372036854775807", 0, -(1<<63 - 1), nil}, 109 {"9223372036854775808", 0, 1<<63 - 1, ErrRange}, 110 {"-9223372036854775808", 0, -1 << 63, nil}, 111 {"9223372036854775809", 0, 1<<63 - 1, ErrRange}, 112 {"-9223372036854775809", 0, -1 << 63, ErrRange}, 113 114 // other bases 115 {"g", 17, 16, nil}, 116 {"10", 25, 25, nil}, 117 {"holycow", 35, (((((17*35+24)*35+21)*35+34)*35+12)*35+24)*35 + 32, nil}, 118 {"holycow", 36, (((((17*36+24)*36+21)*36+34)*36+12)*36+24)*36 + 32, nil}, 119 120 // base 2 121 {"0", 2, 0, nil}, 122 {"-1", 2, -1, nil}, 123 {"1010", 2, 10, nil}, 124 {"1000000000000000", 2, 1 << 15, nil}, 125 {"111111111111111111111111111111111111111111111111111111111111111", 2, 1<<63 - 1, nil}, 126 {"1000000000000000000000000000000000000000000000000000000000000000", 2, 1<<63 - 1, ErrRange}, 127 {"-1000000000000000000000000000000000000000000000000000000000000000", 2, -1 << 63, nil}, 128 {"-1000000000000000000000000000000000000000000000000000000000000001", 2, -1 << 63, ErrRange}, 129 130 // base 8 131 {"-10", 8, -8, nil}, 132 {"57635436545", 8, 057635436545, nil}, 133 {"100000000", 8, 1 << 24, nil}, 134 135 // base 16 136 {"10", 16, 16, nil}, 137 {"-123456789abcdef", 16, -0x123456789abcdef, nil}, 138 {"7fffffffffffffff", 16, 1<<63 - 1, nil}, 139 } 140 141 type atoui32Test struct { 142 in string 143 out uint32 144 err error 145 } 146 147 var atoui32tests = []atoui32Test{ 148 {"", 0, ErrSyntax}, 149 {"0", 0, nil}, 150 {"1", 1, nil}, 151 {"12345", 12345, nil}, 152 {"012345", 12345, nil}, 153 {"12345x", 0, ErrSyntax}, 154 {"987654321", 987654321, nil}, 155 {"4294967295", 1<<32 - 1, nil}, 156 {"4294967296", 1<<32 - 1, ErrRange}, 157 } 158 159 type atoi32Test struct { 160 in string 161 out int32 162 err error 163 } 164 165 var atoi32tests = []atoi32Test{ 166 {"", 0, ErrSyntax}, 167 {"0", 0, nil}, 168 {"-0", 0, nil}, 169 {"1", 1, nil}, 170 {"-1", -1, nil}, 171 {"12345", 12345, nil}, 172 {"-12345", -12345, nil}, 173 {"012345", 12345, nil}, 174 {"-012345", -12345, nil}, 175 {"12345x", 0, ErrSyntax}, 176 {"-12345x", 0, ErrSyntax}, 177 {"987654321", 987654321, nil}, 178 {"-987654321", -987654321, nil}, 179 {"2147483647", 1<<31 - 1, nil}, 180 {"-2147483647", -(1<<31 - 1), nil}, 181 {"2147483648", 1<<31 - 1, ErrRange}, 182 {"-2147483648", -1 << 31, nil}, 183 {"2147483649", 1<<31 - 1, ErrRange}, 184 {"-2147483649", -1 << 31, ErrRange}, 185 } 186 187 type numErrorTest struct { 188 num, want string 189 } 190 191 var numErrorTests = []numErrorTest{ 192 {"0", `strconv.ParseFloat: parsing "0": failed`}, 193 {"`", "strconv.ParseFloat: parsing \"`\": failed"}, 194 {"1\x00.2", `strconv.ParseFloat: parsing "1\x00.2": failed`}, 195 } 196 197 func init() { 198 // The atoi routines return NumErrors wrapping 199 // the error and the string. Convert the tables above. 200 for i := range atoui64tests { 201 test := &atoui64tests[i] 202 if test.err != nil { 203 test.err = &NumError{"ParseUint", test.in, test.err} 204 } 205 } 206 for i := range btoui64tests { 207 test := &btoui64tests[i] 208 if test.err != nil { 209 test.err = &NumError{"ParseUint", test.in, test.err} 210 } 211 } 212 for i := range atoi64tests { 213 test := &atoi64tests[i] 214 if test.err != nil { 215 test.err = &NumError{"ParseInt", test.in, test.err} 216 } 217 } 218 for i := range btoi64tests { 219 test := &btoi64tests[i] 220 if test.err != nil { 221 test.err = &NumError{"ParseInt", test.in, test.err} 222 } 223 } 224 for i := range atoui32tests { 225 test := &atoui32tests[i] 226 if test.err != nil { 227 test.err = &NumError{"ParseUint", test.in, test.err} 228 } 229 } 230 for i := range atoi32tests { 231 test := &atoi32tests[i] 232 if test.err != nil { 233 test.err = &NumError{"ParseInt", test.in, test.err} 234 } 235 } 236 } 237 238 func TestParseUint64(t *testing.T) { 239 for i := range atoui64tests { 240 test := &atoui64tests[i] 241 out, err := ParseUint(test.in, 10, 64) 242 if test.out != out || !reflect.DeepEqual(test.err, err) { 243 t.Errorf("Atoui64(%q) = %v, %v want %v, %v", 244 test.in, out, err, test.out, test.err) 245 } 246 } 247 } 248 249 func TestParseUint64Base(t *testing.T) { 250 for i := range btoui64tests { 251 test := &btoui64tests[i] 252 out, err := ParseUint(test.in, 0, 64) 253 if test.out != out || !reflect.DeepEqual(test.err, err) { 254 t.Errorf("ParseUint(%q) = %v, %v want %v, %v", 255 test.in, out, err, test.out, test.err) 256 } 257 } 258 } 259 260 func TestParseInt64(t *testing.T) { 261 for i := range atoi64tests { 262 test := &atoi64tests[i] 263 out, err := ParseInt(test.in, 10, 64) 264 if test.out != out || !reflect.DeepEqual(test.err, err) { 265 t.Errorf("Atoi64(%q) = %v, %v want %v, %v", 266 test.in, out, err, test.out, test.err) 267 } 268 } 269 } 270 271 func TestParseInt64Base(t *testing.T) { 272 for i := range btoi64tests { 273 test := &btoi64tests[i] 274 out, err := ParseInt(test.in, test.base, 64) 275 if test.out != out || !reflect.DeepEqual(test.err, err) { 276 t.Errorf("ParseInt(%q) = %v, %v want %v, %v", 277 test.in, out, err, test.out, test.err) 278 } 279 } 280 } 281 282 func TestParseUint(t *testing.T) { 283 switch IntSize { 284 case 32: 285 for i := range atoui32tests { 286 test := &atoui32tests[i] 287 out, err := ParseUint(test.in, 10, 0) 288 if test.out != uint32(out) || !reflect.DeepEqual(test.err, err) { 289 t.Errorf("Atoui(%q) = %v, %v want %v, %v", 290 test.in, out, err, test.out, test.err) 291 } 292 } 293 case 64: 294 for i := range atoui64tests { 295 test := &atoui64tests[i] 296 out, err := ParseUint(test.in, 10, 0) 297 if test.out != uint64(out) || !reflect.DeepEqual(test.err, err) { 298 t.Errorf("Atoui(%q) = %v, %v want %v, %v", 299 test.in, out, err, test.out, test.err) 300 } 301 } 302 } 303 } 304 305 func TestParseInt(t *testing.T) { 306 switch IntSize { 307 case 32: 308 for i := range atoi32tests { 309 test := &atoi32tests[i] 310 out, err := ParseInt(test.in, 10, 0) 311 if test.out != int32(out) || !reflect.DeepEqual(test.err, err) { 312 t.Errorf("Atoi(%q) = %v, %v want %v, %v", 313 test.in, out, err, test.out, test.err) 314 } 315 } 316 case 64: 317 for i := range atoi64tests { 318 test := &atoi64tests[i] 319 out, err := ParseInt(test.in, 10, 0) 320 if test.out != int64(out) || !reflect.DeepEqual(test.err, err) { 321 t.Errorf("Atoi(%q) = %v, %v want %v, %v", 322 test.in, out, err, test.out, test.err) 323 } 324 } 325 } 326 } 327 328 func TestNumError(t *testing.T) { 329 for _, test := range numErrorTests { 330 err := &NumError{ 331 Func: "ParseFloat", 332 Num: test.num, 333 Err: errors.New("failed"), 334 } 335 if got := err.Error(); got != test.want { 336 t.Errorf(`(&NumError{"ParseFloat", %q, "failed"}).Error() = %v, want %v`, test.num, got, test.want) 337 } 338 } 339 } 340 341 func BenchmarkAtoi(b *testing.B) { 342 for i := 0; i < b.N; i++ { 343 ParseInt("12345678", 10, 0) 344 } 345 } 346 347 func BenchmarkAtoiNeg(b *testing.B) { 348 for i := 0; i < b.N; i++ { 349 ParseInt("-12345678", 10, 0) 350 } 351 } 352 353 func BenchmarkAtoi64(b *testing.B) { 354 for i := 0; i < b.N; i++ { 355 ParseInt("12345678901234", 10, 64) 356 } 357 } 358 359 func BenchmarkAtoi64Neg(b *testing.B) { 360 for i := 0; i < b.N; i++ { 361 ParseInt("-12345678901234", 10, 64) 362 } 363 } 364