1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package zap
22
23 import (
24 "errors"
25 "fmt"
26 "testing"
27 "time"
28
29 "go.uber.org/zap/zapcore"
30
31 "github.com/stretchr/testify/assert"
32 "github.com/stretchr/testify/require"
33 )
34
35 func BenchmarkBoolsArrayMarshaler(b *testing.B) {
36
37
38 bs := make([]bool, 50)
39 enc := zapcore.NewJSONEncoder(zapcore.EncoderConfig{})
40 b.ResetTimer()
41 for i := 0; i < b.N; i++ {
42 Bools("array", bs).AddTo(enc.Clone())
43 }
44 }
45
46 func BenchmarkBoolsReflect(b *testing.B) {
47 bs := make([]bool, 50)
48 enc := zapcore.NewJSONEncoder(zapcore.EncoderConfig{})
49 b.ResetTimer()
50 for i := 0; i < b.N; i++ {
51 Reflect("array", bs).AddTo(enc.Clone())
52 }
53 }
54
55 func TestArrayWrappers(t *testing.T) {
56 tests := []struct {
57 desc string
58 field Field
59 expected []interface{}
60 }{
61 {"empty bools", Bools("", []bool{}), []interface{}{}},
62 {"empty byte strings", ByteStrings("", [][]byte{}), []interface{}{}},
63 {"empty complex128s", Complex128s("", []complex128{}), []interface{}{}},
64 {"empty complex64s", Complex64s("", []complex64{}), []interface{}{}},
65 {"empty durations", Durations("", []time.Duration{}), []interface{}{}},
66 {"empty float64s", Float64s("", []float64{}), []interface{}{}},
67 {"empty float32s", Float32s("", []float32{}), []interface{}{}},
68 {"empty ints", Ints("", []int{}), []interface{}{}},
69 {"empty int64s", Int64s("", []int64{}), []interface{}{}},
70 {"empty int32s", Int32s("", []int32{}), []interface{}{}},
71 {"empty int16s", Int16s("", []int16{}), []interface{}{}},
72 {"empty int8s", Int8s("", []int8{}), []interface{}{}},
73 {"empty strings", Strings("", []string{}), []interface{}{}},
74 {"empty times", Times("", []time.Time{}), []interface{}{}},
75 {"empty uints", Uints("", []uint{}), []interface{}{}},
76 {"empty uint64s", Uint64s("", []uint64{}), []interface{}{}},
77 {"empty uint32s", Uint32s("", []uint32{}), []interface{}{}},
78 {"empty uint16s", Uint16s("", []uint16{}), []interface{}{}},
79 {"empty uint8s", Uint8s("", []uint8{}), []interface{}{}},
80 {"empty uintptrs", Uintptrs("", []uintptr{}), []interface{}{}},
81 {"bools", Bools("", []bool{true, false}), []interface{}{true, false}},
82 {"byte strings", ByteStrings("", [][]byte{{1, 2}, {3, 4}}), []interface{}{"\x01\x02", "\x03\x04"}},
83 {"complex128s", Complex128s("", []complex128{1 + 2i, 3 + 4i}), []interface{}{1 + 2i, 3 + 4i}},
84 {"complex64s", Complex64s("", []complex64{1 + 2i, 3 + 4i}), []interface{}{complex64(1 + 2i), complex64(3 + 4i)}},
85 {"durations", Durations("", []time.Duration{1, 2}), []interface{}{time.Nanosecond, 2 * time.Nanosecond}},
86 {"float64s", Float64s("", []float64{1.2, 3.4}), []interface{}{1.2, 3.4}},
87 {"float32s", Float32s("", []float32{1.2, 3.4}), []interface{}{float32(1.2), float32(3.4)}},
88 {"ints", Ints("", []int{1, 2}), []interface{}{1, 2}},
89 {"int64s", Int64s("", []int64{1, 2}), []interface{}{int64(1), int64(2)}},
90 {"int32s", Int32s("", []int32{1, 2}), []interface{}{int32(1), int32(2)}},
91 {"int16s", Int16s("", []int16{1, 2}), []interface{}{int16(1), int16(2)}},
92 {"int8s", Int8s("", []int8{1, 2}), []interface{}{int8(1), int8(2)}},
93 {"strings", Strings("", []string{"foo", "bar"}), []interface{}{"foo", "bar"}},
94 {"times", Times("", []time.Time{time.Unix(0, 0), time.Unix(0, 0)}), []interface{}{time.Unix(0, 0), time.Unix(0, 0)}},
95 {"uints", Uints("", []uint{1, 2}), []interface{}{uint(1), uint(2)}},
96 {"uint64s", Uint64s("", []uint64{1, 2}), []interface{}{uint64(1), uint64(2)}},
97 {"uint32s", Uint32s("", []uint32{1, 2}), []interface{}{uint32(1), uint32(2)}},
98 {"uint16s", Uint16s("", []uint16{1, 2}), []interface{}{uint16(1), uint16(2)}},
99 {"uint8s", Uint8s("", []uint8{1, 2}), []interface{}{uint8(1), uint8(2)}},
100 {"uintptrs", Uintptrs("", []uintptr{1, 2}), []interface{}{uintptr(1), uintptr(2)}},
101 }
102
103 for _, tt := range tests {
104 enc := zapcore.NewMapObjectEncoder()
105 tt.field.Key = "k"
106 tt.field.AddTo(enc)
107 assert.Equal(t, tt.expected, enc.Fields["k"], "%s: unexpected map contents.", tt.desc)
108 assert.Equal(t, 1, len(enc.Fields), "%s: found extra keys in map: %v", tt.desc, enc.Fields)
109 }
110 }
111
112 func TestObjectsAndObjectValues(t *testing.T) {
113 t.Parallel()
114
115 tests := []struct {
116 desc string
117 give Field
118 want []any
119 }{
120 {
121 desc: "Objects/nil slice",
122 give: Objects[*emptyObject]("", nil),
123 want: []any{},
124 },
125 {
126 desc: "ObjectValues/nil slice",
127 give: ObjectValues[emptyObject]("", nil),
128 want: []any{},
129 },
130 {
131 desc: "ObjectValues/empty slice",
132 give: ObjectValues("", []emptyObject{}),
133 want: []any{},
134 },
135 {
136 desc: "ObjectValues/single item",
137 give: ObjectValues("", []emptyObject{
138 {},
139 }),
140 want: []any{
141 map[string]any{},
142 },
143 },
144 {
145 desc: "Objects/multiple different objects",
146 give: Objects("", []*fakeObject{
147 {value: "foo"},
148 {value: "bar"},
149 {value: "baz"},
150 }),
151 want: []any{
152 map[string]any{"value": "foo"},
153 map[string]any{"value": "bar"},
154 map[string]any{"value": "baz"},
155 },
156 },
157 {
158 desc: "ObjectValues/multiple different objects",
159 give: ObjectValues("", []fakeObject{
160 {value: "foo"},
161 {value: "bar"},
162 {value: "baz"},
163 }),
164 want: []any{
165 map[string]any{"value": "foo"},
166 map[string]any{"value": "bar"},
167 map[string]any{"value": "baz"},
168 },
169 },
170 }
171
172 for _, tt := range tests {
173 tt := tt
174 t.Run(tt.desc, func(t *testing.T) {
175 t.Parallel()
176
177 tt.give.Key = "k"
178
179 enc := zapcore.NewMapObjectEncoder()
180 tt.give.AddTo(enc)
181 assert.Equal(t, tt.want, enc.Fields["k"])
182 })
183 }
184 }
185
186 type emptyObject struct{}
187
188 func (*emptyObject) MarshalLogObject(zapcore.ObjectEncoder) error {
189 return nil
190 }
191
192 type fakeObject struct {
193 value string
194 err error
195 }
196
197 func (o *fakeObject) MarshalLogObject(enc zapcore.ObjectEncoder) error {
198 enc.AddString("value", o.value)
199 return o.err
200 }
201
202 func TestObjectsAndObjectValues_marshalError(t *testing.T) {
203 t.Parallel()
204
205 tests := []struct {
206 desc string
207 give Field
208 want []any
209 wantErr string
210 }{
211 {
212 desc: "Objects",
213 give: Objects("", []*fakeObject{
214 {value: "foo"},
215 {value: "bar", err: errors.New("great sadness")},
216 {value: "baz"},
217 }),
218 want: []any{
219 map[string]any{"value": "foo"},
220 map[string]any{"value": "bar"},
221 },
222 wantErr: "great sadness",
223 },
224 {
225 desc: "ObjectValues",
226 give: ObjectValues("", []fakeObject{
227 {value: "foo"},
228 {value: "bar", err: errors.New("stuff failed")},
229 {value: "baz"},
230 }),
231 want: []any{
232 map[string]any{"value": "foo"},
233 map[string]any{"value": "bar"},
234 },
235 wantErr: "stuff failed",
236 },
237 }
238
239 for _, tt := range tests {
240 tt := tt
241 t.Run(tt.desc, func(t *testing.T) {
242 t.Parallel()
243
244 tt.give.Key = "k"
245
246 enc := zapcore.NewMapObjectEncoder()
247 tt.give.AddTo(enc)
248
249 require.Contains(t, enc.Fields, "k")
250 assert.Equal(t, tt.want, enc.Fields["k"])
251
252
253
254 require.Contains(t, enc.Fields, "kError")
255 assert.Equal(t, tt.wantErr, enc.Fields["kError"])
256 })
257 }
258 }
259
260 type stringerObject struct {
261 value string
262 }
263
264 func (s stringerObject) String() string {
265 return s.value
266 }
267
268 func TestStringers(t *testing.T) {
269 t.Parallel()
270
271 tests := []struct {
272 desc string
273 give Field
274 want []any
275 }{
276 {
277 desc: "Stringers",
278 give: Stringers("", []stringerObject{
279 {value: "foo"},
280 {value: "bar"},
281 {value: "baz"},
282 }),
283 want: []any{
284 "foo",
285 "bar",
286 "baz",
287 },
288 },
289 {
290 desc: "Stringers with []fmt.Stringer",
291 give: Stringers("", []fmt.Stringer{
292 stringerObject{value: "foo"},
293 stringerObject{value: "bar"},
294 stringerObject{value: "baz"},
295 }),
296 want: []any{
297 "foo",
298 "bar",
299 "baz",
300 },
301 },
302 }
303
304 for _, tt := range tests {
305 tt := tt
306 t.Run(tt.desc, func(t *testing.T) {
307 t.Parallel()
308
309 tt.give.Key = "k"
310
311 enc := zapcore.NewMapObjectEncoder()
312 tt.give.AddTo(enc)
313 assert.Equal(t, tt.want, enc.Fields["k"])
314 })
315 }
316 }
317
View as plain text