dcsctp: Report duplicate TSNs

Reporting the duplicate TSNs is a SHOULD in the RFC, and using the
duplicate TNSs is a MAY, and in reality I haven't seen an implementation
use it yet. However, it's good for debugging and for stats generation.

Bug: webrtc:12614
Change-Id: I1cc3f86961a8d289708cbf50d98dedfd25077955
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/219462
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34053}
diff --git a/net/dcsctp/rx/data_tracker_test.cc b/net/dcsctp/rx/data_tracker_test.cc
index d714b0b..7518d6d 100644
--- a/net/dcsctp/rx/data_tracker_test.cc
+++ b/net/dcsctp/rx/data_tracker_test.cc
@@ -25,6 +25,7 @@
 namespace {
 using ::testing::ElementsAre;
 using ::testing::IsEmpty;
+using ::testing::UnorderedElementsAre;
 
 constexpr size_t kArwnd = 10000;
 constexpr TSN kInitialTSN(11);
@@ -230,5 +231,43 @@
   EXPECT_FALSE(buf_.IsTSNValid(TSN(*last_tsn - 0x8000000)));
 }
 
+TEST_F(DataTrackerTest, ReportSingleDuplicateTsns) {
+  Observer({11, 12, 11});
+  SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
+  EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(12));
+  EXPECT_THAT(sack.gap_ack_blocks(), IsEmpty());
+  EXPECT_THAT(sack.duplicate_tsns(), UnorderedElementsAre(TSN(11)));
+}
+
+TEST_F(DataTrackerTest, ReportMultipleDuplicateTsns) {
+  Observer({11, 12, 13, 14, 12, 13, 12, 13, 15, 16});
+  SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
+  EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(16));
+  EXPECT_THAT(sack.gap_ack_blocks(), IsEmpty());
+  EXPECT_THAT(sack.duplicate_tsns(), UnorderedElementsAre(TSN(12), TSN(13)));
+}
+
+TEST_F(DataTrackerTest, ReportDuplicateTsnsInGapAckBlocks) {
+  Observer({11, /*12,*/ 13, 14, 13, 14, 15, 16});
+  SackChunk sack = buf_.CreateSelectiveAck(kArwnd);
+  EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(11));
+  EXPECT_THAT(sack.gap_ack_blocks(), ElementsAre(SackChunk::GapAckBlock(2, 5)));
+  EXPECT_THAT(sack.duplicate_tsns(), UnorderedElementsAre(TSN(13), TSN(14)));
+}
+
+TEST_F(DataTrackerTest, ClearsDuplicateTsnsAfterCreatingSack) {
+  Observer({11, 12, 13, 14, 12, 13, 12, 13, 15, 16});
+  SackChunk sack1 = buf_.CreateSelectiveAck(kArwnd);
+  EXPECT_EQ(sack1.cumulative_tsn_ack(), TSN(16));
+  EXPECT_THAT(sack1.gap_ack_blocks(), IsEmpty());
+  EXPECT_THAT(sack1.duplicate_tsns(), UnorderedElementsAre(TSN(12), TSN(13)));
+
+  Observer({17});
+  SackChunk sack2 = buf_.CreateSelectiveAck(kArwnd);
+  EXPECT_EQ(sack2.cumulative_tsn_ack(), TSN(17));
+  EXPECT_THAT(sack2.gap_ack_blocks(), IsEmpty());
+  EXPECT_THAT(sack2.duplicate_tsns(), IsEmpty());
+}
+
 }  // namespace
 }  // namespace dcsctp