1 package zerolog
2
3 import (
4 "bytes"
5 "io/ioutil"
6 "testing"
7 )
8
9 var (
10 levelNameHook = HookFunc(func(e *Event, level Level, msg string) {
11 levelName := level.String()
12 if level == NoLevel {
13 levelName = "nolevel"
14 }
15 e.Str("level_name", levelName)
16 })
17 simpleHook = HookFunc(func(e *Event, level Level, msg string) {
18 e.Bool("has_level", level != NoLevel)
19 e.Str("test", "logged")
20 })
21 copyHook = HookFunc(func(e *Event, level Level, msg string) {
22 hasLevel := level != NoLevel
23 e.Bool("copy_has_level", hasLevel)
24 if hasLevel {
25 e.Str("copy_level", level.String())
26 }
27 e.Str("copy_msg", msg)
28 })
29 nopHook = HookFunc(func(e *Event, level Level, message string) {
30 })
31 discardHook = HookFunc(func(e *Event, level Level, message string) {
32 e.Discard()
33 })
34 )
35
36 func TestHook(t *testing.T) {
37 tests := []struct {
38 name string
39 want string
40 test func(log Logger)
41 }{
42 {"Message", `{"level_name":"nolevel","message":"test message"}` + "\n", func(log Logger) {
43 log = log.Hook(levelNameHook)
44 log.Log().Msg("test message")
45 }},
46 {"NoLevel", `{"level_name":"nolevel"}` + "\n", func(log Logger) {
47 log = log.Hook(levelNameHook)
48 log.Log().Msg("")
49 }},
50 {"Print", `{"level":"debug","level_name":"debug"}` + "\n", func(log Logger) {
51 log = log.Hook(levelNameHook)
52 log.Print("")
53 }},
54 {"Error", `{"level":"error","level_name":"error"}` + "\n", func(log Logger) {
55 log = log.Hook(levelNameHook)
56 log.Error().Msg("")
57 }},
58 {"Copy/1", `{"copy_has_level":false,"copy_msg":""}` + "\n", func(log Logger) {
59 log = log.Hook(copyHook)
60 log.Log().Msg("")
61 }},
62 {"Copy/2", `{"level":"info","copy_has_level":true,"copy_level":"info","copy_msg":"a message","message":"a message"}` + "\n", func(log Logger) {
63 log = log.Hook(copyHook)
64 log.Info().Msg("a message")
65 }},
66 {"Multi", `{"level":"error","level_name":"error","has_level":true,"test":"logged"}` + "\n", func(log Logger) {
67 log = log.Hook(levelNameHook).Hook(simpleHook)
68 log.Error().Msg("")
69 }},
70 {"Multi/Message", `{"level":"error","level_name":"error","has_level":true,"test":"logged","message":"a message"}` + "\n", func(log Logger) {
71 log = log.Hook(levelNameHook).Hook(simpleHook)
72 log.Error().Msg("a message")
73 }},
74 {"Output/single/pre", `{"level":"error","level_name":"error"}` + "\n", func(log Logger) {
75 ignored := &bytes.Buffer{}
76 log = New(ignored).Hook(levelNameHook).Output(log.w)
77 log.Error().Msg("")
78 }},
79 {"Output/single/post", `{"level":"error","level_name":"error"}` + "\n", func(log Logger) {
80 ignored := &bytes.Buffer{}
81 log = New(ignored).Output(log.w).Hook(levelNameHook)
82 log.Error().Msg("")
83 }},
84 {"Output/multi/pre", `{"level":"error","level_name":"error","has_level":true,"test":"logged"}` + "\n", func(log Logger) {
85 ignored := &bytes.Buffer{}
86 log = New(ignored).Hook(levelNameHook).Hook(simpleHook).Output(log.w)
87 log.Error().Msg("")
88 }},
89 {"Output/multi/post", `{"level":"error","level_name":"error","has_level":true,"test":"logged"}` + "\n", func(log Logger) {
90 ignored := &bytes.Buffer{}
91 log = New(ignored).Output(log.w).Hook(levelNameHook).Hook(simpleHook)
92 log.Error().Msg("")
93 }},
94 {"Output/mixed", `{"level":"error","level_name":"error","has_level":true,"test":"logged"}` + "\n", func(log Logger) {
95 ignored := &bytes.Buffer{}
96 log = New(ignored).Hook(levelNameHook).Output(log.w).Hook(simpleHook)
97 log.Error().Msg("")
98 }},
99 {"With/single/pre", `{"level":"error","with":"pre","level_name":"error"}` + "\n", func(log Logger) {
100 log = log.Hook(levelNameHook).With().Str("with", "pre").Logger()
101 log.Error().Msg("")
102 }},
103 {"With/single/post", `{"level":"error","with":"post","level_name":"error"}` + "\n", func(log Logger) {
104 log = log.With().Str("with", "post").Logger().Hook(levelNameHook)
105 log.Error().Msg("")
106 }},
107 {"With/multi/pre", `{"level":"error","with":"pre","level_name":"error","has_level":true,"test":"logged"}` + "\n", func(log Logger) {
108 log = log.Hook(levelNameHook).Hook(simpleHook).With().Str("with", "pre").Logger()
109 log.Error().Msg("")
110 }},
111 {"With/multi/post", `{"level":"error","with":"post","level_name":"error","has_level":true,"test":"logged"}` + "\n", func(log Logger) {
112 log = log.With().Str("with", "post").Logger().Hook(levelNameHook).Hook(simpleHook)
113 log.Error().Msg("")
114 }},
115 {"With/mixed", `{"level":"error","with":"mixed","level_name":"error","has_level":true,"test":"logged"}` + "\n", func(log Logger) {
116 log = log.Hook(levelNameHook).With().Str("with", "mixed").Logger().Hook(simpleHook)
117 log.Error().Msg("")
118 }},
119 {"Discard", "", func(log Logger) {
120 log = log.Hook(discardHook)
121 log.Log().Msg("test message")
122 }},
123 {"None", `{"level":"error"}` + "\n", func(log Logger) {
124 log.Error().Msg("")
125 }},
126 }
127 for _, tt := range tests {
128 tt := tt
129 t.Run(tt.name, func(t *testing.T) {
130 out := &bytes.Buffer{}
131 log := New(out)
132 tt.test(log)
133 if got, want := decodeIfBinaryToString(out.Bytes()), tt.want; got != want {
134 t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
135 }
136 })
137 }
138 }
139
140 func BenchmarkHooks(b *testing.B) {
141 logger := New(ioutil.Discard)
142 b.ResetTimer()
143 b.Run("Nop/Single", func(b *testing.B) {
144 log := logger.Hook(nopHook)
145 b.RunParallel(func(pb *testing.PB) {
146 for pb.Next() {
147 log.Log().Msg("")
148 }
149 })
150 })
151 b.Run("Nop/Multi", func(b *testing.B) {
152 log := logger.Hook(nopHook).Hook(nopHook)
153 b.RunParallel(func(pb *testing.PB) {
154 for pb.Next() {
155 log.Log().Msg("")
156 }
157 })
158 })
159 b.Run("Simple", func(b *testing.B) {
160 log := logger.Hook(simpleHook)
161 b.RunParallel(func(pb *testing.PB) {
162 for pb.Next() {
163 log.Log().Msg("")
164 }
165 })
166 })
167 }
168
View as plain text