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, ch <-chan time.Time) Handler {
92 ctx, cancel := context.WithCancel(context.Background())
93 go func() {
94 <-ch
95 cancel()
96 }()
97 return &timeoutHandler{
98 handler: handler,
99 testContext: ctx,
100
101 }
102 }
103
104 func ResetCachedEnvironment() {
105 resetProxyConfig()
106 }
107
108 func (t *Transport) NumPendingRequestsForTesting() int {
109 t.reqMu.Lock()
110 defer t.reqMu.Unlock()
111 return len(t.reqCanceler)
112 }
113
114 func (t *Transport) IdleConnKeysForTesting() (keys []string) {
115 keys = make([]string, 0)
116 t.idleMu.Lock()
117 defer t.idleMu.Unlock()
118 for key := range t.idleConn {
119 keys = append(keys, key.String())
120 }
121 sort.Strings(keys)
122 return
123 }
124
125 func (t *Transport) IdleConnKeyCountForTesting() int {
126 t.idleMu.Lock()
127 defer t.idleMu.Unlock()
128 return len(t.idleConn)
129 }
130
131 func (t *Transport) IdleConnStrsForTesting() []string {
132 var ret []string
133 t.idleMu.Lock()
134 defer t.idleMu.Unlock()
135 for _, conns := range t.idleConn {
136 for _, pc := range conns {
137 ret = append(ret, pc.conn.LocalAddr().String()+"/"+pc.conn.RemoteAddr().String())
138 }
139 }
140 sort.Strings(ret)
141 return ret
142 }
143
144 func (t *Transport) IdleConnStrsForTesting_h2() []string {
145 var ret []string
146 noDialPool := t.h2transport.(*http2Transport).ConnPool.(http2noDialClientConnPool)
147 pool := noDialPool.http2clientConnPool
148
149 pool.mu.Lock()
150 defer pool.mu.Unlock()
151
152 for k, cc := range pool.conns {
153 for range cc {
154 ret = append(ret, k)
155 }
156 }
157
158 sort.Strings(ret)
159 return ret
160 }
161
162 func (t *Transport) IdleConnCountForTesting(scheme, addr string) int {
163 t.idleMu.Lock()
164 defer t.idleMu.Unlock()
165 key := connectMethodKey{"", scheme, addr, false}
166 cacheKey := key.String()
167 for k, conns := range t.idleConn {
168 if k.String() == cacheKey {
169 return len(conns)
170 }
171 }
172 return 0
173 }
174
175 func (t *Transport) IdleConnWaitMapSizeForTesting() int {
176 t.idleMu.Lock()
177 defer t.idleMu.Unlock()
178 return len(t.idleConnWait)
179 }
180
181 func (t *Transport) IsIdleForTesting() bool {
182 t.idleMu.Lock()
183 defer t.idleMu.Unlock()
184 return t.closeIdle
185 }
186
187 func (t *Transport) QueueForIdleConnForTesting() {
188 t.queueForIdleConn(nil)
189 }
190
191
192
193 func (t *Transport) PutIdleTestConn(scheme, addr string) bool {
194 c, _ := net.Pipe()
195 key := connectMethodKey{"", scheme, addr, false}
196
197 if t.MaxConnsPerHost > 0 {
198
199
200
201 t.connsPerHostMu.Lock()
202 if t.connsPerHost == nil {
203 t.connsPerHost = make(map[connectMethodKey]int)
204 }
205 t.connsPerHost[key]++
206 t.connsPerHostMu.Unlock()
207 }
208
209 return t.tryPutIdleConn(&persistConn{
210 t: t,
211 conn: c,
212 closech: make(chan struct{}),
213 cacheKey: key,
214 }) == nil
215 }
216
217
218
219 func (t *Transport) PutIdleTestConnH2(scheme, addr string, alt RoundTripper) bool {
220 key := connectMethodKey{"", scheme, addr, false}
221
222 if t.MaxConnsPerHost > 0 {
223
224
225
226 t.connsPerHostMu.Lock()
227 if t.connsPerHost == nil {
228 t.connsPerHost = make(map[connectMethodKey]int)
229 }
230 t.connsPerHost[key]++
231 t.connsPerHostMu.Unlock()
232 }
233
234 return t.tryPutIdleConn(&persistConn{
235 t: t,
236 alt: alt,
237 cacheKey: key,
238 }) == nil
239 }
240
241
242
243 func unnilTestHook(f *func()) {
244 if *f == nil {
245 *f = nop
246 }
247 }
248
249 func hookSetter(dst *func()) func(func()) {
250 return func(fn func()) {
251 unnilTestHook(&fn)
252 *dst = fn
253 }
254 }
255
256 func ExportHttp2ConfigureTransport(t *Transport) error {
257 t2, err := http2configureTransports(t)
258 if err != nil {
259 return err
260 }
261 t.h2transport = t2
262 return nil
263 }
264
265 func (s *Server) ExportAllConnsIdle() bool {
266 s.mu.Lock()
267 defer s.mu.Unlock()
268 for c := range s.activeConn {
269 st, unixSec := c.getState()
270 if unixSec == 0 || st != StateIdle {
271 return false
272 }
273 }
274 return true
275 }
276
277 func (s *Server) ExportAllConnsByState() map[ConnState]int {
278 states := map[ConnState]int{}
279 s.mu.Lock()
280 defer s.mu.Unlock()
281 for c := range s.activeConn {
282 st, _ := c.getState()
283 states[st] += 1
284 }
285 return states
286 }
287
288 func (r *Request) WithT(t *testing.T) *Request {
289 return r.WithContext(context.WithValue(r.Context(), tLogKey{}, t.Logf))
290 }
291
292 func ExportSetH2GoawayTimeout(d time.Duration) (restore func()) {
293 old := http2goAwayTimeout
294 http2goAwayTimeout = d
295 return func() { http2goAwayTimeout = old }
296 }
297
298 func (r *Request) ExportIsReplayable() bool { return r.isReplayable() }
299
300
301
302
303
304
305 func ExportCloseTransportConnsAbruptly(tr *Transport) {
306 tr.idleMu.Lock()
307 for _, pcs := range tr.idleConn {
308 for _, pc := range pcs {
309 pc.conn.Close()
310 }
311 }
312 tr.idleMu.Unlock()
313 }
314
View as plain text