github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/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  	ctx, cancel := context.WithCancel(context.Background())
    67  	go func() {
    68  		<-ch
    69  		cancel()
    70  	}()
    71  	return &timeoutHandler{
    72  		handler:     handler,
    73  		testContext: ctx,
    74  		// (no body)
    75  	}
    76  }
    77  
    78  func ResetCachedEnvironment() {
    79  	httpProxyEnv.reset()
    80  	httpsProxyEnv.reset()
    81  	noProxyEnv.reset()
    82  }
    83  
    84  func (t *Transport) NumPendingRequestsForTesting() int {
    85  	t.reqMu.Lock()
    86  	defer t.reqMu.Unlock()
    87  	return len(t.reqCanceler)
    88  }
    89  
    90  func (t *Transport) IdleConnKeysForTesting() (keys []string) {
    91  	keys = make([]string, 0)
    92  	t.idleMu.Lock()
    93  	defer t.idleMu.Unlock()
    94  	for key := range t.idleConn {
    95  		keys = append(keys, key.String())
    96  	}
    97  	sort.Strings(keys)
    98  	return
    99  }
   100  
   101  func (t *Transport) IdleConnKeyCountForTesting() int {
   102  	t.idleMu.Lock()
   103  	defer t.idleMu.Unlock()
   104  	return len(t.idleConn)
   105  }
   106  
   107  func (t *Transport) IdleConnStrsForTesting() []string {
   108  	var ret []string
   109  	t.idleMu.Lock()
   110  	defer t.idleMu.Unlock()
   111  	for _, conns := range t.idleConn {
   112  		for _, pc := range conns {
   113  			ret = append(ret, pc.conn.LocalAddr().String()+"/"+pc.conn.RemoteAddr().String())
   114  		}
   115  	}
   116  	sort.Strings(ret)
   117  	return ret
   118  }
   119  
   120  func (t *Transport) IdleConnStrsForTesting_h2() []string {
   121  	var ret []string
   122  	noDialPool := t.h2transport.ConnPool.(http2noDialClientConnPool)
   123  	pool := noDialPool.http2clientConnPool
   124  
   125  	pool.mu.Lock()
   126  	defer pool.mu.Unlock()
   127  
   128  	for k, cc := range pool.conns {
   129  		for range cc {
   130  			ret = append(ret, k)
   131  		}
   132  	}
   133  
   134  	sort.Strings(ret)
   135  	return ret
   136  }
   137  
   138  func (t *Transport) IdleConnCountForTesting(cacheKey string) int {
   139  	t.idleMu.Lock()
   140  	defer t.idleMu.Unlock()
   141  	for k, conns := range t.idleConn {
   142  		if k.String() == cacheKey {
   143  			return len(conns)
   144  		}
   145  	}
   146  	return 0
   147  }
   148  
   149  func (t *Transport) IdleConnChMapSizeForTesting() int {
   150  	t.idleMu.Lock()
   151  	defer t.idleMu.Unlock()
   152  	return len(t.idleConnCh)
   153  }
   154  
   155  func (t *Transport) IsIdleForTesting() bool {
   156  	t.idleMu.Lock()
   157  	defer t.idleMu.Unlock()
   158  	return t.wantIdle
   159  }
   160  
   161  func (t *Transport) RequestIdleConnChForTesting() {
   162  	t.getIdleConnCh(connectMethod{nil, "http", "example.com"})
   163  }
   164  
   165  func (t *Transport) PutIdleTestConn() bool {
   166  	c, _ := net.Pipe()
   167  	return t.tryPutIdleConn(&persistConn{
   168  		t:        t,
   169  		conn:     c,                   // dummy
   170  		closech:  make(chan struct{}), // so it can be closed
   171  		cacheKey: connectMethodKey{"", "http", "example.com"},
   172  	}) == nil
   173  }
   174  
   175  // All test hooks must be non-nil so they can be called directly,
   176  // but the tests use nil to mean hook disabled.
   177  func unnilTestHook(f *func()) {
   178  	if *f == nil {
   179  		*f = nop
   180  	}
   181  }
   182  
   183  func hookSetter(dst *func()) func(func()) {
   184  	return func(fn func()) {
   185  		unnilTestHook(&fn)
   186  		*dst = fn
   187  	}
   188  }
   189  
   190  func ExportHttp2ConfigureTransport(t *Transport) error {
   191  	t2, err := http2configureTransport(t)
   192  	if err != nil {
   193  		return err
   194  	}
   195  	t.h2transport = t2
   196  	return nil
   197  }
   198  
   199  func (s *Server) ExportAllConnsIdle() bool {
   200  	s.mu.Lock()
   201  	defer s.mu.Unlock()
   202  	for c := range s.activeConn {
   203  		st, ok := c.curState.Load().(ConnState)
   204  		if !ok || st != StateIdle {
   205  			return false
   206  		}
   207  	}
   208  	return true
   209  }
   210  
   211  func (r *Request) WithT(t *testing.T) *Request {
   212  	return r.WithContext(context.WithValue(r.Context(), tLogKey{}, t.Logf))
   213  }