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 const 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.T) {
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 testHookMu.Lock()
76 defer testHookMu.Unlock()
77 unnilTestHook(&f)
78 testHookReadLoopBeforeNextRead = f
79 }
80
81
82
83 func SetPendingDialHooks(before, after func()) {
84 unnilTestHook(&before)
85 unnilTestHook(&after)
86 testHookPrePendingDial, testHookPostPendingDial = before, after
87 }
88
89 func SetTestHookServerServe(fn func(*Server, net.Listener)) { testHookServerServe = fn }
90
91 func NewTestTimeoutHandler(handler Handler, ctx context.Context) Handler {
92 return &timeoutHandler{
93 handler: handler,
94 testContext: ctx,
95
96 }
97 }
98
99 func ResetCachedEnvironment() {
100 resetProxyConfig()
101 }
102
103 func (t *Transport) NumPendingRequestsForTesting() int {
104 t.reqMu.Lock()
105 defer t.reqMu.Unlock()
106 return len(t.reqCanceler)
107 }
108
109 func (t *Transport) IdleConnKeysForTesting() (keys []string) {
110 keys = make([]string, 0)
111 t.idleMu.Lock()
112 defer t.idleMu.Unlock()
113 for key := range t.idleConn {
114 keys = append(keys, key.String())
115 }
116 sort.Strings(keys)
117 return
118 }
119
120 func (t *Transport) IdleConnKeyCountForTesting() int {
121 t.idleMu.Lock()
122 defer t.idleMu.Unlock()
123 return len(t.idleConn)
124 }
125
126 func (t *Transport) IdleConnStrsForTesting() []string {
127 var ret []string
128 t.idleMu.Lock()
129 defer t.idleMu.Unlock()
130 for _, conns := range t.idleConn {
131 for _, pc := range conns {
132 ret = append(ret, pc.conn.LocalAddr().String()+"/"+pc.conn.RemoteAddr().String())
133 }
134 }
135 sort.Strings(ret)
136 return ret
137 }
138
139 func (t *Transport) IdleConnStrsForTesting_h2() []string {
140 var ret []string
141 noDialPool := t.h2transport.(*http2Transport).ConnPool.(http2noDialClientConnPool)
142 pool := noDialPool.http2clientConnPool
143
144 pool.mu.Lock()
145 defer pool.mu.Unlock()
146
147 for k, cc := range pool.conns {
148 for range cc {
149 ret = append(ret, k)
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
View as plain text