1
2
3
4
5
6
7 package quic
8
9 import (
10 "testing"
11 "time"
12 )
13
14 func TestPacerStartup(t *testing.T) {
15 p := &pacerTest{
16 cwnd: 10000,
17 rtt: 100 * time.Millisecond,
18 timerGranularity: 1 * time.Millisecond,
19 }
20 p.init(t)
21 t.Logf("# initial burst permits sending ten packets")
22 for i := 0; i < 10; i++ {
23 p.sendPacket(1000)
24 }
25
26 t.Logf("# empty bucket allows for one more packet")
27 p.sendPacket(1000)
28
29 t.Logf("# sending 1000 byte packets with 8ms interval:")
30 t.Logf("# (smoothed_rtt * packet_size / congestion_window) / 1.25")
31 t.Logf("# (100ms * 1000 / 10000) / 1.25 = 8ms")
32 p.wantSendDelay(8 * time.Millisecond)
33 p.advance(8 * time.Millisecond)
34 p.sendPacket(1000)
35 p.wantSendDelay(8 * time.Millisecond)
36
37 t.Logf("# accumulate enough window for two packets")
38 p.advance(16 * time.Millisecond)
39 p.sendPacket(1000)
40 p.sendPacket(1000)
41 p.wantSendDelay(8 * time.Millisecond)
42
43 t.Logf("# window does not grow to more than burst limit")
44 p.advance(1 * time.Second)
45 for i := 0; i < 11; i++ {
46 p.sendPacket(1000)
47 }
48 p.wantSendDelay(8 * time.Millisecond)
49 }
50
51 func TestPacerTimerGranularity(t *testing.T) {
52 p := &pacerTest{
53 cwnd: 10000,
54 rtt: 100 * time.Millisecond,
55 timerGranularity: 1 * time.Millisecond,
56 }
57 p.init(t)
58 t.Logf("# consume initial burst")
59 for i := 0; i < 11; i++ {
60 p.sendPacket(1000)
61 }
62 p.wantSendDelay(8 * time.Millisecond)
63
64 t.Logf("# small advance in time does not permit sending")
65 p.advance(4 * time.Millisecond)
66 p.wantSendDelay(4 * time.Millisecond)
67
68 t.Logf("# advancing to within timerGranularity of next send permits send")
69 p.advance(3 * time.Millisecond)
70 p.wantSendDelay(0)
71
72 t.Logf("# early send adds skipped delay (1ms) to next send (8ms)")
73 p.sendPacket(1000)
74 p.wantSendDelay(9 * time.Millisecond)
75 }
76
77 func TestPacerChangingRate(t *testing.T) {
78 p := &pacerTest{
79 cwnd: 10000,
80 rtt: 100 * time.Millisecond,
81 timerGranularity: 0,
82 }
83 p.init(t)
84 t.Logf("# consume initial burst")
85 for i := 0; i < 11; i++ {
86 p.sendPacket(1000)
87 }
88 p.wantSendDelay(8 * time.Millisecond)
89 p.advance(8 * time.Millisecond)
90
91 t.Logf("# set congestion window to 20000, 1000 byte interval is 4ms")
92 p.cwnd = 20000
93 p.sendPacket(1000)
94 p.wantSendDelay(4 * time.Millisecond)
95 p.advance(4 * time.Millisecond)
96
97 t.Logf("# set rtt to 200ms, 1000 byte interval is 8ms")
98 p.rtt = 200 * time.Millisecond
99 p.sendPacket(1000)
100 p.wantSendDelay(8 * time.Millisecond)
101 p.advance(8 * time.Millisecond)
102
103 t.Logf("# set congestion window to 40000, 1000 byte interval is 4ms")
104 p.cwnd = 40000
105 p.advance(8 * time.Millisecond)
106 p.sendPacket(1000)
107 p.sendPacket(1000)
108 p.sendPacket(1000)
109 p.wantSendDelay(4 * time.Millisecond)
110 }
111
112 func TestPacerTimeReverses(t *testing.T) {
113 p := &pacerTest{
114 cwnd: 10000,
115 rtt: 100 * time.Millisecond,
116 timerGranularity: 0,
117 }
118 p.init(t)
119 t.Logf("# consume initial burst")
120 for i := 0; i < 11; i++ {
121 p.sendPacket(1000)
122 }
123 p.wantSendDelay(8 * time.Millisecond)
124 t.Logf("# reverse time")
125 p.advance(-4 * time.Millisecond)
126 p.sendPacket(1000)
127 p.wantSendDelay(8 * time.Millisecond)
128 p.advance(8 * time.Millisecond)
129 p.sendPacket(1000)
130 p.wantSendDelay(8 * time.Millisecond)
131 }
132
133 func TestPacerZeroRTT(t *testing.T) {
134 p := &pacerTest{
135 cwnd: 10000,
136 rtt: 0,
137 timerGranularity: 0,
138 }
139 p.init(t)
140 t.Logf("# with rtt 0, the pacer does not limit sending")
141 for i := 0; i < 20; i++ {
142 p.sendPacket(1000)
143 }
144 p.advance(1 * time.Second)
145 for i := 0; i < 20; i++ {
146 p.sendPacket(1000)
147 }
148 }
149
150 func TestPacerZeroCongestionWindow(t *testing.T) {
151 p := &pacerTest{
152 cwnd: 10000,
153 rtt: 100 * time.Millisecond,
154 timerGranularity: 0,
155 }
156 p.init(t)
157 p.cwnd = 0
158 t.Logf("# with cwnd 0, the pacer does not limit sending")
159 for i := 0; i < 20; i++ {
160 p.sendPacket(1000)
161 }
162 }
163
164 type pacerTest struct {
165 t *testing.T
166 p pacerState
167 timerGranularity time.Duration
168 cwnd int
169 rtt time.Duration
170 now time.Time
171 }
172
173 func newPacerTest(t *testing.T, congestionWindow int, rtt time.Duration) *pacerTest {
174 p := &pacerTest{
175 now: time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC),
176 cwnd: congestionWindow,
177 rtt: rtt,
178 }
179 p.p.init(p.now, congestionWindow, p.timerGranularity)
180 return p
181 }
182
183 func (p *pacerTest) init(t *testing.T) {
184 p.t = t
185 p.now = time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
186 p.p.init(p.now, p.cwnd, p.timerGranularity)
187 t.Logf("# initial congestion window: %v", p.cwnd)
188 t.Logf("# timer granularity: %v", p.timerGranularity)
189 }
190
191 func (p *pacerTest) advance(d time.Duration) {
192 p.t.Logf("advance time %v", d)
193 p.now = p.now.Add(d)
194 p.p.advance(p.now, p.cwnd, p.rtt)
195 }
196
197 func (p *pacerTest) sendPacket(size int) {
198 if canSend, next := p.p.canSend(p.now); !canSend {
199 p.t.Fatalf("ERROR: pacer unexpectedly blocked send, delay=%v", next.Sub(p.now))
200 }
201 p.t.Logf("send packet of size %v", size)
202 p.p.packetSent(p.now, size, p.cwnd, p.rtt)
203 }
204
205 func (p *pacerTest) wantSendDelay(want time.Duration) {
206 wantCanSend := want == 0
207 gotCanSend, next := p.p.canSend(p.now)
208 var got time.Duration
209 if !gotCanSend {
210 got = next.Sub(p.now)
211 }
212 p.t.Logf("# pacer send delay: %v", got)
213 if got != want || gotCanSend != wantCanSend {
214 p.t.Fatalf("ERROR: pacer send delay = %v (can send: %v); want %v, %v", got, gotCanSend, want, wantCanSend)
215 }
216 }
217
218 func (p *pacerTest) sendDelay() time.Duration {
219 canSend, next := p.p.canSend(p.now)
220 if canSend {
221 return 0
222 }
223 return next.Sub(p.now)
224 }
225
View as plain text