golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/pacer_test.go (about) 1 // 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 5 //go:build go1.21 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 }