1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package global
16
17 import (
18 "bytes"
19 "errors"
20 "io"
21 "log"
22 "sync"
23 "testing"
24
25 "github.com/stretchr/testify/suite"
26 )
27
28 type testErrCatcher []string
29
30 func (l *testErrCatcher) Write(p []byte) (int, error) {
31 msg := bytes.TrimRight(p, "\n")
32 (*l) = append(*l, string(msg))
33 return len(msg), nil
34 }
35
36 func (l *testErrCatcher) Reset() {
37 *l = testErrCatcher([]string{})
38 }
39
40 func (l *testErrCatcher) Got() []string {
41 return []string(*l)
42 }
43
44 func causeErr(text string) {
45 Handle(errors.New(text))
46 }
47
48 type HandlerTestSuite struct {
49 suite.Suite
50
51 origHandler ErrorHandler
52 errCatcher *testErrCatcher
53 }
54
55 func (s *HandlerTestSuite) SetupSuite() {
56 s.errCatcher = new(testErrCatcher)
57 s.origHandler = GlobalErrorHandler.getDelegate()
58
59 GlobalErrorHandler.setDelegate(&ErrLogger{l: log.New(s.errCatcher, "", 0)})
60 }
61
62 func (s *HandlerTestSuite) TearDownSuite() {
63 GlobalErrorHandler.setDelegate(s.origHandler)
64 }
65
66 func (s *HandlerTestSuite) SetupTest() {
67 s.errCatcher.Reset()
68 }
69
70 func (s *HandlerTestSuite) TearDownTest() {
71 GlobalErrorHandler.setDelegate(&ErrLogger{l: log.New(s.errCatcher, "", 0)})
72 }
73
74 func (s *HandlerTestSuite) TestGlobalHandler() {
75 errs := []string{"one", "two"}
76 GetErrorHandler().Handle(errors.New(errs[0]))
77 Handle(errors.New(errs[1]))
78 s.Assert().Equal(errs, s.errCatcher.Got())
79 }
80
81 func (s *HandlerTestSuite) TestDelegatedHandler() {
82 eh := GetErrorHandler()
83
84 newErrLogger := new(testErrCatcher)
85 SetErrorHandler(&ErrLogger{l: log.New(newErrLogger, "", 0)})
86
87 errs := []string{"TestDelegatedHandler"}
88 eh.Handle(errors.New(errs[0]))
89 s.Assert().Equal(errs, newErrLogger.Got())
90 }
91
92 func (s *HandlerTestSuite) TestNoDropsOnDelegate() {
93 causeErr("")
94 s.Require().Len(s.errCatcher.Got(), 1)
95
96
97 newErrLogger := new(testErrCatcher)
98 secondary := &ErrLogger{
99 l: log.New(newErrLogger, "", 0),
100 }
101 SetErrorHandler(secondary)
102
103 causeErr("")
104 s.Assert().Len(s.errCatcher.Got(), 1, "original Handler used after delegation")
105 s.Assert().Len(newErrLogger.Got(), 1, "new Handler not used after delegation")
106 }
107
108 func (s *HandlerTestSuite) TestAllowMultipleSets() {
109 notUsed := new(testErrCatcher)
110
111 secondary := &ErrLogger{l: log.New(notUsed, "", 0)}
112 SetErrorHandler(secondary)
113 s.Require().Same(GetErrorHandler(), GlobalErrorHandler, "set changed globalErrorHandler")
114 s.Require().Same(GlobalErrorHandler.getDelegate(), secondary, "new Handler not set")
115
116 tertiary := &ErrLogger{l: log.New(notUsed, "", 0)}
117 SetErrorHandler(tertiary)
118 s.Require().Same(GetErrorHandler(), GlobalErrorHandler, "set changed globalErrorHandler")
119 s.Assert().Same(GlobalErrorHandler.getDelegate(), tertiary, "user Handler not overridden")
120 }
121
122 func TestHandlerTestSuite(t *testing.T) {
123 suite.Run(t, new(HandlerTestSuite))
124 }
125
126 func TestHandlerConcurrentSafe(t *testing.T) {
127
128 SetErrorHandler(&ErrLogger{log.New(io.Discard, "", 0)})
129
130 var wg sync.WaitGroup
131 wg.Add(1)
132 go func() {
133 defer wg.Done()
134 SetErrorHandler(&ErrLogger{log.New(io.Discard, "", 0)})
135 }()
136 wg.Add(1)
137 go func() {
138 defer wg.Done()
139 Handle(errors.New("error"))
140 }()
141
142 wg.Wait()
143 reset()
144 }
145
146 func BenchmarkErrorHandler(b *testing.B) {
147 primary := &ErrLogger{l: log.New(io.Discard, "", 0)}
148 secondary := &ErrLogger{l: log.New(io.Discard, "", 0)}
149 tertiary := &ErrLogger{l: log.New(io.Discard, "", 0)}
150
151 GlobalErrorHandler.setDelegate(primary)
152
153 err := errors.New("benchmark error handler")
154
155 b.ReportAllocs()
156 b.ResetTimer()
157 for i := 0; i < b.N; i++ {
158 GetErrorHandler().Handle(err)
159 Handle(err)
160
161 SetErrorHandler(secondary)
162 GetErrorHandler().Handle(err)
163 Handle(err)
164
165 SetErrorHandler(tertiary)
166 GetErrorHandler().Handle(err)
167 Handle(err)
168
169 GlobalErrorHandler.setDelegate(primary)
170 }
171
172 reset()
173 }
174
175 var eh ErrorHandler
176
177 func BenchmarkGetDefaultErrorHandler(b *testing.B) {
178 b.ReportAllocs()
179 for i := 0; i < b.N; i++ {
180 eh = GetErrorHandler()
181 }
182 }
183
184 func BenchmarkGetDelegatedErrorHandler(b *testing.B) {
185 SetErrorHandler(&ErrLogger{l: log.New(io.Discard, "", 0)})
186
187 b.ReportAllocs()
188 b.ResetTimer()
189 for i := 0; i < b.N; i++ {
190 eh = GetErrorHandler()
191 }
192
193 reset()
194 }
195
196 func BenchmarkDefaultErrorHandlerHandle(b *testing.B) {
197 GlobalErrorHandler.setDelegate(
198 &ErrLogger{l: log.New(io.Discard, "", 0)},
199 )
200
201 eh := GetErrorHandler()
202 err := errors.New("benchmark default error handler handle")
203
204 b.ReportAllocs()
205 b.ResetTimer()
206 for i := 0; i < b.N; i++ {
207 eh.Handle(err)
208 }
209
210 reset()
211 }
212
213 func BenchmarkDelegatedErrorHandlerHandle(b *testing.B) {
214 eh := GetErrorHandler()
215 SetErrorHandler(&ErrLogger{l: log.New(io.Discard, "", 0)})
216 err := errors.New("benchmark delegated error handler handle")
217
218 b.ReportAllocs()
219 b.ResetTimer()
220 for i := 0; i < b.N; i++ {
221 eh.Handle(err)
222 }
223
224 reset()
225 }
226
227 func BenchmarkSetErrorHandlerDelegation(b *testing.B) {
228 alt := &ErrLogger{l: log.New(io.Discard, "", 0)}
229
230 b.ReportAllocs()
231 b.ResetTimer()
232 for i := 0; i < b.N; i++ {
233 SetErrorHandler(alt)
234
235 reset()
236 }
237 }
238
239 func reset() {
240 GlobalErrorHandler = defaultErrorHandler()
241 }
242
View as plain text