Source file
src/go.uber.org/zap/http_handler_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package zap_test
22
23 import (
24 "encoding/json"
25 "errors"
26 "net/http"
27 "net/http/httptest"
28 "strings"
29 "testing"
30
31 "go.uber.org/zap"
32 "go.uber.org/zap/zapcore"
33
34 "github.com/stretchr/testify/assert"
35 "github.com/stretchr/testify/require"
36 )
37
38 func TestAtomicLevelServeHTTP(t *testing.T) {
39 tests := []struct {
40 desc string
41 method string
42 query string
43 contentType string
44 body string
45 expectedCode int
46 expectedLevel zapcore.Level
47 }{
48 {
49 desc: "GET",
50 method: http.MethodGet,
51 expectedCode: http.StatusOK,
52 expectedLevel: zap.InfoLevel,
53 },
54 {
55 desc: "PUT JSON",
56 method: http.MethodPut,
57 expectedCode: http.StatusOK,
58 expectedLevel: zap.WarnLevel,
59 body: `{"level":"warn"}`,
60 },
61 {
62 desc: "PUT URL encoded",
63 method: http.MethodPut,
64 expectedCode: http.StatusOK,
65 expectedLevel: zap.WarnLevel,
66 contentType: "application/x-www-form-urlencoded",
67 body: "level=warn",
68 },
69 {
70 desc: "PUT query parameters",
71 method: http.MethodPut,
72 query: "?level=warn",
73 expectedCode: http.StatusOK,
74 expectedLevel: zap.WarnLevel,
75 contentType: "application/x-www-form-urlencoded",
76 },
77 {
78 desc: "body takes precedence over query",
79 method: http.MethodPut,
80 query: "?level=info",
81 expectedCode: http.StatusOK,
82 expectedLevel: zap.WarnLevel,
83 contentType: "application/x-www-form-urlencoded",
84 body: "level=warn",
85 },
86 {
87 desc: "JSON ignores query",
88 method: http.MethodPut,
89 query: "?level=info",
90 expectedCode: http.StatusOK,
91 expectedLevel: zap.WarnLevel,
92 body: `{"level":"warn"}`,
93 },
94 {
95 desc: "PUT JSON unrecognized",
96 method: http.MethodPut,
97 expectedCode: http.StatusBadRequest,
98 body: `{"level":"unrecognized"}`,
99 },
100 {
101 desc: "PUT URL encoded unrecognized",
102 method: http.MethodPut,
103 expectedCode: http.StatusBadRequest,
104 contentType: "application/x-www-form-urlencoded",
105 body: "level=unrecognized",
106 },
107 {
108 desc: "PUT JSON malformed",
109 method: http.MethodPut,
110 expectedCode: http.StatusBadRequest,
111 body: `{"level":"warn`,
112 },
113 {
114 desc: "PUT URL encoded malformed",
115 method: http.MethodPut,
116 query: "?level=%",
117 expectedCode: http.StatusBadRequest,
118 contentType: "application/x-www-form-urlencoded",
119 },
120 {
121 desc: "PUT Query parameters malformed",
122 method: http.MethodPut,
123 expectedCode: http.StatusBadRequest,
124 contentType: "application/x-www-form-urlencoded",
125 body: "level=%",
126 },
127 {
128 desc: "PUT JSON unspecified",
129 method: http.MethodPut,
130 expectedCode: http.StatusBadRequest,
131 body: `{}`,
132 },
133 {
134 desc: "PUT URL encoded unspecified",
135 method: http.MethodPut,
136 expectedCode: http.StatusBadRequest,
137 contentType: "application/x-www-form-urlencoded",
138 body: "",
139 },
140 {
141 desc: "POST JSON",
142 method: http.MethodPost,
143 expectedCode: http.StatusMethodNotAllowed,
144 body: `{"level":"warn"}`,
145 },
146 {
147 desc: "POST URL",
148 method: http.MethodPost,
149 expectedCode: http.StatusMethodNotAllowed,
150 contentType: "application/x-www-form-urlencoded",
151 body: "level=warn",
152 },
153 }
154
155 for _, tt := range tests {
156 t.Run(tt.desc, func(t *testing.T) {
157 lvl := zap.NewAtomicLevel()
158 lvl.SetLevel(zapcore.InfoLevel)
159
160 server := httptest.NewServer(lvl)
161 defer server.Close()
162
163 req, err := http.NewRequest(tt.method, server.URL+tt.query, strings.NewReader(tt.body))
164 require.NoError(t, err, "Error constructing %s request.", req.Method)
165 if tt.contentType != "" {
166 req.Header.Set("Content-Type", tt.contentType)
167 }
168
169 res, err := http.DefaultClient.Do(req)
170 require.NoError(t, err, "Error making %s request.", req.Method)
171 defer func() {
172 assert.NoError(t, res.Body.Close(), "Error closing response body.")
173 }()
174
175 require.Equal(t, tt.expectedCode, res.StatusCode, "Unexpected status code.")
176 if tt.expectedCode != http.StatusOK {
177
178 var pld struct {
179 Error string `json:"error"`
180 }
181 require.NoError(t, json.NewDecoder(res.Body).Decode(&pld), "Decoding response body")
182 assert.NotEmpty(t, pld.Error, "Expected an error message")
183 return
184 }
185
186 var pld struct {
187 Level zapcore.Level `json:"level"`
188 }
189 require.NoError(t, json.NewDecoder(res.Body).Decode(&pld), "Decoding response body")
190 assert.Equal(t, tt.expectedLevel, pld.Level, "Unexpected logging level returned")
191 })
192 }
193 }
194
195 func TestAtomicLevelServeHTTPBrokenWriter(t *testing.T) {
196 t.Parallel()
197
198 lvl := zap.NewAtomicLevel()
199
200 request, err := http.NewRequest(http.MethodGet, "http://localhost:1234/log/level", nil)
201 require.NoError(t, err, "Error constructing request.")
202
203 recorder := httptest.NewRecorder()
204 lvl.ServeHTTP(&brokenHTTPResponseWriter{
205 ResponseWriter: recorder,
206 }, request)
207
208 assert.Equal(t, http.StatusInternalServerError, recorder.Code, "Unexpected status code.")
209 }
210
211 type brokenHTTPResponseWriter struct {
212 http.ResponseWriter
213 }
214
215 func (w *brokenHTTPResponseWriter) Write([]byte) (int, error) {
216 return 0, errors.New("great sadness")
217 }
218
View as plain text