1package quic
2
3import (
4	"github.com/lucas-clemente/quic-go/internal/mocks"
5	"github.com/lucas-clemente/quic-go/internal/protocol"
6	"github.com/lucas-clemente/quic-go/internal/wire"
7
8	. "github.com/onsi/ginkgo"
9	. "github.com/onsi/gomega"
10)
11
12var _ = Describe("Window Update Queue", func() {
13	var (
14		q            *windowUpdateQueue
15		streamGetter *MockStreamGetter
16		connFC       *mocks.MockConnectionFlowController
17		queuedFrames []wire.Frame
18	)
19
20	BeforeEach(func() {
21		streamGetter = NewMockStreamGetter(mockCtrl)
22		connFC = mocks.NewMockConnectionFlowController(mockCtrl)
23		queuedFrames = queuedFrames[:0]
24		q = newWindowUpdateQueue(streamGetter, connFC, func(f wire.Frame) {
25			queuedFrames = append(queuedFrames, f)
26		})
27	})
28
29	It("adds stream offsets and gets MAX_STREAM_DATA frames", func() {
30		stream1 := NewMockStreamI(mockCtrl)
31		stream1.EXPECT().getWindowUpdate().Return(protocol.ByteCount(10))
32		stream3 := NewMockStreamI(mockCtrl)
33		stream3.EXPECT().getWindowUpdate().Return(protocol.ByteCount(30))
34		streamGetter.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(3)).Return(stream3, nil)
35		streamGetter.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(1)).Return(stream1, nil)
36		q.AddStream(3)
37		q.AddStream(1)
38		q.QueueAll()
39		Expect(queuedFrames).To(ContainElement(&wire.MaxStreamDataFrame{StreamID: 1, MaximumStreamData: 10}))
40		Expect(queuedFrames).To(ContainElement(&wire.MaxStreamDataFrame{StreamID: 3, MaximumStreamData: 30}))
41	})
42
43	It("deletes the entry after getting the MAX_STREAM_DATA frame", func() {
44		stream10 := NewMockStreamI(mockCtrl)
45		stream10.EXPECT().getWindowUpdate().Return(protocol.ByteCount(100))
46		streamGetter.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(10)).Return(stream10, nil)
47		q.AddStream(10)
48		q.QueueAll()
49		Expect(queuedFrames).To(HaveLen(1))
50		q.QueueAll()
51		Expect(queuedFrames).To(HaveLen(1))
52	})
53
54	It("doesn't queue a MAX_STREAM_DATA for a closed stream", func() {
55		q.AddStream(12)
56		streamGetter.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(12)).Return(nil, nil)
57		q.QueueAll()
58		Expect(queuedFrames).To(BeEmpty())
59	})
60
61	It("removes closed streams from the queue", func() {
62		q.AddStream(12)
63		streamGetter.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(12)).Return(nil, nil)
64		q.QueueAll()
65		Expect(queuedFrames).To(BeEmpty())
66		// don't EXPECT any further calls to GetOrOpenReceiveStream
67		q.QueueAll()
68		Expect(queuedFrames).To(BeEmpty())
69	})
70
71	It("doesn't queue a MAX_STREAM_DATA if the flow controller returns an offset of 0", func() {
72		stream5 := NewMockStreamI(mockCtrl)
73		stream5.EXPECT().getWindowUpdate().Return(protocol.ByteCount(0))
74		q.AddStream(5)
75		streamGetter.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(5)).Return(stream5, nil)
76		q.QueueAll()
77		Expect(queuedFrames).To(BeEmpty())
78	})
79
80	It("removes streams for which the flow controller returns an offset of 0 from the queue", func() {
81		stream5 := NewMockStreamI(mockCtrl)
82		stream5.EXPECT().getWindowUpdate().Return(protocol.ByteCount(0))
83		q.AddStream(5)
84		streamGetter.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(5)).Return(stream5, nil)
85		q.QueueAll()
86		Expect(queuedFrames).To(BeEmpty())
87		// don't EXPECT any further calls to GetOrOpenReveiveStream and to getWindowUpdate
88		q.QueueAll()
89		Expect(queuedFrames).To(BeEmpty())
90	})
91
92	It("queues MAX_DATA frames", func() {
93		connFC.EXPECT().GetWindowUpdate().Return(protocol.ByteCount(0x1337))
94		q.AddConnection()
95		q.QueueAll()
96		Expect(queuedFrames).To(Equal([]wire.Frame{
97			&wire.MaxDataFrame{MaximumData: 0x1337},
98		}))
99	})
100
101	It("deduplicates", func() {
102		stream10 := NewMockStreamI(mockCtrl)
103		stream10.EXPECT().getWindowUpdate().Return(protocol.ByteCount(200))
104		streamGetter.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(10)).Return(stream10, nil)
105		q.AddStream(10)
106		q.AddStream(10)
107		q.QueueAll()
108		Expect(queuedFrames).To(Equal([]wire.Frame{
109			&wire.MaxStreamDataFrame{StreamID: 10, MaximumStreamData: 200},
110		}))
111	})
112})
113