| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Note: These tests are focused mainly on generating the right errors. |
| // The extensive numerical tests are in ../internal/strconv. |
| // Add new tests there instead of here whenever possible. |
| |
| package strconv_test |
| |
| import ( |
| "bytes" |
| "errors" |
| "math" |
| "math/cmplx" |
| "reflect" |
| . "strconv" |
| "testing" |
| ) |
| |
| type atobTest struct { |
| in string |
| out bool |
| err error |
| } |
| |
| var atobtests = []atobTest{ |
| {"", false, ErrSyntax}, |
| {"asdf", false, ErrSyntax}, |
| {"0", false, nil}, |
| {"false", false, nil}, |
| {"true", true, nil}, |
| } |
| |
| func TestParseBool(t *testing.T) { |
| for _, test := range atobtests { |
| b, e := ParseBool(test.in) |
| if test.err != nil { |
| // expect an error |
| if e == nil { |
| t.Errorf("ParseBool(%s) = nil; want %s", test.in, test.err) |
| } else { |
| // NumError assertion must succeed; it's the only thing we return. |
| if e.(*NumError).Err != test.err { |
| t.Errorf("ParseBool(%s) = %s; want %s", test.in, e, test.err) |
| } |
| } |
| } else { |
| if e != nil { |
| t.Errorf("ParseBool(%s) = %s; want nil", test.in, e) |
| } |
| if b != test.out { |
| t.Errorf("ParseBool(%s) = %t; want %t", test.in, b, test.out) |
| } |
| } |
| } |
| } |
| |
| var boolString = map[bool]string{ |
| true: "true", |
| false: "false", |
| } |
| |
| func TestFormatBool(t *testing.T) { |
| for b, s := range boolString { |
| if f := FormatBool(b); f != s { |
| t.Errorf("FormatBool(%v) = %q; want %q", b, f, s) |
| } |
| } |
| } |
| |
| type appendBoolTest struct { |
| b bool |
| in []byte |
| out []byte |
| } |
| |
| var appendBoolTests = []appendBoolTest{ |
| {true, []byte("foo "), []byte("foo true")}, |
| {false, []byte("foo "), []byte("foo false")}, |
| } |
| |
| func TestAppendBool(t *testing.T) { |
| for _, test := range appendBoolTests { |
| b := AppendBool(test.in, test.b) |
| if !bytes.Equal(b, test.out) { |
| t.Errorf("AppendBool(%q, %v) = %q; want %q", test.in, test.b, b, test.out) |
| } |
| } |
| } |
| |
| var ( |
| infp0 = complex(math.Inf(+1), 0) |
| infm0 = complex(math.Inf(-1), 0) |
| inf0p = complex(0, math.Inf(+1)) |
| inf0m = complex(0, math.Inf(-1)) |
| |
| infpp = complex(math.Inf(+1), math.Inf(+1)) |
| infpm = complex(math.Inf(+1), math.Inf(-1)) |
| infmp = complex(math.Inf(-1), math.Inf(+1)) |
| infmm = complex(math.Inf(-1), math.Inf(-1)) |
| ) |
| |
| type atocTest struct { |
| in string |
| out complex128 |
| err error |
| } |
| |
| func TestParseComplex(t *testing.T) { |
| tests := []atocTest{ |
| // Clearly invalid |
| {"", 0, ErrSyntax}, |
| {" ", 0, ErrSyntax}, |
| {"(", 0, ErrSyntax}, |
| {")", 0, ErrSyntax}, |
| {"i", 0, ErrSyntax}, |
| {"+i", 0, ErrSyntax}, |
| {"-i", 0, ErrSyntax}, |
| {"1I", 0, ErrSyntax}, |
| {"10 + 5i", 0, ErrSyntax}, |
| {"3+", 0, ErrSyntax}, |
| {"3+5", 0, ErrSyntax}, |
| {"3+5+5i", 0, ErrSyntax}, |
| |
| // Parentheses |
| {"()", 0, ErrSyntax}, |
| {"(i)", 0, ErrSyntax}, |
| {"(0)", 0, nil}, |
| {"(1i)", 1i, nil}, |
| {"(3.0+5.5i)", 3.0 + 5.5i, nil}, |
| {"(1)+1i", 0, ErrSyntax}, |
| {"(3.0+5.5i", 0, ErrSyntax}, |
| {"3.0+5.5i)", 0, ErrSyntax}, |
| |
| // NaNs |
| {"NaN", complex(math.NaN(), 0), nil}, |
| {"NANi", complex(0, math.NaN()), nil}, |
| {"nan+nAni", complex(math.NaN(), math.NaN()), nil}, |
| {"+NaN", 0, ErrSyntax}, |
| {"-NaN", 0, ErrSyntax}, |
| {"NaN-NaNi", 0, ErrSyntax}, |
| |
| // Infs |
| {"Inf", infp0, nil}, |
| {"+inf", infp0, nil}, |
| {"-inf", infm0, nil}, |
| {"Infinity", infp0, nil}, |
| {"+INFINITY", infp0, nil}, |
| {"-infinity", infm0, nil}, |
| {"+infi", inf0p, nil}, |
| {"0-infinityi", inf0m, nil}, |
| {"Inf+Infi", infpp, nil}, |
| {"+Inf-Infi", infpm, nil}, |
| {"-Infinity+Infi", infmp, nil}, |
| {"inf-inf", 0, ErrSyntax}, |
| |
| // Zeros |
| {"0", 0, nil}, |
| {"0i", 0, nil}, |
| {"-0.0i", 0, nil}, |
| {"0+0.0i", 0, nil}, |
| {"0e+0i", 0, nil}, |
| {"0e-0+0i", 0, nil}, |
| {"-0.0-0.0i", 0, nil}, |
| {"0e+012345", 0, nil}, |
| {"0x0p+012345i", 0, nil}, |
| {"0x0.00p-012345i", 0, nil}, |
| {"+0e-0+0e-0i", 0, nil}, |
| {"0e+0+0e+0i", 0, nil}, |
| {"-0e+0-0e+0i", 0, nil}, |
| |
| // Regular non-zeroes |
| {"0.1", 0.1, nil}, |
| {"0.1i", 0 + 0.1i, nil}, |
| {"0.123", 0.123, nil}, |
| {"0.123i", 0 + 0.123i, nil}, |
| {"0.123+0.123i", 0.123 + 0.123i, nil}, |
| {"99", 99, nil}, |
| {"+99", 99, nil}, |
| {"-99", -99, nil}, |
| {"+1i", 1i, nil}, |
| {"-1i", -1i, nil}, |
| {"+3+1i", 3 + 1i, nil}, |
| {"30+3i", 30 + 3i, nil}, |
| {"+3e+3-3e+3i", 3e+3 - 3e+3i, nil}, |
| {"+3e+3+3e+3i", 3e+3 + 3e+3i, nil}, |
| {"+3e+3+3e+3i+", 0, ErrSyntax}, |
| |
| // Separators |
| {"0.1", 0.1, nil}, |
| {"0.1i", 0 + 0.1i, nil}, |
| {"0.1_2_3", 0.123, nil}, |
| {"+0x_3p3i", 0x3p3i, nil}, |
| {"0_0+0x_0p0i", 0, nil}, |
| {"0x_10.3p-8+0x3p3i", 0x10.3p-8 + 0x3p3i, nil}, |
| {"+0x_1_0.3p-8+0x_3_0p3i", 0x10.3p-8 + 0x30p3i, nil}, |
| {"0x1_0.3p+8-0x_3p3i", 0x10.3p+8 - 0x3p3i, nil}, |
| |
| // Hexadecimals |
| {"0x10.3p-8+0x3p3i", 0x10.3p-8 + 0x3p3i, nil}, |
| {"+0x10.3p-8+0x3p3i", 0x10.3p-8 + 0x3p3i, nil}, |
| {"0x10.3p+8-0x3p3i", 0x10.3p+8 - 0x3p3i, nil}, |
| {"0x1p0", 1, nil}, |
| {"0x1p1", 2, nil}, |
| {"0x1p-1", 0.5, nil}, |
| {"0x1ep-1", 15, nil}, |
| {"-0x1ep-1", -15, nil}, |
| {"-0x2p3", -16, nil}, |
| {"0x1e2", 0, ErrSyntax}, |
| {"1p2", 0, ErrSyntax}, |
| {"0x1e2i", 0, ErrSyntax}, |
| |
| // ErrRange |
| // next float64 - too large |
| {"+0x1p1024", infp0, ErrRange}, |
| {"-0x1p1024", infm0, ErrRange}, |
| {"+0x1p1024i", inf0p, ErrRange}, |
| {"-0x1p1024i", inf0m, ErrRange}, |
| {"+0x1p1024+0x1p1024i", infpp, ErrRange}, |
| {"+0x1p1024-0x1p1024i", infpm, ErrRange}, |
| {"-0x1p1024+0x1p1024i", infmp, ErrRange}, |
| {"-0x1p1024-0x1p1024i", infmm, ErrRange}, |
| // the border is ...158079 |
| // borderline - okay |
| {"+0x1.fffffffffffff7fffp1023+0x1.fffffffffffff7fffp1023i", 1.7976931348623157e+308 + 1.7976931348623157e+308i, nil}, |
| {"+0x1.fffffffffffff7fffp1023-0x1.fffffffffffff7fffp1023i", 1.7976931348623157e+308 - 1.7976931348623157e+308i, nil}, |
| {"-0x1.fffffffffffff7fffp1023+0x1.fffffffffffff7fffp1023i", -1.7976931348623157e+308 + 1.7976931348623157e+308i, nil}, |
| {"-0x1.fffffffffffff7fffp1023-0x1.fffffffffffff7fffp1023i", -1.7976931348623157e+308 - 1.7976931348623157e+308i, nil}, |
| // borderline - too large |
| {"+0x1.fffffffffffff8p1023", infp0, ErrRange}, |
| {"-0x1fffffffffffff.8p+971", infm0, ErrRange}, |
| {"+0x1.fffffffffffff8p1023i", inf0p, ErrRange}, |
| {"-0x1fffffffffffff.8p+971i", inf0m, ErrRange}, |
| {"+0x1.fffffffffffff8p1023+0x1.fffffffffffff8p1023i", infpp, ErrRange}, |
| {"+0x1.fffffffffffff8p1023-0x1.fffffffffffff8p1023i", infpm, ErrRange}, |
| {"-0x1fffffffffffff.8p+971+0x1fffffffffffff.8p+971i", infmp, ErrRange}, |
| {"-0x1fffffffffffff8p+967-0x1fffffffffffff8p+967i", infmm, ErrRange}, |
| // a little too large |
| {"1e308+1e308i", 1e+308 + 1e+308i, nil}, |
| {"2e308+2e308i", infpp, ErrRange}, |
| {"1e309+1e309i", infpp, ErrRange}, |
| {"0x1p1025+0x1p1025i", infpp, ErrRange}, |
| {"2e308", infp0, ErrRange}, |
| {"1e309", infp0, ErrRange}, |
| {"0x1p1025", infp0, ErrRange}, |
| {"2e308i", inf0p, ErrRange}, |
| {"1e309i", inf0p, ErrRange}, |
| {"0x1p1025i", inf0p, ErrRange}, |
| // way too large |
| {"+1e310+1e310i", infpp, ErrRange}, |
| {"+1e310-1e310i", infpm, ErrRange}, |
| {"-1e310+1e310i", infmp, ErrRange}, |
| {"-1e310-1e310i", infmm, ErrRange}, |
| // under/overflow exponent |
| {"1e-4294967296", 0, nil}, |
| {"1e-4294967296i", 0, nil}, |
| {"1e-4294967296+1i", 1i, nil}, |
| {"1+1e-4294967296i", 1, nil}, |
| {"1e-4294967296+1e-4294967296i", 0, nil}, |
| {"1e+4294967296", infp0, ErrRange}, |
| {"1e+4294967296i", inf0p, ErrRange}, |
| {"1e+4294967296+1e+4294967296i", infpp, ErrRange}, |
| {"1e+4294967296-1e+4294967296i", infpm, ErrRange}, |
| } |
| for i := range tests { |
| test := &tests[i] |
| if test.err != nil { |
| test.err = &NumError{Func: "ParseComplex", Num: test.in, Err: test.err} |
| } |
| got, err := ParseComplex(test.in, 128) |
| if !reflect.DeepEqual(err, test.err) { |
| t.Fatalf("ParseComplex(%q, 128) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err) |
| } |
| if !(cmplx.IsNaN(test.out) && cmplx.IsNaN(got)) && got != test.out { |
| t.Fatalf("ParseComplex(%q, 128) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err) |
| } |
| |
| if complex128(complex64(test.out)) == test.out { |
| got, err := ParseComplex(test.in, 64) |
| if !reflect.DeepEqual(err, test.err) { |
| t.Fatalf("ParseComplex(%q, 64) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err) |
| } |
| got64 := complex64(got) |
| if complex128(got64) != test.out { |
| t.Fatalf("ParseComplex(%q, 64) = %v, %v; want %v, %v", test.in, got, err, test.out, test.err) |
| } |
| } |
| } |
| } |
| |
| // Issue 42297: allow ParseComplex(s, not_32_or_64) for legacy reasons |
| func TestParseComplexIncorrectBitSize(t *testing.T) { |
| const s = "1.5e308+1.0e307i" |
| const want = 1.5e308 + 1.0e307i |
| |
| for _, bitSize := range []int{0, 10, 100, 256} { |
| c, err := ParseComplex(s, bitSize) |
| if err != nil { |
| t.Fatalf("ParseComplex(%q, %d) gave error %s", s, bitSize, err) |
| } |
| if c != want { |
| t.Fatalf("ParseComplex(%q, %d) = %g (expected %g)", s, bitSize, c, want) |
| } |
| } |
| } |
| |
| type atofTest struct { |
| in string |
| out string |
| err error |
| } |
| |
| var atoftests = []atofTest{ |
| {"", "0", ErrSyntax}, |
| {"1.25", "1.25", nil}, |
| {"+1", "1", nil}, |
| {"1x", "0", ErrSyntax}, |
| {"1.1.", "0", ErrSyntax}, |
| {"1e23", "1e+23", nil}, |
| {"1E23", "1e+23", nil}, |
| {"0x1fFe2.p0", "131042", nil}, |
| {"0x1fFe2.P0", "131042", nil}, |
| {"-0x2p3", "-16", nil}, |
| {"0x0.fp4", "15", nil}, |
| {"0x0.fp0", "0.9375", nil}, |
| {"0x1e2", "0", ErrSyntax}, |
| {"1p2", "0", ErrSyntax}, |
| {"0x1p1024", "+Inf", ErrRange}, |
| {"-0x1p1024", "-Inf", ErrRange}, |
| {"0x1.fffffffffffff7fffp1023", "1.7976931348623157e+308", nil}, |
| {"-0x1.fffffffffffff7fffp1023", "-1.7976931348623157e+308", nil}, |
| {"1.797693134862315808e308", "+Inf", ErrRange}, |
| {"-1.797693134862315808e308", "-Inf", ErrRange}, |
| } |
| |
| func init() { |
| // The atof routines return NumErrors wrapping |
| // the error and the string. Convert the table above. |
| for i := range atoftests { |
| test := &atoftests[i] |
| if test.err != nil { |
| test.err = &NumError{"ParseFloat", test.in, test.err} |
| } |
| } |
| } |
| |
| func TestAtof(t *testing.T) { |
| for i := 0; i < len(atoftests); i++ { |
| test := &atoftests[i] |
| out, err := ParseFloat(test.in, 64) |
| outs := FormatFloat(out, 'g', -1, 64) |
| if outs != test.out || !reflect.DeepEqual(err, test.err) { |
| t.Errorf("ParseFloat(%v, 64) = %v, %v want %v, %v", |
| test.in, out, err, test.out, test.err) |
| } |
| |
| if float64(float32(out)) == out { |
| out, err := ParseFloat(test.in, 32) |
| out32 := float32(out) |
| if float64(out32) != out { |
| t.Errorf("ParseFloat(%v, 32) = %v, not a float32 (closest is %v)", test.in, out, float64(out32)) |
| continue |
| } |
| outs := FormatFloat(float64(out32), 'g', -1, 32) |
| if outs != test.out || !reflect.DeepEqual(err, test.err) { |
| t.Errorf("ParseFloat(%v, 32) = %v, %v want %v, %v # %v", |
| test.in, out32, err, test.out, test.err, out) |
| } |
| } |
| } |
| } |
| |
| type parseUint64Test struct { |
| in string |
| out uint64 |
| err error |
| } |
| |
| var parseUint64Tests = []parseUint64Test{ |
| {"", 0, ErrSyntax}, |
| {"0", 0, nil}, |
| {"1", 1, nil}, |
| {"12345", 12345, nil}, |
| {"012345", 12345, nil}, |
| {"18446744073709551616", 1<<64 - 1, ErrRange}, |
| {"-1", 0, ErrSyntax}, |
| } |
| |
| type parseUint64BaseTest struct { |
| in string |
| base int |
| out uint64 |
| err error |
| } |
| |
| var parseUint64BaseTests = []parseUint64BaseTest{ |
| {"", 0, 0, ErrSyntax}, |
| {"0", 0, 0, nil}, |
| {"1", 0, 1, nil}, |
| {"-1", 0, 0, ErrSyntax}, |
| {"12345", 0, 12345, nil}, |
| {"012345", 0, 012345, nil}, |
| {"18446744073709551616", 0, 1<<64 - 1, ErrRange}, |
| {"0b", 0, 0, ErrSyntax}, |
| {"101", 2, 5, nil}, |
| {"101_", 2, 0, ErrSyntax}, |
| } |
| |
| type parseInt64Test struct { |
| in string |
| out int64 |
| err error |
| } |
| |
| var parseInt64Tests = []parseInt64Test{ |
| {"", 0, ErrSyntax}, |
| {"0", 0, nil}, |
| {"1", 1, nil}, |
| {"-1", -1, nil}, |
| {"12345", 12345, nil}, |
| {"9223372036854775808", 1<<63 - 1, ErrRange}, |
| {"123%45", 0, ErrSyntax}, |
| } |
| |
| type parseInt64BaseTest struct { |
| in string |
| base int |
| out int64 |
| err error |
| } |
| |
| var parseInt64BaseTests = []parseInt64BaseTest{ |
| {"", 0, 0, ErrSyntax}, |
| {"0", 0, 0, nil}, |
| {"1", 0, 1, nil}, |
| {"-1", 0, -1, nil}, |
| {"12345", 0, 12345, nil}, |
| {"12345", 9, 8303, nil}, |
| {"012345", 0, 012345, nil}, |
| {"9223372036854775808", 10, 1<<63 - 1, ErrRange}, |
| {"0b", 0, 0, ErrSyntax}, |
| {"101", 2, 5, nil}, |
| {"101_", 2, 0, ErrSyntax}, |
| } |
| |
| type parseUint32Test struct { |
| in string |
| out uint32 |
| err error |
| } |
| |
| var parseUint32Tests = []parseUint32Test{ |
| {"", 0, ErrSyntax}, |
| {"0", 0, nil}, |
| {"1", 1, nil}, |
| {"12345", 12345, nil}, |
| {"12345x", 0, ErrSyntax}, |
| {"987654321", 987654321, nil}, |
| {"4294967296", 1<<32 - 1, ErrRange}, |
| {"1_2_3_4_5", 0, ErrSyntax}, // base=10 so no underscores allowed |
| {"12345_", 0, ErrSyntax}, |
| } |
| |
| type parseInt32Test struct { |
| in string |
| out int32 |
| err error |
| } |
| |
| var parseInt32Tests = []parseInt32Test{ |
| {"", 0, ErrSyntax}, |
| {"0", 0, nil}, |
| {"-0", 0, nil}, |
| {"1", 1, nil}, |
| {"-1", -1, nil}, |
| {"12345", 12345, nil}, |
| {"-12345", -12345, nil}, |
| {"2147483648", 1<<31 - 1, ErrRange}, |
| {"12345_", 0, ErrSyntax}, |
| } |
| |
| type numErrorTest struct { |
| num, want string |
| } |
| |
| var numErrorTests = []numErrorTest{ |
| {"0", `strconv.ParseFloat: parsing "0": failed`}, |
| {"`", "strconv.ParseFloat: parsing \"`\": failed"}, |
| {"1\x00.2", `strconv.ParseFloat: parsing "1\x00.2": failed`}, |
| } |
| |
| func init() { |
| // The parse routines return NumErrors wrapping |
| // the error and the string. Convert the tables above. |
| for i := range parseUint64Tests { |
| test := &parseUint64Tests[i] |
| if test.err != nil { |
| test.err = &NumError{"ParseUint", test.in, test.err} |
| } |
| } |
| for i := range parseUint64BaseTests { |
| test := &parseUint64BaseTests[i] |
| if test.err != nil { |
| test.err = &NumError{"ParseUint", test.in, test.err} |
| } |
| } |
| for i := range parseInt64Tests { |
| test := &parseInt64Tests[i] |
| if test.err != nil { |
| test.err = &NumError{"ParseInt", test.in, test.err} |
| } |
| } |
| for i := range parseInt64BaseTests { |
| test := &parseInt64BaseTests[i] |
| if test.err != nil { |
| test.err = &NumError{"ParseInt", test.in, test.err} |
| } |
| } |
| for i := range parseUint32Tests { |
| test := &parseUint32Tests[i] |
| if test.err != nil { |
| test.err = &NumError{"ParseUint", test.in, test.err} |
| } |
| } |
| for i := range parseInt32Tests { |
| test := &parseInt32Tests[i] |
| if test.err != nil { |
| test.err = &NumError{"ParseInt", test.in, test.err} |
| } |
| } |
| } |
| |
| func TestParseUint32(t *testing.T) { |
| for i := range parseUint32Tests { |
| test := &parseUint32Tests[i] |
| out, err := ParseUint(test.in, 10, 32) |
| if uint64(test.out) != out || !reflect.DeepEqual(test.err, err) { |
| t.Errorf("ParseUint(%q, 10, 32) = %v, %v want %v, %v", |
| test.in, out, err, test.out, test.err) |
| } |
| } |
| } |
| |
| func TestParseUint64(t *testing.T) { |
| for i := range parseUint64Tests { |
| test := &parseUint64Tests[i] |
| out, err := ParseUint(test.in, 10, 64) |
| if test.out != out || !reflect.DeepEqual(test.err, err) { |
| t.Errorf("ParseUint(%q, 10, 64) = %v, %v want %v, %v", |
| test.in, out, err, test.out, test.err) |
| } |
| } |
| } |
| |
| func TestParseUint64Base(t *testing.T) { |
| for i := range parseUint64BaseTests { |
| test := &parseUint64BaseTests[i] |
| out, err := ParseUint(test.in, test.base, 64) |
| if test.out != out || !reflect.DeepEqual(test.err, err) { |
| t.Errorf("ParseUint(%q, %v, 64) = %v, %v want %v, %v", |
| test.in, test.base, out, err, test.out, test.err) |
| } |
| } |
| } |
| |
| func TestParseInt32(t *testing.T) { |
| for i := range parseInt32Tests { |
| test := &parseInt32Tests[i] |
| out, err := ParseInt(test.in, 10, 32) |
| if int64(test.out) != out || !reflect.DeepEqual(test.err, err) { |
| t.Errorf("ParseInt(%q, 10 ,32) = %v, %v want %v, %v", |
| test.in, out, err, test.out, test.err) |
| } |
| } |
| } |
| |
| func TestParseInt64(t *testing.T) { |
| for i := range parseInt64Tests { |
| test := &parseInt64Tests[i] |
| out, err := ParseInt(test.in, 10, 64) |
| if test.out != out || !reflect.DeepEqual(test.err, err) { |
| t.Errorf("ParseInt(%q, 10, 64) = %v, %v want %v, %v", |
| test.in, out, err, test.out, test.err) |
| } |
| } |
| } |
| |
| func TestParseInt64Base(t *testing.T) { |
| for i := range parseInt64BaseTests { |
| test := &parseInt64BaseTests[i] |
| out, err := ParseInt(test.in, test.base, 64) |
| if test.out != out || !reflect.DeepEqual(test.err, err) { |
| t.Errorf("ParseInt(%q, %v, 64) = %v, %v want %v, %v", |
| test.in, test.base, out, err, test.out, test.err) |
| } |
| } |
| } |
| |
| func TestParseUint(t *testing.T) { |
| switch IntSize { |
| case 32: |
| for i := range parseUint32Tests { |
| test := &parseUint32Tests[i] |
| out, err := ParseUint(test.in, 10, 0) |
| if uint64(test.out) != out || !reflect.DeepEqual(test.err, err) { |
| t.Errorf("ParseUint(%q, 10, 0) = %v, %v want %v, %v", |
| test.in, out, err, test.out, test.err) |
| } |
| } |
| case 64: |
| for i := range parseUint64Tests { |
| test := &parseUint64Tests[i] |
| out, err := ParseUint(test.in, 10, 0) |
| if test.out != out || !reflect.DeepEqual(test.err, err) { |
| t.Errorf("ParseUint(%q, 10, 0) = %v, %v want %v, %v", |
| test.in, out, err, test.out, test.err) |
| } |
| } |
| } |
| } |
| |
| func TestParseInt(t *testing.T) { |
| switch IntSize { |
| case 32: |
| for i := range parseInt32Tests { |
| test := &parseInt32Tests[i] |
| out, err := ParseInt(test.in, 10, 0) |
| if int64(test.out) != out || !reflect.DeepEqual(test.err, err) { |
| t.Errorf("ParseInt(%q, 10, 0) = %v, %v want %v, %v", |
| test.in, out, err, test.out, test.err) |
| } |
| } |
| case 64: |
| for i := range parseInt64Tests { |
| test := &parseInt64Tests[i] |
| out, err := ParseInt(test.in, 10, 0) |
| if test.out != out || !reflect.DeepEqual(test.err, err) { |
| t.Errorf("ParseInt(%q, 10, 0) = %v, %v want %v, %v", |
| test.in, out, err, test.out, test.err) |
| } |
| } |
| } |
| } |
| |
| func TestAtoi(t *testing.T) { |
| switch IntSize { |
| case 32: |
| for i := range parseInt32Tests { |
| test := &parseInt32Tests[i] |
| out, err := Atoi(test.in) |
| var testErr error |
| if test.err != nil { |
| testErr = &NumError{"Atoi", test.in, test.err.(*NumError).Err} |
| } |
| if int(test.out) != out || !reflect.DeepEqual(testErr, err) { |
| t.Errorf("Atoi(%q) = %v, %v want %v, %v", |
| test.in, out, err, test.out, testErr) |
| } |
| } |
| case 64: |
| for i := range parseInt64Tests { |
| test := &parseInt64Tests[i] |
| out, err := Atoi(test.in) |
| var testErr error |
| if test.err != nil { |
| testErr = &NumError{"Atoi", test.in, test.err.(*NumError).Err} |
| } |
| if test.out != int64(out) || !reflect.DeepEqual(testErr, err) { |
| t.Errorf("Atoi(%q) = %v, %v want %v, %v", |
| test.in, out, err, test.out, testErr) |
| } |
| } |
| } |
| } |
| |
| func bitSizeErrStub(name string, bitSize int) error { |
| return bitSizeError(name, "0", bitSize) |
| } |
| |
| func baseErrStub(name string, base int) error { |
| return baseError(name, "0", base) |
| } |
| |
| func noErrStub(name string, arg int) error { |
| return nil |
| } |
| |
| type parseErrorTest struct { |
| arg int |
| errStub func(name string, arg int) error |
| } |
| |
| var parseBitSizeTests = []parseErrorTest{ |
| {-1, bitSizeErrStub}, |
| {0, noErrStub}, |
| {64, noErrStub}, |
| {65, bitSizeErrStub}, |
| } |
| |
| var parseBaseTests = []parseErrorTest{ |
| {-1, baseErrStub}, |
| {0, noErrStub}, |
| {1, baseErrStub}, |
| {2, noErrStub}, |
| {36, noErrStub}, |
| {37, baseErrStub}, |
| } |
| |
| func equalError(a, b error) bool { |
| if a == nil { |
| return b == nil |
| } |
| if b == nil { |
| return a == nil |
| } |
| return a.Error() == b.Error() |
| } |
| |
| func TestParseIntBitSize(t *testing.T) { |
| for i := range parseBitSizeTests { |
| test := &parseBitSizeTests[i] |
| testErr := test.errStub("ParseInt", test.arg) |
| _, err := ParseInt("0", 0, test.arg) |
| if !equalError(testErr, err) { |
| t.Errorf("ParseInt(\"0\", 0, %v) = 0, %v want 0, %v", |
| test.arg, err, testErr) |
| } |
| } |
| } |
| |
| func TestParseUintBitSize(t *testing.T) { |
| for i := range parseBitSizeTests { |
| test := &parseBitSizeTests[i] |
| testErr := test.errStub("ParseUint", test.arg) |
| _, err := ParseUint("0", 0, test.arg) |
| if !equalError(testErr, err) { |
| t.Errorf("ParseUint(\"0\", 0, %v) = 0, %v want 0, %v", |
| test.arg, err, testErr) |
| } |
| } |
| } |
| |
| func TestParseIntBase(t *testing.T) { |
| for i := range parseBaseTests { |
| test := &parseBaseTests[i] |
| testErr := test.errStub("ParseInt", test.arg) |
| _, err := ParseInt("0", test.arg, 0) |
| if !equalError(testErr, err) { |
| t.Errorf("ParseInt(\"0\", %v, 0) = 0, %v want 0, %v", |
| test.arg, err, testErr) |
| } |
| } |
| } |
| |
| func TestParseUintBase(t *testing.T) { |
| for i := range parseBaseTests { |
| test := &parseBaseTests[i] |
| testErr := test.errStub("ParseUint", test.arg) |
| _, err := ParseUint("0", test.arg, 0) |
| if !equalError(testErr, err) { |
| t.Errorf("ParseUint(\"0\", %v, 0) = 0, %v want 0, %v", |
| test.arg, err, testErr) |
| } |
| } |
| } |
| |
| func TestNumError(t *testing.T) { |
| for _, test := range numErrorTests { |
| err := &NumError{ |
| Func: "ParseFloat", |
| Num: test.num, |
| Err: errors.New("failed"), |
| } |
| if got := err.Error(); got != test.want { |
| t.Errorf(`(&NumError{"ParseFloat", %q, "failed"}).Error() = %v, want %v`, test.num, got, test.want) |
| } |
| } |
| } |
| |
| func TestNumErrorUnwrap(t *testing.T) { |
| err := &NumError{Err: ErrSyntax} |
| if !errors.Is(err, ErrSyntax) { |
| t.Error("errors.Is failed, wanted success") |
| } |
| } |
| |
| func TestFormatComplex(t *testing.T) { |
| tests := []struct { |
| c complex128 |
| fmt byte |
| prec int |
| bitSize int |
| out string |
| }{ |
| // a variety of signs |
| {1 + 2i, 'g', -1, 128, "(1+2i)"}, |
| {3 - 4i, 'g', -1, 128, "(3-4i)"}, |
| {-5 + 6i, 'g', -1, 128, "(-5+6i)"}, |
| {-7 - 8i, 'g', -1, 128, "(-7-8i)"}, |
| |
| // test that fmt and prec are working |
| {3.14159 + 0.00123i, 'e', 3, 128, "(3.142e+00+1.230e-03i)"}, |
| {3.14159 + 0.00123i, 'f', 3, 128, "(3.142+0.001i)"}, |
| {3.14159 + 0.00123i, 'g', 3, 128, "(3.14+0.00123i)"}, |
| |
| // ensure bitSize rounding is working |
| {1.2345678901234567 + 9.876543210987654i, 'f', -1, 128, "(1.2345678901234567+9.876543210987654i)"}, |
| {1.2345678901234567 + 9.876543210987654i, 'f', -1, 64, "(1.2345679+9.876543i)"}, |
| |
| // other cases are handled by FormatFloat tests |
| } |
| for _, test := range tests { |
| out := FormatComplex(test.c, test.fmt, test.prec, test.bitSize) |
| if out != test.out { |
| t.Fatalf("FormatComplex(%v, %q, %d, %d) = %q; want %q", |
| test.c, test.fmt, test.prec, test.bitSize, out, test.out) |
| } |
| } |
| } |
| |
| func TestFormatComplexInvalidBitSize(t *testing.T) { |
| defer func() { |
| if r := recover(); r == nil { |
| t.Fatalf("expected panic due to invalid bitSize") |
| } |
| }() |
| _ = FormatComplex(1+2i, 'g', -1, 100) |
| } |
| |
| type itob64Test struct { |
| in int64 |
| base int |
| out string |
| } |
| |
| var itob64tests = []itob64Test{ |
| {0, 10, "0"}, |
| {1, 10, "1"}, |
| {-1, 10, "-1"}, |
| {12345678, 10, "12345678"}, |
| {-1 << 63, 10, "-9223372036854775808"}, |
| {16, 17, "g"}, |
| {25, 25, "10"}, |
| {(((((17*36+24)*36+21)*36+34)*36+12)*36+24)*36 + 32, 36, "holycow"}, |
| } |
| |
| func TestItoa(t *testing.T) { |
| for _, test := range itob64tests { |
| s := FormatInt(test.in, test.base) |
| if s != test.out { |
| t.Errorf("FormatInt(%v, %v) = %v want %v", |
| test.in, test.base, s, test.out) |
| } |
| x := AppendInt([]byte("abc"), test.in, test.base) |
| if string(x) != "abc"+test.out { |
| t.Errorf("AppendInt(%q, %v, %v) = %q want %v", |
| "abc", test.in, test.base, x, test.out) |
| } |
| |
| if test.in >= 0 { |
| s := FormatUint(uint64(test.in), test.base) |
| if s != test.out { |
| t.Errorf("FormatUint(%v, %v) = %v want %v", |
| test.in, test.base, s, test.out) |
| } |
| x := AppendUint(nil, uint64(test.in), test.base) |
| if string(x) != test.out { |
| t.Errorf("AppendUint(%q, %v, %v) = %q want %v", |
| "abc", uint64(test.in), test.base, x, test.out) |
| } |
| } |
| |
| if test.base == 10 && int64(int(test.in)) == test.in { |
| s := Itoa(int(test.in)) |
| if s != test.out { |
| t.Errorf("Itoa(%v) = %v want %v", |
| test.in, s, test.out) |
| } |
| } |
| } |
| |
| // Override when base is illegal |
| defer func() { |
| if r := recover(); r == nil { |
| t.Fatalf("expected panic due to illegal base") |
| } |
| }() |
| FormatUint(12345678, 1) |
| } |
| |
| type uitob64Test struct { |
| in uint64 |
| base int |
| out string |
| } |
| |
| var uitob64tests = []uitob64Test{ |
| {1<<63 - 1, 10, "9223372036854775807"}, |
| {1 << 63, 10, "9223372036854775808"}, |
| {1<<63 + 1, 10, "9223372036854775809"}, |
| {1<<64 - 2, 10, "18446744073709551614"}, |
| {1<<64 - 1, 10, "18446744073709551615"}, |
| {1<<64 - 1, 2, "1111111111111111111111111111111111111111111111111111111111111111"}, |
| } |
| |
| func TestUitoa(t *testing.T) { |
| for _, test := range uitob64tests { |
| s := FormatUint(test.in, test.base) |
| if s != test.out { |
| t.Errorf("FormatUint(%v, %v) = %v want %v", |
| test.in, test.base, s, test.out) |
| } |
| x := AppendUint([]byte("abc"), test.in, test.base) |
| if string(x) != "abc"+test.out { |
| t.Errorf("AppendUint(%q, %v, %v) = %q want %v", |
| "abc", test.in, test.base, x, test.out) |
| } |
| |
| } |
| } |
| |
| var varlenUints = []struct { |
| in uint64 |
| out string |
| }{ |
| {1, "1"}, |
| {12, "12"}, |
| {123, "123"}, |
| {1234, "1234"}, |
| {12345, "12345"}, |
| {123456, "123456"}, |
| {1234567, "1234567"}, |
| {12345678, "12345678"}, |
| {123456789, "123456789"}, |
| {1234567890, "1234567890"}, |
| {12345678901, "12345678901"}, |
| {123456789012, "123456789012"}, |
| {1234567890123, "1234567890123"}, |
| {12345678901234, "12345678901234"}, |
| {123456789012345, "123456789012345"}, |
| {1234567890123456, "1234567890123456"}, |
| {12345678901234567, "12345678901234567"}, |
| {123456789012345678, "123456789012345678"}, |
| {1234567890123456789, "1234567890123456789"}, |
| {12345678901234567890, "12345678901234567890"}, |
| } |
| |
| func TestFormatUintVarlen(t *testing.T) { |
| for _, test := range varlenUints { |
| s := FormatUint(test.in, 10) |
| if s != test.out { |
| t.Errorf("FormatUint(%v, 10) = %v want %v", test.in, s, test.out) |
| } |
| } |
| } |