Home | History | Annotate | Download | only in strconv
      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