github.com/zebozhuang/go@v0.0.0-20200207033046-f8a98f6f5c5d/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 "net" 13 "sort" 14 "sync" 15 "testing" 16 "time" 17 ) 18 19 var ( 20 DefaultUserAgent = defaultUserAgent 21 NewLoggingConn = newLoggingConn 22 ExportAppendTime = appendTime 23 ExportRefererForURL = refererForURL 24 ExportServerNewConn = (*Server).newConn 25 ExportCloseWriteAndWait = (*conn).closeWriteAndWait 26 ExportErrRequestCanceled = errRequestCanceled 27 ExportErrRequestCanceledConn = errRequestCanceledConn 28 ExportErrServerClosedIdle = errServerClosedIdle 29 ExportServeFile = serveFile 30 ExportScanETag = scanETag 31 ExportHttp2ConfigureServer = http2ConfigureServer 32 Export_shouldCopyHeaderOnRedirect = shouldCopyHeaderOnRedirect 33 Export_writeStatusLine = writeStatusLine 34 ) 35 36 func init() { 37 // We only want to pay for this cost during testing. 38 // When not under test, these values are always nil 39 // and never assigned to. 40 testHookMu = new(sync.Mutex) 41 } 42 43 var ( 44 SetEnterRoundTripHook = hookSetter(&testHookEnterRoundTrip) 45 SetRoundTripRetried = hookSetter(&testHookRoundTripRetried) 46 ) 47 48 func SetReadLoopBeforeNextReadHook(f func()) { 49 testHookMu.Lock() 50 defer testHookMu.Unlock() 51 unnilTestHook(&f) 52 testHookReadLoopBeforeNextRead = f 53 } 54 55 // SetPendingDialHooks sets the hooks that run before and after handling 56 // pending dials. 57 func SetPendingDialHooks(before, after func()) { 58 unnilTestHook(&before) 59 unnilTestHook(&after) 60 testHookPrePendingDial, testHookPostPendingDial = before, after 61 } 62 63 func SetTestHookServerServe(fn func(*Server, net.Listener)) { testHookServerServe = fn } 64 65 func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler { 66 return &timeoutHandler{ 67 handler: handler, 68 testTimeout: ch, 69 // (no body) 70 } 71 } 72 73 func ResetCachedEnvironment() { 74 httpProxyEnv.reset() 75 httpsProxyEnv.reset() 76 noProxyEnv.reset() 77 } 78 79 func (t *Transport) NumPendingRequestsForTesting() int { 80 t.reqMu.Lock() 81 defer t.reqMu.Unlock() 82 return len(t.reqCanceler) 83 } 84 85 func (t *Transport) IdleConnKeysForTesting() (keys []string) { 86 keys = make([]string, 0) 87 t.idleMu.Lock() 88 defer t.idleMu.Unlock() 89 for key := range t.idleConn { 90 keys = append(keys, key.String()) 91 } 92 sort.Strings(keys) 93 return 94 } 95 96 func (t *Transport) IdleConnKeyCountForTesting() int { 97 t.idleMu.Lock() 98 defer t.idleMu.Unlock() 99 return len(t.idleConn) 100 } 101 102 func (t *Transport) IdleConnStrsForTesting() []string { 103 var ret []string 104 t.idleMu.Lock() 105 defer t.idleMu.Unlock() 106 for _, conns := range t.idleConn { 107 for _, pc := range conns { 108 ret = append(ret, pc.conn.LocalAddr().String()+"/"+pc.conn.RemoteAddr().String()) 109 } 110 } 111 sort.Strings(ret) 112 return ret 113 } 114 115 func (t *Transport) IdleConnStrsForTesting_h2() []string { 116 var ret []string 117 noDialPool := t.h2transport.ConnPool.(http2noDialClientConnPool) 118 pool := noDialPool.http2clientConnPool 119 120 pool.mu.Lock() 121 defer pool.mu.Unlock() 122 123 for k, cc := range pool.conns { 124 for range cc { 125 ret = append(ret, k) 126 } 127 } 128 129 sort.Strings(ret) 130 return ret 131 } 132 133 func (t *Transport) IdleConnCountForTesting(cacheKey string) int { 134 t.idleMu.Lock() 135 defer t.idleMu.Unlock() 136 for k, conns := range t.idleConn { 137 if k.String() == cacheKey { 138 return len(conns) 139 } 140 } 141 return 0 142 } 143 144 func (t *Transport) IdleConnChMapSizeForTesting() int { 145 t.idleMu.Lock() 146 defer t.idleMu.Unlock() 147 return len(t.idleConnCh) 148 } 149 150 func (t *Transport) IsIdleForTesting() bool { 151 t.idleMu.Lock() 152 defer t.idleMu.Unlock() 153 return t.wantIdle 154 } 155 156 func (t *Transport) RequestIdleConnChForTesting() { 157 t.getIdleConnCh(connectMethod{nil, "http", "example.com"}) 158 } 159 160 func (t *Transport) PutIdleTestConn() bool { 161 c, _ := net.Pipe() 162 return t.tryPutIdleConn(&persistConn{ 163 t: t, 164 conn: c, // dummy 165 closech: make(chan struct{}), // so it can be closed 166 cacheKey: connectMethodKey{"", "http", "example.com"}, 167 }) == nil 168 } 169 170 // All test hooks must be non-nil so they can be called directly, 171 // but the tests use nil to mean hook disabled. 172 func unnilTestHook(f *func()) { 173 if *f == nil { 174 *f = nop 175 } 176 } 177 178 func hookSetter(dst *func()) func(func()) { 179 return func(fn func()) { 180 unnilTestHook(&fn) 181 *dst = fn 182 } 183 } 184 185 func ExportHttp2ConfigureTransport(t *Transport) error { 186 t2, err := http2configureTransport(t) 187 if err != nil { 188 return err 189 } 190 t.h2transport = t2 191 return nil 192 } 193 194 func (s *Server) ExportAllConnsIdle() bool { 195 s.mu.Lock() 196 defer s.mu.Unlock() 197 for c := range s.activeConn { 198 st, ok := c.curState.Load().(ConnState) 199 if !ok || st != StateIdle { 200 return false 201 } 202 } 203 return true 204 } 205 206 func (r *Request) WithT(t *testing.T) *Request { 207 return r.WithContext(context.WithValue(r.Context(), tLogKey{}, t.Logf)) 208 }