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

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: More compiler nits. Created 3 years, 9 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
« no previous file with comments | « webrtc/voice_engine/transport_feedback_packet_loss_tracker.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 int64_t send_time_interval_ms,
38 bool validate_all = true) {
39 RTC_CHECK_GE(send_time_interval_ms, 0);
40 for (uint16_t sequence_number : sequence_numbers) {
41 tracker->OnPacketAdded(sequence_number, time_ms_);
42 if (validate_all) {
43 tracker->Validate();
44 }
45 time_ms_ += send_time_interval_ms;
46 }
37 47
38 private: 48 // We've either validated after each packet, or, for making sure the UT
39 RTC_DISALLOW_COPY_AND_ASSIGN(TransportFeedbackPacketLossTrackerTest); 49 // doesn't run too long, we might validate only at the end of the range.
40 }; 50 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(); 51 tracker->Validate();
49 } 52 }
50 } 53 }
51 54
52 // We've either validated after each packet, or, for making sure the UT 55 void SendPackets(TransportFeedbackPacketLossTracker* tracker,
53 // doesn't run too long, we might validate only at the end of the range. 56 uint16_t first_seq_num,
54 if (!validate_all) { 57 size_t num_of_packets,
58 int64_t send_time_interval_ms,
59 bool validate_all = true) {
60 RTC_CHECK_GE(send_time_interval_ms, 0);
61 std::vector<uint16_t> sequence_numbers(num_of_packets);
62 std::iota(sequence_numbers.begin(), sequence_numbers.end(), first_seq_num);
63 SendPackets(tracker, sequence_numbers, send_time_interval_ms, validate_all);
64 }
65
66 void AdvanceClock(int64_t time_delta_ms) {
67 RTC_CHECK_GT(time_delta_ms, 0);
68 time_ms_ += time_delta_ms;
69 }
70
71 void AddTransportFeedbackAndValidate(
72 TransportFeedbackPacketLossTracker* tracker,
73 uint16_t base_sequence_num,
74 const std::vector<bool>& reception_status_vec) {
75 const int64_t kBaseTimeUs = 1234; // Irrelevant to this test.
76 TransportFeedback test_feedback;
77 test_feedback.SetBase(base_sequence_num, kBaseTimeUs);
78 uint16_t sequence_num = base_sequence_num;
79 for (bool status : reception_status_vec) {
80 if (status)
81 test_feedback.AddReceivedPacket(sequence_num, kBaseTimeUs);
82 ++sequence_num;
83 }
84
85 // TransportFeedback imposes some limitations on what constitutes a legal
86 // status vector. For instance, the vector cannot terminate in a lost
87 // packet. Make sure all limitations are abided by.
88 RTC_CHECK_EQ(base_sequence_num, test_feedback.GetBaseSequence());
89 const auto& vec = test_feedback.GetStatusVector();
90 RTC_CHECK_EQ(reception_status_vec.size(), vec.size());
91 for (size_t i = 0; i < reception_status_vec.size(); i++) {
92 RTC_CHECK_EQ(reception_status_vec[i],
93 vec[i] != TransportFeedback::StatusSymbol::kNotReceived);
94 }
95
96 tracker->OnReceivedTransportFeedback(test_feedback);
55 tracker->Validate(); 97 tracker->Validate();
56 } 98 }
57 }
58 99
59 void SendPacketRange(TransportFeedbackPacketLossTracker* tracker, 100 // Checks that validty is as expected. If valid, checks also that
60 uint16_t first_seq_num, 101 // value is as expected.
61 size_t num_of_seq_nums, 102 void ValidatePacketLossStatistics(
62 bool validate_all = true) { 103 const TransportFeedbackPacketLossTracker& tracker,
63 std::vector<uint16_t> seq_nums(num_of_seq_nums); 104 rtc::Optional<float> expected_plr,
64 std::iota(seq_nums.begin(), seq_nums.end(), first_seq_num); 105 rtc::Optional<float> expected_rplr) {
65 SendPackets(tracker, seq_nums, validate_all); 106 // TODO(elad.alon): Comparing the rtc::Optional<float> directly would have
66 } 107 // given concise code, but less readable error messages. If we modify
108 // the way rtc::Optional is printed, we can get rid of this.
109 rtc::Optional<float> plr = tracker.GetPacketLossRate();
110 EXPECT_EQ(static_cast<bool>(expected_plr), static_cast<bool>(plr));
111 if (expected_plr && plr) {
112 EXPECT_EQ(*expected_plr, *plr);
113 }
67 114
68 void AddTransportFeedbackAndValidate( 115 rtc::Optional<float> rplr = tracker.GetRecoverablePacketLossRate();
69 TransportFeedbackPacketLossTracker* tracker, 116 EXPECT_EQ(static_cast<bool>(expected_rplr), static_cast<bool>(rplr));
70 uint16_t base_sequence_num, 117 if (expected_rplr && rplr) {
71 const std::vector<bool>& reception_status_vec) { 118 EXPECT_EQ(*expected_rplr, *rplr);
72 const int64_t kBaseTimeUs = 1234; // Irrelevant to this test. 119 }
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 } 120 }
81 121
82 // TransportFeedback imposes some limitations on what constitutes a legal 122 // Convenience function for when both are valid, and explicitly stating
83 // status vector. For instance, the vector cannot terminate in a lost 123 // the rtc::Optional<float> constructor is just cumbersome.
84 // packet. Make sure all limitations are abided by. 124 void ValidatePacketLossStatistics(
85 RTC_CHECK_EQ(base_sequence_num, test_feedback.GetBaseSequence()); 125 const TransportFeedbackPacketLossTracker& tracker,
86 const auto& vec = test_feedback.GetStatusVector(); 126 float expected_plr,
87 RTC_CHECK_EQ(reception_status_vec.size(), vec.size()); 127 float expected_rplr) {
88 for (size_t i = 0; i < reception_status_vec.size(); i++) { 128 ValidatePacketLossStatistics(tracker, rtc::Optional<float>(expected_plr),
89 RTC_CHECK_EQ(reception_status_vec[i], 129 rtc::Optional<float>(expected_rplr));
90 vec[i] != TransportFeedback::StatusSymbol::kNotReceived);
91 } 130 }
92 131
93 tracker->OnReceivedTransportFeedback(test_feedback); 132 uint16_t base_{GetParam()};
94 tracker->Validate();
95 }
96 133
97 // Checks that validty is as expected. If valid, checks also that 134 private:
98 // value is as expected. 135 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 136
111 rtc::Optional<float> rplr = tracker.GetRecoverablePacketLossRate(); 137 RTC_DISALLOW_COPY_AND_ASSIGN(TransportFeedbackPacketLossTrackerTest);
112 EXPECT_EQ(static_cast<bool>(expected_rplr), static_cast<bool>(rplr)); 138 };
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 139
129 } // namespace 140 } // namespace
130 141
131 // Sanity check on an empty window. 142 // Sanity check on an empty window.
132 TEST(TransportFeedbackPacketLossTrackerTest, EmptyWindow) { 143 TEST_P(TransportFeedbackPacketLossTrackerTest, EmptyWindow) {
133 TransportFeedbackPacketLossTracker tracker(10, 5, 5); 144 TransportFeedbackPacketLossTracker tracker(5000, 5, 5);
134 145
135 // PLR and RPLR reported as unknown before reception of first feedback. 146 // PLR and RPLR reported as unknown before reception of first feedback.
136 ValidatePacketLossStatistics(tracker, 147 ValidatePacketLossStatistics(tracker,
137 rtc::Optional<float>(), 148 rtc::Optional<float>(),
138 rtc::Optional<float>()); 149 rtc::Optional<float>());
139 } 150 }
140 151
141 // A feedback received for an empty window has no effect. 152 // A feedback received for an empty window has no effect.
142 TEST_P(TransportFeedbackPacketLossTrackerTest, EmptyWindowFeedback) { 153 TEST_P(TransportFeedbackPacketLossTrackerTest, EmptyWindowFeedback) {
143 TransportFeedbackPacketLossTracker tracker(3, 3, 2); 154 TransportFeedbackPacketLossTracker tracker(5000, 3, 2);
144 155
145 // Feedback doesn't correspond to any packets - ignored. 156 // Feedback doesn't correspond to any packets - ignored.
146 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true}); 157 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true});
147 ValidatePacketLossStatistics(tracker, 158 ValidatePacketLossStatistics(tracker,
148 rtc::Optional<float>(), 159 rtc::Optional<float>(),
149 rtc::Optional<float>()); 160 rtc::Optional<float>());
150 161
151 // After the packets are transmitted, acking them would have an effect. 162 // After the packets are transmitted, acking them would have an effect.
152 SendPacketRange(&tracker, base_, 3); 163 SendPackets(&tracker, base_, 3, 10);
153 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true}); 164 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true});
154 ValidatePacketLossStatistics(tracker, 1.0f / 3.0f, 0.5f); 165 ValidatePacketLossStatistics(tracker, 1.0f / 3.0f, 0.5f);
155 } 166 }
156 167
157 // Sanity check on partially filled window. 168 // Sanity check on partially filled window.
158 TEST_P(TransportFeedbackPacketLossTrackerTest, PartiallyFilledWindow) { 169 TEST_P(TransportFeedbackPacketLossTrackerTest, PartiallyFilledWindow) {
159 TransportFeedbackPacketLossTracker tracker(10, 5, 4); 170 TransportFeedbackPacketLossTracker tracker(5000, 5, 4);
160 171
161 // PLR unknown before minimum window size reached. 172 // PLR unknown before minimum window size reached.
162 // RPLR unknown before minimum pairs reached. 173 // RPLR unknown before minimum pairs reached.
163 // Expected window contents: [] -> [1001]. 174 // Expected window contents: [] -> [1001].
164 SendPacketRange(&tracker, base_, 3); 175 SendPackets(&tracker, base_, 3, 10);
165 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, false, true}); 176 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, false, true});
166 ValidatePacketLossStatistics(tracker, 177 ValidatePacketLossStatistics(tracker,
167 rtc::Optional<float>(), 178 rtc::Optional<float>(),
168 rtc::Optional<float>()); 179 rtc::Optional<float>());
169 } 180 }
170 181
171 // Sanity check on minimum filled window - PLR known, RPLR unknown. 182 // Sanity check on minimum filled window - PLR known, RPLR unknown.
172 TEST_P(TransportFeedbackPacketLossTrackerTest, PlrMinimumFilledWindow) { 183 TEST_P(TransportFeedbackPacketLossTrackerTest, PlrMinimumFilledWindow) {
173 TransportFeedbackPacketLossTracker tracker(10, 5, 5); 184 TransportFeedbackPacketLossTracker tracker(5000, 5, 5);
174 185
175 // PLR correctly calculated after minimum window size reached. 186 // PLR correctly calculated after minimum window size reached.
176 // RPLR not necessarily known at that time (not if min-pairs not reached). 187 // RPLR not necessarily known at that time (not if min-pairs not reached).
177 // Expected window contents: [] -> [10011]. 188 // Expected window contents: [] -> [10011].
178 SendPacketRange(&tracker, base_, 5); 189 SendPackets(&tracker, base_, 5, 10);
179 AddTransportFeedbackAndValidate(&tracker, base_, 190 AddTransportFeedbackAndValidate(&tracker, base_,
180 {true, false, false, true, true}); 191 {true, false, false, true, true});
181 ValidatePacketLossStatistics(tracker, 192 ValidatePacketLossStatistics(tracker,
182 rtc::Optional<float>(2.0f / 5.0f), 193 rtc::Optional<float>(2.0f / 5.0f),
183 rtc::Optional<float>()); 194 rtc::Optional<float>());
184 } 195 }
185 196
186 // Sanity check on minimum filled window - PLR unknown, RPLR known. 197 // Sanity check on minimum filled window - PLR unknown, RPLR known.
187 TEST_P(TransportFeedbackPacketLossTrackerTest, RplrMinimumFilledWindow) { 198 TEST_P(TransportFeedbackPacketLossTrackerTest, RplrMinimumFilledWindow) {
188 TransportFeedbackPacketLossTracker tracker(10, 6, 4); 199 TransportFeedbackPacketLossTracker tracker(5000, 6, 4);
189 200
190 // RPLR correctly calculated after minimum pairs reached. 201 // RPLR correctly calculated after minimum pairs reached.
191 // PLR not necessarily known at that time (not if min window not reached). 202 // PLR not necessarily known at that time (not if min window not reached).
192 // Expected window contents: [] -> [10011]. 203 // Expected window contents: [] -> [10011].
193 SendPacketRange(&tracker, base_, 5); 204 SendPackets(&tracker, base_, 5, 10);
194 AddTransportFeedbackAndValidate(&tracker, base_, 205 AddTransportFeedbackAndValidate(&tracker, base_,
195 {true, false, false, true, true}); 206 {true, false, false, true, true});
196 ValidatePacketLossStatistics(tracker, 207 ValidatePacketLossStatistics(tracker,
197 rtc::Optional<float>(), 208 rtc::Optional<float>(),
198 rtc::Optional<float>(1.0f / 4.0f)); 209 rtc::Optional<float>(1.0f / 4.0f));
199 } 210 }
200 211
212 // If packets are sent close enough together that the clock reading for both
213 // is the same, that's handled properly.
214 TEST_P(TransportFeedbackPacketLossTrackerTest, SameSentTime) {
215 TransportFeedbackPacketLossTracker tracker(5000, 3, 2);
216
217 // Expected window contents: [] -> [101].
218 SendPackets(&tracker, base_, 3, 0); // Note: time interval = 0ms.
219 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true});
220
221 ValidatePacketLossStatistics(tracker, 1.0f / 3.0f, 0.5f);
222 }
223
201 // Additional reports update PLR and RPLR. 224 // Additional reports update PLR and RPLR.
202 TEST_P(TransportFeedbackPacketLossTrackerTest, ExtendWindow) { 225 TEST_P(TransportFeedbackPacketLossTrackerTest, ExtendWindow) {
203 TransportFeedbackPacketLossTracker tracker(20, 5, 5); 226 TransportFeedbackPacketLossTracker tracker(5000, 5, 5);
204 227
205 SendPacketRange(&tracker, base_, 25); 228 SendPackets(&tracker, base_, 25, 10);
206 229
207 // Expected window contents: [] -> [10011]. 230 // Expected window contents: [] -> [10011].
208 AddTransportFeedbackAndValidate(&tracker, base_, 231 AddTransportFeedbackAndValidate(&tracker, base_,
209 {true, false, false, true, true}); 232 {true, false, false, true, true});
210 ValidatePacketLossStatistics(tracker, 233 ValidatePacketLossStatistics(tracker,
211 rtc::Optional<float>(2.0f / 5.0f), 234 rtc::Optional<float>(2.0f / 5.0f),
212 rtc::Optional<float>()); 235 rtc::Optional<float>());
213 236
214 // Expected window contents: [10011] -> [1001110101]. 237 // Expected window contents: [10011] -> [1001110101].
215 AddTransportFeedbackAndValidate(&tracker, base_ + 5, 238 AddTransportFeedbackAndValidate(&tracker, base_ + 5,
216 {true, false, true, false, true}); 239 {true, false, true, false, true});
217 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); 240 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f);
218 241
219 // Expected window contents: [1001110101] -> [1001110101-GAP-10001]. 242 // Expected window contents: [1001110101] -> [1001110101-GAP-10001].
220 AddTransportFeedbackAndValidate(&tracker, base_ + 20, 243 AddTransportFeedbackAndValidate(&tracker, base_ + 20,
221 {true, false, false, false, true}); 244 {true, false, false, false, true});
222 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 4.0f / 13.0f); 245 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 4.0f / 13.0f);
223 } 246 }
224 247
225 // Sanity - all packets correctly received. 248 // Correct calculation with different packet lengths.
249 TEST_P(TransportFeedbackPacketLossTrackerTest, DifferentSentIntervals) {
250 TransportFeedbackPacketLossTracker tracker(5000, 5, 4);
251
252 int64_t now_ms = 0;
253 int64_t frames[] = {20, 60, 120, 20, 60};
254 for (size_t i = 0; i < sizeof(frames) / sizeof(frames[0]); i++) {
255 tracker.OnPacketAdded(static_cast<uint16_t>(base_ + i), now_ms);
256 now_ms += frames[i];
257 }
258
259 // Expected window contents: [] -> [10011].
260 AddTransportFeedbackAndValidate(&tracker, base_,
261 {true, false, false, true, true});
262 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
263 }
264
265 // The window retains information up to sent times that exceed the the max
266 // window size. The oldest packets get shifted out of window to make room
267 // for the newer ones.
268 TEST_P(TransportFeedbackPacketLossTrackerTest, MaxWindowSize) {
269 TransportFeedbackPacketLossTracker tracker(40, 5, 1);
270
271 SendPackets(&tracker, base_, 6, 10, true);
272
273 // Up to the maximum time-span retained (first + 4 * 10ms).
274 // Expected window contents: [] -> [01001].
275 AddTransportFeedbackAndValidate(&tracker, base_,
276 {false, true, false, false, true});
277 ValidatePacketLossStatistics(tracker, 3.0f / 5.0f, 2.0f / 4.0f);
278
279 // After the maximum time-span, older entries are discarded to accommodate
280 // newer ones.
281 // Expected window contents: [01001] -> [10011].
282 AddTransportFeedbackAndValidate(&tracker, base_ + 5, {true});
283 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.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, 10);
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, 10);
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, 10);
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, 10);
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, 10);
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 * 10, 5, 1);
304 365
305 SendPacketRange(&tracker, base_, 200); 366 SendPackets(&tracker, base_, 200, 10);
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 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 // Therefore, the delta in sequence numbers equals the timestamps delta.
324 // Up to max-window-size retained. 386 SendPackets(&tracker, base_, 4 * max_window_size_ms, 1);
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 387
344 // Expected window contents: [] -> [10101]. 388 // Expected window contents: [] -> [10101].
345 AddTransportFeedbackAndValidate(&tracker, base_, 389 AddTransportFeedbackAndValidate(&tracker, base_,
346 {true, false, true, false, true}); 390 {true, false, true, false, true});
347 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); 391 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f);
348 392
349 // Expected window contents: [10101] -> [10101-GAP-10001]. 393 // Expected window contents: [10101] -> [100011].
350 AddTransportFeedbackAndValidate(&tracker, base_ + 100, 394 const int64_t moved_oldest_acked = base_ + 2 * max_window_size_ms;
351 {true, false, false, false, true}); 395 const std::vector<bool> feedback = {true, false, false, false, true, true};
352 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 3.0f / 8.0f); 396 AddTransportFeedbackAndValidate(&tracker, moved_oldest_acked, feedback);
397 ValidatePacketLossStatistics(tracker, 3.0f / 6.0f, 1.0f / 5.0f);
353 398
354 // Insert into the middle of this full window - it discards the older data. 399 // Having acked |feedback.size()| starting with |moved_oldest_acked|, the
355 // Expected window contents: [10101-GAP-10001] -> [11111-GAP-10001]. 400 // newest of the acked ones is now:
356 AddTransportFeedbackAndValidate(&tracker, base_ + 50, 401 const int64_t moved_newest_acked = moved_oldest_acked + feedback.size() - 1;
357 {true, true, true, true, true}); 402
358 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 1.0f / 8.0f); 403 // Messages that *are* more than the span-limit away from the newest
404 // acked message *are* too old. Acking them would have no effect.
405 AddTransportFeedbackAndValidate(
406 &tracker, moved_newest_acked - max_window_size_ms - 1, {true});
407 ValidatePacketLossStatistics(tracker, 3.0f / 6.0f, 1.0f / 5.0f);
408
409 // Messages that are *not* more than the span-limit away from the newest
410 // acked message are *not* too old. Acking them would have an effect.
411 AddTransportFeedbackAndValidate(
412 &tracker, moved_newest_acked - max_window_size_ms, {true});
413 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 1.0f / 5.0f);
359 } 414 }
360 415
361 // Inserting feedback into the middle of a full window works correctly - can 416 // Inserting feedback into the middle of a window works correctly - can
362 // complete two pairs. 417 // complete two pairs.
363 TEST_P(TransportFeedbackPacketLossTrackerTest, InsertionCompletesTwoPairs) { 418 TEST_P(TransportFeedbackPacketLossTrackerTest, InsertionCompletesTwoPairs) {
364 TransportFeedbackPacketLossTracker tracker(15, 5, 1); 419 TransportFeedbackPacketLossTracker tracker(1500, 5, 1);
365 420
366 SendPacketRange(&tracker, base_, 300); 421 SendPackets(&tracker, base_, 15, 10);
367 422
368 // Expected window contents: [] -> [10111]. 423 // Expected window contents: [] -> [10111].
369 AddTransportFeedbackAndValidate(&tracker, base_, 424 AddTransportFeedbackAndValidate(&tracker, base_,
370 {true, false, true, true, true}); 425 {true, false, true, true, true});
371 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); 426 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f);
372 427
373 // Expected window contents: [10111] -> [10111-GAP-10101]. 428 // Expected window contents: [10111] -> [10111-GAP-10101].
374 AddTransportFeedbackAndValidate(&tracker, base_ + 7, 429 AddTransportFeedbackAndValidate(&tracker, base_ + 7,
375 {true, false, true, false, true}); 430 {true, false, true, false, true});
376 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f); 431 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f);
377 432
378 // Insert in between, closing the gap completely. 433 // Insert in between, closing the gap completely.
379 // Expected window contents: [10111-GAP-10101] -> [101111010101]. 434 // Expected window contents: [10111-GAP-10101] -> [101110110101].
380 AddTransportFeedbackAndValidate(&tracker, base_ + 5, {false, true}); 435 AddTransportFeedbackAndValidate(&tracker, base_ + 5, {false, true});
381 ValidatePacketLossStatistics(tracker, 4.0f / 12.0f, 4.0f / 11.0f); 436 ValidatePacketLossStatistics(tracker, 4.0f / 12.0f, 4.0f / 11.0f);
382 } 437 }
383 438
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 439 // 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. 440 // are still possible, if a packet which WAS sent on the stream is not acked.
523 TEST_P(TransportFeedbackPacketLossTrackerTest, SanityGapsInSequenceNumbers) { 441 TEST_P(TransportFeedbackPacketLossTrackerTest, SanityGapsInSequenceNumbers) {
524 TransportFeedbackPacketLossTracker tracker(20, 5, 1); 442 TransportFeedbackPacketLossTracker tracker(500, 5, 1);
525 443
526 SendPackets(&tracker, {static_cast<uint16_t>(base_), 444 SendPackets(&tracker,
527 static_cast<uint16_t>(base_ + 2), 445 {static_cast<uint16_t>(base_),
528 static_cast<uint16_t>(base_ + 4), 446 static_cast<uint16_t>(base_ + 2),
529 static_cast<uint16_t>(base_ + 6), 447 static_cast<uint16_t>(base_ + 4),
530 static_cast<uint16_t>(base_ + 8)}); 448 static_cast<uint16_t>(base_ + 6),
449 static_cast<uint16_t>(base_ + 8)},
450 10);
531 451
532 // Gaps in sequence numbers not considered as gaps in window, because only 452 // Gaps in sequence numbers not considered as gaps in window, because only
533 // those sequence numbers which were associated with the stream count. 453 // those sequence numbers which were associated with the stream count.
534 // Expected window contents: [] -> [11011]. 454 // Expected window contents: [] -> [11011].
535 AddTransportFeedbackAndValidate( 455 AddTransportFeedbackAndValidate(
536 // Note: Left packets belong to this stream, odd ones ignored. 456 // Note: Left packets belong to this stream, right ones ignored.
537 &tracker, base_, {true, false, 457 &tracker, base_, {true, false,
538 true, false, 458 true, false,
539 false, false, 459 false, false,
540 true, false, 460 true, false,
541 true, true}); 461 true, true});
542 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); 462 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f);
543 463
544 // Create gap by sending [base + 10] but not acking it. 464 // Create gap by sending [base + 10] but not acking it.
545 // Note: Acks for [base + 11] and [base + 13] ignored (other stream). 465 // Note: Acks for [base + 11] and [base + 13] ignored (other stream).
546 // Expected window contents: [11011] -> [11011-GAP-01]. 466 // Expected window contents: [11011] -> [11011-GAP-01].
547 SendPackets(&tracker, {static_cast<uint16_t>(base_ + 10), 467 SendPackets(&tracker,
548 static_cast<uint16_t>(base_ + 12), 468 {static_cast<uint16_t>(base_ + 10),
549 static_cast<uint16_t>(base_ + 14)}); 469 static_cast<uint16_t>(base_ + 12),
470 static_cast<uint16_t>(base_ + 14)},
471 10);
550 AddTransportFeedbackAndValidate(&tracker, base_ + 11, 472 AddTransportFeedbackAndValidate(&tracker, base_ + 11,
551 {false, false, false, true, true}); 473 {false, false, false, true, true});
552 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 2.0f / 5.0f); 474 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 2.0f / 5.0f);
553 } 475 }
554 476
555 // Sending a packet which is less than 0x8000 away from the baseline does 477 // The window cannot span more than 0x8000 in sequence numbers, regardless
556 // not move the window. 478 // of time stamps and ack/unacked status.
557 TEST_P(TransportFeedbackPacketLossTrackerTest, 479 TEST_P(TransportFeedbackPacketLossTrackerTest, MaxUnackedPackets) {
558 UnackedInWindowDoesNotMoveWindow) { 480 TransportFeedbackPacketLossTracker tracker(0x10000, 4, 1);
559 TransportFeedbackPacketLossTracker tracker(5, 3, 1); 481
482 SendPackets(&tracker, base_, 0x2000, 1, false);
483
484 // Expected window contents: [] -> [10011].
485 AddTransportFeedbackAndValidate(&tracker, base_,
486 {true, false, false, true, true});
487 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
488
489 // Sending more unacked packets, up to 0x7fff from the base, does not
490 // move the window or discard any information.
491 SendPackets(&tracker, static_cast<uint16_t>(base_ + 0x8000 - 0x2000), 0x2000,
492 1, false);
493 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
494
495 // Sending more unacked packets, up to 0x7fff from the base, does not
496 // move the window or discard any information.
497 // Expected window contents: [10011] -> [0011].
498 SendPackets(&tracker, static_cast<uint16_t>(base_ + 0x8000), 1, 1);
499 ValidatePacketLossStatistics(tracker, 2.0f / 4.0f, 1.0f / 3.0f);
500 }
501
502 // The window holds acked packets up until the difference in timestamps between
503 // the oldest and newest reaches the configured maximum. Once this maximum
504 // is exceeded, old packets are shifted out of window until the maximum is
505 // once again observed.
506 TEST_P(TransportFeedbackPacketLossTrackerTest, TimeDifferenceMaximumObserved) {
507 constexpr int64_t max_window_size_ms = 500;
508 TransportFeedbackPacketLossTracker tracker(max_window_size_ms, 3, 1);
509
510 // Note: All messages in this test are sent 1ms apart from each other.
511 // Therefore, the delta in sequence numbers equals the timestamps delta.
560 512
561 // Baseline - window has acked messages. 513 // Baseline - window has acked messages.
562 // Expected window contents: [] -> [10101]. 514 // Expected window contents: [] -> [01101].
563 SendPacketRange(&tracker, base_, 5); 515 const std::vector<bool> feedback = {false, true, true, false, true};
564 AddTransportFeedbackAndValidate(&tracker, base_, 516 SendPackets(&tracker, base_, feedback.size(), 1);
565 {true, false, true, false, true}); 517 AddTransportFeedbackAndValidate(&tracker, base_, feedback);
566 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); 518 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f);
567 519
568 // Test - window not moved. 520 // Test - window base not moved.
569 // Expected window contents: [10101] -> [10101]. 521 // Expected window contents: [01101] -> [011011].
570 SendPackets(&tracker, {static_cast<uint16_t>(base_ + 0x7fff)}); 522 AdvanceClock(max_window_size_ms - feedback.size());
571 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); 523 SendPackets(&tracker, static_cast<uint16_t>(base_ + feedback.size()), 1, 1);
524 AddTransportFeedbackAndValidate(
525 &tracker, static_cast<uint16_t>(base_ + feedback.size()), {true});
526 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 2.0f / 5.0f);
527
528 // Another packet, sent 1ms later, would already be too late. The window will
529 // be moved, but only after the ACK is received.
530 const uint16_t new_packet_seq_num =
531 static_cast<uint16_t>(base_ + feedback.size() + 1);
532 SendPackets(&tracker, {new_packet_seq_num}, 1);
533 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 2.0f / 5.0f);
534 // Expected window contents: [011011] -> [110111].
535 AddTransportFeedbackAndValidate(&tracker, new_packet_seq_num, {true});
536 ValidatePacketLossStatistics(tracker, 1.0f / 6.0f, 1.0f / 5.0f);
572 } 537 }
573 538
574 // Sending a packet which is at least 0x8000 away from the baseline, but not 539 TEST_P(TransportFeedbackPacketLossTrackerTest, RepeatedSeqNumResetsWindow) {
575 // 0x8000 or more away from the newest packet in the window, moves the window, 540 TransportFeedbackPacketLossTracker tracker(500, 2, 1);
576 // but does not reset it.
577 TEST_P(TransportFeedbackPacketLossTrackerTest, UnackedOutOfWindowMovesWindow) {
578 TransportFeedbackPacketLossTracker tracker(5, 3, 1);
579 541
580 // Baseline - window has acked messages. 542 // Baseline - window has acked messages.
581 // Expected window contents: [] -> [10101]. 543 // Expected window contents: [] -> [01101].
582 SendPacketRange(&tracker, base_, 5); 544 SendPackets(&tracker, base_, 5, 10);
583 AddTransportFeedbackAndValidate(&tracker, base_, 545 AddTransportFeedbackAndValidate(&tracker, base_,
584 {true, false, true, false, true}); 546 {false, true, true, false, true});
585 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); 547 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f);
586 548
587 // 0x8000 from baseline, but only 0x7ffc from newest - window moved. 549 // A reset occurs.
588 // Expected window contents: [10101] -> [0101]. 550 SendPackets(&tracker, static_cast<uint16_t>(base_ + 2), 1, 10);
589 SendPackets(&tracker, {static_cast<uint16_t>(base_ + 0x8000)});
590 ValidatePacketLossStatistics(tracker, 2.0f / 4.0f, 2.0f / 3.0f);
591 }
592
593 // TODO(elad.alon): More tests possible here, but a CL is in the pipeline which
594 // significantly changes the entire class's operation (makes the window
595 // time-based), so no sense in writing complicated UTs which will be replaced
596 // very soon.
597
598 // The window is reset by the sending of a packet which is 0x8000 or more
599 // away from the newest packet.
600 TEST_P(TransportFeedbackPacketLossTrackerTest, WindowResetAfterLongNoSend) {
601 TransportFeedbackPacketLossTracker tracker(10, 2, 1);
602
603 // Baseline - window has acked messages.
604 // Expected window contents: [] -> [1-GAP-10101].
605 SendPacketRange(&tracker, base_, 1);
606 SendPacketRange(&tracker, base_ + 0x7fff - 4, 5);
607 AddTransportFeedbackAndValidate(&tracker, base_, {true});
608 AddTransportFeedbackAndValidate(&tracker, base_ + 0x7fff - 4,
609 {true, false, true, false, true});
610 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 2.0f / 5.0f);
611
612 // Sent packet too new - the entire window is reset.
613 // Expected window contents: [1-GAP-10101] -> [].
614 SendPacketRange(&tracker, base_ + 0x7fff + 0x8000, 1);
615 ValidatePacketLossStatistics(tracker,
616 rtc::Optional<float>(),
617 rtc::Optional<float>());
618
619 // To show it was really reset, prove show that acking the sent packet
620 // still leaves us at unknown, because no acked (or unacked) packets were
621 // left in the window.
622 // Expected window contents: [] -> [1].
623 AddTransportFeedbackAndValidate(&tracker, base_ + 0x7fff + 0x8000, {true});
624 ValidatePacketLossStatistics(tracker, 551 ValidatePacketLossStatistics(tracker,
625 rtc::Optional<float>(), 552 rtc::Optional<float>(),
626 rtc::Optional<float>()); 553 rtc::Optional<float>());
627 } 554 }
628 555
556 // The window is reset by the sending of a packet which is 0x8000 or more
557 // away from the newest packet acked/unacked packet.
558 TEST_P(TransportFeedbackPacketLossTrackerTest,
559 SendAfterLongSuspensionResetsWindow) {
560 TransportFeedbackPacketLossTracker tracker(500, 2, 1);
561
562 // Baseline - window has acked messages.
563 // Expected window contents: [] -> [01101].
564 SendPackets(&tracker, base_, 5, 10);
565 AddTransportFeedbackAndValidate(&tracker, base_,
566 {false, true, true, false, true});
567 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f);
568
569 // A reset occurs.
570 SendPackets(&tracker, static_cast<uint16_t>(base_ + 5 + 0x8000), 1, 10);
571 ValidatePacketLossStatistics(tracker,
572 rtc::Optional<float>(),
573 rtc::Optional<float>());
574 }
575
576 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
577 TEST(TransportFeedbackPacketLossTrackerTest, InvalidConfigMaxWindowSize) {
578 EXPECT_DEATH(TransportFeedbackPacketLossTracker tracker(0, 20, 10), "");
579 }
580
581 TEST(TransportFeedbackPacketLossTrackerTest, InvalidConfigPlrMinAcked) {
582 EXPECT_DEATH(TransportFeedbackPacketLossTracker tracker(5000, 0, 10), "");
583 }
584
585 TEST(TransportFeedbackPacketLossTrackerTest, InvalidConfigRplrMinPairs) {
586 EXPECT_DEATH(TransportFeedbackPacketLossTracker tracker(5000, 20, 0), "");
587 }
588
589 TEST(TransportFeedbackPacketLossTrackerTest, TimeCantFlowBackwards) {
590 TransportFeedbackPacketLossTracker tracker(5000, 2, 1);
591 tracker.OnPacketAdded(100, 0);
592 tracker.OnPacketAdded(101, 2);
593 EXPECT_DEATH(tracker.OnPacketAdded(102, 1), "");
594 }
595 #endif
596
629 // All tests are run multiple times with various baseline sequence number, 597 // All tests are run multiple times with various baseline sequence number,
630 // to weed out potential bugs with wrap-around handling. 598 // to weed out potential bugs with wrap-around handling.
631 constexpr uint16_t kBases[] = {0x0000, 0x3456, 0xc032, 0xfffe}; 599 constexpr uint16_t kBases[] = {0x0000, 0x3456, 0xc032, 0xfffe};
632 600
633 INSTANTIATE_TEST_CASE_P(_, 601 INSTANTIATE_TEST_CASE_P(_,
634 TransportFeedbackPacketLossTrackerTest, 602 TransportFeedbackPacketLossTrackerTest,
635 testing::ValuesIn(kBases)); 603 testing::ValuesIn(kBases));
636 604
637 } // namespace webrtc 605 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/voice_engine/transport_feedback_packet_loss_tracker.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698