-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathzltest.go
170 lines (141 loc) · 4.61 KB
/
zltest.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// Package zltest provides facilities to test zerolog log messages.
package zltest
import (
"bytes"
"encoding/json"
"sync"
"github.com/rs/zerolog"
)
// Tester represents zerolog log tester.
type Tester struct {
mx sync.RWMutex // Guards the buffer.
buf []byte // Buffer zerolog writes to.
cnt int // Number of all log messages (calls to Write).
t T // Test manager.
}
// New creates new instance of zerolog tester.
func New(t T) *Tester {
return &Tester{
buf: make([]byte, 0, 500),
t: t,
}
}
// Logger returns zerolog.Logger using this tester as io.Writer.
func (tst *Tester) Logger() zerolog.Logger {
return zerolog.New(tst)
}
// Write implements io.Writer interface.
func (tst *Tester) Write(p []byte) (n int, err error) {
tst.mx.Lock()
defer tst.mx.Unlock()
tst.cnt++
tst.buf = append(tst.buf, p...)
return len(p), nil
}
// Len returns number of log messages written to the Tester.
func (tst *Tester) Len() int {
return tst.cnt
}
// String implements fmt.Stringer interface and returns everything written
// to the Tester so far. Calls Fatal on error.
func (tst *Tester) String() string {
tst.mx.RLock()
defer tst.mx.RUnlock()
return string(tst.buf)
}
// Entries returns all logged entries in the order they were logged. It calls
// Fatal if any of the log entries cannot be decoded or Scanner error.
func (tst *Tester) Entries() Entries {
tst.mx.RLock()
defer tst.mx.RUnlock()
tst.t.Helper()
ets := make([]*Entry, 0, tst.cnt)
var off int64
dec := json.NewDecoder(bytes.NewReader(tst.buf))
for dec.More() {
m := make(map[string]interface{})
if err := dec.Decode(&m); err != nil {
tst.t.Fatal(err)
return Entries{t: tst.t}
}
tmp := tst.buf[off:dec.InputOffset()]
off = dec.InputOffset()
ets = append(ets, &Entry{
raw: string(bytes.TrimSpace(tmp)),
m: m,
t: tst.t,
})
}
return Entries{e: ets, t: tst.t}
}
// Filter returns only entries matching log level.
func (tst *Tester) Filter(level zerolog.Level) Entries {
ets := make([]*Entry, 0)
for _, ent := range tst.Entries().Get() {
if lvl, _ := ent.Str(zerolog.LevelFieldName); lvl == level.String() {
ets = append(ets, ent)
}
}
return Entries{e: ets, t: tst.t}
}
// FirstEntry returns first log entry or nil if no log entries written
// to the Tester. It calls Fatal if any of the log entries cannot be decoded.
func (tst *Tester) FirstEntry() *Entry {
tst.mx.RLock()
defer tst.mx.RUnlock()
ets := tst.Entries().Get()
if len(ets) == 0 {
return nil
}
return ets[0]
}
// LastEntry returns last log entry or nil if no log entries written
// to the Tester. It calls Fatal if any of the log entries cannot be decoded.
func (tst *Tester) LastEntry() *Entry {
tst.mx.RLock()
defer tst.mx.RUnlock()
ets := tst.Entries().Get()
if len(ets) == 0 {
return nil
}
return ets[len(ets)-1]
}
// Reset resets the Tester.
func (tst *Tester) Reset() {
tst.mx.Lock()
defer tst.mx.Unlock()
tst.cnt = 0
tst.buf = tst.buf[:0]
}
// T is a subset of testing.TB interface.
// It's primarily used to test zltest package but can be used to implement
// custom actions to be taken on errors.
type T interface {
// Error is equivalent to Log followed by Fail.
Error(args ...interface{})
// Errorf is equivalent to Logf followed by Fail.
Errorf(format string, args ...interface{})
// Fatal is equivalent to Log followed by FailNow.
Fatal(args ...interface{})
// Fatalf is equivalent to Logf followed by FailNow.
Fatalf(format string, args ...interface{})
// Helper marks the calling function as a test helper function.
// When printing file and line information, that function will be skipped.
// Helper may be called simultaneously from multiple goroutines.
Helper()
// Log formats its arguments using default formatting, analogous to Println,
// and records the text in the error log. For tests, the text will be printed only if
// the test fails or the -test.v flag is set. For benchmarks, the text is always
// printed to avoid having performance depend on the value of the -test.v flag.
Log(args ...interface{})
// Logf formats its arguments according to the format, analogous to Printf, and
// records the text in the error log. A final newline is added if not provided. For
// tests, the text will be printed only if the test fails or the -test.v flag is
// set. For benchmarks, the text is always printed to avoid having performance
// depend on the value of the -test.v flag.
Logf(format string, args ...interface{})
// Cleanup registers a function to be called when the test (or subtest) and all its
// subtests complete. Cleanup functions will be called in last added,
// first called order.
Cleanup(func())
}