1
2
3
4
5 package http2
6
7 import (
8 "context"
9 "fmt"
10 "net"
11 "net/textproto"
12 "sync"
13 "testing"
14 "time"
15
16 "net/http/internal/httpcommon"
17
18 "golang.org/x/net/http2/hpack"
19 )
20
21 func init() {
22 inTests = true
23 }
24
25 const (
26 DefaultMaxReadFrameSize = defaultMaxReadFrameSize
27 DefaultMaxStreams = defaultMaxStreams
28 InflowMinRefresh = inflowMinRefresh
29 InitialHeaderTableSize = initialHeaderTableSize
30 InitialMaxConcurrentStreams = initialMaxConcurrentStreams
31 InitialWindowSize = initialWindowSize
32 MaxFrameSize = maxFrameSize
33 MaxQueuedControlFrames = maxQueuedControlFrames
34 MinMaxFrameSize = minMaxFrameSize
35 )
36
37 type (
38 ServerConn = serverConn
39 Stream = stream
40 StreamState = streamState
41
42 PseudoHeaderError = pseudoHeaderError
43 HeaderFieldNameError = headerFieldNameError
44 HeaderFieldValueError = headerFieldValueError
45 )
46
47 const (
48 StateIdle = stateIdle
49 StateOpen = stateOpen
50 StateHalfClosedLocal = stateHalfClosedLocal
51 StateHalfClosedRemote = stateHalfClosedRemote
52 StateClosed = stateClosed
53 )
54
55 var (
56 ErrClientConnForceClosed = errClientConnForceClosed
57 ErrClientConnNotEstablished = errClientConnNotEstablished
58 ErrClientConnUnusable = errClientConnUnusable
59 ErrExtendedConnectNotSupported = errExtendedConnectNotSupported
60 ErrReqBodyTooLong = errReqBodyTooLong
61 ErrRequestHeaderListSize = errRequestHeaderListSize
62 ErrResponseHeaderListSize = errResponseHeaderListSize
63 )
64
65 func (s *Server) TestServeConn(c net.Conn, opts *ServeConnOpts, newf func(*serverConn)) {
66 s.serveConn(c, opts, newf)
67 }
68
69 func (sc *serverConn) TestFlowControlConsumed() (consumed int32) {
70 conf := configFromServer(sc.hs, sc.srv)
71 donec := make(chan struct{})
72 sc.sendServeMsg(func(sc *serverConn) {
73 defer close(donec)
74 initial := int32(conf.MaxReceiveBufferPerConnection)
75 avail := sc.inflow.avail + sc.inflow.unsent
76 consumed = initial - avail
77 })
78 <-donec
79 return consumed
80 }
81
82 func (sc *serverConn) TestStreamExists(id uint32) bool {
83 ch := make(chan bool, 1)
84 sc.serveMsgCh <- func(int) {
85 ch <- (sc.streams[id] != nil)
86 }
87 return <-ch
88 }
89
90 func (sc *serverConn) TestStreamState(id uint32) streamState {
91 ch := make(chan streamState, 1)
92 sc.serveMsgCh <- func(int) {
93 state, _ := sc.state(id)
94 ch <- state
95 }
96 return <-ch
97 }
98
99 func (sc *serverConn) StartGracefulShutdown() { sc.startGracefulShutdown() }
100
101 func (sc *serverConn) TestHPACKEncoder() *hpack.Encoder {
102 return sc.hpackEncoder
103 }
104
105 func (sc *serverConn) TestFramerMaxHeaderStringLen() int {
106 return sc.framer.maxHeaderStringLen()
107 }
108
109 func (t *Transport) DialClientConn(ctx context.Context, addr string, singleUse bool) (*ClientConn, error) {
110 return t.dialClientConn(ctx, addr, singleUse)
111 }
112
113 func (t *Transport) TestNewClientConn(c net.Conn, singleUse bool, internalStateHook func()) (*ClientConn, error) {
114 return t.newClientConn(c, singleUse, internalStateHook)
115 }
116
117 func (t *Transport) TestSetNewClientConnHook(f func(*ClientConn)) {
118 t.transportTestHooks = &transportTestHooks{
119 newclientconn: f,
120 }
121 }
122
123 func (cc *ClientConn) TestNetConn() net.Conn { return cc.tconn }
124 func (cc *ClientConn) TestSetNetConn(c net.Conn) { cc.tconn = c }
125
126 func (cc *ClientConn) TestRoundTrip(req *ClientRequest, f func(stremaID uint32)) (*ClientResponse, error) {
127 return cc.roundTrip(req, func(cs *clientStream) {
128 f(cs.ID)
129 })
130 }
131
132 func (cc *ClientConn) TestHPACKEncoder() *hpack.Encoder {
133 return cc.henc
134 }
135
136 func (cc *ClientConn) TestPeerMaxHeaderTableSize() uint32 {
137 cc.mu.Lock()
138 defer cc.mu.Unlock()
139 return cc.peerMaxHeaderTableSize
140 }
141
142 func (cc *ClientConn) TestInflowWindow(streamID uint32) (int32, error) {
143 cc.mu.Lock()
144 defer cc.mu.Unlock()
145 if streamID == 0 {
146 return cc.inflow.avail + cc.inflow.unsent, nil
147 }
148 cs := cc.streams[streamID]
149 if cs == nil {
150 return -1, fmt.Errorf("no stream with id %v", streamID)
151 }
152 return cs.inflow.avail + cs.inflow.unsent, nil
153 }
154
155 func (fr *Framer) TestSetDebugReadLoggerf(f func(string, ...any)) {
156 fr.logReads = true
157 fr.debugReadLoggerf = f
158 }
159
160 func (fr *Framer) TestSetDebugWriteLoggerf(f func(string, ...any)) {
161 fr.logWrites = true
162 fr.debugWriteLoggerf = f
163 }
164
165 func SummarizeFrame(f Frame) string {
166 return summarizeFrame(f)
167 }
168
169 func init() {
170 testHookOnPanicMu = new(sync.Mutex)
171 }
172
173 func SetTestHookOnPanic(t testing.TB, f func(sc *serverConn, panicVal interface{}) (rePanic bool)) {
174 testHookOnPanicMu.Lock()
175 defer testHookOnPanicMu.Unlock()
176 old := testHookOnPanic
177 testHookOnPanic = f
178 t.Cleanup(func() {
179 testHookOnPanicMu.Lock()
180 defer testHookOnPanicMu.Unlock()
181 testHookOnPanic = old
182 })
183 }
184
185 func SetTestHookGot1xx(t testing.TB, f func(int, textproto.MIMEHeader) error) {
186 SetForTest(t, &got1xxFuncForTests, f)
187 }
188
189 func SetDisableExtendedConnectProtocol(t testing.TB, v bool) {
190 SetForTest(t, &disableExtendedConnectProtocol, v)
191 }
192
193 func LogFrameReads() bool { return logFrameReads }
194 func LogFrameWrites() bool { return logFrameWrites }
195
196 const GoAwayTimeout = 25 * time.Millisecond
197
198 func init() {
199 goAwayTimeout = GoAwayTimeout
200 }
201
202 func EncodeHeaderRaw(t testing.TB, headers ...string) []byte {
203 return encodeHeaderRaw(t, headers...)
204 }
205
206 func NewPriorityWriteSchedulerRFC7540(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
207 return newPriorityWriteSchedulerRFC7540(cfg)
208 }
209
210 func NewPriorityWriteSchedulerRFC9218() WriteScheduler {
211 return newPriorityWriteSchedulerRFC9218()
212 }
213
214 func NewRoundRobinWriteScheduler() WriteScheduler {
215 return newRoundRobinWriteScheduler()
216 }
217
218 func DisableGoroutineTracking(t testing.TB) {
219 disableDebugGoroutines.Store(true)
220 t.Cleanup(func() {
221 disableDebugGoroutines.Store(false)
222 })
223 }
224
225 func InvalidHTTP1LookingFrameHeader() FrameHeader {
226 return invalidHTTP1LookingFrameHeader()
227 }
228
229 func NewNoDialClientConnPool() ClientConnPool {
230 return noDialClientConnPool{new(clientConnPool)}
231 }
232
233 func EncodeRequestHeaders(req *ClientRequest, addGzipHeader bool, peerMaxHeaderListSize uint64, headerf func(name, value string)) (httpcommon.EncodeHeadersResult, error) {
234 return encodeRequestHeaders(req, addGzipHeader, peerMaxHeaderListSize, headerf)
235 }
236
View as plain text