summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/pc/rtp_transceiver_unittest.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /third_party/libwebrtc/pc/rtp_transceiver_unittest.cc
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/pc/rtp_transceiver_unittest.cc')
-rw-r--r--third_party/libwebrtc/pc/rtp_transceiver_unittest.cc428
1 files changed, 428 insertions, 0 deletions
diff --git a/third_party/libwebrtc/pc/rtp_transceiver_unittest.cc b/third_party/libwebrtc/pc/rtp_transceiver_unittest.cc
new file mode 100644
index 0000000000..a2f2c362dd
--- /dev/null
+++ b/third_party/libwebrtc/pc/rtp_transceiver_unittest.cc
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+// This file contains tests for `RtpTransceiver`.
+
+#include "pc/rtp_transceiver.h"
+
+#include <memory>
+#include <utility>
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "api/peer_connection_interface.h"
+#include "api/rtp_parameters.h"
+#include "media/base/fake_media_engine.h"
+#include "media/base/media_engine.h"
+#include "pc/test/mock_channel_interface.h"
+#include "pc/test/mock_rtp_receiver_internal.h"
+#include "pc/test/mock_rtp_sender_internal.h"
+#include "rtc_base/thread.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::Optional;
+using ::testing::Property;
+using ::testing::Return;
+using ::testing::ReturnRef;
+
+namespace webrtc {
+
+namespace {
+
+class RtpTransceiverTest : public testing::Test {
+ public:
+ RtpTransceiverTest()
+ : dependencies_(MakeDependencies()),
+ context_(ConnectionContext::Create(&dependencies_)) {}
+
+ protected:
+ cricket::MediaEngineInterface* media_engine() {
+ return context_->media_engine();
+ }
+ ConnectionContext* context() { return context_.get(); }
+
+ private:
+ rtc::AutoThread main_thread_;
+
+ static PeerConnectionFactoryDependencies MakeDependencies() {
+ PeerConnectionFactoryDependencies d;
+ d.network_thread = rtc::Thread::Current();
+ d.worker_thread = rtc::Thread::Current();
+ d.signaling_thread = rtc::Thread::Current();
+ d.media_engine = std::make_unique<cricket::FakeMediaEngine>();
+ return d;
+ }
+
+ PeerConnectionFactoryDependencies dependencies_;
+ rtc::scoped_refptr<ConnectionContext> context_;
+};
+
+// Checks that a channel cannot be set on a stopped `RtpTransceiver`.
+TEST_F(RtpTransceiverTest, CannotSetChannelOnStoppedTransceiver) {
+ const std::string content_name("my_mid");
+ auto transceiver = rtc::make_ref_counted<RtpTransceiver>(
+ cricket::MediaType::MEDIA_TYPE_AUDIO, context());
+ auto channel1 = std::make_unique<cricket::MockChannelInterface>();
+ EXPECT_CALL(*channel1, media_type())
+ .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
+ EXPECT_CALL(*channel1, mid()).WillRepeatedly(ReturnRef(content_name));
+ EXPECT_CALL(*channel1, SetFirstPacketReceivedCallback(_));
+ EXPECT_CALL(*channel1, SetRtpTransport(_)).WillRepeatedly(Return(true));
+ auto channel1_ptr = channel1.get();
+ transceiver->SetChannel(std::move(channel1), [&](const std::string& mid) {
+ EXPECT_EQ(mid, content_name);
+ return nullptr;
+ });
+ EXPECT_EQ(channel1_ptr, transceiver->channel());
+
+ // Stop the transceiver.
+ transceiver->StopInternal();
+ EXPECT_EQ(channel1_ptr, transceiver->channel());
+
+ auto channel2 = std::make_unique<cricket::MockChannelInterface>();
+ EXPECT_CALL(*channel2, media_type())
+ .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
+
+ // Clear the current channel - required to allow SetChannel()
+ EXPECT_CALL(*channel1_ptr, SetFirstPacketReceivedCallback(_));
+ transceiver->ClearChannel();
+ // Channel can no longer be set, so this call should be a no-op.
+ transceiver->SetChannel(std::move(channel2),
+ [](const std::string&) { return nullptr; });
+ EXPECT_EQ(nullptr, transceiver->channel());
+}
+
+// Checks that a channel can be unset on a stopped `RtpTransceiver`
+TEST_F(RtpTransceiverTest, CanUnsetChannelOnStoppedTransceiver) {
+ const std::string content_name("my_mid");
+ auto transceiver = rtc::make_ref_counted<RtpTransceiver>(
+ cricket::MediaType::MEDIA_TYPE_VIDEO, context());
+ auto channel = std::make_unique<cricket::MockChannelInterface>();
+ EXPECT_CALL(*channel, media_type())
+ .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_VIDEO));
+ EXPECT_CALL(*channel, mid()).WillRepeatedly(ReturnRef(content_name));
+ EXPECT_CALL(*channel, SetFirstPacketReceivedCallback(_))
+ .WillRepeatedly(testing::Return());
+ EXPECT_CALL(*channel, SetRtpTransport(_)).WillRepeatedly(Return(true));
+
+ auto channel_ptr = channel.get();
+ transceiver->SetChannel(std::move(channel), [&](const std::string& mid) {
+ EXPECT_EQ(mid, content_name);
+ return nullptr;
+ });
+ EXPECT_EQ(channel_ptr, transceiver->channel());
+
+ // Stop the transceiver.
+ transceiver->StopInternal();
+ EXPECT_EQ(channel_ptr, transceiver->channel());
+
+ // Set the channel to `nullptr`.
+ transceiver->ClearChannel();
+ EXPECT_EQ(nullptr, transceiver->channel());
+}
+
+class RtpTransceiverUnifiedPlanTest : public RtpTransceiverTest {
+ public:
+ RtpTransceiverUnifiedPlanTest()
+ : transceiver_(rtc::make_ref_counted<RtpTransceiver>(
+ RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
+ rtc::Thread::Current(),
+ sender_),
+ RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
+ rtc::Thread::Current(),
+ rtc::Thread::Current(),
+ receiver_),
+ context(),
+ media_engine()->voice().GetRtpHeaderExtensions(),
+ /* on_negotiation_needed= */ [] {})) {}
+
+ static rtc::scoped_refptr<MockRtpReceiverInternal> MockReceiver() {
+ auto receiver = rtc::make_ref_counted<MockRtpReceiverInternal>();
+ EXPECT_CALL(*receiver.get(), media_type())
+ .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
+ return receiver;
+ }
+
+ static rtc::scoped_refptr<MockRtpSenderInternal> MockSender() {
+ auto sender = rtc::make_ref_counted<MockRtpSenderInternal>();
+ EXPECT_CALL(*sender.get(), media_type())
+ .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
+ return sender;
+ }
+
+ rtc::AutoThread main_thread_;
+ rtc::scoped_refptr<MockRtpReceiverInternal> receiver_ = MockReceiver();
+ rtc::scoped_refptr<MockRtpSenderInternal> sender_ = MockSender();
+ rtc::scoped_refptr<RtpTransceiver> transceiver_;
+};
+
+// Basic tests for Stop()
+TEST_F(RtpTransceiverUnifiedPlanTest, StopSetsDirection) {
+ EXPECT_CALL(*receiver_.get(), Stop());
+ EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
+ EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
+ EXPECT_CALL(*sender_.get(), Stop());
+
+ EXPECT_EQ(RtpTransceiverDirection::kInactive, transceiver_->direction());
+ EXPECT_FALSE(transceiver_->current_direction());
+ transceiver_->StopStandard();
+ EXPECT_EQ(RtpTransceiverDirection::kStopped, transceiver_->direction());
+ EXPECT_FALSE(transceiver_->current_direction());
+ transceiver_->StopTransceiverProcedure();
+ EXPECT_TRUE(transceiver_->current_direction());
+ EXPECT_EQ(RtpTransceiverDirection::kStopped, transceiver_->direction());
+ EXPECT_EQ(RtpTransceiverDirection::kStopped,
+ *transceiver_->current_direction());
+}
+
+class RtpTransceiverTestForHeaderExtensions : public RtpTransceiverTest {
+ public:
+ RtpTransceiverTestForHeaderExtensions()
+ : extensions_(
+ {RtpHeaderExtensionCapability("uri1",
+ 1,
+ RtpTransceiverDirection::kSendOnly),
+ RtpHeaderExtensionCapability("uri2",
+ 2,
+ RtpTransceiverDirection::kRecvOnly),
+ RtpHeaderExtensionCapability(RtpExtension::kMidUri,
+ 3,
+ RtpTransceiverDirection::kSendRecv),
+ RtpHeaderExtensionCapability(RtpExtension::kVideoRotationUri,
+ 4,
+ RtpTransceiverDirection::kSendRecv)}),
+ transceiver_(rtc::make_ref_counted<RtpTransceiver>(
+ RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
+ rtc::Thread::Current(),
+ sender_),
+ RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
+ rtc::Thread::Current(),
+ rtc::Thread::Current(),
+ receiver_),
+ context(),
+ extensions_,
+ /* on_negotiation_needed= */ [] {})) {}
+
+ static rtc::scoped_refptr<MockRtpReceiverInternal> MockReceiver() {
+ auto receiver = rtc::make_ref_counted<MockRtpReceiverInternal>();
+ EXPECT_CALL(*receiver.get(), media_type())
+ .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
+ return receiver;
+ }
+
+ static rtc::scoped_refptr<MockRtpSenderInternal> MockSender() {
+ auto sender = rtc::make_ref_counted<MockRtpSenderInternal>();
+ EXPECT_CALL(*sender.get(), media_type())
+ .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
+ return sender;
+ }
+
+ void ClearChannel() {
+ EXPECT_CALL(*sender_.get(), SetMediaChannel(_));
+ transceiver_->ClearChannel();
+ }
+
+ rtc::AutoThread main_thread_;
+ rtc::scoped_refptr<MockRtpReceiverInternal> receiver_ = MockReceiver();
+ rtc::scoped_refptr<MockRtpSenderInternal> sender_ = MockSender();
+
+ std::vector<RtpHeaderExtensionCapability> extensions_;
+ rtc::scoped_refptr<RtpTransceiver> transceiver_;
+};
+
+TEST_F(RtpTransceiverTestForHeaderExtensions, OffersChannelManagerList) {
+ EXPECT_CALL(*receiver_.get(), Stop());
+ EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
+ EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
+ EXPECT_CALL(*sender_.get(), Stop());
+
+ EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), extensions_);
+}
+
+TEST_F(RtpTransceiverTestForHeaderExtensions, ModifiesDirection) {
+ EXPECT_CALL(*receiver_.get(), Stop());
+ EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
+ EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
+ EXPECT_CALL(*sender_.get(), Stop());
+
+ auto modified_extensions = extensions_;
+ modified_extensions[0].direction = RtpTransceiverDirection::kSendOnly;
+ EXPECT_TRUE(
+ transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
+ EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
+ modified_extensions[0].direction = RtpTransceiverDirection::kRecvOnly;
+ EXPECT_TRUE(
+ transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
+ EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
+ modified_extensions[0].direction = RtpTransceiverDirection::kSendRecv;
+ EXPECT_TRUE(
+ transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
+ EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
+ modified_extensions[0].direction = RtpTransceiverDirection::kInactive;
+ EXPECT_TRUE(
+ transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
+ EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
+}
+
+TEST_F(RtpTransceiverTestForHeaderExtensions, AcceptsStoppedExtension) {
+ EXPECT_CALL(*receiver_.get(), Stop());
+ EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
+ EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
+ EXPECT_CALL(*sender_.get(), Stop());
+
+ auto modified_extensions = extensions_;
+ modified_extensions[0].direction = RtpTransceiverDirection::kStopped;
+ EXPECT_TRUE(
+ transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
+ EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
+}
+
+TEST_F(RtpTransceiverTestForHeaderExtensions, RejectsUnsupportedExtension) {
+ EXPECT_CALL(*receiver_.get(), Stop());
+ EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
+ EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
+ EXPECT_CALL(*sender_.get(), Stop());
+
+ std::vector<RtpHeaderExtensionCapability> modified_extensions(
+ {RtpHeaderExtensionCapability("uri3", 1,
+ RtpTransceiverDirection::kSendRecv)});
+ EXPECT_THAT(transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions),
+ Property(&RTCError::type, RTCErrorType::UNSUPPORTED_PARAMETER));
+ EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), extensions_);
+}
+
+TEST_F(RtpTransceiverTestForHeaderExtensions,
+ RejectsStoppedMandatoryExtensions) {
+ EXPECT_CALL(*receiver_.get(), Stop());
+ EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
+ EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
+ EXPECT_CALL(*sender_.get(), Stop());
+
+ std::vector<RtpHeaderExtensionCapability> modified_extensions = extensions_;
+ // Attempting to stop the mandatory MID extension.
+ modified_extensions[2].direction = RtpTransceiverDirection::kStopped;
+ EXPECT_THAT(transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions),
+ Property(&RTCError::type, RTCErrorType::INVALID_MODIFICATION));
+ EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), extensions_);
+ modified_extensions = extensions_;
+ // Attempting to stop the mandatory video orientation extension.
+ modified_extensions[3].direction = RtpTransceiverDirection::kStopped;
+ EXPECT_THAT(transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions),
+ Property(&RTCError::type, RTCErrorType::INVALID_MODIFICATION));
+ EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), extensions_);
+}
+
+TEST_F(RtpTransceiverTestForHeaderExtensions,
+ NoNegotiatedHdrExtsWithoutChannel) {
+ EXPECT_CALL(*receiver_.get(), Stop());
+ EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
+ EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
+ EXPECT_CALL(*sender_.get(), Stop());
+ EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(), ElementsAre());
+}
+
+TEST_F(RtpTransceiverTestForHeaderExtensions,
+ NoNegotiatedHdrExtsWithChannelWithoutNegotiation) {
+ const std::string content_name("my_mid");
+ EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)).WillRepeatedly(Return());
+ EXPECT_CALL(*receiver_.get(), Stop()).WillRepeatedly(Return());
+ EXPECT_CALL(*sender_.get(), SetMediaChannel(_));
+ EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
+ EXPECT_CALL(*sender_.get(), Stop());
+ auto mock_channel = std::make_unique<cricket::MockChannelInterface>();
+ auto mock_channel_ptr = mock_channel.get();
+ EXPECT_CALL(*mock_channel, SetFirstPacketReceivedCallback(_));
+ EXPECT_CALL(*mock_channel, media_type())
+ .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
+ EXPECT_CALL(*mock_channel, media_send_channel())
+ .WillRepeatedly(Return(nullptr));
+ EXPECT_CALL(*mock_channel, mid()).WillRepeatedly(ReturnRef(content_name));
+ EXPECT_CALL(*mock_channel, SetRtpTransport(_)).WillRepeatedly(Return(true));
+ transceiver_->SetChannel(std::move(mock_channel),
+ [](const std::string&) { return nullptr; });
+ EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(), ElementsAre());
+
+ EXPECT_CALL(*mock_channel_ptr, SetFirstPacketReceivedCallback(_));
+ ClearChannel();
+}
+
+TEST_F(RtpTransceiverTestForHeaderExtensions, ReturnsNegotiatedHdrExts) {
+ const std::string content_name("my_mid");
+ EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)).WillRepeatedly(Return());
+ EXPECT_CALL(*receiver_.get(), Stop()).WillRepeatedly(Return());
+ EXPECT_CALL(*sender_.get(), SetMediaChannel(_));
+ EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
+ EXPECT_CALL(*sender_.get(), Stop());
+
+ auto mock_channel = std::make_unique<cricket::MockChannelInterface>();
+ auto mock_channel_ptr = mock_channel.get();
+ EXPECT_CALL(*mock_channel, SetFirstPacketReceivedCallback(_));
+ EXPECT_CALL(*mock_channel, media_type())
+ .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
+ EXPECT_CALL(*mock_channel, media_send_channel())
+ .WillRepeatedly(Return(nullptr));
+ EXPECT_CALL(*mock_channel, mid()).WillRepeatedly(ReturnRef(content_name));
+ EXPECT_CALL(*mock_channel, SetRtpTransport(_)).WillRepeatedly(Return(true));
+
+ cricket::RtpHeaderExtensions extensions = {webrtc::RtpExtension("uri1", 1),
+ webrtc::RtpExtension("uri2", 2)};
+ cricket::AudioContentDescription description;
+ description.set_rtp_header_extensions(extensions);
+ transceiver_->OnNegotiationUpdate(SdpType::kAnswer, &description);
+
+ transceiver_->SetChannel(std::move(mock_channel),
+ [](const std::string&) { return nullptr; });
+ EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(),
+ ElementsAre(RtpHeaderExtensionCapability(
+ "uri1", 1, RtpTransceiverDirection::kSendRecv),
+ RtpHeaderExtensionCapability(
+ "uri2", 2, RtpTransceiverDirection::kSendRecv)));
+
+ EXPECT_CALL(*mock_channel_ptr, SetFirstPacketReceivedCallback(_));
+ ClearChannel();
+}
+
+TEST_F(RtpTransceiverTestForHeaderExtensions,
+ ReturnsNegotiatedHdrExtsSecondTime) {
+ EXPECT_CALL(*receiver_.get(), Stop());
+ EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
+ EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
+ EXPECT_CALL(*sender_.get(), Stop());
+
+ cricket::RtpHeaderExtensions extensions = {webrtc::RtpExtension("uri1", 1),
+ webrtc::RtpExtension("uri2", 2)};
+ cricket::AudioContentDescription description;
+ description.set_rtp_header_extensions(extensions);
+ transceiver_->OnNegotiationUpdate(SdpType::kAnswer, &description);
+
+ EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(),
+ ElementsAre(RtpHeaderExtensionCapability(
+ "uri1", 1, RtpTransceiverDirection::kSendRecv),
+ RtpHeaderExtensionCapability(
+ "uri2", 2, RtpTransceiverDirection::kSendRecv)));
+
+ extensions = {webrtc::RtpExtension("uri3", 4),
+ webrtc::RtpExtension("uri5", 6)};
+ description.set_rtp_header_extensions(extensions);
+ transceiver_->OnNegotiationUpdate(SdpType::kAnswer, &description);
+
+ EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(),
+ ElementsAre(RtpHeaderExtensionCapability(
+ "uri3", 4, RtpTransceiverDirection::kSendRecv),
+ RtpHeaderExtensionCapability(
+ "uri5", 6, RtpTransceiverDirection::kSendRecv)));
+}
+
+} // namespace
+
+} // namespace webrtc