xref: /aosp_15_r20/external/webrtc/media/sctp/dcsctp_transport_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2022 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 "media/sctp/dcsctp_transport.h"
12 
13 #include <memory>
14 #include <utility>
15 
16 #include "net/dcsctp/public/mock_dcsctp_socket.h"
17 #include "net/dcsctp/public/mock_dcsctp_socket_factory.h"
18 #include "p2p/base/fake_packet_transport.h"
19 #include "test/gtest.h"
20 
21 using ::testing::_;
22 using ::testing::ByMove;
23 using ::testing::DoAll;
24 using ::testing::ElementsAre;
25 using ::testing::InSequence;
26 using ::testing::Invoke;
27 using ::testing::NiceMock;
28 using ::testing::Return;
29 using ::testing::ReturnPointee;
30 
31 namespace webrtc {
32 
33 namespace {
34 class MockDataChannelObserver : public DataChannelSink {
35  public:
36   MOCK_METHOD(void, OnConnected, ());
37 
38   // DataChannelSink
39   MOCK_METHOD(void,
40               OnDataReceived,
41               (int, DataMessageType, const rtc::CopyOnWriteBuffer&));
42   MOCK_METHOD(void, OnChannelClosing, (int));
43   MOCK_METHOD(void, OnChannelClosed, (int));
44   MOCK_METHOD(void, OnReadyToSend, ());
45   MOCK_METHOD(void, OnTransportClosed, (RTCError));
46 };
47 
48 class Peer {
49  public:
Peer()50   Peer() : fake_packet_transport_("transport"), simulated_clock_(1000) {
51     auto socket_ptr = std::make_unique<dcsctp::MockDcSctpSocket>();
52     socket_ = socket_ptr.get();
53 
54     auto mock_dcsctp_socket_factory =
55         std::make_unique<dcsctp::MockDcSctpSocketFactory>();
56     EXPECT_CALL(*mock_dcsctp_socket_factory, Create)
57         .Times(1)
58         .WillOnce(Return(ByMove(std::move(socket_ptr))));
59 
60     sctp_transport_ = std::make_unique<webrtc::DcSctpTransport>(
61         rtc::Thread::Current(), &fake_packet_transport_, &simulated_clock_,
62         std::move(mock_dcsctp_socket_factory));
63     sctp_transport_->SetDataChannelSink(&observer_);
64     sctp_transport_->SetOnConnectedCallback(
65         [this]() { observer_.OnConnected(); });
66   }
67 
68   rtc::FakePacketTransport fake_packet_transport_;
69   webrtc::SimulatedClock simulated_clock_;
70   dcsctp::MockDcSctpSocket* socket_;
71   std::unique_ptr<webrtc::DcSctpTransport> sctp_transport_;
72   NiceMock<MockDataChannelObserver> observer_;
73 };
74 }  // namespace
75 
TEST(DcSctpTransportTest,OpenSequence)76 TEST(DcSctpTransportTest, OpenSequence) {
77   rtc::AutoThread main_thread;
78   Peer peer_a;
79   peer_a.fake_packet_transport_.SetWritable(true);
80 
81   EXPECT_CALL(*peer_a.socket_, Connect)
82       .Times(1)
83       .WillOnce(Invoke(peer_a.sctp_transport_.get(),
84                        &dcsctp::DcSctpSocketCallbacks::OnConnected));
85   EXPECT_CALL(peer_a.observer_, OnReadyToSend);
86   EXPECT_CALL(peer_a.observer_, OnConnected);
87 
88   peer_a.sctp_transport_->Start(5000, 5000, 256 * 1024);
89 }
90 
91 // Tests that the close sequence invoked from one end results in the stream to
92 // be reset from both ends and all the proper signals are sent.
TEST(DcSctpTransportTest,CloseSequence)93 TEST(DcSctpTransportTest, CloseSequence) {
94   rtc::AutoThread main_thread;
95   Peer peer_a;
96   Peer peer_b;
97   peer_a.fake_packet_transport_.SetDestination(&peer_b.fake_packet_transport_,
98                                                false);
99   {
100     InSequence sequence;
101 
102     EXPECT_CALL(*peer_a.socket_, ResetStreams(ElementsAre(dcsctp::StreamID(1))))
103         .WillOnce(Return(dcsctp::ResetStreamsStatus::kPerformed));
104 
105     EXPECT_CALL(*peer_b.socket_, ResetStreams(ElementsAre(dcsctp::StreamID(1))))
106         .WillOnce(Return(dcsctp::ResetStreamsStatus::kPerformed));
107 
108     EXPECT_CALL(peer_a.observer_, OnChannelClosing(1)).Times(0);
109     EXPECT_CALL(peer_b.observer_, OnChannelClosing(1));
110     EXPECT_CALL(peer_a.observer_, OnChannelClosed(1));
111     EXPECT_CALL(peer_b.observer_, OnChannelClosed(1));
112   }
113 
114   peer_a.sctp_transport_->Start(5000, 5000, 256 * 1024);
115   peer_b.sctp_transport_->Start(5000, 5000, 256 * 1024);
116   peer_a.sctp_transport_->OpenStream(1);
117   peer_b.sctp_transport_->OpenStream(1);
118   peer_a.sctp_transport_->ResetStream(1);
119 
120   // Simulate the callbacks from the stream resets
121   dcsctp::StreamID streams[1] = {dcsctp::StreamID(1)};
122   static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_a.sctp_transport_.get())
123       ->OnStreamsResetPerformed(streams);
124   static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_b.sctp_transport_.get())
125       ->OnIncomingStreamsReset(streams);
126   static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_a.sctp_transport_.get())
127       ->OnIncomingStreamsReset(streams);
128   static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_b.sctp_transport_.get())
129       ->OnStreamsResetPerformed(streams);
130 }
131 
132 // Tests that the close sequence initiated from both peers at the same time
133 // terminates properly. Both peers will think they initiated it, so no
134 // OnClosingProcedureStartedRemotely should be called.
TEST(DcSctpTransportTest,CloseSequenceSimultaneous)135 TEST(DcSctpTransportTest, CloseSequenceSimultaneous) {
136   rtc::AutoThread main_thread;
137   Peer peer_a;
138   Peer peer_b;
139   peer_a.fake_packet_transport_.SetDestination(&peer_b.fake_packet_transport_,
140                                                false);
141   {
142     InSequence sequence;
143 
144     EXPECT_CALL(*peer_a.socket_, ResetStreams(ElementsAre(dcsctp::StreamID(1))))
145         .WillOnce(Return(dcsctp::ResetStreamsStatus::kPerformed));
146 
147     EXPECT_CALL(*peer_b.socket_, ResetStreams(ElementsAre(dcsctp::StreamID(1))))
148         .WillOnce(Return(dcsctp::ResetStreamsStatus::kPerformed));
149 
150     EXPECT_CALL(peer_a.observer_, OnChannelClosing(1)).Times(0);
151     EXPECT_CALL(peer_b.observer_, OnChannelClosing(1)).Times(0);
152     EXPECT_CALL(peer_a.observer_, OnChannelClosed(1));
153     EXPECT_CALL(peer_b.observer_, OnChannelClosed(1));
154   }
155 
156   peer_a.sctp_transport_->Start(5000, 5000, 256 * 1024);
157   peer_b.sctp_transport_->Start(5000, 5000, 256 * 1024);
158   peer_a.sctp_transport_->OpenStream(1);
159   peer_b.sctp_transport_->OpenStream(1);
160   peer_a.sctp_transport_->ResetStream(1);
161   peer_b.sctp_transport_->ResetStream(1);
162 
163   // Simulate the callbacks from the stream resets
164   dcsctp::StreamID streams[1] = {dcsctp::StreamID(1)};
165   static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_a.sctp_transport_.get())
166       ->OnStreamsResetPerformed(streams);
167   static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_b.sctp_transport_.get())
168       ->OnStreamsResetPerformed(streams);
169   static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_a.sctp_transport_.get())
170       ->OnIncomingStreamsReset(streams);
171   static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_b.sctp_transport_.get())
172       ->OnIncomingStreamsReset(streams);
173 }
174 
TEST(DcSctpTransportTest,DiscardMessageClosedChannel)175 TEST(DcSctpTransportTest, DiscardMessageClosedChannel) {
176   rtc::AutoThread main_thread;
177   Peer peer_a;
178 
179   EXPECT_CALL(*peer_a.socket_, Send(_, _)).Times(0);
180 
181   peer_a.sctp_transport_->Start(5000, 5000, 256 * 1024);
182 
183   cricket::SendDataResult result;
184   SendDataParams params;
185   rtc::CopyOnWriteBuffer payload;
186   bool send_data_return =
187       peer_a.sctp_transport_->SendData(1, params, payload, &result);
188   EXPECT_FALSE(send_data_return);
189   EXPECT_EQ(cricket::SDR_ERROR, result);
190 }
191 
TEST(DcSctpTransportTest,DiscardMessageClosingChannel)192 TEST(DcSctpTransportTest, DiscardMessageClosingChannel) {
193   rtc::AutoThread main_thread;
194   Peer peer_a;
195 
196   EXPECT_CALL(*peer_a.socket_, Send(_, _)).Times(0);
197 
198   peer_a.sctp_transport_->OpenStream(1);
199   peer_a.sctp_transport_->Start(5000, 5000, 256 * 1024);
200   peer_a.sctp_transport_->ResetStream(1);
201 
202   cricket::SendDataResult result;
203   SendDataParams params;
204   rtc::CopyOnWriteBuffer payload;
205 
206   bool send_data_return =
207       peer_a.sctp_transport_->SendData(1, params, payload, &result);
208   EXPECT_FALSE(send_data_return);
209   EXPECT_EQ(cricket::SDR_ERROR, result);
210 }
211 
TEST(DcSctpTransportTest,SendDataOpenChannel)212 TEST(DcSctpTransportTest, SendDataOpenChannel) {
213   rtc::AutoThread main_thread;
214   Peer peer_a;
215   dcsctp::DcSctpOptions options;
216 
217   EXPECT_CALL(*peer_a.socket_, Send(_, _)).Times(1);
218   EXPECT_CALL(*peer_a.socket_, options()).WillOnce(ReturnPointee(&options));
219 
220   peer_a.sctp_transport_->OpenStream(1);
221   peer_a.sctp_transport_->Start(5000, 5000, 256 * 1024);
222 
223   cricket::SendDataResult result;
224   SendDataParams params;
225   rtc::CopyOnWriteBuffer payload;
226 
227   bool send_data_return =
228       peer_a.sctp_transport_->SendData(1, params, payload, &result);
229   EXPECT_TRUE(send_data_return);
230   EXPECT_EQ(cricket::SDR_SUCCESS, result);
231 }
232 
233 }  // namespace webrtc
234