Source file
src/strconv/strconv_test.go
1
2
3
4
5 package strconv_test
6
7 import (
8 "runtime"
9 . "strconv"
10 "strings"
11 "testing"
12 )
13
14 var (
15 globalBuf [64]byte
16 nextToOne = "1.00000000000000011102230246251565404236316680908203125" + strings.Repeat("0", 10000) + "1"
17
18 mallocTest = []struct {
19 count int
20 desc string
21 fn func()
22 }{
23 {0, `AppendInt(localBuf[:0], 123, 10)`, func() {
24 var localBuf [64]byte
25 AppendInt(localBuf[:0], 123, 10)
26 }},
27 {0, `AppendInt(globalBuf[:0], 123, 10)`, func() { AppendInt(globalBuf[:0], 123, 10) }},
28 {0, `AppendFloat(localBuf[:0], 1.23, 'g', 5, 64)`, func() {
29 var localBuf [64]byte
30 AppendFloat(localBuf[:0], 1.23, 'g', 5, 64)
31 }},
32 {0, `AppendFloat(globalBuf[:0], 1.23, 'g', 5, 64)`, func() { AppendFloat(globalBuf[:0], 1.23, 'g', 5, 64) }},
33
34
35 {10, `AppendQuoteToASCII(nil, oneMB)`, func() { AppendQuoteToASCII(nil, string(oneMB)) }},
36 {0, `ParseFloat("123.45", 64)`, func() { ParseFloat("123.45", 64) }},
37 {0, `ParseFloat("123.456789123456789", 64)`, func() { ParseFloat("123.456789123456789", 64) }},
38 {0, `ParseFloat("1.000000000000000111022302462515654042363166809082031251", 64)`, func() {
39 ParseFloat("1.000000000000000111022302462515654042363166809082031251", 64)
40 }},
41 {0, `ParseFloat("1.0000000000000001110223024625156540423631668090820312500...001", 64)`, func() {
42 ParseFloat(nextToOne, 64)
43 }},
44 }
45 )
46
47 var oneMB []byte
48
49 func TestCountMallocs(t *testing.T) {
50 if testing.Short() {
51 t.Skip("skipping malloc count in short mode")
52 }
53 if runtime.GOMAXPROCS(0) > 1 {
54 t.Skip("skipping; GOMAXPROCS>1")
55 }
56
57 oneMB = make([]byte, 1e6)
58 for i := range oneMB {
59 oneMB[i] = byte(i)
60 }
61 for _, mt := range mallocTest {
62 allocs := testing.AllocsPerRun(100, mt.fn)
63 if max := float64(mt.count); allocs > max {
64 t.Errorf("%s: %v allocs, want <=%v", mt.desc, allocs, max)
65 }
66 }
67 }
68
69
70 var Sink struct {
71 Bool bool
72 Int int
73 Int64 int64
74 Uint64 uint64
75 Float64 float64
76 Complex128 complex128
77 Error error
78 Bytes []byte
79 }
80
81 func TestAllocationsFromBytes(t *testing.T) {
82 const runsPerTest = 100
83 bytes := struct{ Bool, Number, String, Buffer []byte }{
84 Bool: []byte("false"),
85 Number: []byte("123456789"),
86 String: []byte("hello, world!"),
87 Buffer: make([]byte, 1024),
88 }
89
90 checkNoAllocs := func(f func()) func(t *testing.T) {
91 return func(t *testing.T) {
92 t.Helper()
93 if allocs := testing.AllocsPerRun(runsPerTest, f); allocs != 0 {
94 t.Errorf("got %v allocs, want 0 allocs", allocs)
95 }
96 }
97 }
98
99 t.Run("Atoi", checkNoAllocs(func() {
100 Sink.Int, Sink.Error = Atoi(string(bytes.Number))
101 }))
102 t.Run("ParseBool", checkNoAllocs(func() {
103 Sink.Bool, Sink.Error = ParseBool(string(bytes.Bool))
104 }))
105 t.Run("ParseInt", checkNoAllocs(func() {
106 Sink.Int64, Sink.Error = ParseInt(string(bytes.Number), 10, 64)
107 }))
108 t.Run("ParseUint", checkNoAllocs(func() {
109 Sink.Uint64, Sink.Error = ParseUint(string(bytes.Number), 10, 64)
110 }))
111 t.Run("ParseFloat", checkNoAllocs(func() {
112 Sink.Float64, Sink.Error = ParseFloat(string(bytes.Number), 64)
113 }))
114 t.Run("ParseComplex", checkNoAllocs(func() {
115 Sink.Complex128, Sink.Error = ParseComplex(string(bytes.Number), 128)
116 }))
117 t.Run("CanBackquote", checkNoAllocs(func() {
118 Sink.Bool = CanBackquote(string(bytes.String))
119 }))
120 t.Run("AppendQuote", checkNoAllocs(func() {
121 Sink.Bytes = AppendQuote(bytes.Buffer[:0], string(bytes.String))
122 }))
123 t.Run("AppendQuoteToASCII", checkNoAllocs(func() {
124 Sink.Bytes = AppendQuoteToASCII(bytes.Buffer[:0], string(bytes.String))
125 }))
126 t.Run("AppendQuoteToGraphic", checkNoAllocs(func() {
127 Sink.Bytes = AppendQuoteToGraphic(bytes.Buffer[:0], string(bytes.String))
128 }))
129 }
130
131 func TestErrorPrefixes(t *testing.T) {
132 _, errInt := Atoi("INVALID")
133 _, errBool := ParseBool("INVALID")
134 _, errFloat := ParseFloat("INVALID", 64)
135 _, errInt64 := ParseInt("INVALID", 10, 64)
136 _, errUint64 := ParseUint("INVALID", 10, 64)
137
138 vectors := []struct {
139 err error
140 want string
141 }{
142 {errInt, "Atoi"},
143 {errBool, "ParseBool"},
144 {errFloat, "ParseFloat"},
145 {errInt64, "ParseInt"},
146 {errUint64, "ParseUint"},
147 }
148
149 for _, v := range vectors {
150 nerr, ok := v.err.(*NumError)
151 if !ok {
152 t.Errorf("test %s, error was not a *NumError", v.want)
153 continue
154 }
155 if got := nerr.Func; got != v.want {
156 t.Errorf("mismatching Func: got %s, want %s", got, v.want)
157 }
158 }
159
160 }
161
View as plain text