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
8package http
9
10import (
11	"net"
12	"net/url"
13	"sync"
14	"time"
15)
16
17func init() {
18	// We only want to pay for this cost during testing.
19	// When not under test, these values are always nil
20	// and never assigned to.
21	testHookMu = new(sync.Mutex)
22}
23
24func NewLoggingConn(baseName string, c net.Conn) net.Conn {
25	return newLoggingConn(baseName, c)
26}
27
28var ExportAppendTime = appendTime
29
30func (t *Transport) NumPendingRequestsForTesting() int {
31	t.reqMu.Lock()
32	defer t.reqMu.Unlock()
33	return len(t.reqCanceler)
34}
35
36func (t *Transport) IdleConnKeysForTesting() (keys []string) {
37	keys = make([]string, 0)
38	t.idleMu.Lock()
39	defer t.idleMu.Unlock()
40	if t.idleConn == nil {
41		return
42	}
43	for key := range t.idleConn {
44		keys = append(keys, key.String())
45	}
46	return
47}
48
49func (t *Transport) IdleConnCountForTesting(cacheKey string) int {
50	t.idleMu.Lock()
51	defer t.idleMu.Unlock()
52	if t.idleConn == nil {
53		return 0
54	}
55	for k, conns := range t.idleConn {
56		if k.String() == cacheKey {
57			return len(conns)
58		}
59	}
60	return 0
61}
62
63func (t *Transport) IdleConnChMapSizeForTesting() int {
64	t.idleMu.Lock()
65	defer t.idleMu.Unlock()
66	return len(t.idleConnCh)
67}
68
69func (t *Transport) IsIdleForTesting() bool {
70	t.idleMu.Lock()
71	defer t.idleMu.Unlock()
72	return t.wantIdle
73}
74
75func (t *Transport) RequestIdleConnChForTesting() {
76	t.getIdleConnCh(connectMethod{nil, "http", "example.com"})
77}
78
79func (t *Transport) PutIdleTestConn() bool {
80	c, _ := net.Pipe()
81	return t.putIdleConn(&persistConn{
82		t:        t,
83		conn:     c,                   // dummy
84		closech:  make(chan struct{}), // so it can be closed
85		cacheKey: connectMethodKey{"", "http", "example.com"},
86	})
87}
88
89func SetInstallConnClosedHook(f func()) {
90	testHookPersistConnClosedGotRes = f
91}
92
93func SetEnterRoundTripHook(f func()) {
94	testHookEnterRoundTrip = f
95}
96
97func SetReadLoopBeforeNextReadHook(f func()) {
98	testHookMu.Lock()
99	defer testHookMu.Unlock()
100	testHookReadLoopBeforeNextRead = f
101}
102
103func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler {
104	f := func() <-chan time.Time {
105		return ch
106	}
107	return &timeoutHandler{handler, f, ""}
108}
109
110func ResetCachedEnvironment() {
111	httpProxyEnv.reset()
112	httpsProxyEnv.reset()
113	noProxyEnv.reset()
114}
115
116var DefaultUserAgent = defaultUserAgent
117
118func ExportRefererForURL(lastReq, newReq *url.URL) string {
119	return refererForURL(lastReq, newReq)
120}
121
122// SetPendingDialHooks sets the hooks that run before and after handling
123// pending dials.
124func SetPendingDialHooks(before, after func()) {
125	prePendingDial, postPendingDial = before, after
126}
127
128var ExportServerNewConn = (*Server).newConn
129
130var ExportCloseWriteAndWait = (*conn).closeWriteAndWait
131
132var ExportErrRequestCanceled = errRequestCanceled
133