Source file
src/net/http/export_test.go
1
2
3
4
5
6
7
8 package http
9
10 import (
11 "context"
12 "fmt"
13 "net"
14 "net/url"
15 "sort"
16 "sync"
17 "testing"
18 "time"
19 )
20
21 var (
22 DefaultUserAgent = defaultUserAgent
23 NewLoggingConn = newLoggingConn
24 ExportAppendTime = appendTime
25 ExportRefererForURL = refererForURL
26 ExportServerNewConn = (*Server).newConn
27 ExportCloseWriteAndWait = (*conn).closeWriteAndWait
28 ExportErrRequestCanceled = errRequestCanceled
29 ExportErrRequestCanceledConn = errRequestCanceledConn
30 ExportErrServerClosedIdle = errServerClosedIdle
31 ExportServeFile = serveFile
32 ExportScanETag = scanETag
33 ExportHttp2ConfigureServer = http2ConfigureServer
34 Export_shouldCopyHeaderOnRedirect = shouldCopyHeaderOnRedirect
35 Export_writeStatusLine = writeStatusLine
36 Export_is408Message = is408Message
37 )
38
39 var MaxWriteWaitBeforeConnReuse = &maxWriteWaitBeforeConnReuse
40
41 func init() {
42
43
44
45 testHookMu = new(sync.Mutex)
46
47 testHookClientDoResult = func(res *Response, err error) {
48 if err != nil {
49 if _, ok := err.(*url.Error); !ok {
50 panic(fmt.Sprintf("unexpected Client.Do error of type %T; want *url.Error", err))
51 }
52 } else {
53 if res == nil {
54 panic("Client.Do returned nil, nil")
55 }
56 if res.Body == nil {
57 panic("Client.Do returned nil res.Body and no error")
58 }
59 }
60 }
61 }
62
63 func CondSkipHTTP2(t testing.TB) {
64 if omitBundledHTTP2 {
65 t.Skip("skipping HTTP/2 test when nethttpomithttp2 build tag in use")
66 }
67 }
68
69 var (
70 SetEnterRoundTripHook = hookSetter(&testHookEnterRoundTrip)
71 SetRoundTripRetried = hookSetter(&testHookRoundTripRetried)
72 )
73
74 func SetReadLoopBeforeNextReadHook(f func()) {
75 unnilTestHook(&f)
76 testHookReadLoopBeforeNextRead = f
77 }
78
79
80
81 func SetPendingDialHooks(before, after func()) {
82 unnilTestHook(&before)
83 unnilTestHook(&after)
84 testHookPrePendingDial, testHookPostPendingDial = before, after
85 }
86
87 func SetTestHookServerServe(fn func(*Server, net.Listener)) { testHookServerServe = fn }
88
89 func NewTestTimeoutHandler(handler Handler, ctx context.Context) Handler {
90 return &timeoutHandler{
91 handler: handler,
92 testContext: ctx,
93
94 }
95 }
96
97 func ResetCachedEnvironment() {
98 resetProxyConfig()
99 }
100
101 func (t *Transport) NumPendingRequestsForTesting() int {
102 t.reqMu.Lock()
103 defer t.reqMu.Unlock()
104 return len(t.reqCanceler)
105 }
106
107 func (t *Transport) IdleConnKeysForTesting() (keys []string) {
108 keys = make([]string, 0)
109 t.idleMu.Lock()
110 defer t.idleMu.Unlock()
111 for key := range t.idleConn {
112 keys = append(keys, key.String())
113 }
114 sort.Strings(keys)
115 return
116 }
117
118 func (t *Transport) IdleConnKeyCountForTesting() int {
119 t.idleMu.Lock()
120 defer t.idleMu.Unlock()
121 return len(t.idleConn)
122 }
123
124 func (t *Transport) IdleConnStrsForTesting() []string {
125 var ret []string
126 t.idleMu.Lock()
127 defer t.idleMu.Unlock()
128 for _, conns := range t.idleConn {
129 for _, pc := range conns {
130 ret = append(ret, pc.conn.LocalAddr().String()+"/"+pc.conn.RemoteAddr().String())
131 }
132 }
133 sort.Strings(ret)
134 return ret
135 }
136
137 func (t *Transport) IdleConnStrsForTesting_h2() []string {
138 var ret []string
139 noDialPool := t.h2transport.(*http2Transport).ConnPool.(http2noDialClientConnPool)
140 pool := noDialPool.http2clientConnPool
141
142 pool.mu.Lock()
143 defer pool.mu.Unlock()
144
145 for k, ccs := range pool.conns {
146 for _, cc := range ccs {
147 if cc.idleState().canTakeNewRequest {
148 ret = append(ret, k)
149 }
150 }
151 }
152
153 sort.Strings(ret)
154 return ret
155 }
156
157 func (t *Transport) IdleConnCountForTesting(scheme, addr string) int {
158 t.idleMu.Lock()
159 defer t.idleMu.Unlock()
160 key := connectMethodKey{"", scheme, addr, false}
161 cacheKey := key.String()
162 for k, conns := range t.idleConn {
163 if k.String() == cacheKey {
164 return len(conns)
165 }
166 }
167 return 0
168 }
169
170 func (t *Transport) IdleConnWaitMapSizeForTesting() int {
171 t.idleMu.Lock()
172 defer t.idleMu.Unlock()
173 return len(t.idleConnWait)
174 }
175
176 func (t *Transport) IsIdleForTesting() bool {
177 t.idleMu.Lock()
178 defer t.idleMu.Unlock()
179 return t.closeIdle
180 }
181
182 func (t *Transport) QueueForIdleConnForTesting() {
183 t.queueForIdleConn(nil)
184 }
185
186
187
188 func (t *Transport) PutIdleTestConn(scheme, addr string) bool {
189 c, _ := net.Pipe()
190 key := connectMethodKey{"", scheme, addr, false}
191
192 if t.MaxConnsPerHost > 0 {
193
194
195
196 t.connsPerHostMu.Lock()
197 if t.connsPerHost == nil {
198 t.connsPerHost = make(map[connectMethodKey]int)
199 }
200 t.connsPerHost[key]++
201 t.connsPerHostMu.Unlock()
202 }
203
204 return t.tryPutIdleConn(&persistConn{
205 t: t,
206 conn: c,
207 closech: make(chan struct{}),
208 cacheKey: key,
209 }) == nil
210 }
211
212
213
214 func (t *Transport) PutIdleTestConnH2(scheme, addr string, alt RoundTripper) bool {
215 key := connectMethodKey{"", scheme, addr, false}
216
217 if t.MaxConnsPerHost > 0 {
218
219
220
221 t.connsPerHostMu.Lock()
222 if t.connsPerHost == nil {
223 t.connsPerHost = make(map[connectMethodKey]int)
224 }
225 t.connsPerHost[key]++
226 t.connsPerHostMu.Unlock()
227 }
228
229 return t.tryPutIdleConn(&persistConn{
230 t: t,
231 alt: alt,
232 cacheKey: key,
233 }) == nil
234 }
235
236
237
238 func unnilTestHook(f *func()) {
239 if *f == nil {
240 *f = nop
241 }
242 }
243
244 func hookSetter(dst *func()) func(func()) {
245 return func(fn func()) {
246 unnilTestHook(&fn)
247 *dst = fn
248 }
249 }
250
251 func ExportHttp2ConfigureTransport(t *Transport) error {
252 t2, err := http2configureTransports(t)
253 if err != nil {
254 return err
255 }
256 t.h2transport = t2
257 return nil
258 }
259
260 func (s *Server) ExportAllConnsIdle() bool {
261 s.mu.Lock()
262 defer s.mu.Unlock()
263 for c := range s.activeConn {
264 st, unixSec := c.getState()
265 if unixSec == 0 || st != StateIdle {
266 return false
267 }
268 }
269 return true
270 }
271
272 func (s *Server) ExportAllConnsByState() map[ConnState]int {
273 states := map[ConnState]int{}
274 s.mu.Lock()
275 defer s.mu.Unlock()
276 for c := range s.activeConn {
277 st, _ := c.getState()
278 states[st] += 1
279 }
280 return states
281 }
282
283 func (r *Request) WithT(t *testing.T) *Request {
284 return r.WithContext(context.WithValue(r.Context(), tLogKey{}, t.Logf))
285 }
286
287 func ExportSetH2GoawayTimeout(d time.Duration) (restore func()) {
288 old := http2goAwayTimeout
289 http2goAwayTimeout = d
290 return func() { http2goAwayTimeout = old }
291 }
292
293 func (r *Request) ExportIsReplayable() bool { return r.isReplayable() }
294
295
296
297
298
299
300 func ExportCloseTransportConnsAbruptly(tr *Transport) {
301 tr.idleMu.Lock()
302 for _, pcs := range tr.idleConn {
303 for _, pc := range pcs {
304 pc.conn.Close()
305 }
306 }
307 tr.idleMu.Unlock()
308 }
309
310
311
312 func ResponseWriterConnForTesting(w ResponseWriter) (c net.Conn, ok bool) {
313 if r, ok := w.(*response); ok {
314 return r.conn.rwc, true
315 }
316 return nil, false
317 }
318
319 func init() {
320
321
322
323
324 rstAvoidanceDelay = 1 * time.Nanosecond
325 }
326
327
328
329 func SetRSTAvoidanceDelay(t *testing.T, d time.Duration) {
330 prevDelay := rstAvoidanceDelay
331 t.Cleanup(func() {
332 rstAvoidanceDelay = prevDelay
333 })
334 rstAvoidanceDelay = d
335 }
336
View as plain text