• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3  *
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
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "modules/rtp_rtcp/source/rtp_sequence_number_map.h"
12 
13 #include <algorithm>
14 #include <iterator>
15 #include <limits>
16 #include <memory>
17 #include <tuple>
18 #include <vector>
19 
20 #include "absl/memory/memory.h"
21 #include "absl/types/optional.h"
22 #include "rtc_base/checks.h"
23 #include "rtc_base/numerics/sequence_number_util.h"
24 #include "rtc_base/random.h"
25 #include "test/gtest.h"
26 
27 namespace webrtc {
28 namespace {
29 using Info = RtpSequenceNumberMap::Info;
30 
31 constexpr uint16_t kUint16Max = std::numeric_limits<uint16_t>::max();
32 constexpr size_t kMaxPossibleMaxEntries = 1 << 15;
33 
34 // Just a named pair.
35 struct Association final {
Associationwebrtc::__anon8a1913970111::Association36   Association(uint16_t sequence_number, Info info)
37       : sequence_number(sequence_number), info(info) {}
38 
39   uint16_t sequence_number;
40   Info info;
41 };
42 
43 class RtpSequenceNumberMapTest : public ::testing::Test {
44  protected:
RtpSequenceNumberMapTest()45   RtpSequenceNumberMapTest() : random_(1983) {}
46   ~RtpSequenceNumberMapTest() override = default;
47 
CreateAssociation(uint16_t sequence_number,uint32_t timestamp)48   Association CreateAssociation(uint16_t sequence_number, uint32_t timestamp) {
49     return Association(sequence_number,
50                        {timestamp, random_.Rand<bool>(), random_.Rand<bool>()});
51   }
52 
VerifyAssociations(const RtpSequenceNumberMap & uut,const std::vector<Association> & associations)53   void VerifyAssociations(const RtpSequenceNumberMap& uut,
54                           const std::vector<Association>& associations) {
55     return VerifyAssociations(uut, associations.begin(), associations.end());
56   }
57 
VerifyAssociations(const RtpSequenceNumberMap & uut,std::vector<Association>::const_iterator associations_begin,std::vector<Association>::const_iterator associations_end)58   void VerifyAssociations(
59       const RtpSequenceNumberMap& uut,
60       std::vector<Association>::const_iterator associations_begin,
61       std::vector<Association>::const_iterator associations_end) {
62     RTC_DCHECK(associations_begin < associations_end);
63     ASSERT_EQ(static_cast<size_t>(associations_end - associations_begin),
64               uut.AssociationCountForTesting());
65     for (auto association = associations_begin; association != associations_end;
66          ++association) {
67       EXPECT_EQ(uut.Get(association->sequence_number), association->info);
68     }
69   }
70 
71   // Allows several variations of the same test; definition next to the tests.
72   void GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted(
73       bool with_wrap_around,
74       bool last_element_kept);
75 
76   // Allows several variations of the same test; definition next to the tests.
77   void RepeatedSequenceNumberInvalidatesAll(size_t index_of_repeated);
78 
79   // Allows several variations of the same test; definition next to the tests.
80   void MaxEntriesReachedAtSameTimeAsObsoletionOfItem(size_t max_entries,
81                                                      size_t obsoleted_count);
82 
83   Random random_;
84 };
85 
86 class RtpSequenceNumberMapTestWithParams
87     : public RtpSequenceNumberMapTest,
88       public ::testing::WithParamInterface<std::tuple<size_t, uint16_t>> {
89  protected:
90   RtpSequenceNumberMapTestWithParams() = default;
91   ~RtpSequenceNumberMapTestWithParams() override = default;
92 
ProduceRandomAssociationSequence(size_t association_count,uint16_t first_sequence_number,bool allow_obsoletion)93   std::vector<Association> ProduceRandomAssociationSequence(
94       size_t association_count,
95       uint16_t first_sequence_number,
96       bool allow_obsoletion) {
97     std::vector<Association> associations;
98     associations.reserve(association_count);
99 
100     if (association_count == 0) {
101       return associations;
102     }
103 
104     associations.emplace_back(
105         first_sequence_number,
106         Info(0, random_.Rand<bool>(), random_.Rand<bool>()));
107 
108     for (size_t i = 1; i < association_count; ++i) {
109       const uint16_t sequence_number =
110           associations[i - 1].sequence_number + random_.Rand(1, 100);
111       RTC_DCHECK(allow_obsoletion ||
112                  AheadOf(sequence_number, associations[0].sequence_number));
113 
114       const uint32_t timestamp =
115           associations[i - 1].info.timestamp + random_.Rand(1, 10000);
116 
117       associations.emplace_back(
118           sequence_number,
119           Info(timestamp, random_.Rand<bool>(), random_.Rand<bool>()));
120     }
121 
122     return associations;
123   }
124 };
125 
126 INSTANTIATE_TEST_SUITE_P(All,
127                          RtpSequenceNumberMapTestWithParams,
128                          ::testing::Combine(
129                              // Association count.
130                              ::testing::Values(1, 2, 100),
131                              // First sequence number.
132                              ::testing::Values(0,
133                                                100,
134                                                kUint16Max - 100,
135                                                kUint16Max - 1,
136                                                kUint16Max)));
137 
TEST_F(RtpSequenceNumberMapTest,GetBeforeAssociationsRecordedReturnsNullOpt)138 TEST_F(RtpSequenceNumberMapTest, GetBeforeAssociationsRecordedReturnsNullOpt) {
139   RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
140   constexpr uint16_t kArbitrarySequenceNumber = 321;
141   EXPECT_FALSE(uut.Get(kArbitrarySequenceNumber));
142 }
143 
144 // Version #1 - any old unknown sequence number.
TEST_F(RtpSequenceNumberMapTest,GetUnknownSequenceNumberReturnsNullOpt1)145 TEST_F(RtpSequenceNumberMapTest, GetUnknownSequenceNumberReturnsNullOpt1) {
146   RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
147 
148   constexpr uint16_t kKnownSequenceNumber = 10;
149   constexpr uint32_t kArbitrary = 987;
150   uut.InsertPacket(kKnownSequenceNumber, {kArbitrary, false, false});
151 
152   constexpr uint16_t kUnknownSequenceNumber = kKnownSequenceNumber + 1;
153   EXPECT_FALSE(uut.Get(kUnknownSequenceNumber));
154 }
155 
156 // Version #2 - intentionally pick a value in the range of currently held
157 // values, so as to trigger lower_bound / upper_bound.
TEST_F(RtpSequenceNumberMapTest,GetUnknownSequenceNumberReturnsNullOpt2)158 TEST_F(RtpSequenceNumberMapTest, GetUnknownSequenceNumberReturnsNullOpt2) {
159   RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
160 
161   const std::vector<Association> setup = {CreateAssociation(1000, 500),  //
162                                           CreateAssociation(1020, 501)};
163   for (const Association& association : setup) {
164     uut.InsertPacket(association.sequence_number, association.info);
165   }
166 
167   EXPECT_FALSE(uut.Get(1001));
168 }
169 
TEST_P(RtpSequenceNumberMapTestWithParams,GetKnownSequenceNumberReturnsCorrectValue)170 TEST_P(RtpSequenceNumberMapTestWithParams,
171        GetKnownSequenceNumberReturnsCorrectValue) {
172   RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
173 
174   const size_t association_count = std::get<0>(GetParam());
175   const uint16_t first_sequence_number = std::get<1>(GetParam());
176 
177   const std::vector<Association> associations =
178       ProduceRandomAssociationSequence(association_count, first_sequence_number,
179                                        /*allow_obsoletion=*/false);
180 
181   for (const Association& association : associations) {
182     uut.InsertPacket(association.sequence_number, association.info);
183   }
184 
185   VerifyAssociations(uut, associations);
186 }
187 
TEST_F(RtpSequenceNumberMapTest,InsertFrameOnSinglePacketFrame)188 TEST_F(RtpSequenceNumberMapTest, InsertFrameOnSinglePacketFrame) {
189   RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
190 
191   constexpr uint16_t kSequenceNumber = 888;
192   constexpr uint32_t kTimestamp = 98765;
193   uut.InsertFrame(kSequenceNumber, 1, kTimestamp);
194 
195   EXPECT_EQ(uut.Get(kSequenceNumber), Info(kTimestamp, true, true));
196 }
197 
TEST_F(RtpSequenceNumberMapTest,InsertFrameOnMultiPacketFrameNoWrapAround)198 TEST_F(RtpSequenceNumberMapTest, InsertFrameOnMultiPacketFrameNoWrapAround) {
199   RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
200 
201   constexpr uint16_t kFirstSequenceNumber = 0;
202   constexpr uint32_t kTimestamp = 98765;
203   uut.InsertFrame(kFirstSequenceNumber, 3, kTimestamp);
204 
205   EXPECT_EQ(uut.Get(kFirstSequenceNumber + 0), Info(kTimestamp, true, false));
206   EXPECT_EQ(uut.Get(kFirstSequenceNumber + 1), Info(kTimestamp, false, false));
207   EXPECT_EQ(uut.Get(kFirstSequenceNumber + 2), Info(kTimestamp, false, true));
208 }
209 
TEST_F(RtpSequenceNumberMapTest,InsertFrameOnMultiPacketFrameWithWrapAround)210 TEST_F(RtpSequenceNumberMapTest, InsertFrameOnMultiPacketFrameWithWrapAround) {
211   RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
212 
213   constexpr uint16_t kFirstSequenceNumber = kUint16Max;
214   constexpr uint32_t kTimestamp = 98765;
215   uut.InsertFrame(kFirstSequenceNumber, 3, kTimestamp);
216 
217 // Suppress "truncation of constant value" warning; wrap-around is intended.
218 #ifdef _MSC_VER
219 #pragma warning(push)
220 #pragma warning(disable : 4309)
221 #endif
222   EXPECT_EQ(uut.Get(static_cast<uint16_t>(kFirstSequenceNumber + 0u)),
223             Info(kTimestamp, true, false));
224   EXPECT_EQ(uut.Get(static_cast<uint16_t>(kFirstSequenceNumber + 1u)),
225             Info(kTimestamp, false, false));
226   EXPECT_EQ(uut.Get(static_cast<uint16_t>(kFirstSequenceNumber + 2u)),
227             Info(kTimestamp, false, true));
228 #ifdef _MSC_VER
229 #pragma warning(pop)
230 #endif
231 }
232 
TEST_F(RtpSequenceNumberMapTest,GetObsoleteSequenceNumberReturnsNullOptSingleValueObsoleted)233 TEST_F(RtpSequenceNumberMapTest,
234        GetObsoleteSequenceNumberReturnsNullOptSingleValueObsoleted) {
235   RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
236 
237   const std::vector<Association> associations = {
238       CreateAssociation(0, 10),       //
239       CreateAssociation(0x8000, 20),  //
240       CreateAssociation(0x8001u, 30)};
241 
242   uut.InsertPacket(associations[0].sequence_number, associations[0].info);
243 
244   // First association not yet obsolete, and therefore remembered.
245   RTC_DCHECK(AheadOf(associations[1].sequence_number,
246                      associations[0].sequence_number));
247   uut.InsertPacket(associations[1].sequence_number, associations[1].info);
248   VerifyAssociations(uut, {associations[0], associations[1]});
249 
250   // Test focus - new entry obsoletes first entry.
251   RTC_DCHECK(!AheadOf(associations[2].sequence_number,
252                       associations[0].sequence_number));
253   uut.InsertPacket(associations[2].sequence_number, associations[2].info);
254   VerifyAssociations(uut, {associations[1], associations[2]});
255 }
256 
257 void RtpSequenceNumberMapTest::
GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted(bool with_wrap_around,bool last_element_kept)258     GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted(
259         bool with_wrap_around,
260         bool last_element_kept) {
261   RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
262 
263   std::vector<Association> associations;
264   if (with_wrap_around) {
265     associations = {CreateAssociation(kUint16Max - 1, 10),  //
266                     CreateAssociation(kUint16Max, 20),      //
267                     CreateAssociation(0, 30),               //
268                     CreateAssociation(1, 40),               //
269                     CreateAssociation(2, 50)};
270   } else {
271     associations = {CreateAssociation(1, 10),  //
272                     CreateAssociation(2, 20),  //
273                     CreateAssociation(3, 30),  //
274                     CreateAssociation(4, 40),  //
275                     CreateAssociation(5, 50)};
276   }
277 
278   for (auto association : associations) {
279     uut.InsertPacket(association.sequence_number, association.info);
280   }
281   VerifyAssociations(uut, associations);
282 
283   // Define a new association that will obsolete either all previous entries,
284   // or all previous entries except for the last one, depending on the
285   // parameter instantiation of this test.
286   RTC_DCHECK_EQ(
287       static_cast<uint16_t>(
288           associations[associations.size() - 1].sequence_number),
289       static_cast<uint16_t>(
290           associations[associations.size() - 2].sequence_number + 1u));
291   uint16_t new_sequence_number;
292   if (last_element_kept) {
293     new_sequence_number =
294         associations[associations.size() - 1].sequence_number + 0x8000;
295     RTC_DCHECK(AheadOf(new_sequence_number,
296                        associations[associations.size() - 1].sequence_number));
297   } else {
298     new_sequence_number =
299         associations[associations.size() - 1].sequence_number + 0x8001;
300     RTC_DCHECK(!AheadOf(new_sequence_number,
301                         associations[associations.size() - 1].sequence_number));
302   }
303   RTC_DCHECK(!AheadOf(new_sequence_number,
304                       associations[associations.size() - 2].sequence_number));
305 
306   // Record the new association.
307   const Association new_association =
308       CreateAssociation(new_sequence_number, 60);
309   uut.InsertPacket(new_association.sequence_number, new_association.info);
310 
311   // Make sure all obsoleted elements were removed.
312   const size_t obsoleted_count =
313       associations.size() - (last_element_kept ? 1 : 0);
314   for (size_t i = 0; i < obsoleted_count; ++i) {
315     EXPECT_FALSE(uut.Get(associations[i].sequence_number));
316   }
317 
318   // Make sure the expected elements were not removed, and return the
319   // expected value.
320   if (last_element_kept) {
321     EXPECT_EQ(uut.Get(associations.back().sequence_number),
322               associations.back().info);
323   }
324   EXPECT_EQ(uut.Get(new_association.sequence_number), new_association.info);
325 }
326 
TEST_F(RtpSequenceNumberMapTest,GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted0)327 TEST_F(RtpSequenceNumberMapTest,
328        GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted0) {
329   const bool with_wrap_around = false;
330   const bool last_element_kept = false;
331   GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted(
332       with_wrap_around, last_element_kept);
333 }
334 
TEST_F(RtpSequenceNumberMapTest,GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted1)335 TEST_F(RtpSequenceNumberMapTest,
336        GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted1) {
337   const bool with_wrap_around = true;
338   const bool last_element_kept = false;
339   GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted(
340       with_wrap_around, last_element_kept);
341 }
342 
TEST_F(RtpSequenceNumberMapTest,GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted2)343 TEST_F(RtpSequenceNumberMapTest,
344        GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted2) {
345   const bool with_wrap_around = false;
346   const bool last_element_kept = true;
347   GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted(
348       with_wrap_around, last_element_kept);
349 }
350 
TEST_F(RtpSequenceNumberMapTest,GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted3)351 TEST_F(RtpSequenceNumberMapTest,
352        GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted3) {
353   const bool with_wrap_around = true;
354   const bool last_element_kept = true;
355   GetObsoleteSequenceNumberReturnsNullOptMultipleEntriesObsoleted(
356       with_wrap_around, last_element_kept);
357 }
358 
RepeatedSequenceNumberInvalidatesAll(size_t index_of_repeated)359 void RtpSequenceNumberMapTest::RepeatedSequenceNumberInvalidatesAll(
360     size_t index_of_repeated) {
361   RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
362 
363   const std::vector<Association> setup = {CreateAssociation(100, 500),  //
364                                           CreateAssociation(101, 501),  //
365                                           CreateAssociation(102, 502)};
366   RTC_DCHECK_LT(index_of_repeated, setup.size());
367   for (const Association& association : setup) {
368     uut.InsertPacket(association.sequence_number, association.info);
369   }
370 
371   const Association new_association =
372       CreateAssociation(setup[index_of_repeated].sequence_number, 503);
373   uut.InsertPacket(new_association.sequence_number, new_association.info);
374 
375   // All entries from setup invalidated.
376   // New entry valid and mapped to new value.
377   for (size_t i = 0; i < setup.size(); ++i) {
378     if (i == index_of_repeated) {
379       EXPECT_EQ(uut.Get(new_association.sequence_number), new_association.info);
380     } else {
381       EXPECT_FALSE(uut.Get(setup[i].sequence_number));
382     }
383   }
384 }
385 
TEST_F(RtpSequenceNumberMapTest,RepeatedSequenceNumberInvalidatesAllRepeatFirst)386 TEST_F(RtpSequenceNumberMapTest,
387        RepeatedSequenceNumberInvalidatesAllRepeatFirst) {
388   RepeatedSequenceNumberInvalidatesAll(0);
389 }
390 
TEST_F(RtpSequenceNumberMapTest,RepeatedSequenceNumberInvalidatesAllRepeatMiddle)391 TEST_F(RtpSequenceNumberMapTest,
392        RepeatedSequenceNumberInvalidatesAllRepeatMiddle) {
393   RepeatedSequenceNumberInvalidatesAll(1);
394 }
395 
TEST_F(RtpSequenceNumberMapTest,RepeatedSequenceNumberInvalidatesAllRepeatLast)396 TEST_F(RtpSequenceNumberMapTest,
397        RepeatedSequenceNumberInvalidatesAllRepeatLast) {
398   RepeatedSequenceNumberInvalidatesAll(2);
399 }
400 
TEST_F(RtpSequenceNumberMapTest,SequenceNumberInsideMemorizedRangeInvalidatesAll)401 TEST_F(RtpSequenceNumberMapTest,
402        SequenceNumberInsideMemorizedRangeInvalidatesAll) {
403   RtpSequenceNumberMap uut(kMaxPossibleMaxEntries);
404 
405   const std::vector<Association> setup = {CreateAssociation(1000, 500),  //
406                                           CreateAssociation(1020, 501),  //
407                                           CreateAssociation(1030, 502)};
408   for (const Association& association : setup) {
409     uut.InsertPacket(association.sequence_number, association.info);
410   }
411 
412   const Association new_association = CreateAssociation(1010, 503);
413   uut.InsertPacket(new_association.sequence_number, new_association.info);
414 
415   // All entries from setup invalidated.
416   // New entry valid and mapped to new value.
417   for (size_t i = 0; i < setup.size(); ++i) {
418     EXPECT_FALSE(uut.Get(setup[i].sequence_number));
419   }
420   EXPECT_EQ(uut.Get(new_association.sequence_number), new_association.info);
421 }
422 
TEST_F(RtpSequenceNumberMapTest,MaxEntriesObserved)423 TEST_F(RtpSequenceNumberMapTest, MaxEntriesObserved) {
424   constexpr size_t kMaxEntries = 100;
425   RtpSequenceNumberMap uut(kMaxEntries);
426 
427   std::vector<Association> associations;
428   associations.reserve(kMaxEntries);
429   uint32_t timestamp = 789;
430   for (size_t i = 0; i < kMaxEntries; ++i) {
431     associations.push_back(CreateAssociation(i, ++timestamp));
432     uut.InsertPacket(associations[i].sequence_number, associations[i].info);
433   }
434   VerifyAssociations(uut, associations);  // Sanity.
435 
436   const Association new_association =
437       CreateAssociation(kMaxEntries, ++timestamp);
438   uut.InsertPacket(new_association.sequence_number, new_association.info);
439   associations.push_back(new_association);
440 
441   // The +1 is for `new_association`.
442   const size_t kExpectedAssociationCount = 3 * kMaxEntries / 4 + 1;
443   const auto expected_begin =
444       std::prev(associations.end(), kExpectedAssociationCount);
445   VerifyAssociations(uut, expected_begin, associations.end());
446 }
447 
MaxEntriesReachedAtSameTimeAsObsoletionOfItem(size_t max_entries,size_t obsoleted_count)448 void RtpSequenceNumberMapTest::MaxEntriesReachedAtSameTimeAsObsoletionOfItem(
449     size_t max_entries,
450     size_t obsoleted_count) {
451   RtpSequenceNumberMap uut(max_entries);
452 
453   std::vector<Association> associations;
454   associations.reserve(max_entries);
455   uint32_t timestamp = 789;
456   for (size_t i = 0; i < max_entries; ++i) {
457     associations.push_back(CreateAssociation(i, ++timestamp));
458     uut.InsertPacket(associations[i].sequence_number, associations[i].info);
459   }
460   VerifyAssociations(uut, associations);  // Sanity.
461 
462   const uint16_t new_association_sequence_number =
463       static_cast<uint16_t>(obsoleted_count) + (1 << 15);
464   const Association new_association =
465       CreateAssociation(new_association_sequence_number, ++timestamp);
466   uut.InsertPacket(new_association.sequence_number, new_association.info);
467   associations.push_back(new_association);
468 
469   // The +1 is for `new_association`.
470   const size_t kExpectedAssociationCount =
471       std::min(3 * max_entries / 4, max_entries - obsoleted_count) + 1;
472   const auto expected_begin =
473       std::prev(associations.end(), kExpectedAssociationCount);
474   VerifyAssociations(uut, expected_begin, associations.end());
475 }
476 
477 // Version #1 - #(obsoleted entries) < #(entries after paring down below max).
TEST_F(RtpSequenceNumberMapTest,MaxEntriesReachedAtSameTimeAsObsoletionOfItem1)478 TEST_F(RtpSequenceNumberMapTest,
479        MaxEntriesReachedAtSameTimeAsObsoletionOfItem1) {
480   constexpr size_t kMaxEntries = 100;
481   constexpr size_t kObsoletionTarget = (kMaxEntries / 4) - 1;
482   MaxEntriesReachedAtSameTimeAsObsoletionOfItem(kMaxEntries, kObsoletionTarget);
483 }
484 
485 // Version #2 - #(obsoleted entries) == #(entries after paring down below max).
TEST_F(RtpSequenceNumberMapTest,MaxEntriesReachedAtSameTimeAsObsoletionOfItem2)486 TEST_F(RtpSequenceNumberMapTest,
487        MaxEntriesReachedAtSameTimeAsObsoletionOfItem2) {
488   constexpr size_t kMaxEntries = 100;
489   constexpr size_t kObsoletionTarget = kMaxEntries / 4;
490   MaxEntriesReachedAtSameTimeAsObsoletionOfItem(kMaxEntries, kObsoletionTarget);
491 }
492 
493 // Version #3 - #(obsoleted entries) > #(entries after paring down below max).
TEST_F(RtpSequenceNumberMapTest,MaxEntriesReachedAtSameTimeAsObsoletionOfItem3)494 TEST_F(RtpSequenceNumberMapTest,
495        MaxEntriesReachedAtSameTimeAsObsoletionOfItem3) {
496   constexpr size_t kMaxEntries = 100;
497   constexpr size_t kObsoletionTarget = (kMaxEntries / 4) + 1;
498   MaxEntriesReachedAtSameTimeAsObsoletionOfItem(kMaxEntries, kObsoletionTarget);
499 }
500 
501 }  // namespace
502 }  // namespace webrtc
503