blob: 0a374e63b9e8b591472e5b6b3a44ec6861f4e7aa [file] [log] [blame]
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +01001/*
2 * Copyright (c) 2017 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/rtcp_transceiver.h"
12
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +010013#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010014#include "rtc_base/event.h"
15#include "rtc_base/ptr_util.h"
16#include "test/gmock.h"
17#include "test/gtest.h"
18#include "test/mock_transport.h"
19
20namespace {
21
22using ::testing::AtLeast;
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +010023using ::testing::Invoke;
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010024using ::testing::InvokeWithoutArgs;
25using ::testing::NiceMock;
26using ::testing::_;
27using ::webrtc::MockTransport;
28using ::webrtc::RtcpTransceiver;
29using ::webrtc::RtcpTransceiverConfig;
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +010030using ::webrtc::rtcp::TransportFeedback;
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +010031
32void WaitPostedTasks(rtc::TaskQueue* queue) {
33 rtc::Event done(false, false);
34 queue->PostTask([&done] { done.Set(); });
35 ASSERT_TRUE(done.Wait(1000));
36}
37
38TEST(RtcpTransceiverTest, SendsRtcpOnTaskQueueWhenCreatedOffTaskQueue) {
39 rtc::TaskQueue queue("rtcp");
40 MockTransport outgoing_transport;
41 RtcpTransceiverConfig config;
42 config.outgoing_transport = &outgoing_transport;
43 config.task_queue = &queue;
44 EXPECT_CALL(outgoing_transport, SendRtcp(_, _))
45 .WillRepeatedly(InvokeWithoutArgs([&] {
46 EXPECT_TRUE(queue.IsCurrent());
47 return true;
48 }));
49
50 RtcpTransceiver rtcp_transceiver(config);
51 rtcp_transceiver.SendCompoundPacket();
52 WaitPostedTasks(&queue);
53}
54
55TEST(RtcpTransceiverTest, SendsRtcpOnTaskQueueWhenCreatedOnTaskQueue) {
56 rtc::TaskQueue queue("rtcp");
57 MockTransport outgoing_transport;
58 RtcpTransceiverConfig config;
59 config.outgoing_transport = &outgoing_transport;
60 config.task_queue = &queue;
61 EXPECT_CALL(outgoing_transport, SendRtcp(_, _))
62 .WillRepeatedly(InvokeWithoutArgs([&] {
63 EXPECT_TRUE(queue.IsCurrent());
64 return true;
65 }));
66
67 std::unique_ptr<RtcpTransceiver> rtcp_transceiver;
68 queue.PostTask([&] {
69 rtcp_transceiver = rtc::MakeUnique<RtcpTransceiver>(config);
70 rtcp_transceiver->SendCompoundPacket();
71 });
72 WaitPostedTasks(&queue);
73}
74
75TEST(RtcpTransceiverTest, CanBeDestoryedOnTaskQueue) {
76 rtc::TaskQueue queue("rtcp");
77 NiceMock<MockTransport> outgoing_transport;
78 RtcpTransceiverConfig config;
79 config.outgoing_transport = &outgoing_transport;
80 config.task_queue = &queue;
81 auto rtcp_transceiver = rtc::MakeUnique<RtcpTransceiver>(config);
82
83 queue.PostTask([&] { rtcp_transceiver.reset(); });
84 WaitPostedTasks(&queue);
85}
86
87TEST(RtcpTransceiverTest, CanCallSendCompoundPacketFromAnyThread) {
88 MockTransport outgoing_transport;
89 rtc::TaskQueue queue("rtcp");
90 RtcpTransceiverConfig config;
91 config.outgoing_transport = &outgoing_transport;
92 config.task_queue = &queue;
93
94 EXPECT_CALL(outgoing_transport, SendRtcp(_, _))
95 // If test is slow, a periodic task may send an extra packet.
96 .Times(AtLeast(3))
97 .WillRepeatedly(InvokeWithoutArgs([&] {
98 EXPECT_TRUE(queue.IsCurrent());
99 return true;
100 }));
101
102 RtcpTransceiver rtcp_transceiver(config);
103
104 // Call from the construction thread.
105 rtcp_transceiver.SendCompoundPacket();
106 // Call from the same queue transceiver use for processing.
107 queue.PostTask([&] { rtcp_transceiver.SendCompoundPacket(); });
108 // Call from unrelated task queue.
109 rtc::TaskQueue queue_send("send_packet");
110 queue_send.PostTask([&] { rtcp_transceiver.SendCompoundPacket(); });
111
112 WaitPostedTasks(&queue_send);
113 WaitPostedTasks(&queue);
114}
115
116TEST(RtcpTransceiverTest, DoesntSendPacketsAfterDestruction) {
117 MockTransport outgoing_transport;
118 rtc::TaskQueue queue("rtcp");
119 RtcpTransceiverConfig config;
120 config.outgoing_transport = &outgoing_transport;
121 config.task_queue = &queue;
122 config.schedule_periodic_compound_packets = false;
123
124 EXPECT_CALL(outgoing_transport, SendRtcp(_, _)).Times(0);
125
126 auto rtcp_transceiver = rtc::MakeUnique<RtcpTransceiver>(config);
127 rtc::Event pause(false, false);
128 queue.PostTask([&] {
129 pause.Wait(rtc::Event::kForever);
130 rtcp_transceiver.reset();
131 });
132 rtcp_transceiver->SendCompoundPacket();
133 pause.Set();
134 WaitPostedTasks(&queue);
135 EXPECT_FALSE(rtcp_transceiver);
136}
137
Danil Chapovalovd5cae4d2017-12-14 11:14:35 +0100138TEST(RtcpTransceiverTest, SendsTransportFeedbackOnTaskQueue) {
139 static constexpr uint32_t kSenderSsrc = 12345;
140 MockTransport outgoing_transport;
141 rtc::TaskQueue queue("rtcp");
142 RtcpTransceiverConfig config;
143 config.feedback_ssrc = kSenderSsrc;
144 config.outgoing_transport = &outgoing_transport;
145 config.task_queue = &queue;
146 config.schedule_periodic_compound_packets = false;
147 RtcpTransceiver rtcp_transceiver(config);
148
149 EXPECT_CALL(outgoing_transport, SendRtcp(_, _))
150 .WillOnce(Invoke([&](const uint8_t* buffer, size_t size) {
151 EXPECT_TRUE(queue.IsCurrent());
152
153 std::unique_ptr<TransportFeedback> transport_feedback =
154 TransportFeedback::ParseFrom(buffer, size);
155 EXPECT_TRUE(transport_feedback);
156 EXPECT_EQ(transport_feedback->sender_ssrc(), kSenderSsrc);
157 return true;
158 }));
159
160 // Create minimalistic transport feedback packet.
161 TransportFeedback transport_feedback;
162 transport_feedback.SetSenderSsrc(rtcp_transceiver.SSRC());
163 transport_feedback.AddReceivedPacket(321, 10000);
164
165 EXPECT_TRUE(rtcp_transceiver.SendFeedbackPacket(transport_feedback));
166
167 WaitPostedTasks(&queue);
168}
169
Danil Chapovalovc0fd5f92017-11-16 14:35:32 +0100170} // namespace