1 package logfmt
2
3 import (
4 "bytes"
5 "errors"
6 "fmt"
7 "io/ioutil"
8 "reflect"
9 "testing"
10 )
11
12 func TestSafeString(t *testing.T) {
13 _, ok := safeString((*stringStringer)(nil))
14 if got, want := ok, false; got != want {
15 t.Errorf(" got %v, want %v", got, want)
16 }
17 }
18
19 func TestSafeMarshal(t *testing.T) {
20 kb, err := safeMarshal((*stringMarshaler)(nil))
21 if got := kb; got != nil {
22 t.Errorf(" got %v, want nil", got)
23 }
24 if got, want := err, error(nil); got != want {
25 t.Errorf(" got %v, want %v", got, want)
26 }
27 }
28
29 func TestWriteKeyStrings(t *testing.T) {
30 keygen := []struct {
31 name string
32 fn func(string) interface{}
33 }{
34 {
35 name: "string",
36 fn: func(s string) interface{} { return s },
37 },
38 {
39 name: "named-string",
40 fn: func(s string) interface{} { return stringData(s) },
41 },
42 {
43 name: "Stringer",
44 fn: func(s string) interface{} { return stringStringer(s) },
45 },
46 {
47 name: "TextMarshaler",
48 fn: func(s string) interface{} { return stringMarshaler(s) },
49 },
50 }
51
52 data := []struct {
53 key string
54 want string
55 err error
56 }{
57 {key: "k", want: "k"},
58 {key: `\`, want: `\`},
59 {key: "\n", err: ErrInvalidKey},
60 {key: "\x00", err: ErrInvalidKey},
61 {key: "\x10", err: ErrInvalidKey},
62 {key: "\x1F", err: ErrInvalidKey},
63 {key: "", err: ErrInvalidKey},
64 {key: " ", err: ErrInvalidKey},
65 {key: "=", err: ErrInvalidKey},
66 {key: `"`, err: ErrInvalidKey},
67 {key: "k\n", want: "k"},
68 {key: "k\nk", want: "kk"},
69 {key: "k\tk", want: "kk"},
70 {key: "k=k", want: "kk"},
71 {key: `"kk"`, want: "kk"},
72 }
73
74 for _, g := range keygen {
75 t.Run(g.name, func(t *testing.T) {
76 for _, d := range data {
77 w := &bytes.Buffer{}
78 key := g.fn(d.key)
79 err := writeKey(w, key)
80 if err != d.err {
81 t.Errorf("%#v: got error: %v, want error: %v", key, err, d.err)
82 }
83 if err != nil {
84 continue
85 }
86 if got, want := w.String(), d.want; got != want {
87 t.Errorf("%#v: got '%s', want '%s'", key, got, want)
88 }
89 }
90 })
91 }
92 }
93
94 func TestWriteKey(t *testing.T) {
95 var (
96 nilPtr *int
97 one = 1
98 ptr = &one
99 )
100
101 data := []struct {
102 key interface{}
103 want string
104 err error
105 }{
106 {key: nil, err: ErrNilKey},
107 {key: nilPtr, err: ErrNilKey},
108 {key: (*stringStringer)(nil), err: ErrNilKey},
109 {key: (*stringMarshaler)(nil), err: ErrNilKey},
110 {key: (*stringerMarshaler)(nil), err: ErrNilKey},
111 {key: ptr, want: "1"},
112
113 {key: errorMarshaler{}, err: &MarshalerError{Type: reflect.TypeOf(errorMarshaler{}), Err: errMarshaling}},
114 {key: make(chan int), err: ErrUnsupportedKeyType},
115 {key: []int{}, err: ErrUnsupportedKeyType},
116 {key: map[int]int{}, err: ErrUnsupportedKeyType},
117 {key: [2]int{}, err: ErrUnsupportedKeyType},
118 {key: struct{}{}, err: ErrUnsupportedKeyType},
119 {key: fmt.Sprint, err: ErrUnsupportedKeyType},
120 }
121
122 for _, d := range data {
123 w := &bytes.Buffer{}
124 err := writeKey(w, d.key)
125 if !reflect.DeepEqual(err, d.err) {
126 t.Errorf("%#v: got error: %v, want error: %v", d.key, err, d.err)
127 }
128 if err != nil {
129 continue
130 }
131 if got, want := w.String(), d.want; got != want {
132 t.Errorf("%#v: got '%s', want '%s'", d.key, got, want)
133 }
134 }
135 }
136
137 func TestWriteValueStrings(t *testing.T) {
138 keygen := []func(string) interface{}{
139 func(s string) interface{} { return s },
140 func(s string) interface{} { return errors.New(s) },
141 func(s string) interface{} { return stringData(s) },
142 func(s string) interface{} { return stringStringer(s) },
143 func(s string) interface{} { return stringMarshaler(s) },
144 }
145
146 data := []struct {
147 value string
148 want string
149 err error
150 }{
151 {value: "", want: ""},
152 {value: "v", want: "v"},
153 {value: " ", want: `" "`},
154 {value: "=", want: `"="`},
155 {value: `\`, want: `\`},
156 {value: `"`, want: `"\""`},
157 {value: `\"`, want: `"\\\""`},
158 {value: "\n", want: `"\n"`},
159 {value: "\x00", want: `"\u0000"`},
160 {value: "\x10", want: `"\u0010"`},
161 {value: "\x1F", want: `"\u001f"`},
162 {value: "µ", want: `µ`},
163 }
164
165 for _, g := range keygen {
166 for _, d := range data {
167 w := &bytes.Buffer{}
168 value := g(d.value)
169 err := writeValue(w, value)
170 if err != d.err {
171 t.Errorf("%#v (%[1]T): got error: %v, want error: %v", value, err, d.err)
172 }
173 if err != nil {
174 continue
175 }
176 if got, want := w.String(), d.want; got != want {
177 t.Errorf("%#v (%[1]T): got '%s', want '%s'", value, got, want)
178 }
179 }
180 }
181 }
182
183 func TestWriteValue(t *testing.T) {
184 var (
185 nilPtr *int
186 one = 1
187 ptr = &one
188 )
189
190 data := []struct {
191 value interface{}
192 want string
193 err error
194 }{
195 {value: nil, want: "null"},
196 {value: nilPtr, want: "null"},
197 {value: (*stringStringer)(nil), want: "null"},
198 {value: (*stringMarshaler)(nil), want: "null"},
199 {value: (*stringerMarshaler)(nil), want: "null"},
200 {value: ptr, want: "1"},
201
202 {value: errorMarshaler{}, err: &MarshalerError{Type: reflect.TypeOf(errorMarshaler{}), Err: errMarshaling}},
203 {value: make(chan int), err: ErrUnsupportedValueType},
204 {value: []int{}, err: ErrUnsupportedValueType},
205 {value: map[int]int{}, err: ErrUnsupportedValueType},
206 {value: [2]int{}, err: ErrUnsupportedValueType},
207 {value: struct{}{}, err: ErrUnsupportedValueType},
208 {value: fmt.Sprint, err: ErrUnsupportedValueType},
209 }
210
211 for _, d := range data {
212 w := &bytes.Buffer{}
213 err := writeValue(w, d.value)
214 if !reflect.DeepEqual(err, d.err) {
215 t.Errorf("%#v: got error: %v, want error: %v", d.value, err, d.err)
216 }
217 if err != nil {
218 continue
219 }
220 if got, want := w.String(), d.want; got != want {
221 t.Errorf("%#v: got '%s', want '%s'", d.value, got, want)
222 }
223 }
224 }
225
226 type stringData string
227
228 type stringStringer string
229
230 func (s stringStringer) String() string {
231 return string(s)
232 }
233
234 type stringMarshaler string
235
236 func (s stringMarshaler) MarshalText() ([]byte, error) {
237 return []byte(s), nil
238 }
239
240 type stringerMarshaler string
241
242 func (s stringerMarshaler) String() string {
243 return "String() called"
244 }
245
246 func (s stringerMarshaler) MarshalText() ([]byte, error) {
247 return []byte(s), nil
248 }
249
250 var errMarshaling = errors.New("marshal error")
251
252 type errorMarshaler struct{}
253
254 func (errorMarshaler) MarshalText() ([]byte, error) {
255 return nil, errMarshaling
256 }
257
258 func BenchmarkWriteStringKey(b *testing.B) {
259 keys := []string{
260 "k",
261 "caller",
262 "has space",
263 `"quoted"`,
264 }
265
266 for _, k := range keys {
267 b.Run(k, func(b *testing.B) {
268 for i := 0; i < b.N; i++ {
269 writeStringKey(ioutil.Discard, k)
270 }
271 })
272 }
273 }
274
View as plain text