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

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: CR response. 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 = 1,
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 = 1,
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 Wait(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 // Comparing the rtc::Optional<float> directly would have given concise
66 } 107 // code, but less readable error messages.
108 rtc::Optional<float> plr = tracker.GetPacketLossRate();
109 EXPECT_EQ(static_cast<bool>(expected_plr), static_cast<bool>(plr));
110 if (expected_plr && plr) {
111 EXPECT_EQ(*expected_plr, *plr);
112 }
67 113
68 void AddTransportFeedbackAndValidate( 114 rtc::Optional<float> rplr = tracker.GetRecoverablePacketLossRate();
69 TransportFeedbackPacketLossTracker* tracker, 115 EXPECT_EQ(static_cast<bool>(expected_rplr), static_cast<bool>(rplr));
70 uint16_t base_sequence_num, 116 if (expected_rplr && rplr) {
71 const std::vector<bool>& reception_status_vec) { 117 EXPECT_EQ(*expected_rplr, *rplr);
72 const int64_t kBaseTimeUs = 1234; // Irrelevant to this test. 118 }
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 } 119 }
81 120
82 // TransportFeedback imposes some limitations on what constitutes a legal 121 // Convenience function for when both are valid, and explicitly stating
83 // status vector. For instance, the vector cannot terminate in a lost 122 // the rtc::Optional<float> constructor is just cumbersome.
84 // packet. Make sure all limitations are abided by. 123 void ValidatePacketLossStatistics(
85 RTC_CHECK_EQ(base_sequence_num, test_feedback.GetBaseSequence()); 124 const TransportFeedbackPacketLossTracker& tracker,
86 const auto& vec = test_feedback.GetStatusVector(); 125 float expected_plr,
87 RTC_CHECK_EQ(reception_status_vec.size(), vec.size()); 126 float expected_rplr) {
88 for (size_t i = 0; i < reception_status_vec.size(); i++) { 127 ValidatePacketLossStatistics(tracker, rtc::Optional<float>(expected_plr),
89 RTC_CHECK_EQ(reception_status_vec[i], 128 rtc::Optional<float>(expected_rplr));
90 vec[i] != TransportFeedback::StatusSymbol::kNotReceived);
91 } 129 }
92 130
93 tracker->OnReceivedTransportFeedback(test_feedback); 131 uint16_t base_{GetParam()};
94 tracker->Validate();
95 }
96 132
97 // Checks that validty is as expected. If valid, checks also that 133 private:
98 // value is as expected. 134 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 135
111 rtc::Optional<float> rplr = tracker.GetRecoverablePacketLossRate(); 136 RTC_DISALLOW_COPY_AND_ASSIGN(TransportFeedbackPacketLossTrackerTest);
112 EXPECT_EQ(static_cast<bool>(expected_rplr), static_cast<bool>(rplr)); 137 };
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 138
129 } // namespace 139 } // namespace
130 140
131 // Sanity check on an empty window. 141 // Sanity check on an empty window.
132 TEST(TransportFeedbackPacketLossTrackerTest, EmptyWindow) { 142 TEST_P(TransportFeedbackPacketLossTrackerTest, EmptyWindow) {
133 TransportFeedbackPacketLossTracker tracker(10, 5, 5); 143 TransportFeedbackPacketLossTracker tracker(5000, 5, 5);
134 144
135 // PLR and RPLR reported as unknown before reception of first feedback. 145 // PLR and RPLR reported as unknown before reception of first feedback.
136 ValidatePacketLossStatistics(tracker, 146 ValidatePacketLossStatistics(tracker,
137 rtc::Optional<float>(), 147 rtc::Optional<float>(),
138 rtc::Optional<float>()); 148 rtc::Optional<float>());
139 } 149 }
140 150
141 // A feedback received for an empty window has no effect. 151 // A feedback received for an empty window has no effect.
142 TEST_P(TransportFeedbackPacketLossTrackerTest, EmptyWindowFeedback) { 152 TEST_P(TransportFeedbackPacketLossTrackerTest, EmptyWindowFeedback) {
143 TransportFeedbackPacketLossTracker tracker(3, 3, 2); 153 TransportFeedbackPacketLossTracker tracker(5000, 3, 2);
144 154
145 // Feedback doesn't correspond to any packets - ignored. 155 // Feedback doesn't correspond to any packets - ignored.
146 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true}); 156 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true});
147 ValidatePacketLossStatistics(tracker, 157 ValidatePacketLossStatistics(tracker,
148 rtc::Optional<float>(), 158 rtc::Optional<float>(),
149 rtc::Optional<float>()); 159 rtc::Optional<float>());
150 160
151 // After the packets are transmitted, acking them would have an effect. 161 // After the packets are transmitted, acking them would have an effect.
152 SendPacketRange(&tracker, base_, 3); 162 SendPackets(&tracker, base_, 3);
153 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true}); 163 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true});
154 ValidatePacketLossStatistics(tracker, 1.0f / 3.0f, 0.5f); 164 ValidatePacketLossStatistics(tracker, 1.0f / 3.0f, 0.5f);
155 } 165 }
156 166
157 // Sanity check on partially filled window. 167 // Sanity check on partially filled window.
158 TEST_P(TransportFeedbackPacketLossTrackerTest, PartiallyFilledWindow) { 168 TEST_P(TransportFeedbackPacketLossTrackerTest, PartiallyFilledWindow) {
159 TransportFeedbackPacketLossTracker tracker(10, 5, 4); 169 TransportFeedbackPacketLossTracker tracker(5000, 5, 4);
160 170
161 // PLR unknown before minimum window size reached. 171 // PLR unknown before minimum window size reached.
162 // RPLR unknown before minimum pairs reached. 172 // RPLR unknown before minimum pairs reached.
163 // Expected window contents: [] -> [1001]. 173 // Expected window contents: [] -> [1001].
164 SendPacketRange(&tracker, base_, 3); 174 SendPackets(&tracker, base_, 3);
165 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, false, true}); 175 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, false, true});
166 ValidatePacketLossStatistics(tracker, 176 ValidatePacketLossStatistics(tracker,
167 rtc::Optional<float>(), 177 rtc::Optional<float>(),
168 rtc::Optional<float>()); 178 rtc::Optional<float>());
169 } 179 }
170 180
171 // Sanity check on minimum filled window - PLR known, RPLR unknown. 181 // Sanity check on minimum filled window - PLR known, RPLR unknown.
172 TEST_P(TransportFeedbackPacketLossTrackerTest, PlrMinimumFilledWindow) { 182 TEST_P(TransportFeedbackPacketLossTrackerTest, PlrMinimumFilledWindow) {
173 TransportFeedbackPacketLossTracker tracker(10, 5, 5); 183 TransportFeedbackPacketLossTracker tracker(5000, 5, 5);
174 184
175 // PLR correctly calculated after minimum window size reached. 185 // PLR correctly calculated after minimum window size reached.
176 // RPLR not necessarily known at that time (not if min-pairs not reached). 186 // RPLR not necessarily known at that time (not if min-pairs not reached).
177 // Expected window contents: [] -> [10011]. 187 // Expected window contents: [] -> [10011].
178 SendPacketRange(&tracker, base_, 5); 188 SendPackets(&tracker, base_, 5);
179 AddTransportFeedbackAndValidate(&tracker, base_, 189 AddTransportFeedbackAndValidate(&tracker, base_,
180 {true, false, false, true, true}); 190 {true, false, false, true, true});
181 ValidatePacketLossStatistics(tracker, 191 ValidatePacketLossStatistics(tracker,
182 rtc::Optional<float>(2.0f / 5.0f), 192 rtc::Optional<float>(2.0f / 5.0f),
183 rtc::Optional<float>()); 193 rtc::Optional<float>());
184 } 194 }
185 195
186 // Sanity check on minimum filled window - PLR unknown, RPLR known. 196 // Sanity check on minimum filled window - PLR unknown, RPLR known.
187 TEST_P(TransportFeedbackPacketLossTrackerTest, RplrMinimumFilledWindow) { 197 TEST_P(TransportFeedbackPacketLossTrackerTest, RplrMinimumFilledWindow) {
188 TransportFeedbackPacketLossTracker tracker(10, 6, 4); 198 TransportFeedbackPacketLossTracker tracker(5000, 6, 4);
189 199
190 // RPLR correctly calculated after minimum pairs reached. 200 // RPLR correctly calculated after minimum pairs reached.
191 // PLR not necessarily known at that time (not if min window not reached). 201 // PLR not necessarily known at that time (not if min window not reached).
192 // Expected window contents: [] -> [10011]. 202 // Expected window contents: [] -> [10011].
193 SendPacketRange(&tracker, base_, 5); 203 SendPackets(&tracker, base_, 5);
194 AddTransportFeedbackAndValidate(&tracker, base_, 204 AddTransportFeedbackAndValidate(&tracker, base_,
195 {true, false, false, true, true}); 205 {true, false, false, true, true});
196 ValidatePacketLossStatistics(tracker, 206 ValidatePacketLossStatistics(tracker,
197 rtc::Optional<float>(), 207 rtc::Optional<float>(),
198 rtc::Optional<float>(1.0f / 4.0f)); 208 rtc::Optional<float>(1.0f / 4.0f));
199 } 209 }
200 210
211 // If packets are sent close enough together that the clock reading for both
212 // is the same, that's handled properly.
213 TEST_P(TransportFeedbackPacketLossTrackerTest, CloseClockReads) {
214 TransportFeedbackPacketLossTracker tracker(5000, 3, 2);
215
216 constexpr int64_t time_ms = 5678; // Value doesn't matter.
217
218 // Expected window contents: [] -> [101].
219 tracker.OnPacketAdded(base_ + 0, time_ms);
michaelt 2017/03/07 12:33:13 Can we use SendPackets with a interval of Zero her
elad.alon_webrtc.org 2017/03/07 13:26:41 Yeah, that's now possible.
220 tracker.OnPacketAdded(base_ + 1, time_ms);
221 tracker.OnPacketAdded(base_ + 2, time_ms);
222 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true});
223
224 ValidatePacketLossStatistics(tracker, 1.0f / 3.0f, 0.5f);
225 }
226
201 // Additional reports update PLR and RPLR. 227 // Additional reports update PLR and RPLR.
202 TEST_P(TransportFeedbackPacketLossTrackerTest, ExtendWindow) { 228 TEST_P(TransportFeedbackPacketLossTrackerTest, ExtendWindow) {
203 TransportFeedbackPacketLossTracker tracker(20, 5, 5); 229 TransportFeedbackPacketLossTracker tracker(5000, 5, 5);
204 230
205 SendPacketRange(&tracker, base_, 25); 231 SendPackets(&tracker, base_, 25);
206 232
207 // Expected window contents: [] -> [10011]. 233 // Expected window contents: [] -> [10011].
208 AddTransportFeedbackAndValidate(&tracker, base_, 234 AddTransportFeedbackAndValidate(&tracker, base_,
209 {true, false, false, true, true}); 235 {true, false, false, true, true});
210 ValidatePacketLossStatistics(tracker, 236 ValidatePacketLossStatistics(tracker,
211 rtc::Optional<float>(2.0f / 5.0f), 237 rtc::Optional<float>(2.0f / 5.0f),
212 rtc::Optional<float>()); 238 rtc::Optional<float>());
213 239
214 // Expected window contents: [10011] -> [1001110101]. 240 // Expected window contents: [10011] -> [1001110101].
215 AddTransportFeedbackAndValidate(&tracker, base_ + 5, 241 AddTransportFeedbackAndValidate(&tracker, base_ + 5,
216 {true, false, true, false, true}); 242 {true, false, true, false, true});
217 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f); 243 ValidatePacketLossStatistics(tracker, 4.0f / 10.0f, 3.0f / 9.0f);
218 244
219 // Expected window contents: [1001110101] -> [1001110101-GAP-10001]. 245 // Expected window contents: [1001110101] -> [1001110101-GAP-10001].
220 AddTransportFeedbackAndValidate(&tracker, base_ + 20, 246 AddTransportFeedbackAndValidate(&tracker, base_ + 20,
221 {true, false, false, false, true}); 247 {true, false, false, false, true});
222 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 4.0f / 13.0f); 248 ValidatePacketLossStatistics(tracker, 7.0f / 15.0f, 4.0f / 13.0f);
223 } 249 }
224 250
225 // Sanity - all packets correctly received. 251 // Correct calculation with different packet lengths.
252 TEST_P(TransportFeedbackPacketLossTrackerTest, DifferentPacketLengthSanity) {
253 TransportFeedbackPacketLossTracker tracker(5000, 5, 4);
254
255 int64_t now_ms = 0;
256 int64_t frames[] = {20, 60, 120, 20, 60};
257 for (size_t i = 0; i < sizeof(frames) / sizeof(frames[0]); i++) {
258 tracker.OnPacketAdded(base_ + i, now_ms);
259 now_ms += frames[i];
260 }
261
262 // Expected window contents: [] -> [10011].
263 AddTransportFeedbackAndValidate(&tracker, base_,
264 {true, false, false, true, true});
265 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
266 }
267
268 // The window retain information up until the timestamps exceed the configured
269 // maximum. Then, the oldest packets get shifted out of window to make room
270 // for the newer ones.
271 TEST_P(TransportFeedbackPacketLossTrackerTest, MaxWindowSize) {
272 TransportFeedbackPacketLossTracker tracker(900, 10, 1);
273
274 SendPackets(&tracker, base_, 20, 100, true);
275
276 // Up to the maximum time-span retained (first + 9 * 100ms).
277 // Expected window contents: [] -> [0110100001].
278 AddTransportFeedbackAndValidate(
279 &tracker, base_,
280 {false, true, true, false, true, false, false, false, false, true});
281 ValidatePacketLossStatistics(tracker, 6.0f / 10.0f, 3.0f / 9.0f);
282
283 // After the maximum time-span, older entries discarded to accommodate
284 // newer ones.
285 // Expected window contents: [0110100001] -> [1101000011].
286 AddTransportFeedbackAndValidate(&tracker, base_ + 10, {true});
287 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 2.0f / 9.0f);
288 }
289
290 // All packets received.
226 TEST_P(TransportFeedbackPacketLossTrackerTest, AllReceived) { 291 TEST_P(TransportFeedbackPacketLossTrackerTest, AllReceived) {
227 TransportFeedbackPacketLossTracker tracker(10, 5, 4); 292 TransportFeedbackPacketLossTracker tracker(5000, 5, 4);
228 293
229 // Expected window contents: [] -> [11111]. 294 // Expected window contents: [] -> [11111].
230 SendPacketRange(&tracker, base_, 5); 295 SendPackets(&tracker, base_, 5);
231 AddTransportFeedbackAndValidate(&tracker, base_, 296 AddTransportFeedbackAndValidate(&tracker, base_,
232 {true, true, true, true, true}); 297 {true, true, true, true, true});
233 ValidatePacketLossStatistics(tracker, 0.0f, 0.0f); 298 ValidatePacketLossStatistics(tracker, 0.0f, 0.0f);
234 } 299 }
235 300
236 // Sanity - all packets lost. 301 // All packets lost.
237 TEST_P(TransportFeedbackPacketLossTrackerTest, AllLost) { 302 TEST_P(TransportFeedbackPacketLossTrackerTest, AllLost) {
238 TransportFeedbackPacketLossTracker tracker(10, 5, 4); 303 TransportFeedbackPacketLossTracker tracker(5000, 5, 4);
239 304
305 // Note: The last packet in the feedback does not belong to the stream.
306 // It's only there because we're not allowed to end a feedback with a loss.
240 // Expected window contents: [] -> [00000]. 307 // Expected window contents: [] -> [00000].
241 SendPacketRange(&tracker, base_, 5); 308 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_, 309 AddTransportFeedbackAndValidate(&tracker, base_,
245 {false, false, false, false, false, true}); 310 {false, false, false, false, false, true});
246 ValidatePacketLossStatistics(tracker, 1.0f, 0.0f); 311 ValidatePacketLossStatistics(tracker, 1.0f, 0.0f);
247 } 312 }
248 313
249 // Repeated reports are ignored. 314 // Repeated reports are ignored.
250 TEST_P(TransportFeedbackPacketLossTrackerTest, ReportRepetition) { 315 TEST_P(TransportFeedbackPacketLossTrackerTest, ReportRepetition) {
251 TransportFeedbackPacketLossTracker tracker(10, 5, 4); 316 TransportFeedbackPacketLossTracker tracker(5000, 5, 4);
252 317
253 SendPacketRange(&tracker, base_, 5); 318 SendPackets(&tracker, base_, 5);
254 319
255 // Expected window contents: [] -> [10011]. 320 // Expected window contents: [] -> [10011].
256 AddTransportFeedbackAndValidate(&tracker, base_, 321 AddTransportFeedbackAndValidate(&tracker, base_,
257 {true, false, false, true, true}); 322 {true, false, false, true, true});
258 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); 323 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
259 324
260 // Repeat entire previous feedback 325 // Repeat entire previous feedback
261 // Expected window contents: [10011] -> [10011]. 326 // Expected window contents: [10011] -> [10011].
262 AddTransportFeedbackAndValidate(&tracker, base_, 327 AddTransportFeedbackAndValidate(&tracker, base_,
263 {true, false, false, true, true}); 328 {true, false, false, true, true});
264 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); 329 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
265 } 330 }
266 331
267 // Report overlap. 332 // Report overlap.
268 TEST_P(TransportFeedbackPacketLossTrackerTest, ReportOverlap) { 333 TEST_P(TransportFeedbackPacketLossTrackerTest, ReportOverlap) {
269 TransportFeedbackPacketLossTracker tracker(10, 5, 1); 334 TransportFeedbackPacketLossTracker tracker(5000, 5, 1);
270 335
271 SendPacketRange(&tracker, base_, 15); 336 SendPackets(&tracker, base_, 15);
272 337
273 // Expected window contents: [] -> [10011]. 338 // Expected window contents: [] -> [10011].
274 AddTransportFeedbackAndValidate(&tracker, base_, 339 AddTransportFeedbackAndValidate(&tracker, base_,
275 {true, false, false, true, true}); 340 {true, false, false, true, true});
276 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); 341 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
277 342
278 // Expected window contents: [10011] -> [1001101]. 343 // Expected window contents: [10011] -> [1001101].
279 AddTransportFeedbackAndValidate(&tracker, base_ + 3, 344 AddTransportFeedbackAndValidate(&tracker, base_ + 3,
280 {true, true, false, true}); 345 {true, true, false, true});
281 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f); 346 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 2.0f / 6.0f);
282 } 347 }
283 348
284 // Report conflict. 349 // Report conflict.
285 TEST_P(TransportFeedbackPacketLossTrackerTest, ReportConflict) { 350 TEST_P(TransportFeedbackPacketLossTrackerTest, ReportConflict) {
286 TransportFeedbackPacketLossTracker tracker(10, 5, 4); 351 TransportFeedbackPacketLossTracker tracker(5000, 5, 4);
287 352
288 SendPacketRange(&tracker, base_, 15); 353 SendPackets(&tracker, base_, 15);
289 354
290 // Expected window contents: [] -> [01001]. 355 // Expected window contents: [] -> [01001].
291 AddTransportFeedbackAndValidate(&tracker, base_, 356 AddTransportFeedbackAndValidate(&tracker, base_,
292 {false, true, false, false, true}); 357 {false, true, false, false, true});
293 ValidatePacketLossStatistics(tracker, 3.0f / 5.0f, 2.0f / 4.0f); 358 ValidatePacketLossStatistics(tracker, 3.0f / 5.0f, 2.0f / 4.0f);
294 359
295 // Expected window contents: [01001] -> [11101]. 360 // Expected window contents: [01001] -> [11101].
296 // While false->true will be applied, true -> false will be ignored. 361 // While false->true will be applied, true -> false will be ignored.
297 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true}); 362 AddTransportFeedbackAndValidate(&tracker, base_, {true, false, true});
298 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); 363 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f);
299 } 364 }
300 365
301 // Skipped packets treated as unknown (not lost). 366 // Skipped packets treated as unknown (not lost).
302 TEST_P(TransportFeedbackPacketLossTrackerTest, SkippedPackets) { 367 TEST_P(TransportFeedbackPacketLossTrackerTest, SkippedPackets) {
303 TransportFeedbackPacketLossTracker tracker(10, 5, 1); 368 TransportFeedbackPacketLossTracker tracker(200 * 100, 5, 1);
304 369
305 SendPacketRange(&tracker, base_, 200); 370 SendPackets(&tracker, base_, 200);
306 371
307 // Expected window contents: [] -> [10011]. 372 // Expected window contents: [] -> [10011].
308 AddTransportFeedbackAndValidate(&tracker, base_, 373 AddTransportFeedbackAndValidate(&tracker, base_,
309 {true, false, false, true, true}); 374 {true, false, false, true, true});
310 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f); 375 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
311 376
312 // Expected window contents: [10011] -> [10011-GAP-101]. 377 // Expected window contents: [10011] -> [10011-GAP-101].
313 AddTransportFeedbackAndValidate(&tracker, base_ + 100, {true, false, true}); 378 AddTransportFeedbackAndValidate(&tracker, base_ + 100, {true, false, true});
314 ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 6.0f); 379 ValidatePacketLossStatistics(tracker, 3.0f / 8.0f, 2.0f / 6.0f);
315 } 380 }
316 381
317 // The window retains information up to the configured max-window-size, but 382 // Moving a window, if if it excludes some old acked messages, can leave
318 // starts discarding after that. (Sent packets are not counted.) 383 // in-window unacked messages intact, and ready to be used later.
319 TEST_P(TransportFeedbackPacketLossTrackerTest, MaxWindowSize) { 384 TEST_P(TransportFeedbackPacketLossTrackerTest, MovedWindowRetainsRelevantInfo) {
320 TransportFeedbackPacketLossTracker tracker(10, 10, 1); 385 constexpr int64_t max_window_size_ms = 100;
386 TransportFeedbackPacketLossTracker tracker(max_window_size_ms, 5, 1);
321 387
322 SendPacketRange(&tracker, base_, 200); 388 // Note: All messages in this test are sent 1ms apart from each other.
323 389 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 390
344 // Expected window contents: [] -> [10101]. 391 // Expected window contents: [] -> [10101].
345 AddTransportFeedbackAndValidate(&tracker, base_, 392 AddTransportFeedbackAndValidate(&tracker, base_,
346 {true, false, true, false, true}); 393 {true, false, true, false, true});
347 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); 394 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f);
348 395
349 // Expected window contents: [10101] -> [10101-GAP-10001]. 396 // Expected window contents: [10101] -> [100011].
350 AddTransportFeedbackAndValidate(&tracker, base_ + 100, 397 const int64_t moved_oldest_acked = base_ + 2 * max_window_size_ms;
351 {true, false, false, false, true}); 398 const std::vector<bool> feedback = {true, false, false, false, true, true};
352 ValidatePacketLossStatistics(tracker, 5.0f / 10.0f, 3.0f / 8.0f); 399 AddTransportFeedbackAndValidate(&tracker, moved_oldest_acked, feedback);
400 ValidatePacketLossStatistics(tracker, 3.0f / 6.0f, 1.0f / 5.0f);
353 401
354 // Insert into the middle of this full window - it discards the older data. 402 // Having acked |feedback.size()| starting with |moved_oldest_acked|, the
355 // Expected window contents: [10101-GAP-10001] -> [11111-GAP-10001]. 403 // newest of the acked ones is now:
356 AddTransportFeedbackAndValidate(&tracker, base_ + 50, 404 const int64_t moved_newest_acked = moved_oldest_acked + feedback.size() - 1;
357 {true, true, true, true, true}); 405
358 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 1.0f / 8.0f); 406 // Messages that *are* more than the span-limit away from the newest
407 // acked message *are* too old. Acking them would have no effect.
408 AddTransportFeedbackAndValidate(
409 &tracker, moved_newest_acked - max_window_size_ms - 1, {true});
410 ValidatePacketLossStatistics(tracker, 3.0f / 6.0f, 1.0f / 5.0f);
411
412 // Messages that are *not* more than the span-limit away from the newest
413 // acked message are *not* too old. Acking them would have an effect.
414 AddTransportFeedbackAndValidate(
415 &tracker, moved_newest_acked - max_window_size_ms, {true});
416 ValidatePacketLossStatistics(tracker, 3.0f / 7.0f, 1.0f / 5.0f);
359 } 417 }
360 418
361 // Inserting feedback into the middle of a full window works correctly - can 419 // Inserting feedback into the middle of a window works correctly - can
362 // complete two pairs. 420 // complete two pairs.
363 TEST_P(TransportFeedbackPacketLossTrackerTest, InsertionCompletesTwoPairs) { 421 TEST_P(TransportFeedbackPacketLossTrackerTest, InsertionCompletesTwoPairs) {
364 TransportFeedbackPacketLossTracker tracker(15, 5, 1); 422 TransportFeedbackPacketLossTracker tracker(1500, 5, 1);
365 423
366 SendPacketRange(&tracker, base_, 300); 424 SendPackets(&tracker, base_, 15);
367 425
368 // Expected window contents: [] -> [10111]. 426 // Expected window contents: [] -> [10111].
369 AddTransportFeedbackAndValidate(&tracker, base_, 427 AddTransportFeedbackAndValidate(&tracker, base_,
370 {true, false, true, true, true}); 428 {true, false, true, true, true});
371 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); 429 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f);
372 430
373 // Expected window contents: [10111] -> [10111-GAP-10101]. 431 // Expected window contents: [10111] -> [10111-GAP-10101].
374 AddTransportFeedbackAndValidate(&tracker, base_ + 7, 432 AddTransportFeedbackAndValidate(&tracker, base_ + 7,
375 {true, false, true, false, true}); 433 {true, false, true, false, true});
376 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f); 434 ValidatePacketLossStatistics(tracker, 3.0f / 10.0f, 3.0f / 8.0f);
377 435
378 // Insert in between, closing the gap completely. 436 // Insert in between, closing the gap completely.
379 // Expected window contents: [10111-GAP-10101] -> [101111010101]. 437 // Expected window contents: [10111-GAP-10101] -> [101110110101].
380 AddTransportFeedbackAndValidate(&tracker, base_ + 5, {false, true}); 438 AddTransportFeedbackAndValidate(&tracker, base_ + 5, {false, true});
381 ValidatePacketLossStatistics(tracker, 4.0f / 12.0f, 4.0f / 11.0f); 439 ValidatePacketLossStatistics(tracker, 4.0f / 12.0f, 4.0f / 11.0f);
382 } 440 }
383 441
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 442 // 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. 443 // are still possible, if a packet which WAS sent on the stream is not acked.
523 TEST_P(TransportFeedbackPacketLossTrackerTest, SanityGapsInSequenceNumbers) { 444 TEST_P(TransportFeedbackPacketLossTrackerTest, SanityGapsInSequenceNumbers) {
524 TransportFeedbackPacketLossTracker tracker(20, 5, 1); 445 TransportFeedbackPacketLossTracker tracker(500, 5, 1);
525 446
526 SendPackets(&tracker, {static_cast<uint16_t>(base_), 447 SendPackets(&tracker, {static_cast<uint16_t>(base_),
527 static_cast<uint16_t>(base_ + 2), 448 static_cast<uint16_t>(base_ + 2),
528 static_cast<uint16_t>(base_ + 4), 449 static_cast<uint16_t>(base_ + 4),
529 static_cast<uint16_t>(base_ + 6), 450 static_cast<uint16_t>(base_ + 6),
530 static_cast<uint16_t>(base_ + 8)}); 451 static_cast<uint16_t>(base_ + 8)});
531 452
532 // Gaps in sequence numbers not considered as gaps in window, because only 453 // Gaps in sequence numbers not considered as gaps in window, because only
533 // those sequence numbers which were associated with the stream count. 454 // those sequence numbers which were associated with the stream count.
534 // Expected window contents: [] -> [11011]. 455 // Expected window contents: [] -> [11011].
535 AddTransportFeedbackAndValidate( 456 AddTransportFeedbackAndValidate(
536 // Note: Left packets belong to this stream, odd ones ignored. 457 // Note: Left packets belong to this stream, right ones ignored.
537 &tracker, base_, {true, false, 458 &tracker, base_, {true, false,
538 true, false, 459 true, false,
539 false, false, 460 false, false,
540 true, false, 461 true, false,
541 true, true}); 462 true, true});
542 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f); 463 ValidatePacketLossStatistics(tracker, 1.0f / 5.0f, 1.0f / 4.0f);
543 464
544 // Create gap by sending [base + 10] but not acking it. 465 // Create gap by sending [base + 10] but not acking it.
545 // Note: Acks for [base + 11] and [base + 13] ignored (other stream). 466 // Note: Acks for [base + 11] and [base + 13] ignored (other stream).
546 // Expected window contents: [11011] -> [11011-GAP-01]. 467 // Expected window contents: [11011] -> [11011-GAP-01].
547 SendPackets(&tracker, {static_cast<uint16_t>(base_ + 10), 468 SendPackets(&tracker, {static_cast<uint16_t>(base_ + 10),
548 static_cast<uint16_t>(base_ + 12), 469 static_cast<uint16_t>(base_ + 12),
549 static_cast<uint16_t>(base_ + 14)}); 470 static_cast<uint16_t>(base_ + 14)});
550 AddTransportFeedbackAndValidate(&tracker, base_ + 11, 471 AddTransportFeedbackAndValidate(&tracker, base_ + 11,
551 {false, false, false, true, true}); 472 {false, false, false, true, true});
552 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 2.0f / 5.0f); 473 ValidatePacketLossStatistics(tracker, 2.0f / 7.0f, 2.0f / 5.0f);
553 } 474 }
554 475
555 // Sending a packet which is less than 0x8000 away from the baseline does 476 // The window cannot span more than 0x8000 in sequence numbers, regardless
556 // not move the window. 477 // of time stamps and ack/unacked status.
557 TEST_P(TransportFeedbackPacketLossTrackerTest, 478 TEST_P(TransportFeedbackPacketLossTrackerTest, MaxUnackedPackets) {
558 UnackedInWindowDoesNotMoveWindow) { 479 TransportFeedbackPacketLossTracker tracker(0x10000, 4, 1);
559 TransportFeedbackPacketLossTracker tracker(5, 3, 1); 480
481 SendPackets(&tracker, base_, 0x2000, 1, false);
482
483 // Expected window contents: [] -> [10011].
484 AddTransportFeedbackAndValidate(&tracker, base_,
485 {true, false, false, true, true});
486 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
487
488 // Sending more unacked packets, up to 0x7fff from the base, does not
489 // move the window or discard any information.
490 SendPackets(&tracker, static_cast<uint16_t>(base_ + 0x8000 - 0x2000), 0x2000,
491 1, false);
492 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 1.0f / 4.0f);
493
494 // Sending more unacked packets, up to 0x7fff from the base, does not
495 // move the window or discard any information.
496 // Expected window contents: [10011] -> [0011].
497 SendPackets(&tracker, static_cast<uint16_t>(base_ + 0x8000), 1);
498 ValidatePacketLossStatistics(tracker, 2.0f / 4.0f, 1.0f / 3.0f);
499 }
500
501 // Maximum configured time difference between newest and oldest acked observed.
502 TEST_P(TransportFeedbackPacketLossTrackerTest, TimeDifferenceMaximumObserved) {
503 constexpr int64_t max_window_size_ms = 5000;
504 TransportFeedbackPacketLossTracker tracker(5000, 3, 1);
560 505
561 // Baseline - window has acked messages. 506 // Baseline - window has acked messages.
562 // Expected window contents: [] -> [10101]. 507 // Expected window contents: [] -> [01101].
563 SendPacketRange(&tracker, base_, 5); 508 const std::vector<bool> feedback = {false, true, true, false, true};
564 AddTransportFeedbackAndValidate(&tracker, base_, 509 SendPackets(&tracker, base_, feedback.size());
565 {true, false, true, false, true}); 510 AddTransportFeedbackAndValidate(&tracker, base_, feedback);
566 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); 511 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f);
567 512
568 // Test - window not moved. 513 // Test - window base not moved.
569 // Expected window contents: [10101] -> [10101]. 514 // Expected window contents: [01101] -> [011011].
570 SendPackets(&tracker, {static_cast<uint16_t>(base_ + 0x7fff)}); 515 Wait(max_window_size_ms - feedback.size());
571 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); 516 SendPackets(&tracker, static_cast<uint16_t>(base_ + feedback.size()), 1);
517 AddTransportFeedbackAndValidate(&tracker, base_ + feedback.size(), {true});
518 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 2.0f / 5.0f);
519
520 // Another packet, sent 1ms later, would already be too late. The window will
521 // be moved, but only after the ACK is received.
522 SendPackets(&tracker, static_cast<uint16_t>(base_ + feedback.size() + 1), 1);
523 ValidatePacketLossStatistics(tracker, 2.0f / 6.0f, 2.0f / 5.0f);
524 // Expected window contents: [011011] -> [110111].
525 AddTransportFeedbackAndValidate(&tracker, base_ + feedback.size() + 1,
526 {true});
527 ValidatePacketLossStatistics(tracker, 1.0f / 6.0f, 1.0f / 5.0f);
572 } 528 }
573 529
574 // Sending a packet which is at least 0x8000 away from the baseline, but not 530 TEST_P(TransportFeedbackPacketLossTrackerTest, ResetByRepeatedSeqNum) {
575 // 0x8000 or more away from the newest packet in the window, moves the window, 531 TransportFeedbackPacketLossTracker tracker(500, 2, 1);
576 // but does not reset it.
577 TEST_P(TransportFeedbackPacketLossTrackerTest, UnackedOutOfWindowMovesWindow) {
578 TransportFeedbackPacketLossTracker tracker(5, 3, 1);
579 532
580 // Baseline - window has acked messages. 533 // Baseline - window has acked messages.
581 // Expected window contents: [] -> [10101]. 534 // Expected window contents: [] -> [01101].
582 SendPacketRange(&tracker, base_, 5); 535 SendPackets(&tracker, base_, 5);
583 AddTransportFeedbackAndValidate(&tracker, base_, 536 AddTransportFeedbackAndValidate(&tracker, base_,
584 {true, false, true, false, true}); 537 {false, true, true, false, true});
585 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f); 538 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f);
586 539
587 // 0x8000 from baseline, but only 0x7ffc from newest - window moved. 540 // A reset occurs.
588 // Expected window contents: [10101] -> [0101]. 541 SendPackets(&tracker, static_cast<uint16_t>(base_ + 2), 1);
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, 542 ValidatePacketLossStatistics(tracker,
625 rtc::Optional<float>(), 543 rtc::Optional<float>(),
626 rtc::Optional<float>()); 544 rtc::Optional<float>());
627 } 545 }
628 546
547 // The window is reset by the sending of a packet which is 0x8000 or more
548 // away from the newest packet acked/unacked packet.
549 TEST_P(TransportFeedbackPacketLossTrackerTest, ResetByTooNew) {
550 TransportFeedbackPacketLossTracker tracker(500, 2, 1);
551
552 // Baseline - window has acked messages.
553 // Expected window contents: [] -> [01101].
554 SendPackets(&tracker, base_, 5);
555 AddTransportFeedbackAndValidate(&tracker, base_,
556 {false, true, true, false, true});
557 ValidatePacketLossStatistics(tracker, 2.0f / 5.0f, 2.0f / 4.0f);
558
559 // A reset occurs.
560 SendPackets(&tracker, static_cast<uint16_t>(base_ + 5 + 0x8000), 1);
561 ValidatePacketLossStatistics(tracker,
562 rtc::Optional<float>(),
563 rtc::Optional<float>());
564 }
565
566 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
567 TEST(TransportFeedbackPacketLossTrackerTest, InvalidConfigMaxWindowSize) {
568 EXPECT_DEATH(TransportFeedbackPacketLossTracker tracker(0, 20, 10), "");
569 }
570
571 TEST(TransportFeedbackPacketLossTrackerTest, InvalidConfigPlrMinAcked) {
572 EXPECT_DEATH(TransportFeedbackPacketLossTracker tracker(5000, 0, 10), "");
573 }
574
575 TEST(TransportFeedbackPacketLossTrackerTest, InvalidConfigRplrMinPairs) {
576 EXPECT_DEATH(TransportFeedbackPacketLossTracker tracker(5000, 20, 0), "");
577 }
578
579 TEST(TransportFeedbackPacketLossTrackerTest, TimeCantFlowBackwards) {
580 TransportFeedbackPacketLossTracker tracker(5000, 2, 1);
581 tracker.OnPacketAdded(100, 0);
582 tracker.OnPacketAdded(101, 2);
583 EXPECT_DEATH(tracker.OnPacketAdded(102, 1), "");
584 }
585 #endif
586
629 // All tests are run multiple times with various baseline sequence number, 587 // All tests are run multiple times with various baseline sequence number,
630 // to weed out potential bugs with wrap-around handling. 588 // to weed out potential bugs with wrap-around handling.
631 constexpr uint16_t kBases[] = {0x0000, 0x3456, 0xc032, 0xfffe}; 589 constexpr uint16_t kBases[] = {0x0000, 0x3456, 0xc032, 0xfffe};
632 590
633 INSTANTIATE_TEST_CASE_P(_, 591 INSTANTIATE_TEST_CASE_P(_,
634 TransportFeedbackPacketLossTrackerTest, 592 TransportFeedbackPacketLossTrackerTest,
635 testing::ValuesIn(kBases)); 593 testing::ValuesIn(kBases));
636 594
637 } // namespace webrtc 595 } // 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