blob: 032b2bc6cd1df4b21abb25e0cc9f3825dfd28e4e [file] [log] [blame]
Damien Neil120fc902023-03-22 14:42:28 -07001// Copyright 2023 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
5package http2
6
7import (
8 "reflect"
9 "testing"
10)
11
12func TestRoundRobinScheduler(t *testing.T) {
13 const maxFrameSize = 16
14 sc := &serverConn{maxFrameSize: maxFrameSize}
15 ws := newRoundRobinWriteScheduler()
16 streams := make([]*stream, 4)
17 for i := range streams {
18 streamID := uint32(i) + 1
19 streams[i] = &stream{
20 id: streamID,
21 sc: sc,
22 }
23 streams[i].flow.add(1 << 20) // arbitrary large value
24 ws.OpenStream(streamID, OpenStreamOptions{})
25 wr := FrameWriteRequest{
26 write: &writeData{
27 streamID: streamID,
28 p: make([]byte, maxFrameSize*(i+1)),
29 endStream: false,
30 },
31 stream: streams[i],
32 }
33 ws.Push(wr)
34 }
35 const controlFrames = 2
36 for i := 0; i < controlFrames; i++ {
37 ws.Push(makeWriteNonStreamRequest())
38 }
39
40 // We should get the control frames first.
41 for i := 0; i < controlFrames; i++ {
42 wr, ok := ws.Pop()
43 if !ok || wr.StreamID() != 0 {
44 t.Fatalf("wr.Pop() = stream %v, %v; want 0, true", wr.StreamID(), ok)
45 }
46 }
47
48 // Each stream should write maxFrameSize bytes until it runs out of data.
49 // Stream 1 has one frame of data, 2 has two frames, etc.
50 want := []uint32{1, 2, 3, 4, 2, 3, 4, 3, 4, 4}
51 var got []uint32
52 for {
53 wr, ok := ws.Pop()
54 if !ok {
55 break
56 }
57 if wr.DataSize() != maxFrameSize {
58 t.Fatalf("wr.Pop() = %v data bytes, want %v", wr.DataSize(), maxFrameSize)
59 }
60 got = append(got, wr.StreamID())
61 }
62 if !reflect.DeepEqual(got, want) {
63 t.Fatalf("popped streams %v, want %v", got, want)
64 }
65}