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