OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include <limits> | 11 #include <limits> |
12 #include <memory> | 12 #include <memory> |
| 13 #include <numeric> |
13 #include <vector> | 14 #include <vector> |
14 | 15 |
15 #include "webrtc/base/checks.h" | 16 #include "webrtc/base/checks.h" |
16 #include "webrtc/base/mod_ops.h" | 17 #include "webrtc/base/mod_ops.h" |
17 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" | 18 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" |
18 #include "webrtc/test/gmock.h" | 19 #include "webrtc/test/gmock.h" |
19 #include "webrtc/test/gtest.h" | 20 #include "webrtc/test/gtest.h" |
20 #include "webrtc/voice_engine/transport_feedback_packet_loss_tracker.h" | 21 #include "webrtc/voice_engine/transport_feedback_packet_loss_tracker.h" |
21 | 22 |
22 using webrtc::rtcp::TransportFeedback; | 23 using webrtc::rtcp::TransportFeedback; |
23 using testing::Return; | 24 using testing::Return; |
24 using testing::StrictMock; | 25 using testing::StrictMock; |
25 | 26 |
26 namespace webrtc { | 27 namespace webrtc { |
27 | 28 |
28 namespace { | 29 namespace { |
29 | 30 |
30 constexpr size_t kMaxConsecutiveOldReports = 4; | |
31 | |
32 // All tests are run multiple times with various baseline sequence number, | 31 // All tests are run multiple times with various baseline sequence number, |
33 // to weed out potential bugs with wrap-around handling. | 32 // to weed out potential bugs with wrap-around handling. |
34 constexpr uint16_t kBases[] = {0x0000, 0x3456, 0xc032, 0xfffe}; | 33 constexpr uint16_t kBases[] = {0x0000, 0x3456, 0xc032, 0xfffe}; |
35 | 34 |
| 35 void SendPacket(TransportFeedbackPacketLossTracker* tracker, |
| 36 const std::vector<uint16_t>& seq_nums, |
| 37 bool validate_all = true) { |
| 38 for (uint16_t seq_num : seq_nums) { |
| 39 tracker->OnPacketAdded(seq_num); |
| 40 if (validate_all) { |
| 41 tracker->Validate(); |
| 42 } |
| 43 } |
| 44 |
| 45 // We've either validated after each packet, or, for making sure the UT |
| 46 // doesn't run too long, we might validate only at the end of the range. |
| 47 if (!validate_all) { |
| 48 tracker->Validate(); |
| 49 } |
| 50 } |
| 51 |
| 52 void SendPacketRange(TransportFeedbackPacketLossTracker* tracker, |
| 53 uint16_t first_seq_num, |
| 54 size_t num_of_seq_nums, |
| 55 bool validate_all = true) { |
| 56 std::vector<uint16_t> seq_nums(num_of_seq_nums); |
| 57 std::iota(seq_nums.begin(), seq_nums.end(), first_seq_num); |
| 58 SendPacket(tracker, seq_nums, validate_all); |
| 59 } |
| 60 |
36 void AddTransportFeedbackAndValidate( | 61 void AddTransportFeedbackAndValidate( |
37 TransportFeedbackPacketLossTracker* tracker, | 62 TransportFeedbackPacketLossTracker* tracker, |
38 uint16_t base_sequence_num, | 63 uint16_t base_sequence_num, |
39 const std::vector<bool>& reception_status_vec) { | 64 const std::vector<bool>& reception_status_vec) { |
40 const int64_t kBaseTimeUs = 1234; // Irrelevant to this test. | 65 const int64_t kBaseTimeUs = 1234; // Irrelevant to this test. |
41 TransportFeedback test_feedback; | 66 TransportFeedback test_feedback; |
42 test_feedback.SetBase(base_sequence_num, kBaseTimeUs); | 67 test_feedback.SetBase(base_sequence_num, kBaseTimeUs); |
43 uint16_t sequence_num = base_sequence_num; | 68 uint16_t sequence_num = base_sequence_num; |
44 for (bool status : reception_status_vec) { | 69 for (bool status : reception_status_vec) { |
45 if (status) | 70 if (status) |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 } | 148 } |
124 | 149 |
125 // Sanity check on minimum filled window - PLR known, RPLR unknown. | 150 // Sanity check on minimum filled window - PLR known, RPLR unknown. |
126 TEST(TransportFeedbackPacketLossTrackerTest, PlrMinimumFilledWindow) { | 151 TEST(TransportFeedbackPacketLossTrackerTest, PlrMinimumFilledWindow) { |
127 for (uint16_t base : kBases) { | 152 for (uint16_t base : kBases) { |
128 TransportFeedbackPacketLossTracker tracker(10, 5, 5); | 153 TransportFeedbackPacketLossTracker tracker(10, 5, 5); |
129 | 154 |
130 // PLR correctly calculated after minimum window size reached. | 155 // PLR correctly calculated after minimum window size reached. |
131 // RPLR not necessarily known at that time (not if min-pairs not reached). | 156 // RPLR not necessarily known at that time (not if min-pairs not reached). |
132 // Expected window contents: [] -> [10011]. | 157 // Expected window contents: [] -> [10011]. |
| 158 SendPacketRange(&tracker, base, 5); |
133 AddTransportFeedbackAndValidate(&tracker, base, | 159 AddTransportFeedbackAndValidate(&tracker, base, |
134 {true, false, false, true, true}); | 160 {true, false, false, true, true}); |
135 ValidatePacketLossStatistics(tracker, | 161 ValidatePacketLossStatistics(tracker, |
136 rtc::Optional<float>(2.0f / 5.0f), | 162 rtc::Optional<float>(2.0f / 5.0f), |
137 rtc::Optional<float>()); | 163 rtc::Optional<float>()); |
138 } | 164 } |
139 } | 165 } |
140 | 166 |
141 // Sanity check on minimum filled window - PLR unknown, RPLR known. | 167 // Sanity check on minimum filled window - PLR unknown, RPLR known. |
142 TEST(TransportFeedbackPacketLossTrackerTest, RplrMinimumFilledWindow) { | 168 TEST(TransportFeedbackPacketLossTrackerTest, RplrMinimumFilledWindow) { |
143 for (uint16_t base : kBases) { | 169 for (uint16_t base : kBases) { |
144 TransportFeedbackPacketLossTracker tracker(10, 6, 4); | 170 TransportFeedbackPacketLossTracker tracker(10, 6, 4); |
145 | 171 |
146 // RPLR correctly calculated after minimum pairs reached. | 172 // RPLR correctly calculated after minimum pairs reached. |
147 // PLR not necessarily known at that time (not if min window not reached). | 173 // PLR not necessarily known at that time (not if min window not reached). |
148 // Expected window contents: [] -> [10011]. | 174 // Expected window contents: [] -> [10011]. |
| 175 SendPacketRange(&tracker, base, 5); |
149 AddTransportFeedbackAndValidate(&tracker, base, | 176 AddTransportFeedbackAndValidate(&tracker, base, |
150 {true, false, false, true, true}); | 177 {true, false, false, true, true}); |
151 ValidatePacketLossStatistics(tracker, | 178 ValidatePacketLossStatistics(tracker, |
152 rtc::Optional<float>(), | 179 rtc::Optional<float>(), |
153 rtc::Optional<float>(1.0f / 4.0f)); | 180 rtc::Optional<float>(1.0f / 4.0f)); |
154 } | 181 } |
155 } | 182 } |
156 | 183 |
157 // Additional reports update PLR and RPLR. | 184 // Additional reports update PLR and RPLR. |
158 TEST(TransportFeedbackPacketLossTrackerTest, ExtendWindow) { | 185 TEST(TransportFeedbackPacketLossTrackerTest, ExtendWindow) { |
159 for (uint16_t base : kBases) { | 186 for (uint16_t base : kBases) { |
160 TransportFeedbackPacketLossTracker tracker(20, 5, 5); | 187 TransportFeedbackPacketLossTracker tracker(20, 5, 5); |
161 | 188 |
| 189 SendPacketRange(&tracker, base, 25); |
| 190 |
162 // Expected window contents: [] -> [10011]. | 191 // Expected window contents: [] -> [10011]. |
163 AddTransportFeedbackAndValidate(&tracker, base, | 192 AddTransportFeedbackAndValidate(&tracker, base, |
164 {true, false, false, true, true}); | 193 {true, false, false, true, true}); |
165 ValidatePacketLossStatistics(tracker, | 194 ValidatePacketLossStatistics(tracker, |
166 rtc::Optional<float>(2.0f / 5.0f), | 195 rtc::Optional<float>(2.0f / 5.0f), |
167 rtc::Optional<float>()); | 196 rtc::Optional<float>()); |
168 | 197 |
169 // Expected window contents: [10011] -> [1001110101]. | 198 // Expected window contents: [10011] -> [1001110101]. |
170 AddTransportFeedbackAndValidate(&tracker, base + 5, | 199 AddTransportFeedbackAndValidate(&tracker, base + 5, |
171 {true, false, true, false, true}); | 200 {true, false, true, false, true}); |
172 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); | 201 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); |
173 | 202 |
174 // Expected window contents: [1001110101] -> [1001110101-GAP-10001]. | 203 // Expected window contents: [1001110101] -> [1001110101-GAP-10001]. |
175 AddTransportFeedbackAndValidate(&tracker, base + 20, | 204 AddTransportFeedbackAndValidate(&tracker, base + 20, |
176 {true, false, false, false, true}); | 205 {true, false, false, false, true}); |
177 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 4.0f / 13.0f); | 206 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 4.0f / 13.0f); |
178 } | 207 } |
179 } | 208 } |
180 | 209 |
181 // All packets correctly received. | 210 // Sanity - all packets correctly received. |
182 TEST(TransportFeedbackPacketLossTrackerTest, AllReceived) { | 211 TEST(TransportFeedbackPacketLossTrackerTest, AllReceived) { |
183 for (uint16_t base : kBases) { | 212 for (uint16_t base : kBases) { |
184 TransportFeedbackPacketLossTracker tracker(10, 5, 4); | 213 TransportFeedbackPacketLossTracker tracker(10, 5, 4); |
185 | 214 |
186 // PLR and RPLR correctly calculated after minimum window size reached. | 215 // PLR and RPLR correctly calculated after minimum window size reached. |
187 // Expected window contents: [] -> [11111]. | 216 // Expected window contents: [] -> [11111]. |
| 217 SendPacketRange(&tracker, base, 5); |
188 AddTransportFeedbackAndValidate(&tracker, base, | 218 AddTransportFeedbackAndValidate(&tracker, base, |
189 {true, true, true, true, true}); | 219 {true, true, true, true, true}); |
190 ValidatePacketLossStatistics(tracker, 0.0f, 0.0f); | 220 ValidatePacketLossStatistics(tracker, 0.0f, 0.0f); |
191 } | 221 } |
192 } | 222 } |
193 | 223 |
194 // Repeated reports are ignored. | 224 // Repeated reports are ignored. |
195 TEST(TransportFeedbackPacketLossTrackerTest, ReportRepetition) { | 225 TEST(TransportFeedbackPacketLossTrackerTest, ReportRepetition) { |
196 for (uint16_t base : kBases) { | 226 for (uint16_t base : kBases) { |
197 TransportFeedbackPacketLossTracker tracker(10, 5, 4); | 227 TransportFeedbackPacketLossTracker tracker(10, 5, 4); |
198 | 228 |
| 229 SendPacketRange(&tracker, base, 5); |
| 230 |
199 // Expected window contents: [] -> [10011]. | 231 // Expected window contents: [] -> [10011]. |
200 AddTransportFeedbackAndValidate(&tracker, base, | 232 AddTransportFeedbackAndValidate(&tracker, base, |
201 {true, false, false, true, true}); | 233 {true, false, false, true, true}); |
202 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | 234 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); |
203 | 235 |
204 // Repeat entire previous feedback | 236 // Repeat entire previous feedback |
205 // Expected window contents: [10011] -> [10011]. | 237 // Expected window contents: [10011] -> [10011]. |
206 AddTransportFeedbackAndValidate(&tracker, base, | 238 AddTransportFeedbackAndValidate(&tracker, base, |
207 {true, false, false, true, true}); | 239 {true, false, false, true, true}); |
208 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | 240 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); |
209 } | 241 } |
210 } | 242 } |
211 | 243 |
212 // Report overlap. | 244 // Report overlap. |
213 TEST(TransportFeedbackPacketLossTrackerTest, ReportOverlap) { | 245 TEST(TransportFeedbackPacketLossTrackerTest, ReportOverlap) { |
214 for (uint16_t base : kBases) { | 246 for (uint16_t base : kBases) { |
215 TransportFeedbackPacketLossTracker tracker(10, 5, 1); | 247 TransportFeedbackPacketLossTracker tracker(10, 5, 1); |
216 | 248 |
| 249 SendPacketRange(&tracker, base, 15); |
| 250 |
217 // Expected window contents: [] -> [10011]. | 251 // Expected window contents: [] -> [10011]. |
218 AddTransportFeedbackAndValidate(&tracker, base, | 252 AddTransportFeedbackAndValidate(&tracker, base, |
219 {true, false, false, true, true}); | 253 {true, false, false, true, true}); |
220 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | 254 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); |
221 | 255 |
222 // Expected window contents: [10011] -> [1001101]. | 256 // Expected window contents: [10011] -> [1001101]. |
223 AddTransportFeedbackAndValidate(&tracker, base + 3, | 257 AddTransportFeedbackAndValidate(&tracker, base + 3, |
224 {true, true, false, true}); | 258 {true, true, false, true}); |
225 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f); | 259 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f); |
226 } | 260 } |
227 } | 261 } |
228 | 262 |
229 // Report conflict. | 263 // Report conflict. |
230 TEST(TransportFeedbackPacketLossTrackerTest, ReportConflict) { | 264 TEST(TransportFeedbackPacketLossTrackerTest, ReportConflict) { |
231 for (uint16_t base : kBases) { | 265 for (uint16_t base : kBases) { |
232 TransportFeedbackPacketLossTracker tracker(10, 5, 4); | 266 TransportFeedbackPacketLossTracker tracker(10, 5, 4); |
233 | 267 |
| 268 SendPacketRange(&tracker, base, 15); |
| 269 |
234 // Expected window contents: [] -> [01001]. | 270 // Expected window contents: [] -> [01001]. |
235 AddTransportFeedbackAndValidate(&tracker, base, | 271 AddTransportFeedbackAndValidate(&tracker, base, |
236 {false, true, false, false, true}); | 272 {false, true, false, false, true}); |
237 ValidatePacketLossStatistics(tracker, 3.0f / 5.0f, 2.0f / 4.0f); | 273 ValidatePacketLossStatistics(tracker, 3.0f / 5.0f, 2.0f / 4.0f); |
238 | 274 |
239 // Expected window contents: [01001] -> [11101]. | 275 // Expected window contents: [01001] -> [11101]. |
240 // While false->true will be applied, true -> false will be ignored. | 276 // While false->true will be applied, true -> false will be ignored. |
241 AddTransportFeedbackAndValidate(&tracker, base, {true, false, true}); | 277 AddTransportFeedbackAndValidate(&tracker, base, {true, false, true}); |
242 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); | 278 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); |
243 } | 279 } |
244 } | 280 } |
245 | 281 |
246 // Skipped packets treated as unknown (not lost). | 282 // Skipped packets treated as unknown (not lost). |
247 TEST(TransportFeedbackPacketLossTrackerTest, SkippedPackets) { | 283 TEST(TransportFeedbackPacketLossTrackerTest, SkippedPackets) { |
248 for (uint16_t base : kBases) { | 284 for (uint16_t base : kBases) { |
249 TransportFeedbackPacketLossTracker tracker(10, 5, 1); | 285 TransportFeedbackPacketLossTracker tracker(10, 5, 1); |
250 | 286 |
| 287 SendPacketRange(&tracker, base, 200); |
| 288 |
251 // Expected window contents: [] -> [10011]. | 289 // Expected window contents: [] -> [10011]. |
252 AddTransportFeedbackAndValidate(&tracker, base, | 290 AddTransportFeedbackAndValidate(&tracker, base, |
253 {true, false, false, true, true}); | 291 {true, false, false, true, true}); |
254 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | 292 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); |
255 | 293 |
256 // Expected window contents: [10011] -> [10011-GAP-101]. | 294 // Expected window contents: [10011] -> [10011-GAP-101]. |
257 AddTransportFeedbackAndValidate(&tracker, base + 100, {true, false, true}); | 295 AddTransportFeedbackAndValidate(&tracker, base + 100, {true, false, true}); |
258 ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 6.0f); | 296 ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 6.0f); |
259 } | 297 } |
260 } | 298 } |
261 | 299 |
262 // The window retain information up to the configured max-window-size, but | 300 // The window retain information up to the configured max-window-size, but |
263 // starts discarding after that. | 301 // starts discarding after that. (Sent packets are not counted.) |
264 TEST(TransportFeedbackPacketLossTrackerTest, MaxWindowSize) { | 302 TEST(TransportFeedbackPacketLossTrackerTest, MaxWindowSize) { |
265 for (uint16_t base : kBases) { | 303 for (uint16_t base : kBases) { |
266 TransportFeedbackPacketLossTracker tracker(10, 10, 1); | 304 TransportFeedbackPacketLossTracker tracker(10, 10, 1); |
267 | 305 |
| 306 SendPacketRange(&tracker, base, 200); |
| 307 |
268 // Up to max-window-size retained. | 308 // Up to max-window-size retained. |
269 // Expected window contents: [] -> [1010100001]. | 309 // Expected window contents: [] -> [1010100001]. |
270 AddTransportFeedbackAndValidate( | 310 AddTransportFeedbackAndValidate( |
271 &tracker, base, | 311 &tracker, base, |
272 {true, false, true, false, true, false, false, false, false, true}); | 312 {true, false, true, false, true, false, false, false, false, true}); |
273 ValidatePacketLossStatistics(tracker, 6.0f / 10.0f, 3.0f / 9.0f); | 313 ValidatePacketLossStatistics(tracker, 6.0f / 10.0f, 3.0f / 9.0f); |
274 | 314 |
275 // After max-window-size, older entries discarded to accommodate newer ones. | 315 // After max-window-size, older entries discarded to accommodate newer ones. |
276 // Expected window contents: [1010100001] -> [0000110111]. | 316 // Expected window contents: [1010100001] -> [0000110111]. |
277 AddTransportFeedbackAndValidate(&tracker, base + 10, | 317 AddTransportFeedbackAndValidate(&tracker, base + 10, |
278 {true, false, true, true, true}); | 318 {true, false, true, true, true}); |
279 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 2.0f / 9.0f); | 319 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 2.0f / 9.0f); |
280 } | 320 } |
281 } | 321 } |
282 | 322 |
283 // Inserting into the middle of a full window works correctly. | 323 // Inserting feedback into the middle of a full window works correctly. |
284 TEST(TransportFeedbackPacketLossTrackerTest, InsertIntoMiddle) { | 324 TEST(TransportFeedbackPacketLossTrackerTest, InsertIntoMiddle) { |
285 for (uint16_t base : kBases) { | 325 for (uint16_t base : kBases) { |
286 TransportFeedbackPacketLossTracker tracker(10, 5, 1); | 326 TransportFeedbackPacketLossTracker tracker(10, 5, 1); |
287 | 327 |
| 328 SendPacketRange(&tracker, base, 300); |
| 329 |
288 // Expected window contents: [] -> [10101]. | 330 // Expected window contents: [] -> [10101]. |
289 AddTransportFeedbackAndValidate(&tracker, base, | 331 AddTransportFeedbackAndValidate(&tracker, base, |
290 {true, false, true, false, true}); | 332 {true, false, true, false, true}); |
291 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); | 333 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); |
292 | 334 |
293 // Expected window contents: [10101] -> [10101-GAP-10001]. | 335 // Expected window contents: [10101] -> [10101-GAP-10001]. |
294 AddTransportFeedbackAndValidate(&tracker, base + 100, | 336 AddTransportFeedbackAndValidate(&tracker, base + 100, |
295 {true, false, false, false, true}); | 337 {true, false, false, false, true}); |
296 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 3.0f / 8.0f); | 338 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 3.0f / 8.0f); |
297 | 339 |
298 // Insert into the middle of this full window - it discards the older data. | 340 // Insert into the middle of this full window - it discards the older data. |
299 // Expected window contents: [10101-GAP-10001] -> [11111-GAP-10001]. | 341 // Expected window contents: [10101-GAP-10001] -> [11111-GAP-10001]. |
300 AddTransportFeedbackAndValidate(&tracker, base + 50, | 342 AddTransportFeedbackAndValidate(&tracker, base + 50, |
301 {true, true, true, true, true}); | 343 {true, true, true, true, true}); |
302 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 1.0f / 8.0f); | 344 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 1.0f / 8.0f); |
303 } | 345 } |
304 } | 346 } |
305 | 347 |
306 // Inserting into the middle of a full window works correctly. | 348 // Inserting feedback into the middle of a full window works correctly - can |
| 349 // complete two pairs. |
307 TEST(TransportFeedbackPacketLossTrackerTest, InsertionCompletesTwoPairs) { | 350 TEST(TransportFeedbackPacketLossTrackerTest, InsertionCompletesTwoPairs) { |
308 for (uint16_t base : kBases) { | 351 for (uint16_t base : kBases) { |
309 TransportFeedbackPacketLossTracker tracker(15, 5, 1); | 352 TransportFeedbackPacketLossTracker tracker(15, 5, 1); |
310 | 353 |
| 354 SendPacketRange(&tracker, base, 300); |
| 355 |
311 // Expected window contents: [] -> [10111]. | 356 // Expected window contents: [] -> [10111]. |
312 AddTransportFeedbackAndValidate(&tracker, base, | 357 AddTransportFeedbackAndValidate(&tracker, base, |
313 {true, false, true, true, true}); | 358 {true, false, true, true, true}); |
314 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); | 359 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); |
315 | 360 |
316 // Expected window contents: [10111] -> [10111-GAP-10101]. | 361 // Expected window contents: [10111] -> [10111-GAP-10101]. |
317 AddTransportFeedbackAndValidate(&tracker, base + 7, | 362 AddTransportFeedbackAndValidate(&tracker, base + 7, |
318 {true, false, true, false, true}); | 363 {true, false, true, false, true}); |
319 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f); | 364 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f); |
320 | 365 |
321 // Insert in between, closing the gap completely. | 366 // Insert in between, closing the gap completely. |
322 // Expected window contents: [10111-GAP-10101] -> [101111010101]. | 367 // Expected window contents: [10111-GAP-10101] -> [101111010101]. |
323 AddTransportFeedbackAndValidate(&tracker, base + 5, {false, true}); | 368 AddTransportFeedbackAndValidate(&tracker, base + 5, {false, true}); |
324 ValidatePacketLossStatistics(tracker, 4.0f / 12.0f, 4.0f / 11.0f); | 369 ValidatePacketLossStatistics(tracker, 4.0f / 12.0f, 4.0f / 11.0f); |
325 } | 370 } |
326 } | 371 } |
327 | 372 |
328 // Entries in the second quadrant treated like those in the first. | 373 // The window can meaningfully hold up to 0x8000 SENT packetts (of which only |
329 // The sequence number is used in a looped manner. 0xFFFF is followed by 0x0000. | 374 // up to max-window acked messages will be kept and regarded). |
330 // In many tests, we divide the circle of sequence number into 4 quadrants, and | |
331 // verify the behavior of TransportFeedbackPacketLossTracker over them. | |
332 TEST(TransportFeedbackPacketLossTrackerTest, SecondQuadrant) { | 375 TEST(TransportFeedbackPacketLossTrackerTest, SecondQuadrant) { |
333 for (uint16_t base : kBases) { | 376 for (uint16_t base : kBases) { |
334 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | 377 TransportFeedbackPacketLossTracker tracker(20, 5, 1); |
335 | 378 |
| 379 SendPacketRange(&tracker, base, 0x8000, false); |
| 380 |
336 // Expected window contents: [] -> [10011]. | 381 // Expected window contents: [] -> [10011]. |
337 AddTransportFeedbackAndValidate(&tracker, base, | 382 AddTransportFeedbackAndValidate(&tracker, base, |
338 {true, false, false, true, true}); | 383 {true, false, false, true, true}); |
339 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | 384 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); |
340 | 385 |
341 // Window *does* get updated with inputs from quadrant #2. | 386 // Window *does* get updated with inputs from quadrant #2. |
342 // Expected window contents: [10011] -> [100111]. | 387 // Expected window contents: [10011] -> [100111]. |
343 AddTransportFeedbackAndValidate(&tracker, base + 0x4321, {true}); | 388 AddTransportFeedbackAndValidate(&tracker, base + 0x4321, {true}); |
344 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 1.0f / 4.0f); | 389 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 1.0f / 4.0f); |
345 | 390 |
346 // Correct recognition of quadrant #2: up to, but not including, base + | 391 // Correct recognition of quadrant #2: up to, but not including, base + |
347 // 0x8000 | 392 // 0x8000 |
348 // Expected window contents: [100111] -> [1001111]. | 393 // Expected window contents: [100111] -> [1001111]. |
349 AddTransportFeedbackAndValidate(&tracker, base + 0x7fff, {true}); | 394 AddTransportFeedbackAndValidate(&tracker, base + 0x7fff, {true}); |
350 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 1.0f / 4.0f); | 395 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 1.0f / 4.0f); |
351 } | 396 } |
352 } | 397 } |
353 | 398 |
354 // Insertion into the third quadrant moves the base of the window. | |
355 TEST(TransportFeedbackPacketLossTrackerTest, ThirdQuadrantMovesBase) { | |
356 for (uint16_t base : kBases) { | |
357 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | |
358 | |
359 // Seed the test. | |
360 // Expected window contents: [] -> [1001101]. | |
361 AddTransportFeedbackAndValidate( | |
362 &tracker, base, {true, false, false, true, true, false, true}); | |
363 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f); | |
364 | |
365 // Quadrant #3 begins at base + 0x8000. It triggers moving the window so | |
366 // that | |
367 // at least one (oldest) report shifts out of window. | |
368 // Expected window contents: [1001101] -> [101-GAP-1001]. | |
369 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | |
370 {true, false, false, true}); | |
371 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 5.0f); | |
372 | |
373 // The base can move more than once, because the minimum quadrant-1 packets | |
374 // were dropped out of the window, and some remain. | |
375 // Expected window contents: [101-GAP-1001] -> [1-GAP-100111]. | |
376 AddTransportFeedbackAndValidate(&tracker, base + 0x8000 + 4, {true, true}); | |
377 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 1.0f / 5.0f); | |
378 } | |
379 } | |
380 | |
381 // After the base has moved due to insertion into the third quadrant, it is | 399 // After the base has moved due to insertion into the third quadrant, it is |
382 // still possible to insert into the middle of the window and obtain the correct | 400 // still possible to get feedbacks in the middle of the window and obtain the |
383 // PLR and RPLR. Insertion into the middle before the max window size has been | 401 // correct PLR and RPLR. Insertion into the middle before the max window size |
384 // achieved does not cause older packets to be dropped. | 402 // has been achieved does not cause older packets to be dropped. |
385 TEST(TransportFeedbackPacketLossTrackerTest, InsertIntoMiddleAfterBaseMove) { | 403 TEST(TransportFeedbackPacketLossTrackerTest, InsertIntoMiddleAfterBaseMoved) { |
386 for (uint16_t base : kBases) { | 404 for (uint16_t base : kBases) { |
387 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | 405 TransportFeedbackPacketLossTracker tracker(20, 5, 1); |
388 | 406 |
389 // Seed the test. | 407 SendPacketRange(&tracker, base, 20); |
| 408 SendPacketRange(&tracker, base + 0x5000, 20); |
| 409 |
390 // Expected window contents: [] -> [1001101]. | 410 // Expected window contents: [] -> [1001101]. |
391 AddTransportFeedbackAndValidate( | 411 AddTransportFeedbackAndValidate( |
392 &tracker, base, {true, false, false, true, true, false, true}); | 412 &tracker, base, {true, false, false, true, true, false, true}); |
393 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f); | 413 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f); |
394 | 414 |
395 // Expected window contents: [1001101] -> [101-GAP-1001]. | 415 // Expected window contents: [1001101] -> [101-GAP-1001]. |
| 416 SendPacketRange(&tracker, base + 0x8000, 4); |
396 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | 417 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, |
397 {true, false, false, true}); | 418 {true, false, false, true}); |
398 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 5.0f); | 419 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 5.0f); |
399 | 420 |
400 // Inserting into the middle still works after the base has shifted. | 421 // Inserting into the middle still works after the base has shifted. |
401 // Expected window contents: | 422 // Expected window contents: |
402 // [101-GAP-1001] -> [101-GAP-100101-GAP-1001] | 423 // [101-GAP-1001] -> [101-GAP-100101-GAP-1001] |
403 AddTransportFeedbackAndValidate(&tracker, base + 0x5000, | 424 AddTransportFeedbackAndValidate(&tracker, base + 0x5000, |
404 {true, false, false, true, false, true}); | 425 {true, false, false, true, false, true}); |
405 ValidatePacketLossStatistics(tracker, 6.0f / 13.0f, 4.0f / 10.0f); | 426 ValidatePacketLossStatistics(tracker, 6.0f / 13.0f, 4.0f / 10.0f); |
406 | 427 |
407 // The base can keep moving after inserting into the middle. | 428 // The base can keep moving after inserting into the middle. |
408 // Expected window contents: | 429 // Expected window contents: |
409 // [101-GAP-100101-GAP-1001] -> [1-GAP-100101-GAP-100111]. | 430 // [101-GAP-100101-GAP-1001] -> [1-GAP-100101-GAP-100111]. |
| 431 SendPacketRange(&tracker, base + 0x8000 + 4, 2); |
410 AddTransportFeedbackAndValidate(&tracker, base + 0x8000 + 4, {true, true}); | 432 AddTransportFeedbackAndValidate(&tracker, base + 0x8000 + 4, {true, true}); |
411 ValidatePacketLossStatistics(tracker, 5.0f / 13.0f, 3.0f / 10.0f); | 433 ValidatePacketLossStatistics(tracker, 5.0f / 13.0f, 3.0f / 10.0f); |
412 } | 434 } |
413 } | 435 } |
414 | 436 |
415 // After moving the base of the window, the max window size is still observed. | 437 // After moving the base of the window, the max window size is still observed. |
416 TEST(TransportFeedbackPacketLossTrackerTest, ThirdQuadrantObservesMaxWindow) { | 438 TEST(TransportFeedbackPacketLossTrackerTest, MaxWindowObservedAfterBaseMoved) { |
417 for (uint16_t base : kBases) { | 439 for (uint16_t base : kBases) { |
418 TransportFeedbackPacketLossTracker tracker(15, 10, 1); | 440 TransportFeedbackPacketLossTracker tracker(15, 10, 1); |
419 | 441 |
420 // Expected window contents: [] -> [1001110101]. | 442 // Expected window contents: [] -> [1001110101]. |
| 443 SendPacketRange(&tracker, base, 10); |
421 AddTransportFeedbackAndValidate( | 444 AddTransportFeedbackAndValidate( |
422 &tracker, base, | 445 &tracker, base, |
423 {true, false, false, true, true, true, false, true, false, true}); | 446 {true, false, false, true, true, true, false, true, false, true}); |
424 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); | 447 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); |
425 | 448 |
| 449 // Create gap (on both sides). |
| 450 SendPacketRange(&tracker, base + 0x4000, 20); |
| 451 |
426 // Expected window contents: [1001110101] -> [1110101-GAP-101]. | 452 // Expected window contents: [1001110101] -> [1110101-GAP-101]. |
| 453 SendPacketRange(&tracker, base + 0x8000, 3); |
427 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | 454 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, |
428 {true, false, true}); | 455 {true, false, true}); |
429 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f); | 456 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f); |
430 | 457 |
431 // Push into middle until max window is reached. | 458 // Push into middle until max window is reached. The gap is NOT completed. |
432 // Expected window contents: | 459 // Expected window contents: |
433 // [1110101-GAP-101] -> [1110101-GAP-10001-GAP-101] | 460 // [1110101-GAP-101] -> [1110101-GAP-10001-GAP-101] |
434 AddTransportFeedbackAndValidate(&tracker, base + 0x4000, | 461 AddTransportFeedbackAndValidate(&tracker, base + 0x4000 + 2, |
435 {true, false, false, false, true}); | 462 {true, false, false, false, true}); |
436 ValidatePacketLossStatistics(tracker, 6.0f / 15.0f, 4.0f / 12.0f); | 463 ValidatePacketLossStatistics(tracker, 6.0f / 15.0f, 4.0f / 12.0f); |
437 | 464 |
438 // Pushing new packets into the middle would discard older packets. | 465 // Pushing new packets into the middle would discard older packets. |
439 // Expected window contents: | 466 // Expected window contents: |
440 // [1110101-GAP-10001-GAP-101] -> [0101-GAP-10001101-GAP-101] | 467 // [1110101-GAP-10001-GAP-101] -> [0101-GAP-10001101-GAP-101] |
441 AddTransportFeedbackAndValidate(&tracker, base + 0x4000 + 5, | 468 AddTransportFeedbackAndValidate(&tracker, base + 0x4000 + 2 + 5, |
442 {true, false, true}); | 469 {true, false, true}); |
443 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 5.0f / 12.0f); | 470 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 5.0f / 12.0f); |
444 } | 471 } |
445 } | 472 } |
446 | 473 |
447 // A new feedback in quadrant #3 might shift enough old feedbacks out of window, | 474 // A packet with a new enough sequence number might shift enough old feedbacks |
448 // that we'd go back to an unknown PLR and RPLR. | 475 // out window, that we'd go back to an unknown PLR and RPLR. |
449 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantThreeMovedBaseMinWindow) { | 476 TEST(TransportFeedbackPacketLossTrackerTest, NewPacketMovesWindowBase) { |
450 for (uint16_t base : kBases) { | 477 for (uint16_t base : kBases) { |
451 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | 478 TransportFeedbackPacketLossTracker tracker(20, 5, 3); |
| 479 |
| 480 SendPacketRange(&tracker, base, 50); |
| 481 SendPacketRange(&tracker, base + 0x4000 - 1, 6); // Gap |
452 | 482 |
453 // Expected window contents: [] -> [1001110101]. | 483 // Expected window contents: [] -> [1001110101]. |
454 AddTransportFeedbackAndValidate( | 484 AddTransportFeedbackAndValidate( |
455 &tracker, base, | 485 &tracker, base, |
456 {true, false, false, true, true, true, false, true, false, true}); | 486 {true, false, false, true, true, true, false, true, false, true}); |
457 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); | 487 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); |
458 | 488 |
459 // A new feedback in quadrant #3 might shift enough old feedbacks out of | 489 // A new sent packet with a new enough sequence number could shift enough |
460 // window, that we'd go back to an unknown PLR and RPLR. This *doesn't* | 490 // acked packets out of window, that we'd go back to an unknown PLR |
461 // necessarily mean all of the old ones were discarded, though. | 491 // and RPLR. This *doesn't* // necessarily mean all of the old ones |
462 // Expected window contents: [1001110101] -> [01-GAP-11]. | 492 // were discarded, though. |
| 493 // Expected window contents: [1001110101] -> [01]. |
| 494 SendPacketRange(&tracker, base + 0x8006, 2); |
| 495 ValidatePacketLossStatistics(tracker, |
| 496 rtc::Optional<float>(), // Still invalid. |
| 497 rtc::Optional<float>()); |
| 498 |
| 499 // Even if those messages are acked, we'd still might be in unknown PLR |
| 500 // and RPLR, because we might have shifted more packets out of the window |
| 501 // than we have inserted. |
| 502 // Expected window contents: [01] -> [01-GAP-11]. |
463 AddTransportFeedbackAndValidate(&tracker, base + 0x8006, {true, true}); | 503 AddTransportFeedbackAndValidate(&tracker, base + 0x8006, {true, true}); |
464 ValidatePacketLossStatistics(tracker, | 504 ValidatePacketLossStatistics(tracker, |
465 rtc::Optional<float>(), // Still invalid. | 505 rtc::Optional<float>(), // Still invalid. |
466 rtc::Optional<float>(1.0f / 2.0f)); | 506 rtc::Optional<float>()); |
467 | 507 |
468 // Inserting in the middle shows that though some of the elements were | 508 // Inserting in the middle shows that though some of the elements were |
469 // ejected, some were retained. | 509 // ejected, some were retained. |
470 // Expected window contents: [01-GAP-11] -> [01-GAP-1001-GAP-11]. | 510 // Expected window contents: [01-GAP-11] -> [01-GAP-1001-GAP-11]. |
471 AddTransportFeedbackAndValidate(&tracker, base + 0x4000, | 511 AddTransportFeedbackAndValidate(&tracker, base + 0x4000, |
472 {true, false, false, true}); | 512 {true, false, false, true}); |
473 ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 5.0f); | 513 ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 5.0f); |
474 } | 514 } |
475 } | 515 } |
476 | 516 |
477 // Quadrant four reports ignored for up to kMaxConsecutiveOldReports times. | 517 // Sequence number gaps are not gaps in reception. However, gaps in reception |
478 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourInitiallyIgnored) { | 518 // are still possible, if a packet which WAS sent on the stream is not acked. |
| 519 TEST(TransportFeedbackPacketLossTrackerTest, SanityGapsInSequenceNumbers) { |
479 for (uint16_t base : kBases) { | 520 for (uint16_t base : kBases) { |
480 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | 521 TransportFeedbackPacketLossTracker tracker(20, 5, 1); |
481 | 522 |
482 // Expected window contents: [] -> [10011]. | 523 SendPacket(&tracker, {base, base + 2, base + 4, base + 6, base + 8}); |
483 AddTransportFeedbackAndValidate(&tracker, base, | |
484 {true, false, false, true, true}); | |
485 | 524 |
486 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | 525 // Gaps in sequence numbers not considered as gaps in window, because only |
487 // consecutive reports). | 526 // those sequence numbers which were associated with the stream count. |
488 // Expected window contents: [10011] -> [10011]. | 527 // Expected window contents: [] -> [11011]. |
489 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | 528 AddTransportFeedbackAndValidate( |
490 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, {true, true}); | 529 // Note: Left packets belong to this stream, odd ones ignored. |
491 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | 530 &tracker, base, {true, false, |
492 } | 531 true, false, |
| 532 false, false, |
| 533 true, false, |
| 534 true, true}); |
| 535 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); |
| 536 |
| 537 // Create gap by sending [base + 10] but not acking it. |
| 538 // Note: Acks for [base + 11] and [base + 13] ignored (other stream). |
| 539 // Expected window contents: [11011] -> [11011-GAP-01]. |
| 540 SendPacket(&tracker, {base + 10, base + 12, base + 14}); |
| 541 AddTransportFeedbackAndValidate(&tracker, base + 11, |
| 542 {false, false, false, true, true}); |
| 543 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 2.0f / 5.0f); |
493 } | 544 } |
494 } | 545 } |
495 | 546 |
496 // Receiving a packet from quadrant #1 resets the counter for quadrant #4. | |
497 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourCounterResetByQ1) { | |
498 for (uint16_t base : kBases) { | |
499 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | |
500 | |
501 // Expected window contents: [] -> [10011]. | |
502 AddTransportFeedbackAndValidate(&tracker, base, | |
503 {true, false, false, true, true}); | |
504 | |
505 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | |
506 // consecutive reports). | |
507 // Expected window contents: [10011] -> [10011]. | |
508 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
509 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, {true, true}); | |
510 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | |
511 } | |
512 | |
513 // If we receive a feedback in quadrant #1, the above counter is reset. | |
514 // Expected window contents: [10011] -> [100111]. | |
515 AddTransportFeedbackAndValidate(&tracker, base + 5, {true}); | |
516 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
517 // Note: though the feedback message reports three packets, it only gets | |
518 // counted once. | |
519 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, | |
520 {true, false, true}); | |
521 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 1.0f / 5.0f); | |
522 } | |
523 | |
524 // The same is true for reports which create a gap - they still reset. | |
525 // Expected window contents: [10011] -> [100111-GAP-01]. | |
526 AddTransportFeedbackAndValidate(&tracker, base + 0x00ff, {false, true}); | |
527 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
528 // Note: though the feedback message reports three packets, it only gets | |
529 // counted once. | |
530 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, | |
531 {true, false, true}); | |
532 ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 6.0f); | |
533 } | |
534 } | |
535 } | |
536 | |
537 // Receiving a packet from quadrant #2 resets the counter for quadrant #4. | |
538 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourCounterResetByQ2) { | |
539 for (uint16_t base : kBases) { | |
540 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | |
541 | |
542 // Expected window contents: [] -> [10011]. | |
543 AddTransportFeedbackAndValidate(&tracker, base, | |
544 {true, false, false, true, true}); | |
545 | |
546 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | |
547 // consecutive reports). | |
548 // Expected window contents: [10011] -> [10011]. | |
549 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
550 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, {true, true}); | |
551 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | |
552 } | |
553 | |
554 // If we receive a feedback in quadrant #2, the above counter is reset. | |
555 // Expected window contents: [10011] -> [10011-GAP-11]. | |
556 AddTransportFeedbackAndValidate(&tracker, base + 0x400f, {true, true}); | |
557 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
558 // Note: though the feedback message reports three packets, it only gets | |
559 // counted once. | |
560 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, | |
561 {true, false, true}); | |
562 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 1.0f / 5.0f); | |
563 } | |
564 } | |
565 } | |
566 | |
567 // Receiving a packet from quadrant #3 resets the counter for quadrant #4. | |
568 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourCounterResetByQ3) { | |
569 for (uint16_t base : kBases) { | |
570 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | |
571 | |
572 // Expected window contents: [] -> [1001110001]. | |
573 AddTransportFeedbackAndValidate( | |
574 &tracker, base, | |
575 {true, false, false, true, true, true, false, false, false, true}); | |
576 | |
577 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | |
578 // consecutive reports). | |
579 // Expected window contents: [1001110001] -> [1001110001]. | |
580 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
581 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, {true, true}); | |
582 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 2.0f / 9.0f); | |
583 } | |
584 | |
585 // If we receive a feedback in quadrant #1, the above counter is reset. | |
586 // Expected window contents: [1001110001] -> [1110001-GAP-111]. | |
587 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | |
588 {true, true, true}); | |
589 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
590 // Note: though the feedback message reports three packets, it only gets | |
591 // counted once. | |
592 AddTransportFeedbackAndValidate(&tracker, base + 0xc000 + 10, | |
593 {true, false, true}); | |
594 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 1.0f / 8.0f); | |
595 } | |
596 } | |
597 } | |
598 | |
599 // Quadrant four reports ignored for up to kMaxConsecutiveOldReports times. | |
600 // After that, the window is reset. | |
601 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourReset) { | |
602 for (uint16_t base : kBases) { | |
603 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | |
604 | |
605 // Expected window contents: [] -> [1001110001]. | |
606 AddTransportFeedbackAndValidate( | |
607 &tracker, base, | |
608 {true, false, false, true, true, true, false, false, false, true}); | |
609 | |
610 // Sanity | |
611 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 2.0f / 9.0f); | |
612 | |
613 // The first kMaxConsecutiveOldReports quadrant #4 reports are ignored. | |
614 // It doesn't matter that they consist of multiple packets - each report | |
615 // is only counted once. | |
616 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
617 // Expected window contents: [1001110001] -> [1001110001]. | |
618 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, | |
619 {true, true, false, true}); | |
620 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 2.0f / 9.0f); | |
621 } | |
622 | |
623 // One additional feedback in quadrant #4 brings us over | |
624 // kMaxConsecutiveOldReports consecutive "old" reports, resetting the | |
625 // window. | |
626 // The new window is not completely empty - it's been seeded with the | |
627 // packets reported in the feedback that has triggered the reset. | |
628 // Note: The report doesn't have to be the same as the previous ones. | |
629 // Expected window contents: [1001110001] -> [10011]. | |
630 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, | |
631 {true, false, false, true, true}); | |
632 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | |
633 } | |
634 } | |
635 | |
636 // Feedbacks spanning multiple quadrant are treated correctly (Q1-Q2). | |
637 TEST(TransportFeedbackPacketLossTrackerTest, MultiQuadrantQ1Q2) { | |
638 for (uint16_t base : kBases) { | |
639 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | |
640 | |
641 // Expected window contents: [] -> [10011]. | |
642 AddTransportFeedbackAndValidate(&tracker, base, | |
643 {true, false, false, true, true}); | |
644 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | |
645 | |
646 // A feedback with entries in both quadrant #1 and #2 gets both counted: | |
647 // Expected window contents: [10011] -> [10011-GAP-1001]. | |
648 AddTransportFeedbackAndValidate(&tracker, base + 0x3ffe, | |
649 {true, false, false, true}); | |
650 ValidatePacketLossStatistics(tracker, 4.0f / 9.0f, 2.0f / 7.0f); | |
651 } | |
652 } | |
653 | |
654 // Feedbacks spanning multiple quadrant are treated correctly (Q2-Q3). | |
655 TEST(TransportFeedbackPacketLossTrackerTest, MultiQuadrantQ2Q3) { | |
656 for (uint16_t base : kBases) { | |
657 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | |
658 | |
659 // Expected window contents: [] -> [1001100001]. | |
660 AddTransportFeedbackAndValidate( | |
661 &tracker, base, | |
662 {true, false, false, true, true, false, false, false, false, true}); | |
663 ValidatePacketLossStatistics(tracker, 6.0f / 10.0f, 2.0f / 9.0f); | |
664 | |
665 // A feedback with entries in both quadrant #2 and #3 gets both counted, | |
666 // but only those from #3 trigger throwing out old entries from quadrant #1: | |
667 // Expected window contents: [1001100001] -> [01100001-GAP-1001]. | |
668 AddTransportFeedbackAndValidate(&tracker, base + 0x7ffe, | |
669 {true, false, false, true}); | |
670 ValidatePacketLossStatistics(tracker, 7.0f / 12.0f, 3.0f / 10.0f); | |
671 } | |
672 } | |
673 | |
674 // Feedbacks spanning multiple quadrant are treated correctly (Q3-Q4). | |
675 TEST(TransportFeedbackPacketLossTrackerTest, MultiQuadrantQ3Q4) { | |
676 for (uint16_t base : kBases) { | |
677 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | |
678 | |
679 // Expected window contents: [] -> [1001100001]. | |
680 AddTransportFeedbackAndValidate( | |
681 &tracker, base, | |
682 {true, false, false, true, true, false, false, false, false, true}); | |
683 ValidatePacketLossStatistics(tracker, 6.0f / 10.0f, 2.0f / 9.0f); | |
684 | |
685 // A feedback with entries in both quadrant #3 and #4 would have the entries | |
686 // from quadrant #3 shift enough quadrant #1 entries out of window, that | |
687 // by the time the #4 packets are examined, the moving baseline has made | |
688 // them into quadrant #3 packets. | |
689 // Expected window contents: [1001100001] -> [10011]. | |
690 AddTransportFeedbackAndValidate(&tracker, base + 0xbfff, | |
691 {true, false, false, true, true}); | |
692 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | |
693 } | |
694 } | |
695 | |
696 } // namespace webrtc | 547 } // namespace webrtc |
OLD | NEW |