1
2
3
4
5 package gin
6
7 import (
8 "fmt"
9 "net"
10 "net/http"
11 "os"
12 "strings"
13 "syscall"
14 "testing"
15
16 "github.com/stretchr/testify/assert"
17 )
18
19 func TestPanicClean(t *testing.T) {
20 buffer := new(strings.Builder)
21 router := New()
22 password := "my-super-secret-password"
23 router.Use(RecoveryWithWriter(buffer))
24 router.GET("/recovery", func(c *Context) {
25 c.AbortWithStatus(http.StatusBadRequest)
26 panic("Oupps, Houston, we have a problem")
27 })
28
29 w := PerformRequest(router, "GET", "/recovery",
30 header{
31 Key: "Host",
32 Value: "www.google.com",
33 },
34 header{
35 Key: "Authorization",
36 Value: fmt.Sprintf("Bearer %s", password),
37 },
38 header{
39 Key: "Content-Type",
40 Value: "application/json",
41 },
42 )
43
44 assert.Equal(t, http.StatusBadRequest, w.Code)
45
46
47 assert.NotContains(t, buffer.String(), password)
48 }
49
50
51 func TestPanicInHandler(t *testing.T) {
52 buffer := new(strings.Builder)
53 router := New()
54 router.Use(RecoveryWithWriter(buffer))
55 router.GET("/recovery", func(_ *Context) {
56 panic("Oupps, Houston, we have a problem")
57 })
58
59 w := PerformRequest(router, "GET", "/recovery")
60
61 assert.Equal(t, http.StatusInternalServerError, w.Code)
62 assert.Contains(t, buffer.String(), "panic recovered")
63 assert.Contains(t, buffer.String(), "Oupps, Houston, we have a problem")
64 assert.Contains(t, buffer.String(), t.Name())
65 assert.NotContains(t, buffer.String(), "GET /recovery")
66
67
68 SetMode(DebugMode)
69
70 w = PerformRequest(router, "GET", "/recovery")
71
72 assert.Equal(t, http.StatusInternalServerError, w.Code)
73 assert.Contains(t, buffer.String(), "GET /recovery")
74
75 SetMode(TestMode)
76 }
77
78
79 func TestPanicWithAbort(t *testing.T) {
80 router := New()
81 router.Use(RecoveryWithWriter(nil))
82 router.GET("/recovery", func(c *Context) {
83 c.AbortWithStatus(http.StatusBadRequest)
84 panic("Oupps, Houston, we have a problem")
85 })
86
87 w := PerformRequest(router, "GET", "/recovery")
88
89 assert.Equal(t, http.StatusBadRequest, w.Code)
90 }
91
92 func TestSource(t *testing.T) {
93 bs := source(nil, 0)
94 assert.Equal(t, dunno, bs)
95
96 in := [][]byte{
97 []byte("Hello world."),
98 []byte("Hi, gin.."),
99 }
100 bs = source(in, 10)
101 assert.Equal(t, dunno, bs)
102
103 bs = source(in, 1)
104 assert.Equal(t, []byte("Hello world."), bs)
105 }
106
107 func TestFunction(t *testing.T) {
108 bs := function(1)
109 assert.Equal(t, dunno, bs)
110 }
111
112
113
114 func TestPanicWithBrokenPipe(t *testing.T) {
115 const expectCode = 204
116
117 expectMsgs := map[syscall.Errno]string{
118 syscall.EPIPE: "broken pipe",
119 syscall.ECONNRESET: "connection reset by peer",
120 }
121
122 for errno, expectMsg := range expectMsgs {
123 t.Run(expectMsg, func(t *testing.T) {
124 var buf strings.Builder
125
126 router := New()
127 router.Use(RecoveryWithWriter(&buf))
128 router.GET("/recovery", func(c *Context) {
129
130 c.Header("X-Test", "Value")
131 c.Status(expectCode)
132
133
134 e := &net.OpError{Err: &os.SyscallError{Err: errno}}
135 panic(e)
136 })
137
138 w := PerformRequest(router, "GET", "/recovery")
139
140 assert.Equal(t, expectCode, w.Code)
141 assert.Contains(t, strings.ToLower(buf.String()), expectMsg)
142 })
143 }
144 }
145
146 func TestCustomRecoveryWithWriter(t *testing.T) {
147 errBuffer := new(strings.Builder)
148 buffer := new(strings.Builder)
149 router := New()
150 handleRecovery := func(c *Context, err any) {
151 errBuffer.WriteString(err.(string))
152 c.AbortWithStatus(http.StatusBadRequest)
153 }
154 router.Use(CustomRecoveryWithWriter(buffer, handleRecovery))
155 router.GET("/recovery", func(_ *Context) {
156 panic("Oupps, Houston, we have a problem")
157 })
158
159 w := PerformRequest(router, "GET", "/recovery")
160
161 assert.Equal(t, http.StatusBadRequest, w.Code)
162 assert.Contains(t, buffer.String(), "panic recovered")
163 assert.Contains(t, buffer.String(), "Oupps, Houston, we have a problem")
164 assert.Contains(t, buffer.String(), t.Name())
165 assert.NotContains(t, buffer.String(), "GET /recovery")
166
167
168 SetMode(DebugMode)
169
170 w = PerformRequest(router, "GET", "/recovery")
171
172 assert.Equal(t, http.StatusBadRequest, w.Code)
173 assert.Contains(t, buffer.String(), "GET /recovery")
174
175 assert.Equal(t, strings.Repeat("Oupps, Houston, we have a problem", 2), errBuffer.String())
176
177 SetMode(TestMode)
178 }
179
180 func TestCustomRecovery(t *testing.T) {
181 errBuffer := new(strings.Builder)
182 buffer := new(strings.Builder)
183 router := New()
184 DefaultErrorWriter = buffer
185 handleRecovery := func(c *Context, err any) {
186 errBuffer.WriteString(err.(string))
187 c.AbortWithStatus(http.StatusBadRequest)
188 }
189 router.Use(CustomRecovery(handleRecovery))
190 router.GET("/recovery", func(_ *Context) {
191 panic("Oupps, Houston, we have a problem")
192 })
193
194 w := PerformRequest(router, "GET", "/recovery")
195
196 assert.Equal(t, http.StatusBadRequest, w.Code)
197 assert.Contains(t, buffer.String(), "panic recovered")
198 assert.Contains(t, buffer.String(), "Oupps, Houston, we have a problem")
199 assert.Contains(t, buffer.String(), t.Name())
200 assert.NotContains(t, buffer.String(), "GET /recovery")
201
202
203 SetMode(DebugMode)
204
205 w = PerformRequest(router, "GET", "/recovery")
206
207 assert.Equal(t, http.StatusBadRequest, w.Code)
208 assert.Contains(t, buffer.String(), "GET /recovery")
209
210 assert.Equal(t, strings.Repeat("Oupps, Houston, we have a problem", 2), errBuffer.String())
211
212 SetMode(TestMode)
213 }
214
215 func TestRecoveryWithWriterWithCustomRecovery(t *testing.T) {
216 errBuffer := new(strings.Builder)
217 buffer := new(strings.Builder)
218 router := New()
219 DefaultErrorWriter = buffer
220 handleRecovery := func(c *Context, err any) {
221 errBuffer.WriteString(err.(string))
222 c.AbortWithStatus(http.StatusBadRequest)
223 }
224 router.Use(RecoveryWithWriter(DefaultErrorWriter, handleRecovery))
225 router.GET("/recovery", func(_ *Context) {
226 panic("Oupps, Houston, we have a problem")
227 })
228
229 w := PerformRequest(router, "GET", "/recovery")
230
231 assert.Equal(t, http.StatusBadRequest, w.Code)
232 assert.Contains(t, buffer.String(), "panic recovered")
233 assert.Contains(t, buffer.String(), "Oupps, Houston, we have a problem")
234 assert.Contains(t, buffer.String(), t.Name())
235 assert.NotContains(t, buffer.String(), "GET /recovery")
236
237
238 SetMode(DebugMode)
239
240 w = PerformRequest(router, "GET", "/recovery")
241
242 assert.Equal(t, http.StatusBadRequest, w.Code)
243 assert.Contains(t, buffer.String(), "GET /recovery")
244
245 assert.Equal(t, strings.Repeat("Oupps, Houston, we have a problem", 2), errBuffer.String())
246
247 SetMode(TestMode)
248 }
249
View as plain text