github.com/zxy12/go_duplicate_112_new@v0.0.0-20200807091221-747231827200/src/net/http/export_test.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Bridge package to expose http internals to tests in the http_test 6 // package. 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 // We only want to pay for this cost during testing. 43 // When not under test, these values are always nil 44 // and never assigned to. 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 var ( 64 SetEnterRoundTripHook = hookSetter(&testHookEnterRoundTrip) 65 SetRoundTripRetried = hookSetter(&testHookRoundTripRetried) 66 ) 67 68 func SetReadLoopBeforeNextReadHook(f func()) { 69 testHookMu.Lock() 70 defer testHookMu.Unlock() 71 unnilTestHook(&f) 72 testHookReadLoopBeforeNextRead = f 73 } 74 75 // SetPendingDialHooks sets the hooks that run before and after handling 76 // pending dials. 77 func SetPendingDialHooks(before, after func()) { 78 unnilTestHook(&before) 79 unnilTestHook(&after) 80 testHookPrePendingDial, testHookPostPendingDial = before, after 81 } 82 83 func SetTestHookServerServe(fn func(*Server, net.Listener)) { testHookServerServe = fn } 84 85 func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler { 86 ctx, cancel := context.WithCancel(context.Background()) 87 go func() { 88 <-ch 89 cancel() 90 }() 91 return &timeoutHandler{ 92 handler: handler, 93 testContext: ctx, 94 // (no body) 95 } 96 } 97 98 func ResetCachedEnvironment() { 99 resetProxyConfig() 100 } 101 102 func (t *Transport) NumPendingRequestsForTesting() int { 103 t.reqMu.Lock() 104 defer t.reqMu.Unlock() 105 return len(t.reqCanceler) 106 } 107 108 func (t *Transport) IdleConnKeysForTesting() (keys []string) { 109 keys = make([]string, 0) 110 t.idleMu.Lock() 111 defer t.idleMu.Unlock() 112 for key := range t.idleConn { 113 keys = append(keys, key.String()) 114 } 115 sort.Strings(keys) 116 return 117 } 118 119 func (t *Transport) IdleConnKeyCountForTesting() int { 120 t.idleMu.Lock() 121 defer t.idleMu.Unlock() 122 return len(t.idleConn) 123 } 124 125 func (t *Transport) IdleConnStrsForTesting() []string { 126 var ret []string 127 t.idleMu.Lock() 128 defer t.idleMu.Unlock() 129 for _, conns := range t.idleConn { 130 for _, pc := range conns { 131 ret = append(ret, pc.conn.LocalAddr().String()+"/"+pc.conn.RemoteAddr().String()) 132 } 133 } 134 sort.Strings(ret) 135 return ret 136 } 137 138 func (t *Transport) IdleConnStrsForTesting_h2() []string { 139 var ret []string 140 noDialPool := t.h2transport.(*http2Transport).ConnPool.(http2noDialClientConnPool) 141 pool := noDialPool.http2clientConnPool 142 143 pool.mu.Lock() 144 defer pool.mu.Unlock() 145 146 for k, cc := range pool.conns { 147 for range cc { 148 ret = append(ret, k) 149 } 150 } 151 152 sort.Strings(ret) 153 return ret 154 } 155 156 func (t *Transport) IdleConnCountForTesting(scheme, addr string) int { 157 t.idleMu.Lock() 158 defer t.idleMu.Unlock() 159 key := connectMethodKey{"", scheme, addr, false} 160 cacheKey := key.String() 161 for k, conns := range t.idleConn { 162 if k.String() == cacheKey { 163 return len(conns) 164 } 165 } 166 return 0 167 } 168 169 func (t *Transport) IdleConnChMapSizeForTesting() int { 170 t.idleMu.Lock() 171 defer t.idleMu.Unlock() 172 return len(t.idleConnCh) 173 } 174 175 func (t *Transport) IsIdleForTesting() bool { 176 t.idleMu.Lock() 177 defer t.idleMu.Unlock() 178 return t.wantIdle 179 } 180 181 func (t *Transport) RequestIdleConnChForTesting() { 182 t.getIdleConnCh(connectMethod{nil, "http", "example.com", false}) 183 } 184 185 func (t *Transport) PutIdleTestConn(scheme, addr string) bool { 186 c, _ := net.Pipe() 187 key := connectMethodKey{"", scheme, addr, false} 188 select { 189 case <-t.incHostConnCount(key): 190 default: 191 return false 192 } 193 return t.tryPutIdleConn(&persistConn{ 194 t: t, 195 conn: c, // dummy 196 closech: make(chan struct{}), // so it can be closed 197 cacheKey: key, 198 }) == nil 199 } 200 201 // All test hooks must be non-nil so they can be called directly, 202 // but the tests use nil to mean hook disabled. 203 func unnilTestHook(f *func()) { 204 if *f == nil { 205 *f = nop 206 } 207 } 208 209 func hookSetter(dst *func()) func(func()) { 210 return func(fn func()) { 211 unnilTestHook(&fn) 212 *dst = fn 213 } 214 } 215 216 func ExportHttp2ConfigureTransport(t *Transport) error { 217 t2, err := http2configureTransport(t) 218 if err != nil { 219 return err 220 } 221 t.h2transport = t2 222 return nil 223 } 224 225 func (s *Server) ExportAllConnsIdle() bool { 226 s.mu.Lock() 227 defer s.mu.Unlock() 228 for c := range s.activeConn { 229 st, unixSec := c.getState() 230 if unixSec == 0 || st != StateIdle { 231 return false 232 } 233 } 234 return true 235 } 236 237 func (r *Request) WithT(t *testing.T) *Request { 238 return r.WithContext(context.WithValue(r.Context(), tLogKey{}, t.Logf)) 239 } 240 241 func ExportSetH2GoawayTimeout(d time.Duration) (restore func()) { 242 old := http2goAwayTimeout 243 http2goAwayTimeout = d 244 return func() { http2goAwayTimeout = old } 245 } 246 247 func (r *Request) ExportIsReplayable() bool { return r.isReplayable() }