@@ -13,10 +13,8 @@ import (
13
13
"fmt"
14
14
"io"
15
15
"net/http"
16
- "os"
17
16
"reflect"
18
17
"runtime"
19
- "slices"
20
18
"sync/atomic"
21
19
"testing"
22
20
"time"
@@ -62,6 +60,7 @@ func TestTestClientConn(t *testing.T) {
62
60
streamID : rt .streamID (),
63
61
endStream : true ,
64
62
size : 10 ,
63
+ multiple : true ,
65
64
})
66
65
67
66
// tc.writeHeaders sends a HEADERS frame back to the client.
@@ -97,6 +96,7 @@ type testClientConn struct {
97
96
fr * Framer
98
97
cc * ClientConn
99
98
group * synctestGroup
99
+ testConnFramer
100
100
101
101
encbuf bytes.Buffer
102
102
enc * hpack.Encoder
@@ -115,6 +115,7 @@ func newTestClientConnFromClientConn(t *testing.T, cc *ClientConn) *testClientCo
115
115
}
116
116
cli , srv := synctestNetPipe (tc .group )
117
117
srv .SetReadDeadline (tc .group .Now ())
118
+ srv .autoWait = true
118
119
tc .netconn = srv
119
120
tc .enc = hpack .NewEncoder (& tc .encbuf )
120
121
@@ -123,8 +124,12 @@ func newTestClientConnFromClientConn(t *testing.T, cc *ClientConn) *testClientCo
123
124
// cli is the ClientConn's side, srv is the side controlled by the test.
124
125
cc .tconn = cli
125
126
tc .fr = NewFramer (srv , srv )
127
+ tc .testConnFramer = testConnFramer {
128
+ t : t ,
129
+ fr : tc .fr ,
130
+ dec : hpack .NewDecoder (initialHeaderTableSize , nil ),
131
+ }
126
132
127
- tc .fr .ReadMetaHeaders = hpack .NewDecoder (initialHeaderTableSize , nil )
128
133
tc .fr .SetMaxReadFrameSize (10 << 20 )
129
134
t .Cleanup (func () {
130
135
tc .closeWrite ()
@@ -174,169 +179,15 @@ func (tc *testClientConn) hasFrame() bool {
174
179
return len (tc .netconn .Peek ()) > 0
175
180
}
176
181
182
+ // isClosed reports whether the peer has closed the connection.
177
183
func (tc * testClientConn ) isClosed () bool {
178
184
return tc .netconn .IsClosedByPeer ()
179
185
}
180
186
181
- // readFrame reads the next frame from the conn.
182
- func (tc * testClientConn ) readFrame () Frame {
183
- tc .t .Helper ()
184
- tc .sync ()
185
- fr , err := tc .fr .ReadFrame ()
186
- if err == io .EOF || err == os .ErrDeadlineExceeded {
187
- return nil
188
- }
189
- if err != nil {
190
- tc .t .Fatalf ("ReadFrame: %v" , err )
191
- }
192
- return fr
193
- }
194
-
195
- // testClientConnReadFrame reads a frame of a specific type from the conn.
196
- func testClientConnReadFrame [T any ](tc * testClientConn ) T {
197
- tc .t .Helper ()
198
- var v T
199
- fr := tc .readFrame ()
200
- if fr == nil {
201
- tc .t .Fatalf ("got no frame, want frame %T" , v )
202
- }
203
- v , ok := fr .(T )
204
- if ! ok {
205
- tc .t .Fatalf ("got frame %T, want %T" , fr , v )
206
- }
207
- return v
208
- }
209
-
210
- // wantFrameType reads the next frame from the conn.
211
- // It produces an error if the frame type is not the expected value.
212
- func (tc * testClientConn ) wantFrameType (want FrameType ) {
213
- tc .t .Helper ()
214
- fr := tc .readFrame ()
215
- if fr == nil {
216
- tc .t .Fatalf ("got no frame, want frame %v" , want )
217
- }
218
- if got := fr .Header ().Type ; got != want {
219
- tc .t .Fatalf ("got frame %v, want %v" , got , want )
220
- }
221
- }
222
-
223
- // wantUnorderedFrames reads frames from the conn until every condition in want has been satisfied.
224
- //
225
- // want is a list of func(*SomeFrame) bool.
226
- // wantUnorderedFrames will call each func with frames of the appropriate type
227
- // until the func returns true.
228
- // It calls t.Fatal if an unexpected frame is received (no func has that frame type,
229
- // or all funcs with that type have returned true), or if the conn runs out of frames
230
- // with unsatisfied funcs.
231
- //
232
- // Example:
233
- //
234
- // // Read a SETTINGS frame, and any number of DATA frames for a stream.
235
- // // The SETTINGS frame may appear anywhere in the sequence.
236
- // // The last DATA frame must indicate the end of the stream.
237
- // tc.wantUnorderedFrames(
238
- // func(f *SettingsFrame) bool {
239
- // return true
240
- // },
241
- // func(f *DataFrame) bool {
242
- // return f.StreamEnded()
243
- // },
244
- // )
245
- func (tc * testClientConn ) wantUnorderedFrames (want ... any ) {
246
- tc .t .Helper ()
247
- want = slices .Clone (want )
248
- seen := 0
249
- frame:
250
- for seen < len (want ) && ! tc .t .Failed () {
251
- fr := tc .readFrame ()
252
- if fr == nil {
253
- break
254
- }
255
- for i , f := range want {
256
- if f == nil {
257
- continue
258
- }
259
- typ := reflect .TypeOf (f )
260
- if typ .Kind () != reflect .Func ||
261
- typ .NumIn () != 1 ||
262
- typ .NumOut () != 1 ||
263
- typ .Out (0 ) != reflect .TypeOf (true ) {
264
- tc .t .Fatalf ("expected func(*SomeFrame) bool, got %T" , f )
265
- }
266
- if typ .In (0 ) == reflect .TypeOf (fr ) {
267
- out := reflect .ValueOf (f ).Call ([]reflect.Value {reflect .ValueOf (fr )})
268
- if out [0 ].Bool () {
269
- want [i ] = nil
270
- seen ++
271
- }
272
- continue frame
273
- }
274
- }
275
- tc .t .Errorf ("got unexpected frame type %T" , fr )
276
- }
277
- if seen < len (want ) {
278
- for _ , f := range want {
279
- if f == nil {
280
- continue
281
- }
282
- tc .t .Errorf ("did not see expected frame: %v" , reflect .TypeOf (f ).In (0 ))
283
- }
284
- tc .t .Fatalf ("did not see %v expected frame types" , len (want )- seen )
285
- }
286
- }
287
-
288
- type wantHeader struct {
289
- streamID uint32
290
- endStream bool
291
- header http.Header
292
- }
293
-
294
- // wantHeaders reads a HEADERS frame and potential CONTINUATION frames,
295
- // and asserts that they contain the expected headers.
296
- func (tc * testClientConn ) wantHeaders (want wantHeader ) {
297
- tc .t .Helper ()
298
- got := testClientConnReadFrame [* MetaHeadersFrame ](tc )
299
- if got , want := got .StreamID , want .streamID ; got != want {
300
- tc .t .Fatalf ("got stream ID %v, want %v" , got , want )
301
- }
302
- if got , want := got .StreamEnded (), want .endStream ; got != want {
303
- tc .t .Fatalf ("got stream ended %v, want %v" , got , want )
304
- }
305
- gotHeader := make (http.Header )
306
- for _ , f := range got .Fields {
307
- gotHeader [f .Name ] = append (gotHeader [f .Name ], f .Value )
308
- }
309
- for k , v := range want .header {
310
- if ! reflect .DeepEqual (v , gotHeader [k ]) {
311
- tc .t .Fatalf ("got header %q = %q; want %q" , k , v , gotHeader [k ])
312
- }
313
- }
314
- }
315
-
316
- type wantData struct {
317
- streamID uint32
318
- endStream bool
319
- size int
320
- }
321
-
322
- // wantData reads zero or more DATA frames, and asserts that they match the expectation.
323
- func (tc * testClientConn ) wantData (want wantData ) {
324
- tc .t .Helper ()
325
- gotSize := 0
326
- gotEndStream := false
327
- for tc .hasFrame () && ! gotEndStream {
328
- data := testClientConnReadFrame [* DataFrame ](tc )
329
- gotSize += len (data .Data ())
330
- if data .StreamEnded () {
331
- gotEndStream = true
332
- }
333
- }
334
- if gotSize != want .size {
335
- tc .t .Fatalf ("got %v bytes of DATA frames, want %v" , gotSize , want .size )
336
- }
337
- if gotEndStream != want .endStream {
338
- tc .t .Fatalf ("after %v bytes of DATA frames, got END_STREAM=%v; want %v" , gotSize , gotEndStream , want .endStream )
339
- }
187
+ // closeWrite causes the net.Conn used by the ClientConn to return a error
188
+ // from Read calls.
189
+ func (tc * testClientConn ) closeWrite () {
190
+ tc .netconn .Close ()
340
191
}
341
192
342
193
// testRequestBody is a Request.Body for use in tests.
@@ -468,38 +319,6 @@ func (tc *testClientConn) greet(settings ...Setting) {
468
319
tc .wantFrameType (FrameSettings ) // acknowledgement
469
320
}
470
321
471
- func (tc * testClientConn ) writeSettings (settings ... Setting ) {
472
- tc .t .Helper ()
473
- if err := tc .fr .WriteSettings (settings ... ); err != nil {
474
- tc .t .Fatal (err )
475
- }
476
- tc .sync ()
477
- }
478
-
479
- func (tc * testClientConn ) writeSettingsAck () {
480
- tc .t .Helper ()
481
- if err := tc .fr .WriteSettingsAck (); err != nil {
482
- tc .t .Fatal (err )
483
- }
484
- tc .sync ()
485
- }
486
-
487
- func (tc * testClientConn ) writeData (streamID uint32 , endStream bool , data []byte ) {
488
- tc .t .Helper ()
489
- if err := tc .fr .WriteData (streamID , endStream , data ); err != nil {
490
- tc .t .Fatal (err )
491
- }
492
- tc .sync ()
493
- }
494
-
495
- func (tc * testClientConn ) writeDataPadded (streamID uint32 , endStream bool , data , pad []byte ) {
496
- tc .t .Helper ()
497
- if err := tc .fr .WriteDataPadded (streamID , endStream , data , pad ); err != nil {
498
- tc .t .Fatal (err )
499
- }
500
- tc .sync ()
501
- }
502
-
503
322
// makeHeaderBlockFragment encodes headers in a form suitable for inclusion
504
323
// in a HEADERS or CONTINUATION frame.
505
324
//
@@ -515,87 +334,6 @@ func (tc *testClientConn) makeHeaderBlockFragment(s ...string) []byte {
515
334
return tc .encbuf .Bytes ()
516
335
}
517
336
518
- func (tc * testClientConn ) writeHeaders (p HeadersFrameParam ) {
519
- tc .t .Helper ()
520
- if err := tc .fr .WriteHeaders (p ); err != nil {
521
- tc .t .Fatal (err )
522
- }
523
- tc .sync ()
524
- }
525
-
526
- // writeHeadersMode writes header frames, as modified by mode:
527
- //
528
- // - noHeader: Don't write the header.
529
- // - oneHeader: Write a single HEADERS frame.
530
- // - splitHeader: Write a HEADERS frame and CONTINUATION frame.
531
- func (tc * testClientConn ) writeHeadersMode (mode headerType , p HeadersFrameParam ) {
532
- tc .t .Helper ()
533
- switch mode {
534
- case noHeader :
535
- case oneHeader :
536
- tc .writeHeaders (p )
537
- case splitHeader :
538
- if len (p .BlockFragment ) < 2 {
539
- panic ("too small" )
540
- }
541
- contData := p .BlockFragment [1 :]
542
- contEnd := p .EndHeaders
543
- p .BlockFragment = p .BlockFragment [:1 ]
544
- p .EndHeaders = false
545
- tc .writeHeaders (p )
546
- tc .writeContinuation (p .StreamID , contEnd , contData )
547
- default :
548
- panic ("bogus mode" )
549
- }
550
- }
551
-
552
- func (tc * testClientConn ) writeContinuation (streamID uint32 , endHeaders bool , headerBlockFragment []byte ) {
553
- tc .t .Helper ()
554
- if err := tc .fr .WriteContinuation (streamID , endHeaders , headerBlockFragment ); err != nil {
555
- tc .t .Fatal (err )
556
- }
557
- tc .sync ()
558
- }
559
-
560
- func (tc * testClientConn ) writeRSTStream (streamID uint32 , code ErrCode ) {
561
- tc .t .Helper ()
562
- if err := tc .fr .WriteRSTStream (streamID , code ); err != nil {
563
- tc .t .Fatal (err )
564
- }
565
- tc .sync ()
566
- }
567
-
568
- func (tc * testClientConn ) writePing (ack bool , data [8 ]byte ) {
569
- tc .t .Helper ()
570
- if err := tc .fr .WritePing (ack , data ); err != nil {
571
- tc .t .Fatal (err )
572
- }
573
- tc .sync ()
574
- }
575
-
576
- func (tc * testClientConn ) writeGoAway (maxStreamID uint32 , code ErrCode , debugData []byte ) {
577
- tc .t .Helper ()
578
- if err := tc .fr .WriteGoAway (maxStreamID , code , debugData ); err != nil {
579
- tc .t .Fatal (err )
580
- }
581
- tc .sync ()
582
- }
583
-
584
- func (tc * testClientConn ) writeWindowUpdate (streamID , incr uint32 ) {
585
- tc .t .Helper ()
586
- if err := tc .fr .WriteWindowUpdate (streamID , incr ); err != nil {
587
- tc .t .Fatal (err )
588
- }
589
- tc .sync ()
590
- }
591
-
592
- // closeWrite causes the net.Conn used by the ClientConn to return a error
593
- // from Read calls.
594
- func (tc * testClientConn ) closeWrite () {
595
- tc .netconn .Close ()
596
- tc .sync ()
597
- }
598
-
599
337
// inflowWindow returns the amount of inbound flow control available for a stream,
600
338
// or for the connection if streamID is 0.
601
339
func (tc * testClientConn ) inflowWindow (streamID uint32 ) int32 {
0 commit comments