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 SendPackets(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 SendPackets(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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 float expected_rplr) { | 116 float expected_rplr) { |
92 ValidatePacketLossStatistics(tracker, | 117 ValidatePacketLossStatistics(tracker, |
93 rtc::Optional<float>(expected_plr), | 118 rtc::Optional<float>(expected_plr), |
94 rtc::Optional<float>(expected_rplr)); | 119 rtc::Optional<float>(expected_rplr)); |
95 } | 120 } |
96 | 121 |
97 } // namespace | 122 } // namespace |
98 | 123 |
99 // Sanity check on an empty window. | 124 // Sanity check on an empty window. |
100 TEST(TransportFeedbackPacketLossTrackerTest, EmptyWindow) { | 125 TEST(TransportFeedbackPacketLossTrackerTest, EmptyWindow) { |
101 std::unique_ptr<TransportFeedback> feedback; | |
102 TransportFeedbackPacketLossTracker tracker(10, 5, 5); | 126 TransportFeedbackPacketLossTracker tracker(10, 5, 5); |
103 | 127 |
104 // PLR and RPLR reported as unknown before reception of first feedback. | 128 // PLR and RPLR reported as unknown before reception of first feedback. |
105 ValidatePacketLossStatistics(tracker, | 129 ValidatePacketLossStatistics(tracker, |
106 rtc::Optional<float>(), | 130 rtc::Optional<float>(), |
107 rtc::Optional<float>()); | 131 rtc::Optional<float>()); |
108 } | 132 } |
109 | 133 |
| 134 // A feedback received for an empty window has no effect. |
| 135 TEST(TransportFeedbackPacketLossTrackerTest, EmptyWindowFeedback) { |
| 136 for (uint16_t base : kBases) { |
| 137 TransportFeedbackPacketLossTracker tracker(3, 3, 2); |
| 138 |
| 139 // Feedback doesn't correspond to any packets - ignored. |
| 140 AddTransportFeedbackAndValidate(&tracker, base, {true, false, true}); |
| 141 ValidatePacketLossStatistics(tracker, |
| 142 rtc::Optional<float>(), |
| 143 rtc::Optional<float>()); |
| 144 |
| 145 // After the packets are transmitted, acking them would have an effect. |
| 146 SendPacketRange(&tracker, base, 3); |
| 147 AddTransportFeedbackAndValidate(&tracker, base, {true, false, true}); |
| 148 ValidatePacketLossStatistics(tracker, 1.0 / 3.0, 0.5); |
| 149 } |
| 150 } |
| 151 |
110 // Sanity check on partially filled window. | 152 // Sanity check on partially filled window. |
111 TEST(TransportFeedbackPacketLossTrackerTest, PlrPartiallyFilledWindow) { | 153 TEST(TransportFeedbackPacketLossTrackerTest, PartiallyFilledWindow) { |
112 for (uint16_t base : kBases) { | 154 for (uint16_t base : kBases) { |
113 TransportFeedbackPacketLossTracker tracker(10, 5, 4); | 155 TransportFeedbackPacketLossTracker tracker(10, 5, 4); |
114 | 156 |
115 // PLR unknown before minimum window size reached. | 157 // PLR unknown before minimum window size reached. |
116 // RPLR unknown before minimum pairs reached. | 158 // RPLR unknown before minimum pairs reached. |
117 // Expected window contents: [] -> [1001]. | 159 // Expected window contents: [] -> [1001]. |
| 160 SendPacketRange(&tracker, base, 3); |
118 AddTransportFeedbackAndValidate(&tracker, base, {true, false, false, true}); | 161 AddTransportFeedbackAndValidate(&tracker, base, {true, false, false, true}); |
119 ValidatePacketLossStatistics(tracker, | 162 ValidatePacketLossStatistics(tracker, |
120 rtc::Optional<float>(), | 163 rtc::Optional<float>(), |
121 rtc::Optional<float>()); | 164 rtc::Optional<float>()); |
122 } | 165 } |
123 } | 166 } |
124 | 167 |
125 // Sanity check on minimum filled window - PLR known, RPLR unknown. | 168 // Sanity check on minimum filled window - PLR known, RPLR unknown. |
126 TEST(TransportFeedbackPacketLossTrackerTest, PlrMinimumFilledWindow) { | 169 TEST(TransportFeedbackPacketLossTrackerTest, PlrMinimumFilledWindow) { |
127 for (uint16_t base : kBases) { | 170 for (uint16_t base : kBases) { |
128 TransportFeedbackPacketLossTracker tracker(10, 5, 5); | 171 TransportFeedbackPacketLossTracker tracker(10, 5, 5); |
129 | 172 |
130 // PLR correctly calculated after minimum window size reached. | 173 // PLR correctly calculated after minimum window size reached. |
131 // RPLR not necessarily known at that time (not if min-pairs not reached). | 174 // RPLR not necessarily known at that time (not if min-pairs not reached). |
132 // Expected window contents: [] -> [10011]. | 175 // Expected window contents: [] -> [10011]. |
| 176 SendPacketRange(&tracker, base, 5); |
133 AddTransportFeedbackAndValidate(&tracker, base, | 177 AddTransportFeedbackAndValidate(&tracker, base, |
134 {true, false, false, true, true}); | 178 {true, false, false, true, true}); |
135 ValidatePacketLossStatistics(tracker, | 179 ValidatePacketLossStatistics(tracker, |
136 rtc::Optional<float>(2.0f / 5.0f), | 180 rtc::Optional<float>(2.0f / 5.0f), |
137 rtc::Optional<float>()); | 181 rtc::Optional<float>()); |
138 } | 182 } |
139 } | 183 } |
140 | 184 |
141 // Sanity check on minimum filled window - PLR unknown, RPLR known. | 185 // Sanity check on minimum filled window - PLR unknown, RPLR known. |
142 TEST(TransportFeedbackPacketLossTrackerTest, RplrMinimumFilledWindow) { | 186 TEST(TransportFeedbackPacketLossTrackerTest, RplrMinimumFilledWindow) { |
143 for (uint16_t base : kBases) { | 187 for (uint16_t base : kBases) { |
144 TransportFeedbackPacketLossTracker tracker(10, 6, 4); | 188 TransportFeedbackPacketLossTracker tracker(10, 6, 4); |
145 | 189 |
146 // RPLR correctly calculated after minimum pairs reached. | 190 // RPLR correctly calculated after minimum pairs reached. |
147 // PLR not necessarily known at that time (not if min window not reached). | 191 // PLR not necessarily known at that time (not if min window not reached). |
148 // Expected window contents: [] -> [10011]. | 192 // Expected window contents: [] -> [10011]. |
| 193 SendPacketRange(&tracker, base, 5); |
149 AddTransportFeedbackAndValidate(&tracker, base, | 194 AddTransportFeedbackAndValidate(&tracker, base, |
150 {true, false, false, true, true}); | 195 {true, false, false, true, true}); |
151 ValidatePacketLossStatistics(tracker, | 196 ValidatePacketLossStatistics(tracker, |
152 rtc::Optional<float>(), | 197 rtc::Optional<float>(), |
153 rtc::Optional<float>(1.0f / 4.0f)); | 198 rtc::Optional<float>(1.0f / 4.0f)); |
154 } | 199 } |
155 } | 200 } |
156 | 201 |
157 // Additional reports update PLR and RPLR. | 202 // Additional reports update PLR and RPLR. |
158 TEST(TransportFeedbackPacketLossTrackerTest, ExtendWindow) { | 203 TEST(TransportFeedbackPacketLossTrackerTest, ExtendWindow) { |
159 for (uint16_t base : kBases) { | 204 for (uint16_t base : kBases) { |
160 TransportFeedbackPacketLossTracker tracker(20, 5, 5); | 205 TransportFeedbackPacketLossTracker tracker(20, 5, 5); |
161 | 206 |
| 207 SendPacketRange(&tracker, base, 25); |
| 208 |
162 // Expected window contents: [] -> [10011]. | 209 // Expected window contents: [] -> [10011]. |
163 AddTransportFeedbackAndValidate(&tracker, base, | 210 AddTransportFeedbackAndValidate(&tracker, base, |
164 {true, false, false, true, true}); | 211 {true, false, false, true, true}); |
165 ValidatePacketLossStatistics(tracker, | 212 ValidatePacketLossStatistics(tracker, |
166 rtc::Optional<float>(2.0f / 5.0f), | 213 rtc::Optional<float>(2.0f / 5.0f), |
167 rtc::Optional<float>()); | 214 rtc::Optional<float>()); |
168 | 215 |
169 // Expected window contents: [10011] -> [1001110101]. | 216 // Expected window contents: [10011] -> [1001110101]. |
170 AddTransportFeedbackAndValidate(&tracker, base + 5, | 217 AddTransportFeedbackAndValidate(&tracker, base + 5, |
171 {true, false, true, false, true}); | 218 {true, false, true, false, true}); |
172 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); | 219 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); |
173 | 220 |
174 // Expected window contents: [1001110101] -> [1001110101-GAP-10001]. | 221 // Expected window contents: [1001110101] -> [1001110101-GAP-10001]. |
175 AddTransportFeedbackAndValidate(&tracker, base + 20, | 222 AddTransportFeedbackAndValidate(&tracker, base + 20, |
176 {true, false, false, false, true}); | 223 {true, false, false, false, true}); |
177 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 4.0f / 13.0f); | 224 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 4.0f / 13.0f); |
178 } | 225 } |
179 } | 226 } |
180 | 227 |
181 // All packets correctly received. | 228 // Sanity - all packets correctly received. |
182 TEST(TransportFeedbackPacketLossTrackerTest, AllReceived) { | 229 TEST(TransportFeedbackPacketLossTrackerTest, AllReceived) { |
183 for (uint16_t base : kBases) { | 230 for (uint16_t base : kBases) { |
184 TransportFeedbackPacketLossTracker tracker(10, 5, 4); | 231 TransportFeedbackPacketLossTracker tracker(10, 5, 4); |
185 | 232 |
186 // PLR and RPLR correctly calculated after minimum window size reached. | |
187 // Expected window contents: [] -> [11111]. | 233 // Expected window contents: [] -> [11111]. |
| 234 SendPacketRange(&tracker, base, 5); |
188 AddTransportFeedbackAndValidate(&tracker, base, | 235 AddTransportFeedbackAndValidate(&tracker, base, |
189 {true, true, true, true, true}); | 236 {true, true, true, true, true}); |
190 ValidatePacketLossStatistics(tracker, 0.0f, 0.0f); | 237 ValidatePacketLossStatistics(tracker, 0.0f, 0.0f); |
191 } | 238 } |
192 } | 239 } |
193 | 240 |
| 241 // Sanity - all packets lost. |
| 242 TEST(TransportFeedbackPacketLossTrackerTest, AllLost) { |
| 243 for (uint16_t base : kBases) { |
| 244 TransportFeedbackPacketLossTracker tracker(10, 5, 4); |
| 245 |
| 246 // Expected window contents: [] -> [00000]. |
| 247 SendPacketRange(&tracker, base, 5); |
| 248 // Note: Last acked packet (the received one) does not belong to the stream, |
| 249 // and is only there to make sure the feedback message is legal. |
| 250 AddTransportFeedbackAndValidate(&tracker, base, |
| 251 {false, false, false, false, false, true}); |
| 252 ValidatePacketLossStatistics(tracker, 1.0f, 0.0f); |
| 253 } |
| 254 } |
| 255 |
194 // Repeated reports are ignored. | 256 // Repeated reports are ignored. |
195 TEST(TransportFeedbackPacketLossTrackerTest, ReportRepetition) { | 257 TEST(TransportFeedbackPacketLossTrackerTest, ReportRepetition) { |
196 for (uint16_t base : kBases) { | 258 for (uint16_t base : kBases) { |
197 TransportFeedbackPacketLossTracker tracker(10, 5, 4); | 259 TransportFeedbackPacketLossTracker tracker(10, 5, 4); |
198 | 260 |
| 261 SendPacketRange(&tracker, base, 5); |
| 262 |
199 // Expected window contents: [] -> [10011]. | 263 // Expected window contents: [] -> [10011]. |
200 AddTransportFeedbackAndValidate(&tracker, base, | 264 AddTransportFeedbackAndValidate(&tracker, base, |
201 {true, false, false, true, true}); | 265 {true, false, false, true, true}); |
202 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | 266 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); |
203 | 267 |
204 // Repeat entire previous feedback | 268 // Repeat entire previous feedback |
205 // Expected window contents: [10011] -> [10011]. | 269 // Expected window contents: [10011] -> [10011]. |
206 AddTransportFeedbackAndValidate(&tracker, base, | 270 AddTransportFeedbackAndValidate(&tracker, base, |
207 {true, false, false, true, true}); | 271 {true, false, false, true, true}); |
208 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | 272 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); |
209 } | 273 } |
210 } | 274 } |
211 | 275 |
212 // Report overlap. | 276 // Report overlap. |
213 TEST(TransportFeedbackPacketLossTrackerTest, ReportOverlap) { | 277 TEST(TransportFeedbackPacketLossTrackerTest, ReportOverlap) { |
214 for (uint16_t base : kBases) { | 278 for (uint16_t base : kBases) { |
215 TransportFeedbackPacketLossTracker tracker(10, 5, 1); | 279 TransportFeedbackPacketLossTracker tracker(10, 5, 1); |
216 | 280 |
| 281 SendPacketRange(&tracker, base, 15); |
| 282 |
217 // Expected window contents: [] -> [10011]. | 283 // Expected window contents: [] -> [10011]. |
218 AddTransportFeedbackAndValidate(&tracker, base, | 284 AddTransportFeedbackAndValidate(&tracker, base, |
219 {true, false, false, true, true}); | 285 {true, false, false, true, true}); |
220 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | 286 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); |
221 | 287 |
222 // Expected window contents: [10011] -> [1001101]. | 288 // Expected window contents: [10011] -> [1001101]. |
223 AddTransportFeedbackAndValidate(&tracker, base + 3, | 289 AddTransportFeedbackAndValidate(&tracker, base + 3, |
224 {true, true, false, true}); | 290 {true, true, false, true}); |
225 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f); | 291 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f); |
226 } | 292 } |
227 } | 293 } |
228 | 294 |
229 // Report conflict. | 295 // Report conflict. |
230 TEST(TransportFeedbackPacketLossTrackerTest, ReportConflict) { | 296 TEST(TransportFeedbackPacketLossTrackerTest, ReportConflict) { |
231 for (uint16_t base : kBases) { | 297 for (uint16_t base : kBases) { |
232 TransportFeedbackPacketLossTracker tracker(10, 5, 4); | 298 TransportFeedbackPacketLossTracker tracker(10, 5, 4); |
233 | 299 |
| 300 SendPacketRange(&tracker, base, 15); |
| 301 |
234 // Expected window contents: [] -> [01001]. | 302 // Expected window contents: [] -> [01001]. |
235 AddTransportFeedbackAndValidate(&tracker, base, | 303 AddTransportFeedbackAndValidate(&tracker, base, |
236 {false, true, false, false, true}); | 304 {false, true, false, false, true}); |
237 ValidatePacketLossStatistics(tracker, 3.0f / 5.0f, 2.0f / 4.0f); | 305 ValidatePacketLossStatistics(tracker, 3.0f / 5.0f, 2.0f / 4.0f); |
238 | 306 |
239 // Expected window contents: [01001] -> [11101]. | 307 // Expected window contents: [01001] -> [11101]. |
240 // While false->true will be applied, true -> false will be ignored. | 308 // While false->true will be applied, true -> false will be ignored. |
241 AddTransportFeedbackAndValidate(&tracker, base, {true, false, true}); | 309 AddTransportFeedbackAndValidate(&tracker, base, {true, false, true}); |
242 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); | 310 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); |
243 } | 311 } |
244 } | 312 } |
245 | 313 |
246 // Skipped packets treated as unknown (not lost). | 314 // Skipped packets treated as unknown (not lost). |
247 TEST(TransportFeedbackPacketLossTrackerTest, SkippedPackets) { | 315 TEST(TransportFeedbackPacketLossTrackerTest, SkippedPackets) { |
248 for (uint16_t base : kBases) { | 316 for (uint16_t base : kBases) { |
249 TransportFeedbackPacketLossTracker tracker(10, 5, 1); | 317 TransportFeedbackPacketLossTracker tracker(10, 5, 1); |
250 | 318 |
| 319 SendPacketRange(&tracker, base, 200); |
| 320 |
251 // Expected window contents: [] -> [10011]. | 321 // Expected window contents: [] -> [10011]. |
252 AddTransportFeedbackAndValidate(&tracker, base, | 322 AddTransportFeedbackAndValidate(&tracker, base, |
253 {true, false, false, true, true}); | 323 {true, false, false, true, true}); |
254 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | 324 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); |
255 | 325 |
256 // Expected window contents: [10011] -> [10011-GAP-101]. | 326 // Expected window contents: [10011] -> [10011-GAP-101]. |
257 AddTransportFeedbackAndValidate(&tracker, base + 100, {true, false, true}); | 327 AddTransportFeedbackAndValidate(&tracker, base + 100, {true, false, true}); |
258 ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 6.0f); | 328 ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 6.0f); |
259 } | 329 } |
260 } | 330 } |
261 | 331 |
262 // The window retain information up to the configured max-window-size, but | 332 // The window retains information up to the configured max-window-size, but |
263 // starts discarding after that. | 333 // starts discarding after that. (Sent packets are not counted.) |
264 TEST(TransportFeedbackPacketLossTrackerTest, MaxWindowSize) { | 334 TEST(TransportFeedbackPacketLossTrackerTest, MaxWindowSize) { |
265 for (uint16_t base : kBases) { | 335 for (uint16_t base : kBases) { |
266 TransportFeedbackPacketLossTracker tracker(10, 10, 1); | 336 TransportFeedbackPacketLossTracker tracker(10, 10, 1); |
267 | 337 |
| 338 SendPacketRange(&tracker, base, 200); |
| 339 |
268 // Up to max-window-size retained. | 340 // Up to max-window-size retained. |
269 // Expected window contents: [] -> [1010100001]. | 341 // Expected window contents: [] -> [1010100001]. |
270 AddTransportFeedbackAndValidate( | 342 AddTransportFeedbackAndValidate( |
271 &tracker, base, | 343 &tracker, base, |
272 {true, false, true, false, true, false, false, false, false, true}); | 344 {true, false, true, false, true, false, false, false, false, true}); |
273 ValidatePacketLossStatistics(tracker, 6.0f / 10.0f, 3.0f / 9.0f); | 345 ValidatePacketLossStatistics(tracker, 6.0f / 10.0f, 3.0f / 9.0f); |
274 | 346 |
275 // After max-window-size, older entries discarded to accommodate newer ones. | 347 // After max-window-size, older entries discarded to accommodate newer ones. |
276 // Expected window contents: [1010100001] -> [0000110111]. | 348 // Expected window contents: [1010100001] -> [0000110111]. |
277 AddTransportFeedbackAndValidate(&tracker, base + 10, | 349 AddTransportFeedbackAndValidate(&tracker, base + 10, |
278 {true, false, true, true, true}); | 350 {true, false, true, true, true}); |
279 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 2.0f / 9.0f); | 351 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 2.0f / 9.0f); |
280 } | 352 } |
281 } | 353 } |
282 | 354 |
283 // Inserting into the middle of a full window works correctly. | 355 // Inserting a feedback into the middle of a full window works correctly. |
284 TEST(TransportFeedbackPacketLossTrackerTest, InsertIntoMiddle) { | 356 TEST(TransportFeedbackPacketLossTrackerTest, InsertIntoMiddle) { |
285 for (uint16_t base : kBases) { | 357 for (uint16_t base : kBases) { |
286 TransportFeedbackPacketLossTracker tracker(10, 5, 1); | 358 TransportFeedbackPacketLossTracker tracker(10, 5, 1); |
287 | 359 |
| 360 SendPacketRange(&tracker, base, 300); |
| 361 |
288 // Expected window contents: [] -> [10101]. | 362 // Expected window contents: [] -> [10101]. |
289 AddTransportFeedbackAndValidate(&tracker, base, | 363 AddTransportFeedbackAndValidate(&tracker, base, |
290 {true, false, true, false, true}); | 364 {true, false, true, false, true}); |
291 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); | 365 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); |
292 | 366 |
293 // Expected window contents: [10101] -> [10101-GAP-10001]. | 367 // Expected window contents: [10101] -> [10101-GAP-10001]. |
294 AddTransportFeedbackAndValidate(&tracker, base + 100, | 368 AddTransportFeedbackAndValidate(&tracker, base + 100, |
295 {true, false, false, false, true}); | 369 {true, false, false, false, true}); |
296 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 3.0f / 8.0f); | 370 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 3.0f / 8.0f); |
297 | 371 |
298 // Insert into the middle of this full window - it discards the older data. | 372 // Insert into the middle of this full window - it discards the older data. |
299 // Expected window contents: [10101-GAP-10001] -> [11111-GAP-10001]. | 373 // Expected window contents: [10101-GAP-10001] -> [11111-GAP-10001]. |
300 AddTransportFeedbackAndValidate(&tracker, base + 50, | 374 AddTransportFeedbackAndValidate(&tracker, base + 50, |
301 {true, true, true, true, true}); | 375 {true, true, true, true, true}); |
302 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 1.0f / 8.0f); | 376 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 1.0f / 8.0f); |
303 } | 377 } |
304 } | 378 } |
305 | 379 |
306 // Inserting into the middle of a full window works correctly. | 380 // Inserting feedback into the middle of a full window works correctly - can |
| 381 // complete two pairs. |
307 TEST(TransportFeedbackPacketLossTrackerTest, InsertionCompletesTwoPairs) { | 382 TEST(TransportFeedbackPacketLossTrackerTest, InsertionCompletesTwoPairs) { |
308 for (uint16_t base : kBases) { | 383 for (uint16_t base : kBases) { |
309 TransportFeedbackPacketLossTracker tracker(15, 5, 1); | 384 TransportFeedbackPacketLossTracker tracker(15, 5, 1); |
310 | 385 |
| 386 SendPacketRange(&tracker, base, 300); |
| 387 |
311 // Expected window contents: [] -> [10111]. | 388 // Expected window contents: [] -> [10111]. |
312 AddTransportFeedbackAndValidate(&tracker, base, | 389 AddTransportFeedbackAndValidate(&tracker, base, |
313 {true, false, true, true, true}); | 390 {true, false, true, true, true}); |
314 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); | 391 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); |
315 | 392 |
316 // Expected window contents: [10111] -> [10111-GAP-10101]. | 393 // Expected window contents: [10111] -> [10111-GAP-10101]. |
317 AddTransportFeedbackAndValidate(&tracker, base + 7, | 394 AddTransportFeedbackAndValidate(&tracker, base + 7, |
318 {true, false, true, false, true}); | 395 {true, false, true, false, true}); |
319 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f); | 396 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f); |
320 | 397 |
321 // Insert in between, closing the gap completely. | 398 // Insert in between, closing the gap completely. |
322 // Expected window contents: [10111-GAP-10101] -> [101111010101]. | 399 // Expected window contents: [10111-GAP-10101] -> [101111010101]. |
323 AddTransportFeedbackAndValidate(&tracker, base + 5, {false, true}); | 400 AddTransportFeedbackAndValidate(&tracker, base + 5, {false, true}); |
324 ValidatePacketLossStatistics(tracker, 4.0f / 12.0f, 4.0f / 11.0f); | 401 ValidatePacketLossStatistics(tracker, 4.0f / 12.0f, 4.0f / 11.0f); |
325 } | 402 } |
326 } | 403 } |
327 | 404 |
328 // Entries in the second quadrant treated like those in the first. | 405 // The window can meaningfully hold up to 0x8000 SENT packets (of which only |
329 // The sequence number is used in a looped manner. 0xFFFF is followed by 0x0000. | 406 // 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) { | 407 TEST(TransportFeedbackPacketLossTrackerTest, SecondQuadrant) { |
333 for (uint16_t base : kBases) { | 408 for (uint16_t base : kBases) { |
334 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | 409 TransportFeedbackPacketLossTracker tracker(20, 5, 1); |
335 | 410 |
| 411 SendPacketRange(&tracker, base, 0x8000, false); |
| 412 |
336 // Expected window contents: [] -> [10011]. | 413 // Expected window contents: [] -> [10011]. |
337 AddTransportFeedbackAndValidate(&tracker, base, | 414 AddTransportFeedbackAndValidate(&tracker, base, |
338 {true, false, false, true, true}); | 415 {true, false, false, true, true}); |
339 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | 416 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); |
340 | 417 |
341 // Window *does* get updated with inputs from quadrant #2. | 418 // Window *does* get updated with inputs from quadrant #2. |
342 // Expected window contents: [10011] -> [100111]. | 419 // Expected window contents: [10011] -> [100111]. |
343 AddTransportFeedbackAndValidate(&tracker, base + 0x4321, {true}); | 420 AddTransportFeedbackAndValidate(&tracker, base + 0x4321, {true}); |
344 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 1.0f / 4.0f); | 421 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 1.0f / 4.0f); |
345 | 422 |
346 // Correct recognition of quadrant #2: up to, but not including, base + | 423 // Correct recognition of quadrant #2: up to, but not including, base + |
347 // 0x8000 | 424 // 0x8000 |
348 // Expected window contents: [100111] -> [1001111]. | 425 // Expected window contents: [100111] -> [1001111]. |
349 AddTransportFeedbackAndValidate(&tracker, base + 0x7fff, {true}); | 426 AddTransportFeedbackAndValidate(&tracker, base + 0x7fff, {true}); |
350 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 1.0f / 4.0f); | 427 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 1.0f / 4.0f); |
351 } | 428 } |
352 } | 429 } |
353 | 430 |
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 | 431 // 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 | 432 // 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 | 433 // correct PLR and RPLR. Insertion into the middle before the max window size |
384 // achieved does not cause older packets to be dropped. | 434 // has been achieved does not cause older packets to be dropped. |
385 TEST(TransportFeedbackPacketLossTrackerTest, InsertIntoMiddleAfterBaseMove) { | 435 TEST(TransportFeedbackPacketLossTrackerTest, InsertIntoMiddleAfterBaseMoved) { |
386 for (uint16_t base : kBases) { | 436 for (uint16_t base : kBases) { |
387 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | 437 TransportFeedbackPacketLossTracker tracker(20, 5, 1); |
388 | 438 |
389 // Seed the test. | 439 SendPacketRange(&tracker, base, 20); |
| 440 SendPacketRange(&tracker, base + 0x5000, 20); |
| 441 |
390 // Expected window contents: [] -> [1001101]. | 442 // Expected window contents: [] -> [1001101]. |
391 AddTransportFeedbackAndValidate( | 443 AddTransportFeedbackAndValidate( |
392 &tracker, base, {true, false, false, true, true, false, true}); | 444 &tracker, base, {true, false, false, true, true, false, true}); |
393 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f); | 445 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f); |
394 | 446 |
395 // Expected window contents: [1001101] -> [101-GAP-1001]. | 447 // Expected window contents: [1001101] -> [101-GAP-1001]. |
| 448 SendPacketRange(&tracker, base + 0x8000, 4); |
396 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | 449 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, |
397 {true, false, false, true}); | 450 {true, false, false, true}); |
398 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 5.0f); | 451 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 5.0f); |
399 | 452 |
400 // Inserting into the middle still works after the base has shifted. | 453 // Inserting into the middle still works after the base has shifted. |
401 // Expected window contents: | 454 // Expected window contents: |
402 // [101-GAP-1001] -> [101-GAP-100101-GAP-1001] | 455 // [101-GAP-1001] -> [101-GAP-100101-GAP-1001] |
403 AddTransportFeedbackAndValidate(&tracker, base + 0x5000, | 456 AddTransportFeedbackAndValidate(&tracker, base + 0x5000, |
404 {true, false, false, true, false, true}); | 457 {true, false, false, true, false, true}); |
405 ValidatePacketLossStatistics(tracker, 6.0f / 13.0f, 4.0f / 10.0f); | 458 ValidatePacketLossStatistics(tracker, 6.0f / 13.0f, 4.0f / 10.0f); |
406 | 459 |
407 // The base can keep moving after inserting into the middle. | 460 // The base can keep moving after inserting into the middle. |
408 // Expected window contents: | 461 // Expected window contents: |
409 // [101-GAP-100101-GAP-1001] -> [1-GAP-100101-GAP-100111]. | 462 // [101-GAP-100101-GAP-1001] -> [1-GAP-100101-GAP-100111]. |
| 463 SendPacketRange(&tracker, base + 0x8000 + 4, 2); |
410 AddTransportFeedbackAndValidate(&tracker, base + 0x8000 + 4, {true, true}); | 464 AddTransportFeedbackAndValidate(&tracker, base + 0x8000 + 4, {true, true}); |
411 ValidatePacketLossStatistics(tracker, 5.0f / 13.0f, 3.0f / 10.0f); | 465 ValidatePacketLossStatistics(tracker, 5.0f / 13.0f, 3.0f / 10.0f); |
412 } | 466 } |
413 } | 467 } |
414 | 468 |
415 // After moving the base of the window, the max window size is still observed. | 469 // After moving the base of the window, the max window size is still observed. |
416 TEST(TransportFeedbackPacketLossTrackerTest, ThirdQuadrantObservesMaxWindow) { | 470 TEST(TransportFeedbackPacketLossTrackerTest, MaxWindowObservedAfterBaseMoved) { |
417 for (uint16_t base : kBases) { | 471 for (uint16_t base : kBases) { |
418 TransportFeedbackPacketLossTracker tracker(15, 10, 1); | 472 TransportFeedbackPacketLossTracker tracker(15, 10, 1); |
419 | 473 |
420 // Expected window contents: [] -> [1001110101]. | 474 // Expected window contents: [] -> [1001110101]. |
| 475 SendPacketRange(&tracker, base, 10); |
421 AddTransportFeedbackAndValidate( | 476 AddTransportFeedbackAndValidate( |
422 &tracker, base, | 477 &tracker, base, |
423 {true, false, false, true, true, true, false, true, false, true}); | 478 {true, false, false, true, true, true, false, true, false, true}); |
424 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); | 479 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); |
425 | 480 |
| 481 // Create gap (on both sides). |
| 482 SendPacketRange(&tracker, base + 0x4000, 20); |
| 483 |
426 // Expected window contents: [1001110101] -> [1110101-GAP-101]. | 484 // Expected window contents: [1001110101] -> [1110101-GAP-101]. |
| 485 SendPacketRange(&tracker, base + 0x8000, 3); |
427 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | 486 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, |
428 {true, false, true}); | 487 {true, false, true}); |
429 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f); | 488 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f); |
430 | 489 |
431 // Push into middle until max window is reached. | 490 // Push into middle until max window is reached. The gap is NOT completed. |
432 // Expected window contents: | 491 // Expected window contents: |
433 // [1110101-GAP-101] -> [1110101-GAP-10001-GAP-101] | 492 // [1110101-GAP-101] -> [1110101-GAP-10001-GAP-101] |
434 AddTransportFeedbackAndValidate(&tracker, base + 0x4000, | 493 AddTransportFeedbackAndValidate(&tracker, base + 0x4000 + 2, |
435 {true, false, false, false, true}); | 494 {true, false, false, false, true}); |
436 ValidatePacketLossStatistics(tracker, 6.0f / 15.0f, 4.0f / 12.0f); | 495 ValidatePacketLossStatistics(tracker, 6.0f / 15.0f, 4.0f / 12.0f); |
437 | 496 |
438 // Pushing new packets into the middle would discard older packets. | 497 // Pushing new packets into the middle would discard older packets. |
439 // Expected window contents: | 498 // Expected window contents: |
440 // [1110101-GAP-10001-GAP-101] -> [0101-GAP-10001101-GAP-101] | 499 // [1110101-GAP-10001-GAP-101] -> [0101-GAP-10001101-GAP-101] |
441 AddTransportFeedbackAndValidate(&tracker, base + 0x4000 + 5, | 500 AddTransportFeedbackAndValidate(&tracker, base + 0x4000 + 2 + 5, |
442 {true, false, true}); | 501 {true, false, true}); |
443 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 5.0f / 12.0f); | 502 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 5.0f / 12.0f); |
444 } | 503 } |
445 } | 504 } |
446 | 505 |
447 // A new feedback in quadrant #3 might shift enough old feedbacks out of window, | 506 // 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. | 507 // out window, that we'd go back to an unknown PLR and RPLR. |
449 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantThreeMovedBaseMinWindow) { | 508 TEST(TransportFeedbackPacketLossTrackerTest, NewPacketMovesWindowBase) { |
450 for (uint16_t base : kBases) { | 509 for (uint16_t base : kBases) { |
451 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | 510 TransportFeedbackPacketLossTracker tracker(20, 5, 3); |
| 511 |
| 512 SendPacketRange(&tracker, base, 50); |
| 513 SendPacketRange(&tracker, base + 0x4000 - 1, 6); // Gap |
452 | 514 |
453 // Expected window contents: [] -> [1001110101]. | 515 // Expected window contents: [] -> [1001110101]. |
454 AddTransportFeedbackAndValidate( | 516 AddTransportFeedbackAndValidate( |
455 &tracker, base, | 517 &tracker, base, |
456 {true, false, false, true, true, true, false, true, false, true}); | 518 {true, false, false, true, true, true, false, true, false, true}); |
457 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); | 519 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); |
458 | 520 |
459 // A new feedback in quadrant #3 might shift enough old feedbacks out of | 521 // 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* | 522 // 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. | 523 // and RPLR. This *doesn't* // necessarily mean all of the old ones |
462 // Expected window contents: [1001110101] -> [01-GAP-11]. | 524 // were discarded, though. |
| 525 // Expected window contents: [1001110101] -> [01]. |
| 526 SendPacketRange(&tracker, base + 0x8006, 2); |
| 527 ValidatePacketLossStatistics(tracker, |
| 528 rtc::Optional<float>(), // Still invalid. |
| 529 rtc::Optional<float>()); |
| 530 |
| 531 // Even if those messages are acked, we'd still might be in unknown PLR |
| 532 // and RPLR, because we might have shifted more packets out of the window |
| 533 // than we have inserted. |
| 534 // Expected window contents: [01] -> [01-GAP-11]. |
463 AddTransportFeedbackAndValidate(&tracker, base + 0x8006, {true, true}); | 535 AddTransportFeedbackAndValidate(&tracker, base + 0x8006, {true, true}); |
464 ValidatePacketLossStatistics(tracker, | 536 ValidatePacketLossStatistics(tracker, |
465 rtc::Optional<float>(), // Still invalid. | 537 rtc::Optional<float>(), // Still invalid. |
466 rtc::Optional<float>(1.0f / 2.0f)); | 538 rtc::Optional<float>()); |
467 | 539 |
468 // Inserting in the middle shows that though some of the elements were | 540 // Inserting in the middle shows that though some of the elements were |
469 // ejected, some were retained. | 541 // ejected, some were retained. |
470 // Expected window contents: [01-GAP-11] -> [01-GAP-1001-GAP-11]. | 542 // Expected window contents: [01-GAP-11] -> [01-GAP-1001-GAP-11]. |
471 AddTransportFeedbackAndValidate(&tracker, base + 0x4000, | 543 AddTransportFeedbackAndValidate(&tracker, base + 0x4000, |
472 {true, false, false, true}); | 544 {true, false, false, true}); |
473 ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 5.0f); | 545 ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 5.0f); |
474 } | 546 } |
475 } | 547 } |
476 | 548 |
477 // Quadrant four reports ignored for up to kMaxConsecutiveOldReports times. | 549 // Sequence number gaps are not gaps in reception. However, gaps in reception |
478 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourInitiallyIgnored) { | 550 // are still possible, if a packet which WAS sent on the stream is not acked. |
| 551 TEST(TransportFeedbackPacketLossTrackerTest, SanityGapsInSequenceNumbers) { |
479 for (uint16_t base : kBases) { | 552 for (uint16_t base : kBases) { |
480 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | 553 TransportFeedbackPacketLossTracker tracker(20, 5, 1); |
481 | 554 |
482 // Expected window contents: [] -> [10011]. | 555 SendPackets(&tracker, {base, base + 2, base + 4, base + 6, base + 8}); |
483 AddTransportFeedbackAndValidate(&tracker, base, | |
484 {true, false, false, true, true}); | |
485 | 556 |
486 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | 557 // Gaps in sequence numbers not considered as gaps in window, because only |
487 // consecutive reports). | 558 // those sequence numbers which were associated with the stream count. |
488 // Expected window contents: [10011] -> [10011]. | 559 // Expected window contents: [] -> [11011]. |
489 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | 560 AddTransportFeedbackAndValidate( |
490 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, {true, true}); | 561 // Note: Left packets belong to this stream, odd ones ignored. |
491 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); | 562 &tracker, base, {true, false, |
492 } | 563 true, false, |
| 564 false, false, |
| 565 true, false, |
| 566 true, true}); |
| 567 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); |
| 568 |
| 569 // Create gap by sending [base + 10] but not acking it. |
| 570 // Note: Acks for [base + 11] and [base + 13] ignored (other stream). |
| 571 // Expected window contents: [11011] -> [11011-GAP-01]. |
| 572 SendPackets(&tracker, {base + 10, base + 12, base + 14}); |
| 573 AddTransportFeedbackAndValidate(&tracker, base + 11, |
| 574 {false, false, false, true, true}); |
| 575 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 2.0f / 5.0f); |
493 } | 576 } |
494 } | 577 } |
495 | 578 |
496 // Receiving a packet from quadrant #1 resets the counter for quadrant #4. | 579 // Sending a packet which is less than 0x8000 away from the baseline does |
497 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourCounterResetByQ1) { | 580 // not move the window. |
| 581 TEST(TransportFeedbackPacketLossTrackerTest, UnackedInWindowDoesNotMoveWindow) { |
498 for (uint16_t base : kBases) { | 582 for (uint16_t base : kBases) { |
499 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | 583 TransportFeedbackPacketLossTracker tracker(5, 3, 1); |
500 | 584 |
501 // Expected window contents: [] -> [10011]. | 585 // Baseline - window has acked messages. |
| 586 // Expected window contents: [] -> [10101]. |
| 587 SendPacketRange(&tracker, base, 5); |
502 AddTransportFeedbackAndValidate(&tracker, base, | 588 AddTransportFeedbackAndValidate(&tracker, base, |
503 {true, false, false, true, true}); | 589 {true, false, true, false, true}); |
| 590 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); |
504 | 591 |
505 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | 592 // Test - window not moved. |
506 // consecutive reports). | 593 // Expected window contents: [10101] -> [10101]. |
507 // Expected window contents: [10011] -> [10011]. | 594 SendPackets(&tracker, {base + 0x7fff}); |
508 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | 595 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); |
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 } | 596 } |
535 } | 597 } |
536 | 598 |
537 // Receiving a packet from quadrant #2 resets the counter for quadrant #4. | 599 // Sending a packet which is at least 0x8000 away from the baseline, but not |
538 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourCounterResetByQ2) { | 600 // 0x8000 or more away from the newest packet in the window, moves the window, |
| 601 // but does not reset it. |
| 602 TEST(TransportFeedbackPacketLossTrackerTest, UnackedOutOfWindowMovesWindow) { |
539 for (uint16_t base : kBases) { | 603 for (uint16_t base : kBases) { |
540 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | 604 TransportFeedbackPacketLossTracker tracker(5, 3, 1); |
541 | 605 |
542 // Expected window contents: [] -> [10011]. | 606 // Baseline - window has acked messages. |
| 607 // Expected window contents: [] -> [10101]. |
| 608 SendPacketRange(&tracker, base, 5); |
543 AddTransportFeedbackAndValidate(&tracker, base, | 609 AddTransportFeedbackAndValidate(&tracker, base, |
544 {true, false, false, true, true}); | 610 {true, false, true, false, true}); |
| 611 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); |
545 | 612 |
546 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | 613 // 0x8000 from baseline, but only 0x7ffc from newest - window moved. |
547 // consecutive reports). | 614 // Expected window contents: [10101] -> [0101]. |
548 // Expected window contents: [10011] -> [10011]. | 615 SendPackets(&tracker, {base + 0x8000}); |
549 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | 616 ValidatePacketLossStatistics(tracker, 2.0f / 4.0f, 2.0f / 3.0f); |
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 } | 617 } |
565 } | 618 } |
566 | 619 |
567 // Receiving a packet from quadrant #3 resets the counter for quadrant #4. | 620 // TODO(elad.alon): More tests possible here, but a CL is in the pipeline which |
568 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourCounterResetByQ3) { | 621 // significantly changes the entire class's operation (makes the window |
| 622 // time-based), so no sense in writing complicated UTs which will be replaced |
| 623 // very soon. |
| 624 |
| 625 // The window is reset by the sending of a packet which is 0x8000 or more |
| 626 // away from the newest packet. |
| 627 TEST(TransportFeedbackPacketLossTrackerTest, WindowResetAfterLongNoSend) { |
569 for (uint16_t base : kBases) { | 628 for (uint16_t base : kBases) { |
570 TransportFeedbackPacketLossTracker tracker(20, 5, 1); | 629 TransportFeedbackPacketLossTracker tracker(10, 2, 1); |
571 | 630 |
572 // Expected window contents: [] -> [1001110001]. | 631 // Baseline - window has acked messages. |
573 AddTransportFeedbackAndValidate( | 632 // Expected window contents: [] -> [1-GAP-10101]. |
574 &tracker, base, | 633 SendPacketRange(&tracker, base, 1); |
575 {true, false, false, true, true, true, false, false, false, true}); | 634 SendPacketRange(&tracker, base + 0x7fff - 4, 5); |
| 635 AddTransportFeedbackAndValidate(&tracker, base, {true}); |
| 636 AddTransportFeedbackAndValidate(&tracker, base + 0x7fff - 4, |
| 637 {true, false, true, false, true}); |
| 638 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 2.0f / 5.0f); |
576 | 639 |
577 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | 640 // Sent packet too new - the entire window is reset. |
578 // consecutive reports). | 641 // Expected window contents: [1-GAP-10101] -> []. |
579 // Expected window contents: [1001110001] -> [1001110001]. | 642 SendPacketRange(&tracker, base + 0x7fff + 0x8000, 1); |
580 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | 643 ValidatePacketLossStatistics(tracker, |
581 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, {true, true}); | 644 rtc::Optional<float>(), |
582 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 2.0f / 9.0f); | 645 rtc::Optional<float>()); |
583 } | |
584 | 646 |
585 // If we receive a feedback in quadrant #1, the above counter is reset. | 647 // To show it was really reset, prove show that acking the sent packet |
586 // Expected window contents: [1001110001] -> [1110001-GAP-111]. | 648 // still leaves us at unknown, because no acked (or unacked) packets were |
587 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | 649 // left in the window. |
588 {true, true, true}); | 650 // Expected window contents: [] -> [1]. |
589 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | 651 AddTransportFeedbackAndValidate(&tracker, base + 0x7fff + 0x8000, {true}); |
590 // Note: though the feedback message reports three packets, it only gets | 652 ValidatePacketLossStatistics(tracker, |
591 // counted once. | 653 rtc::Optional<float>(), |
592 AddTransportFeedbackAndValidate(&tracker, base + 0xc000 + 10, | 654 rtc::Optional<float>()); |
593 {true, false, true}); | |
594 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 1.0f / 8.0f); | |
595 } | |
596 } | 655 } |
597 } | 656 } |
598 | 657 |
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 | 658 } // namespace webrtc |
OLD | NEW |