...
Run Format

Source file src/net/http/export_test.go

Documentation: net/http

     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}
   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"})
   182  }
   183  
   184  func (t *Transport) PutIdleTestConn(scheme, addr string) bool {
   185  	c, _ := net.Pipe()
   186  	key := connectMethodKey{"", scheme, addr}
   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  

View as plain text