xref: /aosp_15_r20/external/webrtc/net/dcsctp/tx/outstanding_data_test.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2021 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 #include "net/dcsctp/tx/outstanding_data.h"
11 
12 #include <vector>
13 
14 #include "absl/types/optional.h"
15 #include "net/dcsctp/common/math.h"
16 #include "net/dcsctp/common/sequence_numbers.h"
17 #include "net/dcsctp/packet/chunk/data_chunk.h"
18 #include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
19 #include "net/dcsctp/public/types.h"
20 #include "net/dcsctp/testing/data_generator.h"
21 #include "net/dcsctp/testing/testing_macros.h"
22 #include "rtc_base/gunit.h"
23 #include "test/gmock.h"
24 
25 namespace dcsctp {
26 namespace {
27 using ::testing::MockFunction;
28 using State = ::dcsctp::OutstandingData::State;
29 using ::testing::_;
30 using ::testing::ElementsAre;
31 using ::testing::IsEmpty;
32 using ::testing::Pair;
33 using ::testing::Return;
34 using ::testing::StrictMock;
35 
36 constexpr TimeMs kNow(42);
37 
38 class OutstandingDataTest : public testing::Test {
39  protected:
OutstandingDataTest()40   OutstandingDataTest()
41       : gen_(MID(42)),
42         buf_(DataChunk::kHeaderSize,
43              unwrapper_.Unwrap(TSN(10)),
44              unwrapper_.Unwrap(TSN(9)),
45              on_discard_.AsStdFunction()) {}
46 
47   UnwrappedTSN::Unwrapper unwrapper_;
48   DataGenerator gen_;
49   StrictMock<MockFunction<bool(IsUnordered, StreamID, MID)>> on_discard_;
50   OutstandingData buf_;
51 };
52 
TEST_F(OutstandingDataTest,HasInitialState)53 TEST_F(OutstandingDataTest, HasInitialState) {
54   EXPECT_TRUE(buf_.empty());
55   EXPECT_EQ(buf_.outstanding_bytes(), 0u);
56   EXPECT_EQ(buf_.outstanding_items(), 0u);
57   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
58   EXPECT_EQ(buf_.last_cumulative_tsn_ack().Wrap(), TSN(9));
59   EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(10));
60   EXPECT_EQ(buf_.highest_outstanding_tsn().Wrap(), TSN(9));
61   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
62               ElementsAre(Pair(TSN(9), State::kAcked)));
63   EXPECT_FALSE(buf_.ShouldSendForwardTsn());
64 }
65 
TEST_F(OutstandingDataTest,InsertChunk)66 TEST_F(OutstandingDataTest, InsertChunk) {
67   ASSERT_HAS_VALUE_AND_ASSIGN(UnwrappedTSN tsn,
68                               buf_.Insert(gen_.Ordered({1}, "BE"), kNow));
69 
70   EXPECT_EQ(tsn.Wrap(), TSN(10));
71 
72   EXPECT_EQ(buf_.outstanding_bytes(), DataChunk::kHeaderSize + RoundUpTo4(1));
73   EXPECT_EQ(buf_.outstanding_items(), 1u);
74   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
75   EXPECT_EQ(buf_.last_cumulative_tsn_ack().Wrap(), TSN(9));
76   EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(11));
77   EXPECT_EQ(buf_.highest_outstanding_tsn().Wrap(), TSN(10));
78   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
79               ElementsAre(Pair(TSN(9), State::kAcked),
80                           Pair(TSN(10), State::kInFlight)));
81 }
82 
TEST_F(OutstandingDataTest,AcksSingleChunk)83 TEST_F(OutstandingDataTest, AcksSingleChunk) {
84   buf_.Insert(gen_.Ordered({1}, "BE"), kNow);
85   OutstandingData::AckInfo ack =
86       buf_.HandleSack(unwrapper_.Unwrap(TSN(10)), {}, false);
87 
88   EXPECT_EQ(ack.bytes_acked, DataChunk::kHeaderSize + RoundUpTo4(1));
89   EXPECT_EQ(ack.highest_tsn_acked.Wrap(), TSN(10));
90   EXPECT_FALSE(ack.has_packet_loss);
91 
92   EXPECT_EQ(buf_.outstanding_bytes(), 0u);
93   EXPECT_EQ(buf_.outstanding_items(), 0u);
94   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
95   EXPECT_EQ(buf_.last_cumulative_tsn_ack().Wrap(), TSN(10));
96   EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(11));
97   EXPECT_EQ(buf_.highest_outstanding_tsn().Wrap(), TSN(10));
98   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
99               ElementsAre(Pair(TSN(10), State::kAcked)));
100 }
101 
TEST_F(OutstandingDataTest,AcksPreviousChunkDoesntUpdate)102 TEST_F(OutstandingDataTest, AcksPreviousChunkDoesntUpdate) {
103   buf_.Insert(gen_.Ordered({1}, "BE"), kNow);
104   buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), {}, false);
105 
106   EXPECT_EQ(buf_.outstanding_bytes(), DataChunk::kHeaderSize + RoundUpTo4(1));
107   EXPECT_EQ(buf_.outstanding_items(), 1u);
108   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
109   EXPECT_EQ(buf_.last_cumulative_tsn_ack().Wrap(), TSN(9));
110   EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(11));
111   EXPECT_EQ(buf_.highest_outstanding_tsn().Wrap(), TSN(10));
112   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
113               ElementsAre(Pair(TSN(9), State::kAcked),
114                           Pair(TSN(10), State::kInFlight)));
115 }
116 
TEST_F(OutstandingDataTest,AcksAndNacksWithGapAckBlocks)117 TEST_F(OutstandingDataTest, AcksAndNacksWithGapAckBlocks) {
118   buf_.Insert(gen_.Ordered({1}, "B"), kNow);
119   buf_.Insert(gen_.Ordered({1}, "E"), kNow);
120 
121   std::vector<SackChunk::GapAckBlock> gab = {SackChunk::GapAckBlock(2, 2)};
122   OutstandingData::AckInfo ack =
123       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab, false);
124   EXPECT_EQ(ack.bytes_acked, DataChunk::kHeaderSize + RoundUpTo4(1));
125   EXPECT_EQ(ack.highest_tsn_acked.Wrap(), TSN(11));
126   EXPECT_FALSE(ack.has_packet_loss);
127 
128   EXPECT_EQ(buf_.outstanding_bytes(), 0u);
129   EXPECT_EQ(buf_.outstanding_items(), 0u);
130   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
131   EXPECT_EQ(buf_.last_cumulative_tsn_ack().Wrap(), TSN(9));
132   EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(12));
133   EXPECT_EQ(buf_.highest_outstanding_tsn().Wrap(), TSN(11));
134   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
135               ElementsAre(Pair(TSN(9), State::kAcked),    //
136                           Pair(TSN(10), State::kNacked),  //
137                           Pair(TSN(11), State::kAcked)));
138 }
139 
TEST_F(OutstandingDataTest,NacksThreeTimesWithSameTsnDoesntRetransmit)140 TEST_F(OutstandingDataTest, NacksThreeTimesWithSameTsnDoesntRetransmit) {
141   buf_.Insert(gen_.Ordered({1}, "B"), kNow);
142   buf_.Insert(gen_.Ordered({1}, "E"), kNow);
143 
144   std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(2, 2)};
145   EXPECT_FALSE(
146       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
147   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
148 
149   EXPECT_FALSE(
150       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
151   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
152 
153   EXPECT_FALSE(
154       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
155   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
156 
157   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
158               ElementsAre(Pair(TSN(9), State::kAcked),    //
159                           Pair(TSN(10), State::kNacked),  //
160                           Pair(TSN(11), State::kAcked)));
161 }
162 
TEST_F(OutstandingDataTest,NacksThreeTimesResultsInRetransmission)163 TEST_F(OutstandingDataTest, NacksThreeTimesResultsInRetransmission) {
164   buf_.Insert(gen_.Ordered({1}, "B"), kNow);
165   buf_.Insert(gen_.Ordered({1}, ""), kNow);
166   buf_.Insert(gen_.Ordered({1}, ""), kNow);
167   buf_.Insert(gen_.Ordered({1}, "E"), kNow);
168 
169   std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(2, 2)};
170   EXPECT_FALSE(
171       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
172   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
173 
174   std::vector<SackChunk::GapAckBlock> gab2 = {SackChunk::GapAckBlock(2, 3)};
175   EXPECT_FALSE(
176       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab2, false).has_packet_loss);
177   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
178 
179   std::vector<SackChunk::GapAckBlock> gab3 = {SackChunk::GapAckBlock(2, 4)};
180   OutstandingData::AckInfo ack =
181       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab3, false);
182   EXPECT_EQ(ack.bytes_acked, DataChunk::kHeaderSize + RoundUpTo4(1));
183   EXPECT_EQ(ack.highest_tsn_acked.Wrap(), TSN(13));
184   EXPECT_TRUE(ack.has_packet_loss);
185 
186   EXPECT_TRUE(buf_.has_data_to_be_retransmitted());
187 
188   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
189               ElementsAre(Pair(TSN(9), State::kAcked),               //
190                           Pair(TSN(10), State::kToBeRetransmitted),  //
191                           Pair(TSN(11), State::kAcked),              //
192                           Pair(TSN(12), State::kAcked),              //
193                           Pair(TSN(13), State::kAcked)));
194 
195   EXPECT_THAT(buf_.GetChunksToBeFastRetransmitted(1000),
196               ElementsAre(Pair(TSN(10), _)));
197   EXPECT_THAT(buf_.GetChunksToBeRetransmitted(1000), IsEmpty());
198 }
199 
TEST_F(OutstandingDataTest,NacksThreeTimesResultsInAbandoning)200 TEST_F(OutstandingDataTest, NacksThreeTimesResultsInAbandoning) {
201   static constexpr MaxRetransmits kMaxRetransmissions(0);
202   buf_.Insert(gen_.Ordered({1}, "B"), kNow, kMaxRetransmissions);
203   buf_.Insert(gen_.Ordered({1}, ""), kNow, kMaxRetransmissions);
204   buf_.Insert(gen_.Ordered({1}, ""), kNow, kMaxRetransmissions);
205   buf_.Insert(gen_.Ordered({1}, "E"), kNow, kMaxRetransmissions);
206 
207   std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(2, 2)};
208   EXPECT_FALSE(
209       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
210   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
211 
212   std::vector<SackChunk::GapAckBlock> gab2 = {SackChunk::GapAckBlock(2, 3)};
213   EXPECT_FALSE(
214       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab2, false).has_packet_loss);
215   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
216 
217   EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
218       .WillOnce(Return(false));
219   std::vector<SackChunk::GapAckBlock> gab3 = {SackChunk::GapAckBlock(2, 4)};
220   OutstandingData::AckInfo ack =
221       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab3, false);
222   EXPECT_EQ(ack.bytes_acked, DataChunk::kHeaderSize + RoundUpTo4(1));
223   EXPECT_EQ(ack.highest_tsn_acked.Wrap(), TSN(13));
224   EXPECT_TRUE(ack.has_packet_loss);
225 
226   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
227   EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(14));
228   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
229               ElementsAre(Pair(TSN(9), State::kAcked),       //
230                           Pair(TSN(10), State::kAbandoned),  //
231                           Pair(TSN(11), State::kAbandoned),  //
232                           Pair(TSN(12), State::kAbandoned),  //
233                           Pair(TSN(13), State::kAbandoned)));
234 }
235 
TEST_F(OutstandingDataTest,NacksThreeTimesResultsInAbandoningWithPlaceholder)236 TEST_F(OutstandingDataTest, NacksThreeTimesResultsInAbandoningWithPlaceholder) {
237   static constexpr MaxRetransmits kMaxRetransmissions(0);
238   buf_.Insert(gen_.Ordered({1}, "B"), kNow, kMaxRetransmissions);
239   buf_.Insert(gen_.Ordered({1}, ""), kNow, kMaxRetransmissions);
240   buf_.Insert(gen_.Ordered({1}, ""), kNow, kMaxRetransmissions);
241   buf_.Insert(gen_.Ordered({1}, ""), kNow, kMaxRetransmissions);
242 
243   std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(2, 2)};
244   EXPECT_FALSE(
245       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
246   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
247 
248   std::vector<SackChunk::GapAckBlock> gab2 = {SackChunk::GapAckBlock(2, 3)};
249   EXPECT_FALSE(
250       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab2, false).has_packet_loss);
251   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
252 
253   EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
254       .WillOnce(Return(true));
255   std::vector<SackChunk::GapAckBlock> gab3 = {SackChunk::GapAckBlock(2, 4)};
256   OutstandingData::AckInfo ack =
257       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab3, false);
258   EXPECT_EQ(ack.bytes_acked, DataChunk::kHeaderSize + RoundUpTo4(1));
259   EXPECT_EQ(ack.highest_tsn_acked.Wrap(), TSN(13));
260   EXPECT_TRUE(ack.has_packet_loss);
261 
262   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
263   EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(15));
264   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
265               ElementsAre(Pair(TSN(9), State::kAcked),       //
266                           Pair(TSN(10), State::kAbandoned),  //
267                           Pair(TSN(11), State::kAbandoned),  //
268                           Pair(TSN(12), State::kAbandoned),  //
269                           Pair(TSN(13), State::kAbandoned),  //
270                           Pair(TSN(14), State::kAbandoned)));
271 }
272 
TEST_F(OutstandingDataTest,ExpiresChunkBeforeItIsInserted)273 TEST_F(OutstandingDataTest, ExpiresChunkBeforeItIsInserted) {
274   static constexpr TimeMs kExpiresAt = kNow + DurationMs(1);
275   EXPECT_TRUE(buf_.Insert(gen_.Ordered({1}, "B"), kNow,
276                           MaxRetransmits::NoLimit(), kExpiresAt)
277                   .has_value());
278   EXPECT_TRUE(buf_.Insert(gen_.Ordered({1}, ""), kNow + DurationMs(0),
279                           MaxRetransmits::NoLimit(), kExpiresAt)
280                   .has_value());
281 
282   EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
283       .WillOnce(Return(false));
284   EXPECT_FALSE(buf_.Insert(gen_.Ordered({1}, "E"), kNow + DurationMs(1),
285                            MaxRetransmits::NoLimit(), kExpiresAt)
286                    .has_value());
287 
288   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
289   EXPECT_EQ(buf_.last_cumulative_tsn_ack().Wrap(), TSN(9));
290   EXPECT_EQ(buf_.next_tsn().Wrap(), TSN(13));
291   EXPECT_EQ(buf_.highest_outstanding_tsn().Wrap(), TSN(12));
292   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
293               ElementsAre(Pair(TSN(9), State::kAcked),       //
294                           Pair(TSN(10), State::kAbandoned),  //
295                           Pair(TSN(11), State::kAbandoned),
296                           Pair(TSN(12), State::kAbandoned)));
297 }
298 
TEST_F(OutstandingDataTest,CanGenerateForwardTsn)299 TEST_F(OutstandingDataTest, CanGenerateForwardTsn) {
300   static constexpr MaxRetransmits kMaxRetransmissions(0);
301   buf_.Insert(gen_.Ordered({1}, "B"), kNow, kMaxRetransmissions);
302   buf_.Insert(gen_.Ordered({1}, ""), kNow, kMaxRetransmissions);
303   buf_.Insert(gen_.Ordered({1}, "E"), kNow, kMaxRetransmissions);
304 
305   EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
306       .WillOnce(Return(false));
307   buf_.NackAll();
308 
309   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
310   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
311               ElementsAre(Pair(TSN(9), State::kAcked),       //
312                           Pair(TSN(10), State::kAbandoned),  //
313                           Pair(TSN(11), State::kAbandoned),
314                           Pair(TSN(12), State::kAbandoned)));
315 
316   EXPECT_TRUE(buf_.ShouldSendForwardTsn());
317   ForwardTsnChunk chunk = buf_.CreateForwardTsn();
318   EXPECT_EQ(chunk.new_cumulative_tsn(), TSN(12));
319 }
320 
TEST_F(OutstandingDataTest,AckWithGapBlocksFromRFC4960Section334)321 TEST_F(OutstandingDataTest, AckWithGapBlocksFromRFC4960Section334) {
322   buf_.Insert(gen_.Ordered({1}, "B"), kNow);
323   buf_.Insert(gen_.Ordered({1}, ""), kNow);
324   buf_.Insert(gen_.Ordered({1}, ""), kNow);
325   buf_.Insert(gen_.Ordered({1}, ""), kNow);
326   buf_.Insert(gen_.Ordered({1}, ""), kNow);
327   buf_.Insert(gen_.Ordered({1}, ""), kNow);
328   buf_.Insert(gen_.Ordered({1}, ""), kNow);
329   buf_.Insert(gen_.Ordered({1}, "E"), kNow);
330 
331   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
332               testing::ElementsAre(Pair(TSN(9), State::kAcked),      //
333                                    Pair(TSN(10), State::kInFlight),  //
334                                    Pair(TSN(11), State::kInFlight),  //
335                                    Pair(TSN(12), State::kInFlight),  //
336                                    Pair(TSN(13), State::kInFlight),  //
337                                    Pair(TSN(14), State::kInFlight),  //
338                                    Pair(TSN(15), State::kInFlight),  //
339                                    Pair(TSN(16), State::kInFlight),  //
340                                    Pair(TSN(17), State::kInFlight)));
341 
342   std::vector<SackChunk::GapAckBlock> gab = {SackChunk::GapAckBlock(2, 3),
343                                              SackChunk::GapAckBlock(5, 5)};
344   buf_.HandleSack(unwrapper_.Unwrap(TSN(12)), gab, false);
345 
346   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
347               ElementsAre(Pair(TSN(12), State::kAcked),   //
348                           Pair(TSN(13), State::kNacked),  //
349                           Pair(TSN(14), State::kAcked),   //
350                           Pair(TSN(15), State::kAcked),   //
351                           Pair(TSN(16), State::kNacked),  //
352                           Pair(TSN(17), State::kAcked)));
353 }
354 
TEST_F(OutstandingDataTest,MeasureRTT)355 TEST_F(OutstandingDataTest, MeasureRTT) {
356   buf_.Insert(gen_.Ordered({1}, "BE"), kNow);
357   buf_.Insert(gen_.Ordered({1}, "BE"), kNow + DurationMs(1));
358   buf_.Insert(gen_.Ordered({1}, "BE"), kNow + DurationMs(2));
359 
360   static constexpr DurationMs kDuration(123);
361   ASSERT_HAS_VALUE_AND_ASSIGN(
362       DurationMs duration,
363       buf_.MeasureRTT(kNow + kDuration, unwrapper_.Unwrap(TSN(11))));
364 
365   EXPECT_EQ(duration, kDuration - DurationMs(1));
366 }
367 
TEST_F(OutstandingDataTest,MustRetransmitBeforeGettingNackedAgain)368 TEST_F(OutstandingDataTest, MustRetransmitBeforeGettingNackedAgain) {
369   // This test case verifies that a chunk that has been nacked, and scheduled to
370   // be retransmitted, doesn't get nacked again until it has been actually sent
371   // on the wire.
372 
373   static constexpr MaxRetransmits kOneRetransmission(1);
374   for (int tsn = 10; tsn <= 20; ++tsn) {
375     buf_.Insert(gen_.Ordered({1}, tsn == 10   ? "B"
376                                   : tsn == 20 ? "E"
377                                               : ""),
378                 kNow, kOneRetransmission);
379   }
380 
381   std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(2, 2)};
382   EXPECT_FALSE(
383       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
384   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
385 
386   std::vector<SackChunk::GapAckBlock> gab2 = {SackChunk::GapAckBlock(2, 3)};
387   EXPECT_FALSE(
388       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab2, false).has_packet_loss);
389   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
390 
391   std::vector<SackChunk::GapAckBlock> gab3 = {SackChunk::GapAckBlock(2, 4)};
392   OutstandingData::AckInfo ack =
393       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab3, false);
394   EXPECT_TRUE(ack.has_packet_loss);
395   EXPECT_TRUE(buf_.has_data_to_be_retransmitted());
396 
397   // Don't call GetChunksToBeRetransmitted yet - simulate that the congestion
398   // window doesn't allow it to be retransmitted yet. It does however get more
399   // SACKs indicating packet loss.
400 
401   std::vector<SackChunk::GapAckBlock> gab4 = {SackChunk::GapAckBlock(2, 5)};
402   EXPECT_FALSE(
403       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab4, false).has_packet_loss);
404   EXPECT_TRUE(buf_.has_data_to_be_retransmitted());
405 
406   std::vector<SackChunk::GapAckBlock> gab5 = {SackChunk::GapAckBlock(2, 6)};
407   EXPECT_FALSE(
408       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab5, false).has_packet_loss);
409   EXPECT_TRUE(buf_.has_data_to_be_retransmitted());
410 
411   std::vector<SackChunk::GapAckBlock> gab6 = {SackChunk::GapAckBlock(2, 7)};
412   OutstandingData::AckInfo ack2 =
413       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab6, false);
414 
415   EXPECT_FALSE(ack2.has_packet_loss);
416   EXPECT_TRUE(buf_.has_data_to_be_retransmitted());
417 
418   // Now it's retransmitted.
419   EXPECT_THAT(buf_.GetChunksToBeFastRetransmitted(1000),
420               ElementsAre(Pair(TSN(10), _)));
421   EXPECT_THAT(buf_.GetChunksToBeRetransmitted(1000), IsEmpty());
422 
423   // And obviously lost, as it will get NACKed and abandoned.
424   std::vector<SackChunk::GapAckBlock> gab7 = {SackChunk::GapAckBlock(2, 8)};
425   EXPECT_FALSE(
426       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab7, false).has_packet_loss);
427   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
428 
429   std::vector<SackChunk::GapAckBlock> gab8 = {SackChunk::GapAckBlock(2, 9)};
430   EXPECT_FALSE(
431       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab8, false).has_packet_loss);
432   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
433 
434   EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
435       .WillOnce(Return(false));
436 
437   std::vector<SackChunk::GapAckBlock> gab9 = {SackChunk::GapAckBlock(2, 10)};
438   OutstandingData::AckInfo ack3 =
439       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab9, false);
440 
441   EXPECT_TRUE(ack3.has_packet_loss);
442   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
443 }
444 
TEST_F(OutstandingDataTest,CanAbandonChunksMarkedForFastRetransmit)445 TEST_F(OutstandingDataTest, CanAbandonChunksMarkedForFastRetransmit) {
446   // This test is a bit convoluted, and can't really happen with a well behaving
447   // client, but this was found by fuzzers. This test will verify that a message
448   // that was both marked as "to be fast retransmitted" and "abandoned" at the
449   // same time doesn't cause any consistency issues.
450 
451   // Add chunks 10-14, but chunk 11 has zero retransmissions. When chunk 10 and
452   // 11 are NACKed three times, chunk 10 will be marked for retransmission, but
453   // chunk 11 will be abandoned, which also abandons chunk 10, as it's part of
454   // the same message.
455   buf_.Insert(gen_.Ordered({1}, "B"), kNow);                    // 10
456   buf_.Insert(gen_.Ordered({1}, ""), kNow, MaxRetransmits(0));  // 11
457   buf_.Insert(gen_.Ordered({1}, ""), kNow);                     // 12
458   buf_.Insert(gen_.Ordered({1}, ""), kNow);                     // 13
459   buf_.Insert(gen_.Ordered({1}, "E"), kNow);                    // 14
460 
461   // ACK 9, 12
462   std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(3, 3)};
463   EXPECT_FALSE(
464       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
465   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
466 
467   // ACK 9, 12, 13
468   std::vector<SackChunk::GapAckBlock> gab2 = {SackChunk::GapAckBlock(3, 4)};
469   EXPECT_FALSE(
470       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab2, false).has_packet_loss);
471   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
472 
473   EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
474       .WillOnce(Return(false));
475 
476   // ACK 9, 12, 13, 14
477   std::vector<SackChunk::GapAckBlock> gab3 = {SackChunk::GapAckBlock(3, 5)};
478   OutstandingData::AckInfo ack =
479       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab3, false);
480   EXPECT_TRUE(ack.has_packet_loss);
481   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
482   EXPECT_THAT(buf_.GetChunksToBeFastRetransmitted(1000), IsEmpty());
483   EXPECT_THAT(buf_.GetChunksToBeRetransmitted(1000), IsEmpty());
484 }
485 
TEST_F(OutstandingDataTest,LifecyleReturnsAckedItemsInAckInfo)486 TEST_F(OutstandingDataTest, LifecyleReturnsAckedItemsInAckInfo) {
487   buf_.Insert(gen_.Ordered({1}, "BE"), kNow, MaxRetransmits::NoLimit(),
488               TimeMs::InfiniteFuture(), LifecycleId(42));
489   buf_.Insert(gen_.Ordered({1}, "BE"), kNow, MaxRetransmits::NoLimit(),
490               TimeMs::InfiniteFuture(), LifecycleId(43));
491   buf_.Insert(gen_.Ordered({1}, "BE"), kNow, MaxRetransmits::NoLimit(),
492               TimeMs::InfiniteFuture(), LifecycleId(44));
493 
494   OutstandingData::AckInfo ack1 =
495       buf_.HandleSack(unwrapper_.Unwrap(TSN(11)), {}, false);
496 
497   EXPECT_THAT(ack1.acked_lifecycle_ids,
498               ElementsAre(LifecycleId(42), LifecycleId(43)));
499 
500   OutstandingData::AckInfo ack2 =
501       buf_.HandleSack(unwrapper_.Unwrap(TSN(12)), {}, false);
502 
503   EXPECT_THAT(ack2.acked_lifecycle_ids, ElementsAre(LifecycleId(44)));
504 }
505 
TEST_F(OutstandingDataTest,LifecycleReturnsAbandonedNackedThreeTimes)506 TEST_F(OutstandingDataTest, LifecycleReturnsAbandonedNackedThreeTimes) {
507   buf_.Insert(gen_.Ordered({1}, "B"), kNow, MaxRetransmits(0));
508   buf_.Insert(gen_.Ordered({1}, ""), kNow, MaxRetransmits(0));
509   buf_.Insert(gen_.Ordered({1}, ""), kNow, MaxRetransmits(0));
510   buf_.Insert(gen_.Ordered({1}, "E"), kNow, MaxRetransmits(0),
511               TimeMs::InfiniteFuture(), LifecycleId(42));
512 
513   std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(2, 2)};
514   EXPECT_FALSE(
515       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
516   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
517 
518   std::vector<SackChunk::GapAckBlock> gab2 = {SackChunk::GapAckBlock(2, 3)};
519   EXPECT_FALSE(
520       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab2, false).has_packet_loss);
521   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
522 
523   std::vector<SackChunk::GapAckBlock> gab3 = {SackChunk::GapAckBlock(2, 4)};
524   EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
525       .WillOnce(Return(false));
526   OutstandingData::AckInfo ack1 =
527       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab3, false);
528   EXPECT_TRUE(ack1.has_packet_loss);
529   EXPECT_THAT(ack1.abandoned_lifecycle_ids, IsEmpty());
530 
531   // This will generate a FORWARD-TSN, which is acked
532   EXPECT_TRUE(buf_.ShouldSendForwardTsn());
533   ForwardTsnChunk chunk = buf_.CreateForwardTsn();
534   EXPECT_EQ(chunk.new_cumulative_tsn(), TSN(13));
535 
536   OutstandingData::AckInfo ack2 =
537       buf_.HandleSack(unwrapper_.Unwrap(TSN(13)), {}, false);
538   EXPECT_FALSE(ack2.has_packet_loss);
539   EXPECT_THAT(ack2.abandoned_lifecycle_ids, ElementsAre(LifecycleId(42)));
540 }
541 
TEST_F(OutstandingDataTest,LifecycleReturnsAbandonedAfterT3rtxExpired)542 TEST_F(OutstandingDataTest, LifecycleReturnsAbandonedAfterT3rtxExpired) {
543   buf_.Insert(gen_.Ordered({1}, "B"), kNow, MaxRetransmits(0));
544   buf_.Insert(gen_.Ordered({1}, ""), kNow, MaxRetransmits(0));
545   buf_.Insert(gen_.Ordered({1}, ""), kNow, MaxRetransmits(0));
546   buf_.Insert(gen_.Ordered({1}, "E"), kNow, MaxRetransmits(0),
547               TimeMs::InfiniteFuture(), LifecycleId(42));
548 
549   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
550               testing::ElementsAre(Pair(TSN(9), State::kAcked),      //
551                                    Pair(TSN(10), State::kInFlight),  //
552                                    Pair(TSN(11), State::kInFlight),  //
553                                    Pair(TSN(12), State::kInFlight),  //
554                                    Pair(TSN(13), State::kInFlight)));
555 
556   std::vector<SackChunk::GapAckBlock> gab1 = {SackChunk::GapAckBlock(2, 4)};
557   EXPECT_FALSE(
558       buf_.HandleSack(unwrapper_.Unwrap(TSN(9)), gab1, false).has_packet_loss);
559   EXPECT_FALSE(buf_.has_data_to_be_retransmitted());
560 
561   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
562               testing::ElementsAre(Pair(TSN(9), State::kAcked),    //
563                                    Pair(TSN(10), State::kNacked),  //
564                                    Pair(TSN(11), State::kAcked),   //
565                                    Pair(TSN(12), State::kAcked),   //
566                                    Pair(TSN(13), State::kAcked)));
567 
568   // T3-rtx triggered.
569   EXPECT_CALL(on_discard_, Call(IsUnordered(false), StreamID(1), MID(42)))
570       .WillOnce(Return(false));
571   buf_.NackAll();
572 
573   EXPECT_THAT(buf_.GetChunkStatesForTesting(),
574               testing::ElementsAre(Pair(TSN(9), State::kAcked),       //
575                                    Pair(TSN(10), State::kAbandoned),  //
576                                    Pair(TSN(11), State::kAbandoned),  //
577                                    Pair(TSN(12), State::kAbandoned),  //
578                                    Pair(TSN(13), State::kAbandoned)));
579 
580   // This will generate a FORWARD-TSN, which is acked
581   EXPECT_TRUE(buf_.ShouldSendForwardTsn());
582   ForwardTsnChunk chunk = buf_.CreateForwardTsn();
583   EXPECT_EQ(chunk.new_cumulative_tsn(), TSN(13));
584 
585   OutstandingData::AckInfo ack2 =
586       buf_.HandleSack(unwrapper_.Unwrap(TSN(13)), {}, false);
587   EXPECT_FALSE(ack2.has_packet_loss);
588   EXPECT_THAT(ack2.abandoned_lifecycle_ids, ElementsAre(LifecycleId(42)));
589 }
590 }  // namespace
591 }  // namespace dcsctp
592