1 package genericr_test
2
3 import (
4 "errors"
5 "fmt"
6 "path/filepath"
7 "runtime"
8 "testing"
9
10 "github.com/go-logr/logr"
11 "github.com/wojas/genericr"
12 )
13
14 func TestNewForTesting(t *testing.T) {
15 log := genericr.NewForTesting(t)
16 log.Info("hello world", "a", 1)
17 log.WithName("foo").WithValues("a", 42).WithName("bar").V(1).WithValues("b", 1).Info("hello world2", "x", 123, "y", 234)
18 t.Log("Normal test log")
19 }
20
21 func TestLogger_Table(t *testing.T) {
22 var last genericr.Entry
23 var lf genericr.LogFunc = func(e genericr.Entry) {
24 last = e
25 t.Log(e.String())
26 }
27 sink := genericr.New(lf)
28
29 tt := []struct {
30 f func()
31 want string
32 }{
33 {
34 func() {
35 sink.Info(0, "hello world")
36 },
37 `[0] "hello world"`,
38 },
39 {
40 func() {
41 sink.Info(0, "hello world", "a", 1)
42 },
43 `[0] "hello world" a=1`,
44 },
45 {
46 func() {
47 sink.Info(4, "hello world", "a", 1)
48 },
49 `[4] "hello world" a=1`,
50 },
51 {
52 func() {
53 sink.WithName("somename").Info(0, "hello world", "a", 1)
54 },
55 `[0] somename "hello world" a=1`,
56 },
57 {
58 func() {
59 sink.WithName("somename").WithName("sub").Info(0, "hello world", "a", 1)
60 },
61 `[0] somename.sub "hello world" a=1`,
62 },
63 {
64 func() {
65 sink.WithName("somename").WithName("sub").Info(1, "hello world", "a", 1, "b", 2)
66 },
67 `[1] somename.sub "hello world" a=1 b=2`,
68 },
69 {
70 func() {
71 sink.WithValues("x", "yz").WithName("somename").WithName("sub").Info(1, "hello world", "a", 1, "b", 2)
72 },
73 `[1] somename.sub "hello world" a=1 b=2 x="yz"`,
74 },
75 {
76 func() {
77
78 sink.WithValues("x", "yz", "z").Info(0, "hello world", "a", 1, "b", 2)
79 },
80 `[0] "hello world" a=1 b=2 x="yz" z=null`,
81 },
82 {
83 func() {
84 sink.WithVerbosity(1).Info(0, "hello world", "a", 1)
85 },
86 `[0] "hello world" a=1`,
87 },
88 {
89 func() {
90 sink.Info(01, "first")
91 sink.WithVerbosity(1).Info(1, "hello world", "a", 1)
92 },
93 `[1] "hello world" a=1`,
94 },
95 {
96 func() {
97 sink.Info(0, "first")
98 sink.WithVerbosity(1).Info(0, "hello world", "a", 1)
99 },
100 `[0] "hello world" a=1`,
101 },
102 {
103 func() {
104 sink.Info(0, "wrong params", "a")
105 },
106 `[0] "wrong params" a=null`,
107 },
108 {
109 func() {
110 sink.Info(0, "wrong params", 42)
111 },
112 `[0] "wrong params" "!(42)"=null`,
113 },
114 {
115 func() {
116 sink.Error(fmt.Errorf("some error"), "help")
117 },
118 `[0] "help" error="some error"`,
119 },
120 {
121 f: func() {
122 sink.WithValues(
123 "int", 42,
124 "string", "foo",
125 "bytes", []byte("foo"),
126 "float", 3.14,
127 "struct", struct {
128 A string
129 B int
130 }{"foo", 12},
131 "map", map[string]int{
132 "foo": 12,
133 },
134 "nilval", nil,
135 "err", errors.New("oops"),
136 "stringslice", []string{"a", "b"},
137 ).Info(0, "types")
138 },
139 want: `[0] "types" bytes="66 6f 6f" err="oops" float=3.14 int=42 map={"foo":12} nilval=null string="foo" stringslice=["a","b"] struct={"A":"foo","B":12}`,
140 },
141 }
142
143 for i, row := range tt {
144 row.f()
145 s := last.String()
146 if s != row.want {
147 t.Errorf("row %d:\n got: `%s`\n want: `%s`", i, s, row.want)
148 }
149 }
150 }
151
152 func TestLogger_Caller(t *testing.T) {
153 var last genericr.Entry
154 var lf genericr.LogFunc = func(e genericr.Entry) {
155 last = e
156 t.Log(e.String())
157 t.Log(runtime.Caller(e.CallerDepth))
158 }
159 sink := genericr.New(lf).WithCaller(true)
160 logSomethingFromOtherFile(logr.New(sink))
161
162 _, fname := filepath.Split(last.Caller.File)
163 if fname != "caller_test.go" {
164 t.Errorf("Caller: expected 'caller_test.go', got %q (full: %s:%d)",
165 fname, last.Caller.File, last.Caller.Line)
166 }
167 if last.CallerDepth != 4 {
168 t.Errorf("Caller depth: expected 4, got %d", last.CallerDepth)
169 }
170 }
171
172 type wrappedLogger struct {
173 log logr.Logger
174 }
175
176 func (wl wrappedLogger) Info(msg string, keysAndValues ...interface{}) {
177 wl.log.Info(msg, keysAndValues...)
178 }
179
180 func TestLogger_WithCallDepth(t *testing.T) {
181 var last genericr.Entry
182 var lf genericr.LogFunc = func(e genericr.Entry) {
183 last = e
184 t.Log(e.String())
185 t.Log(runtime.Caller(e.CallerDepth))
186 }
187 sink := genericr.New(lf).WithCaller(true).WithCallDepth(1)
188 logger := logr.New(sink)
189 wlogger := wrappedLogger{logger}
190
191 logSomethingFromOtherFile(wlogger)
192
193 _, fname := filepath.Split(last.Caller.File)
194 if fname != "caller_test.go" {
195 t.Errorf("Caller: expected 'caller_test.go', got %q (full: %s:%d)",
196 fname, last.Caller.File, last.Caller.Line)
197 }
198 if last.CallerDepth != 5 {
199 t.Errorf("Caller depth: expected 5, got %d", last.CallerDepth)
200 }
201 }
202
203 func BenchmarkLogger_basic(b *testing.B) {
204 foo := 0
205 var lf genericr.LogFunc = func(e genericr.Entry) {
206 foo += e.Level
207 }
208 log := genericr.New(lf)
209
210 b.ReportAllocs()
211 b.ResetTimer()
212 for i := 0; i < b.N; i++ {
213 log.Info(0, "hello")
214 }
215 }
216
217 func BenchmarkLogger_basic_with_caller(b *testing.B) {
218 foo := 0
219 var lf genericr.LogFunc = func(e genericr.Entry) {
220 foo += e.Level
221 }
222 log := genericr.New(lf).WithCaller(true)
223
224 b.ReportAllocs()
225 b.ResetTimer()
226 for i := 0; i < b.N; i++ {
227 log.Info(0, "hello")
228 }
229 }
230
231 func BenchmarkLogger_2vars(b *testing.B) {
232 foo := 0
233 var lf genericr.LogFunc = func(e genericr.Entry) {
234 foo += e.Level
235 }
236 log := genericr.New(lf)
237
238 b.ReportAllocs()
239 b.ResetTimer()
240 for i := 0; i < b.N; i++ {
241 log.Info(0, "hello", "a", 1, "b", 2)
242 }
243 }
244
245 func BenchmarkLogger_clone(b *testing.B) {
246 foo := 0
247 var lf genericr.LogFunc = func(e genericr.Entry) {
248 foo += e.Level
249 }
250 log := genericr.New(lf)
251
252 b.ReportAllocs()
253 b.ResetTimer()
254 for i := 0; i < b.N; i++ {
255 log.Info(0, "hello")
256 }
257 }
258
259 func BenchmarkLogger_complicated(b *testing.B) {
260 foo := 0
261 var lf genericr.LogFunc = func(e genericr.Entry) {
262 foo += e.Level
263 }
264 log := genericr.New(lf)
265
266 b.ReportAllocs()
267 b.ResetTimer()
268 for i := 0; i < b.N; i++ {
269 log.WithName("bench").WithValues("x", 123).Info(0, "hello", "a", 1, "b", 2)
270 }
271 }
272
273 func BenchmarkLogger_complicated_precalculated(b *testing.B) {
274 foo := 0
275 var lf genericr.LogFunc = func(e genericr.Entry) {
276 foo += e.Level
277 }
278 log := genericr.New(lf)
279 log2 := log.WithName("bench").WithValues("x", 123)
280
281 b.ReportAllocs()
282 b.ResetTimer()
283 for i := 0; i < b.N; i++ {
284 log2.Info(0, "hello", "a", 1, "b", 2)
285 }
286 }
287
288 func BenchmarkLogger_2vars_tostring(b *testing.B) {
289 foo := ""
290 var lf genericr.LogFunc = func(e genericr.Entry) {
291 foo = e.String()
292 }
293 log := genericr.New(lf)
294
295 b.ReportAllocs()
296 b.ResetTimer()
297 for i := 0; i < b.N; i++ {
298 log.Info(0, "hello", "a", 1, "b", 2)
299 }
300 _ = foo
301 }
302
View as plain text