Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(167)

Side by Side Diff: webrtc/voice_engine/transport_feedback_packet_loss_tracker_unittest.cc

Issue 2711473003: R/PLR calculation - time-based window (Closed)
Patch Set: Individual probabilities explicitly stated, not cumulative. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <numeric>
14 #include <vector> 14 #include <vector>
15 15
16 #include "webrtc/base/checks.h" 16 #include "webrtc/base/checks.h"
17 #include "webrtc/base/mod_ops.h"
18 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h" 17 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
19 #include "webrtc/test/gmock.h" 18 #include "webrtc/test/gmock.h"
20 #include "webrtc/test/gtest.h" 19 #include "webrtc/test/gtest.h"
21 #include "webrtc/voice_engine/transport_feedback_packet_loss_tracker.h" 20 #include "webrtc/voice_engine/transport_feedback_packet_loss_tracker.h"
22 21
23 using webrtc::rtcp::TransportFeedback;
24
25 namespace webrtc { 22 namespace webrtc {
26 23
27 namespace { 24 namespace {
28 25
29 class TransportFeedbackPacketLossTrackerTest 26 class TransportFeedbackPacketLossTrackerTest
30 : public ::testing::TestWithParam<uint16_t> { 27 : public ::testing::TestWithParam<uint16_t> {
28 using TransportFeedback = webrtc::rtcp::TransportFeedback;
29
31 public: 30 public:
32 TransportFeedbackPacketLossTrackerTest() = default; 31 TransportFeedbackPacketLossTrackerTest() = default;
33 virtual ~TransportFeedbackPacketLossTrackerTest() = default; 32 virtual ~TransportFeedbackPacketLossTrackerTest() = default;
34 33
35 protected: 34 protected:
36 uint16_t base_{GetParam()}; 35 void SendPackets(TransportFeedbackPacketLossTracker* tracker,
36 const std::vector<uint16_t>& sequence_numbers,
37 bool validate_all = true) {
38 for (uint16_t sequence_number : sequence_numbers) {
39 tracker->OnPacketAdded(sequence_number, time_ms_++);
40 if (validate_all) {
41 tracker->Validate();
42 }
43 }
37 44
38 private: 45 // We've either validated after each packet, or, for making sure the UT
39 RTC_DISALLOW_COPY_AND_ASSIGN(TransportFeedbackPacketLossTrackerTest); 46 // doesn't run too long, we might validate only at the end of the range.
40 }; 47 if (!validate_all) {
41
42 void SendPackets(TransportFeedbackPacketLossTracker* tracker,
43 const std::vector<uint16_t>& seq_nums,
44 bool validate_all = true) {
45 for (uint16_t seq_num : seq_nums) {
46 tracker->OnPacketAdded(seq_num);
47 if (validate_all) {
48 tracker->Validate(); 48 tracker->Validate();
49 } 49 }
50 } 50 }
51 51
52 // We've either validated after each packet, or, for making sure the UT 52 void SendPackets(TransportFeedbackPacketLossTracker* tracker,
53 // doesn't run too long, we might validate only at the end of the range. 53 uint16_t first_seq_num,
54 if (!validate_all) { 54 size_t num_of_packets,
55 bool validate_all = true) {
56 std::vector<uint16_t> sequence_numbers(num_of_packets);
57 std::iota(sequence_numbers.begin(), sequence_numbers.end(), first_seq_num);
58 SendPackets(tracker, sequence_numbers, validate_all);
59 }
60
61 void Wait(int64_t time_delta_ms) {
62 RTC_CHECK_GT(time_delta_ms, 0);
63 time_ms_ += time_delta_ms;
64 }
65
66 void AddTransportFeedbackAndValidate(
67 TransportFeedbackPacketLossTracker* tracker,
68 uint16_t base_sequence_num,
69 const std::vector<bool>& reception_status_vec) {
70 const int64_t kBaseTimeUs = 1234; // Irrelevant to this test.
71 TransportFeedback test_feedback;
72 test_feedback.SetBase(base_sequence_num, kBaseTimeUs);
73 uint16_t sequence_num = base_sequence_num;
74 for (bool status : reception_status_vec) {
75 if (status)
76 test_feedback.AddReceivedPacket(sequence_num, kBaseTimeUs);
77 ++sequence_num;
78 }
79
80 // TransportFeedback imposes some limitations on what constitutes a legal
81 // status vector. For instance, the vector cannot terminate in a lost
82 // packet. Make sure all limitations are abided by.
83 RTC_CHECK_EQ(base_sequence_num, test_feedback.GetBaseSequence());
84 const auto& vec = test_feedback.GetStatusVector();
85 RTC_CHECK_EQ(reception_status_vec.size(), vec.size());
86 for (size_t i = 0; i < reception_status_vec.size(); i++) {
87 RTC_CHECK_EQ(reception_status_vec[i],
88 vec[i] != TransportFeedback::StatusSymbol::kNotReceived);
89 }
90
91 tracker->OnReceivedTransportFeedback(test_feedback);
55 tracker->Validate(); 92 tracker->Validate();
56 } 93 }
57 }
58 94
59 void SendPacketRange(TransportFeedbackPacketLossTracker* tracker, 95 // Checks that validty is as expected. If valid, checks also that
60 uint16_t first_seq_num, 96 // value is as expected.
61 size_t num_of_seq_nums, 97 void ValidatePacketLossStatistics(
62 bool validate_all = true) { 98 const TransportFeedbackPacketLossTracker& tracker,
63 std::vector<uint16_t> seq_nums(num_of_seq_nums); 99 rtc::Optional<float> expected_plr,
64 std::iota(seq_nums.begin(), seq_nums.end(), first_seq_num); 100 rtc::Optional<float> expected_rplr) {
65 SendPackets(tracker, seq_nums, validate_all); 101 // Comparing the rtc::Optional<float> directly would have given concise
66 } 102 // code, but less readable error messages.
103 rtc::Optional<float> plr = tracker.GetPacketLossRate();
104 EXPECT_EQ(static_cast<bool>(expected_plr), static_cast<bool>(plr));
105 if (expected_plr && plr) {
106 EXPECT_EQ(*expected_plr, *plr);
107 }
67 108
68 void AddTransportFeedbackAndValidate( 109 rtc::Optional<float> rplr = tracker.GetRecoverablePacketLossRate();
69 TransportFeedbackPacketLossTracker* tracker, 110 EXPECT_EQ(static_cast<bool>(expected_rplr), static_cast<bool>(rplr));
70 uint16_t base_sequence_num, 111 if (expected_rplr && rplr) {
71 const std::vector<bool>& reception_status_vec) { 112 EXPECT_EQ(*expected_rplr, *rplr);
72 const int64_t kBaseTimeUs = 1234; // Irrelevant to this test. 113 }
73 TransportFeedback test_feedback;
74 test_feedback.SetBase(base_sequence_num, kBaseTimeUs);
75 uint16_t sequence_num = base_sequence_num;
76 for (bool status : reception_status_vec) {
77 if (status)
78 test_feedback.AddReceivedPacket(sequence_num, kBaseTimeUs);
79 ++sequence_num;
80 } 114 }
81 115
82 // TransportFeedback imposes some limitations on what constitutes a legal 116 // Convenience function for when both are valid, and explicitly stating
83 // status vector. For instance, the vector cannot terminate in a lost 117 // the rtc::Optional<float> constructor is just cumbersome.
84 // packet. Make sure all limitations are abided by. 118 void ValidatePacketLossStatistics(
85 RTC_CHECK_EQ(base_sequence_num, test_feedback.GetBaseSequence()); 119 const TransportFeedbackPacketLossTracker& tracker,
86 const auto& vec = test_feedback.GetStatusVector(); 120 float expected_plr,
87 RTC_CHECK_EQ(reception_status_vec.size(), vec.size()); 121 float expected_rplr) {
88 for (size_t i = 0; i < reception_status_vec.size(); i++) { 122 ValidatePacketLossStatistics(tracker,
89 RTC_CHECK_EQ(reception_status_vec[i], 123 rtc::Optional<float>(expected_plr),
90 vec[i] != TransportFeedback::StatusSymbol::kNotReceived); 124 rtc::Optional<float>(expected_rplr));
91 } 125 }
92 126
93 tracker->OnReceivedTransportFeedback(test_feedback); 127 uint16_t base_{GetParam()};
94 tracker->Validate();
95 }
96 128
97 // Checks that validty is as expected. If valid, checks also that 129 private:
98 // value is as expected. 130 int64_t time_ms_{0};
99 void ValidatePacketLossStatistics(
100 const TransportFeedbackPacketLossTracker& tracker,
101 rtc::Optional<float> expected_plr,
102 rtc::Optional<float> expected_rplr) {
103 // Comparing the rtc::Optional<float> directly would have given concise code,
104 // but less readable error messages.
105 rtc::Optional<float> plr = tracker.GetPacketLossRate();
106 EXPECT_EQ(static_cast<bool>(expected_plr), static_cast<bool>(plr));
107 if (expected_plr && plr) {
108 EXPECT_EQ(*expected_plr, *plr);
109 }
110 131
111 rtc::Optional<float> rplr = tracker.GetRecoverablePacketLossRate(); 132 RTC_DISALLOW_COPY_AND_ASSIGN(TransportFeedbackPacketLossTrackerTest);
112 EXPECT_EQ(static_cast<bool>(expected_rplr), static_cast<bool>(rplr)); 133 };
113 if (expected_rplr && rplr) {
114 EXPECT_EQ(*expected_rplr, *rplr);
115 }
116 }
117
118 // Convenience function for when both are valid, and explicitly stating
119 // the rtc::Optional<float> constructor is just cumbersome.
120 void ValidatePacketLossStatistics(
121 const TransportFeedbackPacketLossTracker& tracker,
122 float expected_plr,
123 float expected_rplr) {
124 ValidatePacketLossStatistics(tracker,
125 rtc::Optional<float>(expected_plr),
126 rtc::Optional<float>(expected_rplr));
127 }
128 134
129 } // namespace 135 } // namespace
130 136
131 // Sanity check on an empty window. 137 // Sanity check on an empty window.
132 TEST(TransportFeedbackPacketLossTrackerTest, EmptyWindow) { 138 TEST_P(TransportFeedbackPacketLossTrackerTest, EmptyWindow) {
133 TransportFeedbackPacketLossTracker tracker(10, 5, 5); 139 TransportFeedbackPacketLossTracker tracker(5000, 5, 5);
134 140
135 // PLR and RPLR reported as unknown before reception of first feedback. 141 // PLR and RPLR reported as unknown before reception of first feedback.
136 ValidatePacketLossStatistics(tracker, 142 ValidatePacketLossStatistics(tracker,
137 rtc::Optional<float>(), 143 rtc::Optional<float>(),
138 rtc::Optional<float>()); 144 rtc::Optional<float>());
139 } 145 }
140 146
141 // A feedback received for an empty window has no effect. 147 // A feedback received for an empty window has no effect.
142 TEST_P(TransportFeedbackPacketLossTrackerTest, EmptyWindowFeedback) { 148 TEST_P(TransportFeedbackPacketLossTrackerTest, EmptyWindowFeedback) {
143 TransportFeedbackPacketLossTracker tracker(3, 3, 2); 149 TransportFeedbackPacketLossTracker tracker(5000, 3, 2);
144 150
145 // Feedback doesn't correspond to any packets - ignored. 151 // Feedback doesn't correspond to any packets - ignored.
146 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true}); 152 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true});
147 ValidatePacketLossStatistics(tracker, 153 ValidatePacketLossStatistics(tracker,
148 rtc::Optional<float>(), 154 rtc::Optional<float>(),
149 rtc::Optional<float>()); 155 rtc::Optional<float>());
150 156
151 // After the packets are transmitted, acking them would have an effect. 157 // After the packets are transmitted, acking them would have an effect.
152 SendPacketRange(&tracker, base_, 3); 158 SendPackets(&tracker, base_, 3);
153 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true}); 159 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true});
154 ValidatePacketLossStatistics(tracker, 1.0 / 3.0, 0.5); 160 ValidatePacketLossStatistics(tracker, 1.0 / 3.0, 0.5);
155 } 161 }
156 162
157 // Sanity check on partially filled window. 163 // Sanity check on partially filled window.
158 TEST_P(TransportFeedbackPacketLossTrackerTest, PartiallyFilledWindow) { 164 TEST_P(TransportFeedbackPacketLossTrackerTest, PartiallyFilledWindow) {
159 TransportFeedbackPacketLossTracker tracker(10, 5, 4); 165 TransportFeedbackPacketLossTracker tracker(5000, 5, 4);
160 166
161 // PLR unknown before minimum window size reached. 167 // PLR unknown before minimum window size reached.
162 // RPLR unknown before minimum pairs reached. 168 // RPLR unknown before minimum pairs reached.
163 // Expected window contents: [] -> [1001]. 169 // Expected window contents: [] -> [1001].
164 SendPacketRange(&tracker, base_, 3); 170 SendPackets(&tracker, base_, 3);
165 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, false, true}); 171 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, false, true});
166 ValidatePacketLossStatistics(tracker, 172 ValidatePacketLossStatistics(tracker,
167 rtc::Optional<float>(), 173 rtc::Optional<float>(),
168 rtc::Optional<float>()); 174 rtc::Optional<float>());
169 } 175 }
170 176
171 // Sanity check on minimum filled window - PLR known, RPLR unknown. 177 // Sanity check on minimum filled window - PLR known, RPLR unknown.
172 TEST_P(TransportFeedbackPacketLossTrackerTest, PlrMinimumFilledWindow) { 178 TEST_P(TransportFeedbackPacketLossTrackerTest, PlrMinimumFilledWindow) {
173 TransportFeedbackPacketLossTracker tracker(10, 5, 5); 179 TransportFeedbackPacketLossTracker tracker(5000, 5, 5);
174 180
175 // PLR correctly calculated after minimum window size reached. 181 // PLR correctly calculated after minimum window size reached.
176 // RPLR not necessarily known at that time (not if min-pairs not reached). 182 // RPLR not necessarily known at that time (not if min-pairs not reached).
177 // Expected window contents: [] -> [10011]. 183 // Expected window contents: [] -> [10011].
178 SendPacketRange(&tracker, base_, 5); 184 SendPackets(&tracker, base_, 5);
179 AddTransportFeedbackAndValidate(&tracker, base_, 185 AddTransportFeedbackAndValidate(&tracker, base_,
180 {true, false, false, true, true}); 186 {true, false, false, true, true});
181 ValidatePacketLossStatistics(tracker, 187 ValidatePacketLossStatistics(tracker,
182 rtc::Optional<float>(2.0f / 5.0f), 188 rtc::Optional<float>(2.0f / 5.0f),
183 rtc::Optional<float>()); 189 rtc::Optional<float>());
184 } 190 }
185 191
186 // Sanity check on minimum filled window - PLR unknown, RPLR known. 192 // Sanity check on minimum filled window - PLR unknown, RPLR known.
187 TEST_P(TransportFeedbackPacketLossTrackerTest, RplrMinimumFilledWindow) { 193 TEST_P(TransportFeedbackPacketLossTrackerTest, RplrMinimumFilledWindow) {
188 TransportFeedbackPacketLossTracker tracker(10, 6, 4); 194 TransportFeedbackPacketLossTracker tracker(5000, 6, 4);
189 195
190 // RPLR correctly calculated after minimum pairs reached. 196 // RPLR correctly calculated after minimum pairs reached.
191 // PLR not necessarily known at that time (not if min window not reached). 197 // PLR not necessarily known at that time (not if min window not reached).
192 // Expected window contents: [] -> [10011]. 198 // Expected window contents: [] -> [10011].
193 SendPacketRange(&tracker, base_, 5); 199 SendPackets(&tracker, base_, 5);
194 AddTransportFeedbackAndValidate(&tracker, base_, 200 AddTransportFeedbackAndValidate(&tracker, base_,
195 {true, false, false, true, true}); 201 {true, false, false, true, true});
196 ValidatePacketLossStatistics(tracker, 202 ValidatePacketLossStatistics(tracker,
197 rtc::Optional<float>(), 203 rtc::Optional<float>(),
198 rtc::Optional<float>(1.0f / 4.0f)); 204 rtc::Optional<float>(1.0f / 4.0f));
199 } 205 }
200 206
207 // If packets are sent close enough together that the clock reading for both
208 // is the same, that's handled properly.
209 TEST_P(TransportFeedbackPacketLossTrackerTest, CloseClockReads) {
210 TransportFeedbackPacketLossTracker tracker(5000, 3, 2);
211
212 constexpr int64_t time_ms = 5678; // Value doesn't matter.
213
214 // Expected window contents: [] -> [101].
215 tracker.OnPacketAdded(base_ + 0, time_ms);
216 tracker.OnPacketAdded(base_ + 1, time_ms);
217 tracker.OnPacketAdded(base_ + 2, time_ms);
218 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true});
219
220 ValidatePacketLossStatistics(tracker, 1.0f / 3.0f, 0.5f);
221 }
222
201 // Additional reports update PLR and RPLR. 223 // Additional reports update PLR and RPLR.
202 TEST_P(TransportFeedbackPacketLossTrackerTest, ExtendWindow) { 224 TEST_P(TransportFeedbackPacketLossTrackerTest, ExtendWindow) {
203 TransportFeedbackPacketLossTracker tracker(20, 5, 5); 225 TransportFeedbackPacketLossTracker tracker(5000, 5, 5);
204 226
205 SendPacketRange(&tracker, base_, 25); 227 SendPackets(&tracker, base_, 25);
206 228
207 // Expected window contents: [] -> [10011]. 229 // Expected window contents: [] -> [10011].
208 AddTransportFeedbackAndValidate(&tracker, base_, 230 AddTransportFeedbackAndValidate(&tracker, base_,
209 {true, false, false, true, true}); 231 {true, false, false, true, true});
210 ValidatePacketLossStatistics(tracker, 232 ValidatePacketLossStatistics(tracker,
211 rtc::Optional<float>(2.0f / 5.0f), 233 rtc::Optional<float>(2.0f / 5.0f),
212 rtc::Optional<float>()); 234 rtc::Optional<float>());
213 235
214 // Expected window contents: [10011] -> [1001110101]. 236 // Expected window contents: [10011] -> [1001110101].
215 AddTransportFeedbackAndValidate(&tracker, base_ + 5, 237 AddTransportFeedbackAndValidate(&tracker, base_ + 5,
216 {true, false, true, false, true}); 238 {true, false, true, false, true});
217 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); 239 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f);
218 240
219 // Expected window contents: [1001110101] -> [1001110101-GAP-10001]. 241 // Expected window contents: [1001110101] -> [1001110101-GAP-10001].
220 AddTransportFeedbackAndValidate(&tracker, base_ + 20, 242 AddTransportFeedbackAndValidate(&tracker, base_ + 20,
221 {true, false, false, false, true}); 243 {true, false, false, false, true});
222 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 4.0f / 13.0f); 244 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 4.0f / 13.0f);
223 } 245 }
224 246
225 // Sanity - all packets correctly received. 247 // Correct calculation with different packet lengths.
248 TEST_P(TransportFeedbackPacketLossTrackerTest, DifferentPacketLengthSanity) {
249 TransportFeedbackPacketLossTracker tracker(5000, 5, 4);
250
251 int64_t now_ms = 0;
252 int64_t frames[] = {20, 60, 120, 20, 60};
253 for (size_t i = 0; i < sizeof(frames) / sizeof(frames[0]); i++) {
254 tracker.OnPacketAdded(base_ + i, now_ms);
255 now_ms += frames[i];
256 }
257
258 // Expected window contents: [] -> [10011].
259 AddTransportFeedbackAndValidate(&tracker, base_,
260 {true, false, false, true, true});
261 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
262 }
263
264 // The window retain information up until the timestamps exceed the configured
265 // maximum. Then, the oldest packets get shifted out of window to make room
266 // for the newer ones.
267 TEST_P(TransportFeedbackPacketLossTrackerTest, MaxWindowSize) {
268 TransportFeedbackPacketLossTracker tracker(9, 10, 1);
269
270 SendPackets(&tracker, base_, 20);
271
272 // Up to the maximum time-span retained (first + 9 * 100ms).
273 // Expected window contents: [] -> [0110100001].
274 AddTransportFeedbackAndValidate(
275 &tracker, base_,
276 {false, true, true, false, true, false, false, false, false, true});
277 ValidatePacketLossStatistics(tracker, 6.0f / 10.0f, 3.0f / 9.0f);
278
279 // After the maximum time-span, older entries discarded to accommodate
280 // newer ones.
281 // Expected window contents: [0110100001] -> [1101000011].
282 AddTransportFeedbackAndValidate(&tracker, base_ + 10, {true});
283 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 2.0f / 9.0f);
284 }
285
286 // All packets received.
226 TEST_P(TransportFeedbackPacketLossTrackerTest, AllReceived) { 287 TEST_P(TransportFeedbackPacketLossTrackerTest, AllReceived) {
227 TransportFeedbackPacketLossTracker tracker(10, 5, 4); 288 TransportFeedbackPacketLossTracker tracker(5000, 5, 4);
228 289
229 // Expected window contents: [] -> [11111]. 290 // Expected window contents: [] -> [11111].
230 SendPacketRange(&tracker, base_, 5); 291 SendPackets(&tracker, base_, 5);
231 AddTransportFeedbackAndValidate(&tracker, base_, 292 AddTransportFeedbackAndValidate(&tracker, base_,
232 {true, true, true, true, true}); 293 {true, true, true, true, true});
233 ValidatePacketLossStatistics(tracker, 0.0f, 0.0f); 294 ValidatePacketLossStatistics(tracker, 0.0f, 0.0f);
234 } 295 }
235 296
236 // Sanity - all packets lost. 297 // All packets lost.
237 TEST_P(TransportFeedbackPacketLossTrackerTest, AllLost) { 298 TEST_P(TransportFeedbackPacketLossTrackerTest, AllLost) {
238 TransportFeedbackPacketLossTracker tracker(10, 5, 4); 299 TransportFeedbackPacketLossTracker tracker(5000, 5, 4);
239 300
301 // Note: The last packet in the feedback does not belong to the stream.
302 // It's only there because we're not allowed to end a feedback with a loss.
240 // Expected window contents: [] -> [00000]. 303 // Expected window contents: [] -> [00000].
241 SendPacketRange(&tracker, base_, 5); 304 SendPackets(&tracker, base_, 5);
242 // Note: Last acked packet (the received one) does not belong to the stream,
243 // and is only there to make sure the feedback message is legal.
244 AddTransportFeedbackAndValidate(&tracker, base_, 305 AddTransportFeedbackAndValidate(&tracker, base_,
245 {false, false, false, false, false, true}); 306 {false, false, false, false, false, true});
246 ValidatePacketLossStatistics(tracker, 1.0f, 0.0f); 307 ValidatePacketLossStatistics(tracker, 1.0f, 0.0f);
247 } 308 }
248 309
249 // Repeated reports are ignored. 310 // Repeated reports are ignored.
250 TEST_P(TransportFeedbackPacketLossTrackerTest, ReportRepetition) { 311 TEST_P(TransportFeedbackPacketLossTrackerTest, ReportRepetition) {
251 TransportFeedbackPacketLossTracker tracker(10, 5, 4); 312 TransportFeedbackPacketLossTracker tracker(5000, 5, 4);
252 313
253 SendPacketRange(&tracker, base_, 5); 314 SendPackets(&tracker, base_, 5);
254 315
255 // Expected window contents: [] -> [10011]. 316 // Expected window contents: [] -> [10011].
256 AddTransportFeedbackAndValidate(&tracker, base_, 317 AddTransportFeedbackAndValidate(&tracker, base_,
257 {true, false, false, true, true}); 318 {true, false, false, true, true});
258 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); 319 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
259 320
260 // Repeat entire previous feedback 321 // Repeat entire previous feedback
261 // Expected window contents: [10011] -> [10011]. 322 // Expected window contents: [10011] -> [10011].
262 AddTransportFeedbackAndValidate(&tracker, base_, 323 AddTransportFeedbackAndValidate(&tracker, base_,
263 {true, false, false, true, true}); 324 {true, false, false, true, true});
264 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); 325 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
265 } 326 }
266 327
267 // Report overlap. 328 // Report overlap.
268 TEST_P(TransportFeedbackPacketLossTrackerTest, ReportOverlap) { 329 TEST_P(TransportFeedbackPacketLossTrackerTest, ReportOverlap) {
269 TransportFeedbackPacketLossTracker tracker(10, 5, 1); 330 TransportFeedbackPacketLossTracker tracker(5000, 5, 1);
270 331
271 SendPacketRange(&tracker, base_, 15); 332 SendPackets(&tracker, base_, 15);
272 333
273 // Expected window contents: [] -> [10011]. 334 // Expected window contents: [] -> [10011].
274 AddTransportFeedbackAndValidate(&tracker, base_, 335 AddTransportFeedbackAndValidate(&tracker, base_,
275 {true, false, false, true, true}); 336 {true, false, false, true, true});
276 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); 337 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
277 338
278 // Expected window contents: [10011] -> [1001101]. 339 // Expected window contents: [10011] -> [1001101].
279 AddTransportFeedbackAndValidate(&tracker, base_ + 3, 340 AddTransportFeedbackAndValidate(&tracker, base_ + 3,
280 {true, true, false, true}); 341 {true, true, false, true});
281 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f); 342 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f);
282 } 343 }
283 344
284 // Report conflict. 345 // Report conflict.
285 TEST_P(TransportFeedbackPacketLossTrackerTest, ReportConflict) { 346 TEST_P(TransportFeedbackPacketLossTrackerTest, ReportConflict) {
286 TransportFeedbackPacketLossTracker tracker(10, 5, 4); 347 TransportFeedbackPacketLossTracker tracker(5000, 5, 4);
287 348
288 SendPacketRange(&tracker, base_, 15); 349 SendPackets(&tracker, base_, 15);
289 350
290 // Expected window contents: [] -> [01001]. 351 // Expected window contents: [] -> [01001].
291 AddTransportFeedbackAndValidate(&tracker, base_, 352 AddTransportFeedbackAndValidate(&tracker, base_,
292 {false, true, false, false, true}); 353 {false, true, false, false, true});
293 ValidatePacketLossStatistics(tracker, 3.0f / 5.0f, 2.0f / 4.0f); 354 ValidatePacketLossStatistics(tracker, 3.0f / 5.0f, 2.0f / 4.0f);
294 355
295 // Expected window contents: [01001] -> [11101]. 356 // Expected window contents: [01001] -> [11101].
296 // While false->true will be applied, true -> false will be ignored. 357 // While false->true will be applied, true -> false will be ignored.
297 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true}); 358 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true});
298 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); 359 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f);
299 } 360 }
300 361
301 // Skipped packets treated as unknown (not lost). 362 // Skipped packets treated as unknown (not lost).
302 TEST_P(TransportFeedbackPacketLossTrackerTest, SkippedPackets) { 363 TEST_P(TransportFeedbackPacketLossTrackerTest, SkippedPackets) {
303 TransportFeedbackPacketLossTracker tracker(10, 5, 1); 364 TransportFeedbackPacketLossTracker tracker(200 * 100, 5, 1);
304 365
305 SendPacketRange(&tracker, base_, 200); 366 SendPackets(&tracker, base_, 200);
306 367
307 // Expected window contents: [] -> [10011]. 368 // Expected window contents: [] -> [10011].
308 AddTransportFeedbackAndValidate(&tracker, base_, 369 AddTransportFeedbackAndValidate(&tracker, base_,
309 {true, false, false, true, true}); 370 {true, false, false, true, true});
310 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); 371 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
311 372
312 // Expected window contents: [10011] -> [10011-GAP-101]. 373 // Expected window contents: [10011] -> [10011-GAP-101].
313 AddTransportFeedbackAndValidate(&tracker, base_ + 100, {true, false, true}); 374 AddTransportFeedbackAndValidate(&tracker, base_ + 100, {true, false, true});
314 ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 6.0f); 375 ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 6.0f);
315 } 376 }
316 377
317 // The window retains information up to the configured max-window-size, but 378 // Moving a window, if if it excludes some old acked messages, can leave
318 // starts discarding after that. (Sent packets are not counted.) 379 // in-window unacked messages intact, and ready to be used later.
319 TEST_P(TransportFeedbackPacketLossTrackerTest, MaxWindowSize) { 380 TEST_P(TransportFeedbackPacketLossTrackerTest, MovedWindowRetainsRelevantInfo) {
320 TransportFeedbackPacketLossTracker tracker(10, 10, 1); 381 constexpr int64_t max_window_size_ms = 100;
382 TransportFeedbackPacketLossTracker tracker(max_window_size_ms, 5, 1);
321 383
322 SendPacketRange(&tracker, base_, 200); 384 // Note: All messages in this test are sent 1ms apart from each other.
323 385 SendPackets(&tracker, base_, 4 * max_window_size_ms);
324 // Up to max-window-size retained.
325 // Expected window contents: [] -> [1010100001].
326 AddTransportFeedbackAndValidate(
327 &tracker, base_,
328 {true, false, true, false, true, false, false, false, false, true});
329 ValidatePacketLossStatistics(tracker, 6.0f / 10.0f, 3.0f / 9.0f);
330
331 // After max-window-size, older entries discarded to accommodate newer ones.
332 // Expected window contents: [1010100001] -> [0000110111].
333 AddTransportFeedbackAndValidate(&tracker, base_ + 10,
334 {true, false, true, true, true});
335 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 2.0f / 9.0f);
336 }
337
338 // Inserting a feedback into the middle of a full window works correctly.
339 TEST_P(TransportFeedbackPacketLossTrackerTest, InsertIntoMiddle) {
340 TransportFeedbackPacketLossTracker tracker(10, 5, 1);
341
342 SendPacketRange(&tracker, base_, 300);
343 386
344 // Expected window contents: [] -> [10101]. 387 // Expected window contents: [] -> [10101].
345 AddTransportFeedbackAndValidate(&tracker, base_, 388 AddTransportFeedbackAndValidate(&tracker, base_,
346 {true, false, true, false, true}); 389 {true, false, true, false, true});
347 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); 390 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f);
348 391
349 // Expected window contents: [10101] -> [10101-GAP-10001]. 392 // Expected window contents: [10101] -> [100011].
350 AddTransportFeedbackAndValidate(&tracker, base_ + 100, 393 const int64_t moved_oldest_acked = base_ + 2 * max_window_size_ms;
351 {true, false, false, false, true}); 394 const std::vector<bool> feedback = {true, false, false, false, true, true};
352 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 3.0f / 8.0f); 395 AddTransportFeedbackAndValidate(&tracker, moved_oldest_acked, feedback);
396 ValidatePacketLossStatistics(tracker, 3.0f / 6.0f, 1.0f / 5.0f);
353 397
354 // Insert into the middle of this full window - it discards the older data. 398 // Having acked |feedback.size()| starting with |moved_oldest_acked|, the
355 // Expected window contents: [10101-GAP-10001] -> [11111-GAP-10001]. 399 // newest of the acked ones is now:
356 AddTransportFeedbackAndValidate(&tracker, base_ + 50, 400 const int64_t moved_newest_acked = moved_oldest_acked + feedback.size() - 1;
357 {true, true, true, true, true}); 401
358 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 1.0f / 8.0f); 402 // Messages that *are* more than the span-limit away from the newest
403 // acked message *are* too old. Acking them would have no effect.
404 AddTransportFeedbackAndValidate(
405 &tracker, moved_newest_acked - max_window_size_ms - 1, {true});
406 ValidatePacketLossStatistics(tracker, 3.0f / 6.0f, 1.0f / 5.0f);
407
408 // Messages that are *not* more than the span-limit away from the newest
409 // acked message are *not* too old. Acking them would have an effect.
410 AddTransportFeedbackAndValidate(
411 &tracker, moved_newest_acked - max_window_size_ms, {true});
412 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 1.0f / 5.0f);
359 } 413 }
360 414
361 // Inserting feedback into the middle of a full window works correctly - can 415 // Inserting feedback into the middle of a window works correctly - can
362 // complete two pairs. 416 // complete two pairs.
363 TEST_P(TransportFeedbackPacketLossTrackerTest, InsertionCompletesTwoPairs) { 417 TEST_P(TransportFeedbackPacketLossTrackerTest, InsertionCompletesTwoPairs) {
364 TransportFeedbackPacketLossTracker tracker(15, 5, 1); 418 TransportFeedbackPacketLossTracker tracker(1500, 5, 1);
365 419
366 SendPacketRange(&tracker, base_, 300); 420 SendPackets(&tracker, base_, 15);
367 421
368 // Expected window contents: [] -> [10111]. 422 // Expected window contents: [] -> [10111].
369 AddTransportFeedbackAndValidate(&tracker, base_, 423 AddTransportFeedbackAndValidate(&tracker, base_,
370 {true, false, true, true, true}); 424 {true, false, true, true, true});
371 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); 425 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f);
372 426
373 // Expected window contents: [10111] -> [10111-GAP-10101]. 427 // Expected window contents: [10111] -> [10111-GAP-10101].
374 AddTransportFeedbackAndValidate(&tracker, base_ + 7, 428 AddTransportFeedbackAndValidate(&tracker, base_ + 7,
375 {true, false, true, false, true}); 429 {true, false, true, false, true});
376 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f); 430 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f);
377 431
378 // Insert in between, closing the gap completely. 432 // Insert in between, closing the gap completely.
379 // Expected window contents: [10111-GAP-10101] -> [101111010101]. 433 // Expected window contents: [10111-GAP-10101] -> [101110110101].
380 AddTransportFeedbackAndValidate(&tracker, base_ + 5, {false, true}); 434 AddTransportFeedbackAndValidate(&tracker, base_ + 5, {false, true});
381 ValidatePacketLossStatistics(tracker, 4.0f / 12.0f, 4.0f / 11.0f); 435 ValidatePacketLossStatistics(tracker, 4.0f / 12.0f, 4.0f / 11.0f);
382 } 436 }
383 437
384 // The window can meaningfully hold up to 0x8000 SENT packets (of which only
385 // up to max-window acked messages will be kept and regarded).
386 TEST_P(TransportFeedbackPacketLossTrackerTest, SecondQuadrant) {
387 TransportFeedbackPacketLossTracker tracker(20, 5, 1);
388
389 SendPacketRange(&tracker, base_, 0x8000, false);
390
391 // Expected window contents: [] -> [10011].
392 AddTransportFeedbackAndValidate(&tracker, base_,
393 {true, false, false, true, true});
394 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
395
396 // Window *does* get updated with inputs from quadrant #2.
397 // Expected window contents: [10011] -> [100111].
398 AddTransportFeedbackAndValidate(&tracker, base_ + 0x4321, {true});
399 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 1.0f / 4.0f);
400
401 // Correct recognition of quadrant #2: up to, but not including, base_ +
402 // 0x8000
403 // Expected window contents: [100111] -> [1001111].
404 AddTransportFeedbackAndValidate(&tracker, base_ + 0x7fff, {true});
405 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 1.0f / 4.0f);
406 }
407
408 // After the base has moved due to insertion into the third quadrant, it is
409 // still possible to get feedbacks in the middle of the window and obtain the
410 // correct PLR and RPLR. Insertion into the middle before the max window size
411 // has been achieved does not cause older packets to be dropped.
412 TEST_P(TransportFeedbackPacketLossTrackerTest, InsertIntoMiddleAfterBaseMoved) {
413 TransportFeedbackPacketLossTracker tracker(20, 5, 1);
414
415 SendPacketRange(&tracker, base_, 20);
416 SendPacketRange(&tracker, base_ + 0x5000, 20);
417
418 // Expected window contents: [] -> [1001101].
419 AddTransportFeedbackAndValidate(
420 &tracker, base_, {true, false, false, true, true, false, true});
421 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f);
422
423 // Expected window contents: [1001101] -> [101-GAP-1001].
424 SendPacketRange(&tracker, base_ + 0x8000, 4);
425 AddTransportFeedbackAndValidate(&tracker, base_ + 0x8000,
426 {true, false, false, true});
427 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 5.0f);
428
429 // Inserting into the middle still works after the base has shifted.
430 // Expected window contents:
431 // [101-GAP-1001] -> [101-GAP-100101-GAP-1001]
432 AddTransportFeedbackAndValidate(&tracker, base_ + 0x5000,
433 {true, false, false, true, false, true});
434 ValidatePacketLossStatistics(tracker, 6.0f / 13.0f, 4.0f / 10.0f);
435
436 // The base can keep moving after inserting into the middle.
437 // Expected window contents:
438 // [101-GAP-100101-GAP-1001] -> [1-GAP-100101-GAP-100111].
439 SendPacketRange(&tracker, base_ + 0x8000 + 4, 2);
440 AddTransportFeedbackAndValidate(&tracker, base_ + 0x8000 + 4, {true, true});
441 ValidatePacketLossStatistics(tracker, 5.0f / 13.0f, 3.0f / 10.0f);
442 }
443
444 // After moving the base of the window, the max window size is still observed.
445 TEST_P(TransportFeedbackPacketLossTrackerTest,
446 MaxWindowObservedAfterBaseMoved) {
447 TransportFeedbackPacketLossTracker tracker(15, 10, 1);
448
449 // Expected window contents: [] -> [1001110101].
450 SendPacketRange(&tracker, base_, 10);
451 AddTransportFeedbackAndValidate(
452 &tracker, base_,
453 {true, false, false, true, true, true, false, true, false, true});
454 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f);
455
456 // Create gap (on both sides).
457 SendPacketRange(&tracker, base_ + 0x4000, 20);
458
459 // Expected window contents: [1001110101] -> [1110101-GAP-101].
460 SendPacketRange(&tracker, base_ + 0x8000, 3);
461 AddTransportFeedbackAndValidate(&tracker, base_ + 0x8000,
462 {true, false, true});
463 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f);
464
465 // Push into middle until max window is reached. The gap is NOT completed.
466 // Expected window contents:
467 // [1110101-GAP-101] -> [1110101-GAP-10001-GAP-101]
468 AddTransportFeedbackAndValidate(&tracker, base_ + 0x4000 + 2,
469 {true, false, false, false, true});
470 ValidatePacketLossStatistics(tracker, 6.0f / 15.0f, 4.0f / 12.0f);
471
472 // Pushing new packets into the middle would discard older packets.
473 // Expected window contents:
474 // [1110101-GAP-10001-GAP-101] -> [0101-GAP-10001101-GAP-101]
475 AddTransportFeedbackAndValidate(&tracker, base_ + 0x4000 + 2 + 5,
476 {true, false, true});
477 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 5.0f / 12.0f);
478 }
479
480 // A packet with a new enough sequence number might shift enough old feedbacks
481 // out window, that we'd go back to an unknown PLR and RPLR.
482 TEST_P(TransportFeedbackPacketLossTrackerTest, NewPacketMovesWindowBase) {
483 TransportFeedbackPacketLossTracker tracker(20, 5, 3);
484
485 SendPacketRange(&tracker, base_, 50);
486 SendPacketRange(&tracker, base_ + 0x4000 - 1, 6); // Gap
487
488 // Expected window contents: [] -> [1001110101].
489 AddTransportFeedbackAndValidate(
490 &tracker, base_,
491 {true, false, false, true, true, true, false, true, false, true});
492 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f);
493
494 // A new sent packet with a new enough sequence number could shift enough
495 // acked packets out of window, that we'd go back to an unknown PLR
496 // and RPLR. This *doesn't* // necessarily mean all of the old ones
497 // were discarded, though.
498 // Expected window contents: [1001110101] -> [01].
499 SendPacketRange(&tracker, base_ + 0x8006, 2);
500 ValidatePacketLossStatistics(tracker,
501 rtc::Optional<float>(), // Still invalid.
502 rtc::Optional<float>());
503
504 // Even if those messages are acked, we'd still might be in unknown PLR
505 // and RPLR, because we might have shifted more packets out of the window
506 // than we have inserted.
507 // Expected window contents: [01] -> [01-GAP-11].
508 AddTransportFeedbackAndValidate(&tracker, base_ + 0x8006, {true, true});
509 ValidatePacketLossStatistics(tracker,
510 rtc::Optional<float>(), // Still invalid.
511 rtc::Optional<float>());
512
513 // Inserting in the middle shows that though some of the elements were
514 // ejected, some were retained.
515 // Expected window contents: [01-GAP-11] -> [01-GAP-1001-GAP-11].
516 AddTransportFeedbackAndValidate(&tracker, base_ + 0x4000,
517 {true, false, false, true});
518 ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 5.0f);
519 }
520
521 // Sequence number gaps are not gaps in reception. However, gaps in reception 438 // Sequence number gaps are not gaps in reception. However, gaps in reception
522 // are still possible, if a packet which WAS sent on the stream is not acked. 439 // are still possible, if a packet which WAS sent on the stream is not acked.
523 TEST_P(TransportFeedbackPacketLossTrackerTest, SanityGapsInSequenceNumbers) { 440 TEST_P(TransportFeedbackPacketLossTrackerTest, SanityGapsInSequenceNumbers) {
524 TransportFeedbackPacketLossTracker tracker(20, 5, 1); 441 TransportFeedbackPacketLossTracker tracker(500, 5, 1);
525 442
526 SendPackets(&tracker, {base_, base_ + 2, base_ + 4, base_ + 6, base_ + 8}); 443 SendPackets(&tracker, {base_, base_ + 2, base_ + 4, base_ + 6, base_ + 8});
527 444
528 // Gaps in sequence numbers not considered as gaps in window, because only 445 // Gaps in sequence numbers not considered as gaps in window, because only
529 // those sequence numbers which were associated with the stream count. 446 // those sequence numbers which were associated with the stream count.
530 // Expected window contents: [] -> [11011]. 447 // Expected window contents: [] -> [11011].
531 AddTransportFeedbackAndValidate( 448 AddTransportFeedbackAndValidate(
532 // Note: Left packets belong to this stream, odd ones ignored. 449 // Note: Left packets belong to this stream, right ones ignored.
533 &tracker, base_, {true, false, 450 &tracker, base_, {true, false,
534 true, false, 451 true, false,
535 false, false, 452 false, false,
536 true, false, 453 true, false,
537 true, true}); 454 true, true});
538 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); 455 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f);
539 456
540 // Create gap by sending [base + 10] but not acking it. 457 // Create gap by sending [base + 10] but not acking it.
541 // Note: Acks for [base + 11] and [base + 13] ignored (other stream). 458 // Note: Acks for [base + 11] and [base + 13] ignored (other stream).
542 // Expected window contents: [11011] -> [11011-GAP-01]. 459 // Expected window contents: [11011] -> [11011-GAP-01].
543 SendPackets(&tracker, {base_ + 10, base_ + 12, base_ + 14}); 460 SendPackets(&tracker, {base_ + 10, base_ + 12, base_ + 14});
544 AddTransportFeedbackAndValidate(&tracker, base_ + 11, 461 AddTransportFeedbackAndValidate(&tracker, base_ + 11,
545 {false, false, false, true, true}); 462 {false, false, false, true, true});
546 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 2.0f / 5.0f); 463 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 2.0f / 5.0f);
547 } 464 }
548 465
549 // Sending a packet which is less than 0x8000 away from the baseline does 466 // The window cannot span more than 0x8000 in sequence numbers, regardless
550 // not move the window. 467 // of time stamps and ack/unacked status.
551 TEST_P(TransportFeedbackPacketLossTrackerTest, 468 TEST_P(TransportFeedbackPacketLossTrackerTest, MaxUnackedPackets) {
552 UnackedInWindowDoesNotMoveWindow) { 469 TransportFeedbackPacketLossTracker tracker(0x10000, 4, 1);
553 TransportFeedbackPacketLossTracker tracker(5, 3, 1); 470
471 SendPackets(&tracker, base_, 0x2000, false);
472
473 // Expected window contents: [] -> [10011].
474 AddTransportFeedbackAndValidate(&tracker, base_,
475 {true, false, false, true, true});
476 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
477
478 // Sending more unacked packets, up to 0x7fff from the base, does not
479 // move the window or discard any information.
480 SendPackets(&tracker, base_ + 0x8000 - 0x2000, 0x2000, false);
481 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
482
483 // Sending more unacked packets, up to 0x7fff from the base, does not
484 // move the window or discard any information.
485 // Expected window contents: [10011] -> [0011].
486 SendPackets(&tracker, base_ + 0x8000, 1);
487 ValidatePacketLossStatistics(tracker, 2.0f / 4.0f, 1.0f / 3.0f);
488 }
489
490 // Maximum configured time difference between newest and oldest acked observed.
491 TEST_P(TransportFeedbackPacketLossTrackerTest, TimeDifferenceMaximumObserved) {
492 constexpr int64_t max_window_size_ms = 5000;
493 TransportFeedbackPacketLossTracker tracker(5000, 3, 1);
554 494
555 // Baseline - window has acked messages. 495 // Baseline - window has acked messages.
556 // Expected window contents: [] -> [10101]. 496 // Expected window contents: [] -> [01101].
557 SendPacketRange(&tracker, base_, 5); 497 const std::vector<bool> feedback = {false, true, true, false, true};
558 AddTransportFeedbackAndValidate(&tracker, base_, 498 SendPackets(&tracker, base_, feedback.size());
559 {true, false, true, false, true}); 499 AddTransportFeedbackAndValidate(&tracker, base_, feedback);
560 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); 500 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f);
561 501
562 // Test - window not moved. 502 // Test - window base not moved.
563 // Expected window contents: [10101] -> [10101]. 503 // Expected window contents: [01101] -> [011011].
564 SendPackets(&tracker, {base_ + 0x7fff}); 504 Wait(max_window_size_ms - feedback.size());
565 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); 505 SendPackets(&tracker, base_ + feedback.size(), 1);
506 AddTransportFeedbackAndValidate(&tracker, base_ + feedback.size(), {true});
507 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 2.0f / 5.0f);
508
509 // Another packet, sent 1ms later, would already be too late. The window will
510 // be moved, but only after the ACK is received.
511 SendPackets(&tracker, base_ + feedback.size() + 1, 1);
512 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 2.0f / 5.0f);
513 // Expected window contents: [011011] -> [110111].
514 AddTransportFeedbackAndValidate(&tracker,
515 base_ + feedback.size() + 1,
516 {true});
517 ValidatePacketLossStatistics(tracker, 1.0f / 6.0f, 1.0f / 5.0f);
566 } 518 }
567 519
568 // Sending a packet which is at least 0x8000 away from the baseline, but not 520 TEST_P(TransportFeedbackPacketLossTrackerTest, ResetByRepeatedSeqNum) {
569 // 0x8000 or more away from the newest packet in the window, moves the window, 521 TransportFeedbackPacketLossTracker tracker(500, 2, 1);
570 // but does not reset it.
571 TEST_P(TransportFeedbackPacketLossTrackerTest, UnackedOutOfWindowMovesWindow) {
572 TransportFeedbackPacketLossTracker tracker(5, 3, 1);
573 522
574 // Baseline - window has acked messages. 523 // Baseline - window has acked messages.
575 // Expected window contents: [] -> [10101]. 524 // Expected window contents: [] -> [01101].
576 SendPacketRange(&tracker, base_, 5); 525 SendPackets(&tracker, base_, 5);
577 AddTransportFeedbackAndValidate(&tracker, base_, 526 AddTransportFeedbackAndValidate(&tracker, base_,
578 {true, false, true, false, true}); 527 {false, true, true, false, true});
579 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); 528 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f);
580 529
581 // 0x8000 from baseline, but only 0x7ffc from newest - window moved. 530 // A reset occurs.
582 // Expected window contents: [10101] -> [0101]. 531 SendPackets(&tracker, base_ + 2, 1);
583 SendPackets(&tracker, {base_ + 0x8000});
584 ValidatePacketLossStatistics(tracker, 2.0f / 4.0f, 2.0f / 3.0f);
585 }
586
587 // TODO(elad.alon): More tests possible here, but a CL is in the pipeline which
588 // significantly changes the entire class's operation (makes the window
589 // time-based), so no sense in writing complicated UTs which will be replaced
590 // very soon.
591
592 // The window is reset by the sending of a packet which is 0x8000 or more
593 // away from the newest packet.
594 TEST_P(TransportFeedbackPacketLossTrackerTest, WindowResetAfterLongNoSend) {
595 TransportFeedbackPacketLossTracker tracker(10, 2, 1);
596
597 // Baseline - window has acked messages.
598 // Expected window contents: [] -> [1-GAP-10101].
599 SendPacketRange(&tracker, base_, 1);
600 SendPacketRange(&tracker, base_ + 0x7fff - 4, 5);
601 AddTransportFeedbackAndValidate(&tracker, base_, {true});
602 AddTransportFeedbackAndValidate(&tracker, base_ + 0x7fff - 4,
603 {true, false, true, false, true});
604 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 2.0f / 5.0f);
605
606 // Sent packet too new - the entire window is reset.
607 // Expected window contents: [1-GAP-10101] -> [].
608 SendPacketRange(&tracker, base_ + 0x7fff + 0x8000, 1);
609 ValidatePacketLossStatistics(tracker,
610 rtc::Optional<float>(),
611 rtc::Optional<float>());
612
613 // To show it was really reset, prove show that acking the sent packet
614 // still leaves us at unknown, because no acked (or unacked) packets were
615 // left in the window.
616 // Expected window contents: [] -> [1].
617 AddTransportFeedbackAndValidate(&tracker, base_ + 0x7fff + 0x8000, {true});
618 ValidatePacketLossStatistics(tracker, 532 ValidatePacketLossStatistics(tracker,
619 rtc::Optional<float>(), 533 rtc::Optional<float>(),
620 rtc::Optional<float>()); 534 rtc::Optional<float>());
621 } 535 }
622 536
537 // The window is reset by the sending of a packet which is 0x8000 or more
538 // away from the newest packet acked/unacked packet.
539 TEST_P(TransportFeedbackPacketLossTrackerTest, ResetByTooNew) {
540 TransportFeedbackPacketLossTracker tracker(500, 2, 1);
541
542 // Baseline - window has acked messages.
543 // Expected window contents: [] -> [01101].
544 SendPackets(&tracker, base_, 5);
545 AddTransportFeedbackAndValidate(&tracker, base_,
546 {false, true, true, false, true});
547 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f);
548
549 // A reset occurs.
550 SendPackets(&tracker, base_ + 5 + 0x8000, 1);
551 ValidatePacketLossStatistics(tracker,
552 rtc::Optional<float>(),
553 rtc::Optional<float>());
554 }
555
556 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
557 TEST(TransportFeedbackPacketLossTrackerTest, InvalidConfigMaxWindowSize) {
558 EXPECT_DEATH(TransportFeedbackPacketLossTracker tracker(0, 20, 10), "");
559 }
560
561 TEST(TransportFeedbackPacketLossTrackerTest, InvalidConfigPlrMinAcked) {
562 EXPECT_DEATH(TransportFeedbackPacketLossTracker tracker(5000, 0, 10), "");
563 }
564
565 TEST(TransportFeedbackPacketLossTrackerTest, InvalidConfigRplrMinPairs) {
566 EXPECT_DEATH(TransportFeedbackPacketLossTracker tracker(5000, 20, 0), "");
567 }
568
569 TEST(TransportFeedbackPacketLossTrackerTest, TimeCantFlowBackwards) {
570 TransportFeedbackPacketLossTracker tracker(5000, 2, 1);
571 tracker.OnPacketAdded(100, 0);
572 tracker.OnPacketAdded(101, 2);
573 EXPECT_DEATH(tracker.OnPacketAdded(102, 1), "");
574 }
575 #endif
576
623 // All tests are run multiple times with various baseline sequence number, 577 // All tests are run multiple times with various baseline sequence number,
624 // to weed out potential bugs with wrap-around handling. 578 // to weed out potential bugs with wrap-around handling.
625 constexpr uint16_t kBases[] = {0x0000, 0x3456, 0xc032, 0xfffe}; 579 constexpr uint16_t kBases[] = {0x0000, 0x3456, 0xc032, 0xfffe};
626 580
627 INSTANTIATE_TEST_CASE_P(_, 581 INSTANTIATE_TEST_CASE_P(_,
628 TransportFeedbackPacketLossTrackerTest, 582 TransportFeedbackPacketLossTrackerTest,
629 testing::ValuesIn(kBases)); 583 testing::ValuesIn(kBases));
630 584
631 } // namespace webrtc 585 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698