@@ -14,6 +14,7 @@ import (
14
14
"net"
15
15
"net/http"
16
16
"reflect"
17
+ "slices"
17
18
"testing"
18
19
"time"
19
20
@@ -209,6 +210,71 @@ func (tc *testClientConn) wantFrameType(want FrameType) {
209
210
}
210
211
}
211
212
213
+ // wantUnorderedFrames reads frames from the conn until every condition in want has been satisfied.
214
+ //
215
+ // want is a list of func(*SomeFrame) bool.
216
+ // wantUnorderedFrames will call each func with frames of the appropriate type
217
+ // until the func returns true.
218
+ // It calls t.Fatal if an unexpected frame is received (no func has that frame type,
219
+ // or all funcs with that type have returned true), or if the conn runs out of frames
220
+ // with unsatisfied funcs.
221
+ //
222
+ // Example:
223
+ //
224
+ // // Read a SETTINGS frame, and any number of DATA frames for a stream.
225
+ // // The SETTINGS frame may appear anywhere in the sequence.
226
+ // // The last DATA frame must indicate the end of the stream.
227
+ // tc.wantUnorderedFrames(
228
+ // func(f *SettingsFrame) bool {
229
+ // return true
230
+ // },
231
+ // func(f *DataFrame) bool {
232
+ // return f.StreamEnded()
233
+ // },
234
+ // )
235
+ func (tc * testClientConn ) wantUnorderedFrames (want ... any ) {
236
+ tc .t .Helper ()
237
+ want = slices .Clone (want )
238
+ seen := 0
239
+ frame:
240
+ for seen < len (want ) && ! tc .t .Failed () {
241
+ fr := tc .readFrame ()
242
+ if fr == nil {
243
+ break
244
+ }
245
+ for i , f := range want {
246
+ if f == nil {
247
+ continue
248
+ }
249
+ typ := reflect .TypeOf (f )
250
+ if typ .Kind () != reflect .Func ||
251
+ typ .NumIn () != 1 ||
252
+ typ .NumOut () != 1 ||
253
+ typ .Out (0 ) != reflect .TypeOf (true ) {
254
+ tc .t .Fatalf ("expected func(*SomeFrame) bool, got %T" , f )
255
+ }
256
+ if typ .In (0 ) == reflect .TypeOf (fr ) {
257
+ out := reflect .ValueOf (f ).Call ([]reflect.Value {reflect .ValueOf (fr )})
258
+ if out [0 ].Bool () {
259
+ want [i ] = nil
260
+ seen ++
261
+ }
262
+ continue frame
263
+ }
264
+ }
265
+ tc .t .Errorf ("got unexpected frame type %T" , fr )
266
+ }
267
+ if seen < len (want ) {
268
+ for _ , f := range want {
269
+ if f == nil {
270
+ continue
271
+ }
272
+ tc .t .Errorf ("did not see expected frame: %v" , reflect .TypeOf (f ).In (0 ))
273
+ }
274
+ tc .t .Fatalf ("did not see %v expected frame types" , len (want )- seen )
275
+ }
276
+ }
277
+
212
278
type wantHeader struct {
213
279
streamID uint32
214
280
endStream bool
@@ -401,6 +467,14 @@ func (tc *testClientConn) writeData(streamID uint32, endStream bool, data []byte
401
467
tc .sync ()
402
468
}
403
469
470
+ func (tc * testClientConn ) writeDataPadded (streamID uint32 , endStream bool , data , pad []byte ) {
471
+ tc .t .Helper ()
472
+ if err := tc .fr .WriteDataPadded (streamID , endStream , data , pad ); err != nil {
473
+ tc .t .Fatal (err )
474
+ }
475
+ tc .sync ()
476
+ }
477
+
404
478
// makeHeaderBlockFragment encodes headers in a form suitable for inclusion
405
479
// in a HEADERS or CONTINUATION frame.
406
480
//
0 commit comments