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/rx/interleaved_reassembly_streams.h"
11
12 #include <cstdint>
13 #include <memory>
14 #include <utility>
15
16 #include "net/dcsctp/common/sequence_numbers.h"
17 #include "net/dcsctp/packet/chunk/forward_tsn_common.h"
18 #include "net/dcsctp/packet/chunk/iforward_tsn_chunk.h"
19 #include "net/dcsctp/packet/data.h"
20 #include "net/dcsctp/rx/reassembly_streams.h"
21 #include "net/dcsctp/testing/data_generator.h"
22 #include "rtc_base/gunit.h"
23 #include "test/gmock.h"
24
25 namespace dcsctp {
26 namespace {
27 using ::testing::MockFunction;
28 using ::testing::NiceMock;
29
30 class InterleavedReassemblyStreamsTest : public testing::Test {
31 protected:
tsn(uint32_t value)32 UnwrappedTSN tsn(uint32_t value) { return tsn_.Unwrap(TSN(value)); }
33
InterleavedReassemblyStreamsTest()34 InterleavedReassemblyStreamsTest() {}
35 DataGenerator gen_;
36 UnwrappedTSN::Unwrapper tsn_;
37 };
38
TEST_F(InterleavedReassemblyStreamsTest,AddUnorderedMessageReturnsCorrectSize)39 TEST_F(InterleavedReassemblyStreamsTest,
40 AddUnorderedMessageReturnsCorrectSize) {
41 NiceMock<MockFunction<ReassemblyStreams::OnAssembledMessage>> on_assembled;
42
43 InterleavedReassemblyStreams streams("", on_assembled.AsStdFunction());
44
45 EXPECT_EQ(streams.Add(tsn(1), gen_.Unordered({1}, "B")), 1);
46 EXPECT_EQ(streams.Add(tsn(2), gen_.Unordered({2, 3, 4})), 3);
47 EXPECT_EQ(streams.Add(tsn(3), gen_.Unordered({5, 6})), 2);
48 // Adding the end fragment should make it empty again.
49 EXPECT_EQ(streams.Add(tsn(4), gen_.Unordered({7}, "E")), -6);
50 }
51
TEST_F(InterleavedReassemblyStreamsTest,AddSimpleOrderedMessageReturnsCorrectSize)52 TEST_F(InterleavedReassemblyStreamsTest,
53 AddSimpleOrderedMessageReturnsCorrectSize) {
54 NiceMock<MockFunction<ReassemblyStreams::OnAssembledMessage>> on_assembled;
55
56 InterleavedReassemblyStreams streams("", on_assembled.AsStdFunction());
57
58 EXPECT_EQ(streams.Add(tsn(1), gen_.Ordered({1}, "B")), 1);
59 EXPECT_EQ(streams.Add(tsn(2), gen_.Ordered({2, 3, 4})), 3);
60 EXPECT_EQ(streams.Add(tsn(3), gen_.Ordered({5, 6})), 2);
61 EXPECT_EQ(streams.Add(tsn(4), gen_.Ordered({7}, "E")), -6);
62 }
63
TEST_F(InterleavedReassemblyStreamsTest,AddMoreComplexOrderedMessageReturnsCorrectSize)64 TEST_F(InterleavedReassemblyStreamsTest,
65 AddMoreComplexOrderedMessageReturnsCorrectSize) {
66 NiceMock<MockFunction<ReassemblyStreams::OnAssembledMessage>> on_assembled;
67
68 InterleavedReassemblyStreams streams("", on_assembled.AsStdFunction());
69
70 EXPECT_EQ(streams.Add(tsn(1), gen_.Ordered({1}, "B")), 1);
71 Data late = gen_.Ordered({2, 3, 4});
72 EXPECT_EQ(streams.Add(tsn(3), gen_.Ordered({5, 6})), 2);
73 EXPECT_EQ(streams.Add(tsn(4), gen_.Ordered({7}, "E")), 1);
74
75 EXPECT_EQ(streams.Add(tsn(5), gen_.Ordered({1}, "BE")), 1);
76 EXPECT_EQ(streams.Add(tsn(6), gen_.Ordered({5, 6}, "B")), 2);
77 EXPECT_EQ(streams.Add(tsn(7), gen_.Ordered({7}, "E")), 1);
78 EXPECT_EQ(streams.Add(tsn(2), std::move(late)), -8);
79 }
80
TEST_F(InterleavedReassemblyStreamsTest,DeleteUnorderedMessageReturnsCorrectSize)81 TEST_F(InterleavedReassemblyStreamsTest,
82 DeleteUnorderedMessageReturnsCorrectSize) {
83 NiceMock<MockFunction<ReassemblyStreams::OnAssembledMessage>> on_assembled;
84
85 InterleavedReassemblyStreams streams("", on_assembled.AsStdFunction());
86
87 EXPECT_EQ(streams.Add(tsn(1), gen_.Unordered({1}, "B")), 1);
88 EXPECT_EQ(streams.Add(tsn(2), gen_.Unordered({2, 3, 4})), 3);
89 EXPECT_EQ(streams.Add(tsn(3), gen_.Unordered({5, 6})), 2);
90
91 IForwardTsnChunk::SkippedStream skipped[] = {
92 IForwardTsnChunk::SkippedStream(IsUnordered(true), StreamID(1), MID(0))};
93 EXPECT_EQ(streams.HandleForwardTsn(tsn(3), skipped), 6u);
94 }
95
TEST_F(InterleavedReassemblyStreamsTest,DeleteSimpleOrderedMessageReturnsCorrectSize)96 TEST_F(InterleavedReassemblyStreamsTest,
97 DeleteSimpleOrderedMessageReturnsCorrectSize) {
98 NiceMock<MockFunction<ReassemblyStreams::OnAssembledMessage>> on_assembled;
99
100 InterleavedReassemblyStreams streams("", on_assembled.AsStdFunction());
101
102 EXPECT_EQ(streams.Add(tsn(1), gen_.Ordered({1}, "B")), 1);
103 EXPECT_EQ(streams.Add(tsn(2), gen_.Ordered({2, 3, 4})), 3);
104 EXPECT_EQ(streams.Add(tsn(3), gen_.Ordered({5, 6})), 2);
105
106 IForwardTsnChunk::SkippedStream skipped[] = {
107 IForwardTsnChunk::SkippedStream(IsUnordered(false), StreamID(1), MID(0))};
108 EXPECT_EQ(streams.HandleForwardTsn(tsn(3), skipped), 6u);
109 }
110
TEST_F(InterleavedReassemblyStreamsTest,DeleteManyOrderedMessagesReturnsCorrectSize)111 TEST_F(InterleavedReassemblyStreamsTest,
112 DeleteManyOrderedMessagesReturnsCorrectSize) {
113 NiceMock<MockFunction<ReassemblyStreams::OnAssembledMessage>> on_assembled;
114
115 InterleavedReassemblyStreams streams("", on_assembled.AsStdFunction());
116
117 EXPECT_EQ(streams.Add(tsn(1), gen_.Ordered({1}, "B")), 1);
118 gen_.Ordered({2, 3, 4});
119 EXPECT_EQ(streams.Add(tsn(3), gen_.Ordered({5, 6})), 2);
120 EXPECT_EQ(streams.Add(tsn(4), gen_.Ordered({7}, "E")), 1);
121
122 EXPECT_EQ(streams.Add(tsn(5), gen_.Ordered({1}, "BE")), 1);
123 EXPECT_EQ(streams.Add(tsn(6), gen_.Ordered({5, 6}, "B")), 2);
124 EXPECT_EQ(streams.Add(tsn(7), gen_.Ordered({7}, "E")), 1);
125
126 // Expire all three messages
127 IForwardTsnChunk::SkippedStream skipped[] = {
128 IForwardTsnChunk::SkippedStream(IsUnordered(false), StreamID(1), MID(2))};
129 EXPECT_EQ(streams.HandleForwardTsn(tsn(8), skipped), 8u);
130 }
131
TEST_F(InterleavedReassemblyStreamsTest,DeleteOrderedMessageDelivesTwoReturnsCorrectSize)132 TEST_F(InterleavedReassemblyStreamsTest,
133 DeleteOrderedMessageDelivesTwoReturnsCorrectSize) {
134 NiceMock<MockFunction<ReassemblyStreams::OnAssembledMessage>> on_assembled;
135
136 InterleavedReassemblyStreams streams("", on_assembled.AsStdFunction());
137
138 EXPECT_EQ(streams.Add(tsn(1), gen_.Ordered({1}, "B")), 1);
139 gen_.Ordered({2, 3, 4});
140 EXPECT_EQ(streams.Add(tsn(3), gen_.Ordered({5, 6})), 2);
141 EXPECT_EQ(streams.Add(tsn(4), gen_.Ordered({7}, "E")), 1);
142
143 EXPECT_EQ(streams.Add(tsn(5), gen_.Ordered({1}, "BE")), 1);
144 EXPECT_EQ(streams.Add(tsn(6), gen_.Ordered({5, 6}, "B")), 2);
145 EXPECT_EQ(streams.Add(tsn(7), gen_.Ordered({7}, "E")), 1);
146
147 // The first ordered message expire, and the following two are delivered.
148 IForwardTsnChunk::SkippedStream skipped[] = {
149 IForwardTsnChunk::SkippedStream(IsUnordered(false), StreamID(1), MID(0))};
150 EXPECT_EQ(streams.HandleForwardTsn(tsn(4), skipped), 8u);
151 }
152
153 } // namespace
154 } // namespace dcsctp
155