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  }