1
2
3
4
5
6
7 package quic
8
9 import (
10 "testing"
11 "time"
12 )
13
14 func TestAcksDisallowDuplicate(t *testing.T) {
15
16 acks := ackState{}
17 now := time.Now()
18 receive := []packetNumber{0, 1, 2, 4, 7, 6, 9}
19 seen := map[packetNumber]bool{}
20 for i, pnum := range receive {
21 acks.receive(now, appDataSpace, pnum, true)
22 seen[pnum] = true
23 for ppnum := packetNumber(0); ppnum < 11; ppnum++ {
24 if got, want := acks.shouldProcess(ppnum), !seen[ppnum]; got != want {
25 t.Fatalf("after receiving %v: acks.shouldProcess(%v) = %v, want %v", receive[:i+1], ppnum, got, want)
26 }
27 }
28 }
29 }
30
31 func TestAcksDisallowDiscardedAckRanges(t *testing.T) {
32
33 acks := ackState{}
34 now := time.Now()
35 for pnum := packetNumber(0); ; pnum += 2 {
36 acks.receive(now, appDataSpace, pnum, true)
37 send, _ := acks.acksToSend(now)
38 for ppnum := packetNumber(0); ppnum < packetNumber(send.min()); ppnum++ {
39 if acks.shouldProcess(ppnum) {
40 t.Fatalf("after limiting ack ranges to %v: acks.shouldProcess(%v) (in discarded range) = true, want false", send, ppnum)
41 }
42 }
43 if send.min() > 10 {
44 break
45 }
46 }
47 }
48
49 func TestAcksSent(t *testing.T) {
50 type packet struct {
51 pnum packetNumber
52 ackEliciting bool
53 }
54 for _, test := range []struct {
55 name string
56 space numberSpace
57
58
59
60
61 ackedPackets []packet
62 packets []packet
63
64 wantDelay time.Duration
65 wantAcks rangeset[packetNumber]
66 }{{
67 name: "no packets to ack",
68 space: initialSpace,
69 }, {
70 name: "non-ack-eliciting packets are not acked",
71 space: initialSpace,
72 packets: []packet{{
73 pnum: 0,
74 ackEliciting: false,
75 }},
76 }, {
77 name: "ack-eliciting Initial packets are acked immediately",
78 space: initialSpace,
79 packets: []packet{{
80 pnum: 0,
81 ackEliciting: true,
82 }},
83 wantAcks: rangeset[packetNumber]{{0, 1}},
84 wantDelay: 0,
85 }, {
86 name: "ack-eliciting Handshake packets are acked immediately",
87 space: handshakeSpace,
88 packets: []packet{{
89 pnum: 0,
90 ackEliciting: true,
91 }},
92 wantAcks: rangeset[packetNumber]{{0, 1}},
93 wantDelay: 0,
94 }, {
95 name: "ack-eliciting AppData packets are acked after max_ack_delay",
96 space: appDataSpace,
97 packets: []packet{{
98 pnum: 0,
99 ackEliciting: true,
100 }},
101 wantAcks: rangeset[packetNumber]{{0, 1}},
102 wantDelay: maxAckDelay - timerGranularity,
103 }, {
104 name: "reordered ack-eliciting packets are acked immediately",
105 space: appDataSpace,
106 ackedPackets: []packet{{
107 pnum: 1,
108 ackEliciting: true,
109 }},
110 packets: []packet{{
111 pnum: 0,
112 ackEliciting: true,
113 }},
114 wantAcks: rangeset[packetNumber]{{0, 2}},
115 wantDelay: 0,
116 }, {
117 name: "gaps in ack-eliciting packets are acked immediately",
118 space: appDataSpace,
119 packets: []packet{{
120 pnum: 1,
121 ackEliciting: true,
122 }},
123 wantAcks: rangeset[packetNumber]{{1, 2}},
124 wantDelay: 0,
125 }, {
126 name: "reordered non-ack-eliciting packets are not acked immediately",
127 space: appDataSpace,
128 ackedPackets: []packet{{
129 pnum: 1,
130 ackEliciting: true,
131 }},
132 packets: []packet{{
133 pnum: 2,
134 ackEliciting: true,
135 }, {
136 pnum: 0,
137 ackEliciting: false,
138 }, {
139 pnum: 4,
140 ackEliciting: false,
141 }},
142 wantAcks: rangeset[packetNumber]{{0, 3}, {4, 5}},
143 wantDelay: maxAckDelay - timerGranularity,
144 }, {
145 name: "immediate ack after two ack-eliciting packets are received",
146 space: appDataSpace,
147 packets: []packet{{
148 pnum: 0,
149 ackEliciting: true,
150 }, {
151 pnum: 1,
152 ackEliciting: true,
153 }},
154 wantAcks: rangeset[packetNumber]{{0, 2}},
155 wantDelay: 0,
156 }} {
157 t.Run(test.name, func(t *testing.T) {
158 acks := ackState{}
159 start := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
160 for _, p := range test.ackedPackets {
161 t.Logf("receive %v.%v, ack-eliciting=%v", test.space, p.pnum, p.ackEliciting)
162 acks.receive(start, test.space, p.pnum, p.ackEliciting)
163 }
164 t.Logf("send an ACK frame")
165 acks.sentAck()
166 for _, p := range test.packets {
167 t.Logf("receive %v.%v, ack-eliciting=%v", test.space, p.pnum, p.ackEliciting)
168 acks.receive(start, test.space, p.pnum, p.ackEliciting)
169 }
170 switch {
171 case len(test.wantAcks) == 0:
172
173 if acks.shouldSendAck(start.Add(10 * maxAckDelay)) {
174 t.Errorf("acks.shouldSendAck(T+10*max_ack_delay) = true, want false")
175 }
176 case test.wantDelay > 0:
177
178 if acks.shouldSendAck(start.Add(test.wantDelay - 1)) {
179 t.Errorf("acks.shouldSendAck(T+%v-1ns) = true, want false", test.wantDelay)
180 }
181 fallthrough
182 default:
183
184 if !acks.shouldSendAck(start.Add(test.wantDelay)) {
185 t.Errorf("acks.shouldSendAck(T+%v) = false, want true", test.wantDelay)
186 }
187 }
188
189
190
191 for _, delay := range []time.Duration{
192 0,
193 test.wantDelay,
194 test.wantDelay + 1,
195 } {
196 gotNums, gotDelay := acks.acksToSend(start.Add(delay))
197 wantDelay := delay
198 if len(gotNums) == 0 {
199 wantDelay = 0
200 }
201 if !slicesEqual(gotNums, test.wantAcks) || gotDelay != wantDelay {
202 t.Errorf("acks.acksToSend(T+%v) = %v, %v; want %v, %v", delay, gotNums, gotDelay, test.wantAcks, wantDelay)
203 }
204 }
205 })
206 }
207 }
208
209
210
211 func slicesEqual[E comparable](s1, s2 []E) bool {
212 if len(s1) != len(s2) {
213 return false
214 }
215 for i := range s1 {
216 if s1[i] != s2[i] {
217 return false
218 }
219 }
220 return true
221 }
222
223 func TestAcksDiscardAfterAck(t *testing.T) {
224 acks := ackState{}
225 now := time.Now()
226 acks.receive(now, appDataSpace, 0, true)
227 acks.receive(now, appDataSpace, 2, true)
228 acks.receive(now, appDataSpace, 4, true)
229 acks.receive(now, appDataSpace, 5, true)
230 acks.receive(now, appDataSpace, 6, true)
231 acks.handleAck(6)
232 acks.receive(now, appDataSpace, 7, true)
233 got, _ := acks.acksToSend(now)
234 if len(got) != 1 {
235 t.Errorf("acks.acksToSend contains ranges prior to last acknowledged ack; got %v, want 1 range", got)
236 }
237 }
238
239 func TestAcksLargestSeen(t *testing.T) {
240 acks := ackState{}
241 now := time.Now()
242 acks.receive(now, appDataSpace, 0, true)
243 acks.receive(now, appDataSpace, 4, true)
244 acks.receive(now, appDataSpace, 1, true)
245 if got, want := acks.largestSeen(), packetNumber(4); got != want {
246 t.Errorf("acks.largestSeen() = %v, want %v", got, want)
247 }
248 }
249
View as plain text