This repository has been archived by the owner on Jul 22, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 38
/
middleware_test.go
177 lines (154 loc) · 4.27 KB
/
middleware_test.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
171
172
173
174
175
176
177
package servertiming
import (
"net/http"
"net/http/httptest"
"testing"
"time"
)
const (
responseBody = "response"
responseStatus = http.StatusCreated
)
func TestMiddleware(t *testing.T) {
cases := []struct {
Name string
Opts *MiddlewareOpts
Metrics []*Metric
SkipWriteHeaders bool
Expected bool
}{
{
Name: "nil metrics",
Metrics: nil,
Expected: false,
},
{
Name: "empty metrics",
Metrics: []*Metric{},
Expected: false,
},
{
Name: "single metric disable headers option",
Opts: &MiddlewareOpts{DisableHeaders: true},
Metrics: []*Metric{
{
Name: "sql-1",
Duration: 100 * time.Millisecond,
Desc: "MySQL; lookup Server",
},
},
Expected: false,
},
{
Name: "single metric",
Metrics: []*Metric{
{
Name: "sql-1",
Duration: 100 * time.Millisecond,
Desc: "MySQL; lookup Server",
},
},
Expected: true,
},
{
Name: "single metric without invoking WriteHeaders in handler",
Metrics: []*Metric{
{
Name: "sql-1",
Duration: 100 * time.Millisecond,
Desc: "MySQL; lookup Server",
},
},
Expected: true,
SkipWriteHeaders: true,
},
}
for _, tt := range cases {
t.Run(tt.Name, func(t *testing.T) {
r := httptest.NewRequest("GET", "/", nil)
rec := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Set the metrics to the configured case
h := FromContext(r.Context())
if h == nil {
t.Fatal("expected *Header to be present in context")
}
h.Metrics = tt.Metrics
// Write the header to flush the response
if !tt.SkipWriteHeaders {
w.WriteHeader(responseStatus)
}
// Write date to response body
w.Write([]byte(responseBody))
})
// Perform the request
Middleware(handler, tt.Opts).ServeHTTP(rec, r)
// Test that it is present or not
_, present := map[string][]string(rec.Header())[HeaderKey]
if present != tt.Expected {
t.Fatalf("expected header to be present: %v, but wasn't", tt.Expected)
}
// Test the response headers
expected := (&Header{Metrics: tt.Metrics}).String()
if tt.Opts != nil && tt.Opts.DisableHeaders == true {
expected = ""
}
actual := rec.Header().Get(HeaderKey)
if actual != expected {
t.Fatalf("got wrong value, expected != actual: %q != %q", expected, actual)
}
// Test the status code of the response, if we skip the write headers method, the default 200 should be
// the response status code
expectedStatus := responseStatus
if tt.SkipWriteHeaders {
expectedStatus = http.StatusOK
}
if actualStatus := rec.Result().StatusCode; expectedStatus != actualStatus {
t.Fatalf("got unexpected status code value, expected != actual: %q != %q", expectedStatus, actualStatus)
}
// Test the response body was left intact
if responseBody != rec.Body.String() {
t.Fatalf("got unexpected body, expected != actual: %q != %q", responseBody, rec.Body.String())
}
})
}
}
// We need to test this separately since the httptest.ResponseRecorder
// doesn't properly reflect that headers can't be set after writing data,
// so we have to use a real server.
func TestMiddleware_writeHeaderNotCalled(t *testing.T) {
metrics := []*Metric{
{
Name: "sql-1",
Duration: 100 * time.Millisecond,
Desc: "MySQL; lookup Server",
},
}
// Start our test server
ts := httptest.NewServer(Middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Set the metrics to the configured case
h := FromContext(r.Context())
if h == nil {
t.Fatal("expected *Header to be present in context")
}
h.Metrics = metrics
// Write date to response body WITHOUT calling WriteHeader
w.Write([]byte(responseBody))
}), nil))
defer ts.Close()
res, err := http.Get(ts.URL)
if err != nil {
t.Fatal(err)
}
// Test that it is present or not
_, present := map[string][]string(res.Header)[HeaderKey]
if !present {
t.Fatal("expected header to be present")
}
// Test the response headers
expected := (&Header{Metrics: metrics}).String()
actual := res.Header.Get(HeaderKey)
if actual != expected {
t.Fatalf("got wrong value, expected != actual: %q != %q", expected, actual)
}
}