github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/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 ) 37 38 const MaxWriteWaitBeforeConnReuse = maxWriteWaitBeforeConnReuse 39 40 func init() { 41 // We only want to pay for this cost during testing. 42 // When not under test, these values are always nil 43 // and never assigned to. 44 testHookMu = new(sync.Mutex) 45 46 testHookClientDoResult = func(res *Response, err error) { 47 if err != nil { 48 if _, ok := err.(*url.Error); !ok { 49 panic(fmt.Sprintf("unexpected Client.Do error of type %T; want *url.Error", err)) 50 } 51 } else { 52 if res == nil { 53 panic("Client.Do returned nil, nil") 54 } 55 if res.Body == nil { 56 panic("Client.Do returned nil res.Body and no error") 57 } 58 } 59 } 60 } 61 62 var ( 63 SetEnterRoundTripHook = hookSetter(&testHookEnterRoundTrip) 64 SetRoundTripRetried = hookSetter(&testHookRoundTripRetried) 65 ) 66 67 func SetReadLoopBeforeNextReadHook(f func()) { 68 testHookMu.Lock() 69 defer testHookMu.Unlock() 70 unnilTestHook(&f) 71 testHookReadLoopBeforeNextRead = f 72 } 73 74 // SetPendingDialHooks sets the hooks that run before and after handling 75 // pending dials. 76 func SetPendingDialHooks(before, after func()) { 77 unnilTestHook(&before) 78 unnilTestHook(&after) 79 testHookPrePendingDial, testHookPostPendingDial = before, after 80 } 81 82 func SetTestHookServerServe(fn func(*Server, net.Listener)) { testHookServerServe = fn } 83 84 func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler { 85 ctx, cancel := context.WithCancel(context.Background()) 86 go func() { 87 <-ch 88 cancel() 89 }() 90 return &timeoutHandler{ 91 handler: handler, 92 testContext: ctx, 93 // (no body) 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, cc := range pool.conns { 146 for range cc { 147 ret = append(ret, k) 148 } 149 } 150 151 sort.Strings(ret) 152 return ret 153 } 154 155 func (t *Transport) IdleConnCountForTesting(scheme, addr string) int { 156 t.idleMu.Lock() 157 defer t.idleMu.Unlock() 158 key := connectMethodKey{"", scheme, addr, false} 159 cacheKey := key.String() 160 for k, conns := range t.idleConn { 161 if k.String() == cacheKey { 162 return len(conns) 163 } 164 } 165 return 0 166 } 167 168 func (t *Transport) IdleConnChMapSizeForTesting() int { 169 t.idleMu.Lock() 170 defer t.idleMu.Unlock() 171 return len(t.idleConnCh) 172 } 173 174 func (t *Transport) IsIdleForTesting() bool { 175 t.idleMu.Lock() 176 defer t.idleMu.Unlock() 177 return t.wantIdle 178 } 179 180 func (t *Transport) RequestIdleConnChForTesting() { 181 t.getIdleConnCh(connectMethod{nil, "http", "example.com", false}) 182 } 183 184 func (t *Transport) PutIdleTestConn(scheme, addr string) bool { 185 c, _ := net.Pipe() 186 key := connectMethodKey{"", scheme, addr, false} 187 select { 188 case <-t.incHostConnCount(key): 189 default: 190 return false 191 } 192 return t.tryPutIdleConn(&persistConn{ 193 t: t, 194 conn: c, // dummy 195 closech: make(chan struct{}), // so it can be closed 196 cacheKey: key, 197 }) == nil 198 } 199 200 // All test hooks must be non-nil so they can be called directly, 201 // but the tests use nil to mean hook disabled. 202 func unnilTestHook(f *func()) { 203 if *f == nil { 204 *f = nop 205 } 206 } 207 208 func hookSetter(dst *func()) func(func()) { 209 return func(fn func()) { 210 unnilTestHook(&fn) 211 *dst = fn 212 } 213 } 214 215 func ExportHttp2ConfigureTransport(t *Transport) error { 216 t2, err := http2configureTransport(t) 217 if err != nil { 218 return err 219 } 220 t.h2transport = t2 221 return nil 222 } 223 224 func (s *Server) ExportAllConnsIdle() bool { 225 s.mu.Lock() 226 defer s.mu.Unlock() 227 for c := range s.activeConn { 228 st, unixSec := c.getState() 229 if unixSec == 0 || st != StateIdle { 230 return false 231 } 232 } 233 return true 234 } 235 236 func (r *Request) WithT(t *testing.T) *Request { 237 return r.WithContext(context.WithValue(r.Context(), tLogKey{}, t.Logf)) 238 } 239 240 func ExportSetH2GoawayTimeout(d time.Duration) (restore func()) { 241 old := http2goAwayTimeout 242 http2goAwayTimeout = d 243 return func() { http2goAwayTimeout = old } 244 } 245 246 func (r *Request) ExportIsReplayable() bool { return r.isReplayable() }