diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/libwebrtc/pc/sdp_offer_answer_unittest.cc | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream.tar.xz firefox-esr-upstream.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/pc/sdp_offer_answer_unittest.cc')
-rw-r--r-- | third_party/libwebrtc/pc/sdp_offer_answer_unittest.cc | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/third_party/libwebrtc/pc/sdp_offer_answer_unittest.cc b/third_party/libwebrtc/pc/sdp_offer_answer_unittest.cc new file mode 100644 index 0000000000..e16cd6aafc --- /dev/null +++ b/third_party/libwebrtc/pc/sdp_offer_answer_unittest.cc @@ -0,0 +1,454 @@ +/* + * Copyright 2017 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. + */ + +#include <memory> +#include <utility> +#include <vector> + +#include "api/audio/audio_mixer.h" +#include "api/audio_codecs/builtin_audio_decoder_factory.h" +#include "api/audio_codecs/builtin_audio_encoder_factory.h" +#include "api/create_peerconnection_factory.h" +#include "api/media_types.h" +#include "api/peer_connection_interface.h" +#include "api/rtp_transceiver_interface.h" +#include "api/scoped_refptr.h" +#include "api/video_codecs/builtin_video_decoder_factory.h" +#include "api/video_codecs/builtin_video_encoder_factory.h" +#include "modules/audio_device/include/audio_device.h" +#include "modules/audio_processing/include/audio_processing.h" +#include "p2p/base/port_allocator.h" +#include "pc/peer_connection_wrapper.h" +#include "pc/test/fake_audio_capture_module.h" +#include "pc/test/mock_peer_connection_observers.h" +#include "rtc_base/rtc_certificate_generator.h" +#include "rtc_base/thread.h" +#include "system_wrappers/include/metrics.h" +#include "test/gtest.h" + +// This file contains unit tests that relate to the behavior of the +// SdpOfferAnswer module. +// Tests are writen as integration tests with PeerConnection, since the +// behaviors are still linked so closely that it is hard to test them in +// isolation. + +namespace webrtc { + +using RTCConfiguration = PeerConnectionInterface::RTCConfiguration; + +namespace { + +std::unique_ptr<rtc::Thread> CreateAndStartThread() { + auto thread = rtc::Thread::Create(); + thread->Start(); + return thread; +} + +} // namespace + +class SdpOfferAnswerTest : public ::testing::Test { + public: + SdpOfferAnswerTest() + // Note: We use a PeerConnectionFactory with a distinct + // signaling thread, so that thread handling can be tested. + : signaling_thread_(CreateAndStartThread()), + pc_factory_( + CreatePeerConnectionFactory(nullptr, + nullptr, + signaling_thread_.get(), + FakeAudioCaptureModule::Create(), + CreateBuiltinAudioEncoderFactory(), + CreateBuiltinAudioDecoderFactory(), + CreateBuiltinVideoEncoderFactory(), + CreateBuiltinVideoDecoderFactory(), + nullptr /* audio_mixer */, + nullptr /* audio_processing */)) { + webrtc::metrics::Reset(); + } + + std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection() { + RTCConfiguration config; + config.sdp_semantics = SdpSemantics::kUnifiedPlan; + return CreatePeerConnection(config); + } + + std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection( + const RTCConfiguration& config) { + auto observer = std::make_unique<MockPeerConnectionObserver>(); + auto result = pc_factory_->CreatePeerConnectionOrError( + config, PeerConnectionDependencies(observer.get())); + EXPECT_TRUE(result.ok()); + observer->SetPeerConnectionInterface(result.value().get()); + return std::make_unique<PeerConnectionWrapper>( + pc_factory_, result.MoveValue(), std::move(observer)); + } + + protected: + std::unique_ptr<rtc::Thread> signaling_thread_; + rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_; + + private: + rtc::AutoThread main_thread_; +}; + +TEST_F(SdpOfferAnswerTest, OnTrackReturnsProxiedObject) { + auto caller = CreatePeerConnection(); + auto callee = CreatePeerConnection(); + + auto audio_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO); + + ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get())); + // Verify that caller->observer->OnTrack() has been called with a + // proxied transceiver object. + ASSERT_EQ(callee->observer()->on_track_transceivers_.size(), 1u); + auto transceiver = callee->observer()->on_track_transceivers_[0]; + // Since the signaling thread is not the current thread, + // this will DCHECK if the transceiver is not proxied. + transceiver->stopped(); +} + +TEST_F(SdpOfferAnswerTest, BundleRejectsCodecCollisionsAudioVideo) { + auto pc = CreatePeerConnection(); + std::string sdp = + "v=0\r\n" + "o=- 0 3 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + "t=0 0\r\n" + "a=group:BUNDLE 0 1\r\n" + "a=fingerprint:sha-1 " + "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n" + "a=setup:actpass\r\n" + "a=ice-ufrag:ETEn\r\n" + "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n" + "m=audio 9 UDP/TLS/RTP/SAVPF 111\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp-mux\r\n" + "a=sendonly\r\n" + "a=mid:0\r\n" + "a=rtpmap:111 opus/48000/2\r\n" + "m=video 9 UDP/TLS/RTP/SAVPF 111\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp-mux\r\n" + "a=sendonly\r\n" + "a=mid:1\r\n" + "a=rtpmap:111 H264/90000\r\n" + "a=fmtp:111 " + "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=" + "42e01f\r\n"; + + auto desc = CreateSessionDescription(SdpType::kOffer, sdp); + ASSERT_NE(desc, nullptr); + RTCError error; + pc->SetRemoteDescription(std::move(desc), &error); + EXPECT_TRUE(error.ok()); + EXPECT_METRIC_EQ( + 1, webrtc::metrics::NumEvents( + "WebRTC.PeerConnection.ValidBundledPayloadTypes", false)); +} + +TEST_F(SdpOfferAnswerTest, BundleRejectsCodecCollisionsVideoFmtp) { + auto pc = CreatePeerConnection(); + std::string sdp = + "v=0\r\n" + "o=- 0 3 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + "t=0 0\r\n" + "a=group:BUNDLE 0 1\r\n" + "a=fingerprint:sha-1 " + "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n" + "a=setup:actpass\r\n" + "a=ice-ufrag:ETEn\r\n" + "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n" + "m=video 9 UDP/TLS/RTP/SAVPF 111\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp-mux\r\n" + "a=sendonly\r\n" + "a=mid:0\r\n" + "a=rtpmap:111 H264/90000\r\n" + "a=fmtp:111 " + "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=" + "42e01f\r\n" + "m=video 9 UDP/TLS/RTP/SAVPF 111\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp-mux\r\n" + "a=sendonly\r\n" + "a=mid:1\r\n" + "a=rtpmap:111 H264/90000\r\n" + "a=fmtp:111 " + "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=" + "42e01f\r\n"; + + auto desc = CreateSessionDescription(SdpType::kOffer, sdp); + ASSERT_NE(desc, nullptr); + RTCError error; + pc->SetRemoteDescription(std::move(desc), &error); + EXPECT_TRUE(error.ok()); + EXPECT_METRIC_EQ( + 1, webrtc::metrics::NumEvents( + "WebRTC.PeerConnection.ValidBundledPayloadTypes", false)); +} + +TEST_F(SdpOfferAnswerTest, BundleCodecCollisionInDifferentBundlesAllowed) { + auto pc = CreatePeerConnection(); + std::string sdp = + "v=0\r\n" + "o=- 0 3 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + "t=0 0\r\n" + "a=group:BUNDLE 0\r\n" + "a=group:BUNDLE 1\r\n" + "a=fingerprint:sha-1 " + "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n" + "a=setup:actpass\r\n" + "a=ice-ufrag:ETEn\r\n" + "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n" + "m=video 9 UDP/TLS/RTP/SAVPF 111\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp-mux\r\n" + "a=sendonly\r\n" + "a=mid:0\r\n" + "a=rtpmap:111 H264/90000\r\n" + "a=fmtp:111 " + "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=" + "42e01f\r\n" + "m=video 9 UDP/TLS/RTP/SAVPF 111\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp-mux\r\n" + "a=sendonly\r\n" + "a=mid:1\r\n" + "a=rtpmap:111 H264/90000\r\n" + "a=fmtp:111 " + "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=" + "42e01f\r\n"; + + auto desc = CreateSessionDescription(SdpType::kOffer, sdp); + ASSERT_NE(desc, nullptr); + RTCError error; + pc->SetRemoteDescription(std::move(desc), &error); + EXPECT_TRUE(error.ok()); + EXPECT_METRIC_EQ( + 0, webrtc::metrics::NumEvents( + "WebRTC.PeerConnection.ValidBundledPayloadTypes", false)); +} + +TEST_F(SdpOfferAnswerTest, BundleMeasuresHeaderExtensionIdCollision) { + auto pc = CreatePeerConnection(); + std::string sdp = + "v=0\r\n" + "o=- 0 3 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + "t=0 0\r\n" + "a=group:BUNDLE 0 1\r\n" + "a=fingerprint:sha-1 " + "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n" + "a=setup:actpass\r\n" + "a=ice-ufrag:ETEn\r\n" + "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n" + "m=audio 9 UDP/TLS/RTP/SAVPF 111\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp-mux\r\n" + "a=sendonly\r\n" + "a=mid:0\r\n" + "a=rtpmap:111 opus/48000/2\r\n" + "a=extmap:3 " + "http://www.ietf.org/id/" + "draft-holmer-rmcat-transport-wide-cc-extensions-01\r\n" + "m=video 9 UDP/TLS/RTP/SAVPF 112\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp-mux\r\n" + "a=sendonly\r\n" + "a=mid:1\r\n" + "a=rtpmap:112 VP8/90000\r\n" + "a=extmap:3 " + "http://www.ietf.org/id/" + "draft-holmer-rmcat-transport-wide-cc-extensions-01\r\n"; + auto desc = CreateSessionDescription(SdpType::kOffer, sdp); + ASSERT_NE(desc, nullptr); + RTCError error; + pc->SetRemoteDescription(std::move(desc), &error); + EXPECT_TRUE(error.ok()); + EXPECT_METRIC_EQ(1, + webrtc::metrics::NumEvents( + "WebRTC.PeerConnection.ValidBundledExtensionIds", true)); +} + +// extmap:3 is used with two different URIs which is not allowed. +TEST_F(SdpOfferAnswerTest, BundleRejectsHeaderExtensionIdCollision) { + auto pc = CreatePeerConnection(); + std::string sdp = + "v=0\r\n" + "o=- 0 3 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + "t=0 0\r\n" + "a=group:BUNDLE 0 1\r\n" + "a=fingerprint:sha-1 " + "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n" + "a=setup:actpass\r\n" + "a=ice-ufrag:ETEn\r\n" + "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n" + "m=audio 9 UDP/TLS/RTP/SAVPF 111\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp-mux\r\n" + "a=sendonly\r\n" + "a=mid:0\r\n" + "a=rtpmap:111 opus/48000/2\r\n" + "a=extmap:3 " + "http://www.ietf.org/id/" + "draft-holmer-rmcat-transport-wide-cc-extensions-01\r\n" + "m=video 9 UDP/TLS/RTP/SAVPF 112\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp-mux\r\n" + "a=sendonly\r\n" + "a=mid:1\r\n" + "a=rtpmap:112 VP8/90000\r\n" + "a=extmap:3 urn:3gpp:video-orientation\r\n"; + auto desc = CreateSessionDescription(SdpType::kOffer, sdp); + ASSERT_NE(desc, nullptr); + RTCError error; + pc->SetRemoteDescription(std::move(desc), &error); + EXPECT_TRUE(error.ok()); + EXPECT_METRIC_EQ( + 1, webrtc::metrics::NumEvents( + "WebRTC.PeerConnection.ValidBundledExtensionIds", false)); +} + +// transport-wide cc is negotiated with two different ids 3 and 4. +// This is not a good idea but tolerable. +TEST_F(SdpOfferAnswerTest, BundleAcceptsDifferentIdsForSameExtension) { + auto pc = CreatePeerConnection(); + std::string sdp = + "v=0\r\n" + "o=- 0 3 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + "t=0 0\r\n" + "a=group:BUNDLE 0 1\r\n" + "a=fingerprint:sha-1 " + "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n" + "a=setup:actpass\r\n" + "a=ice-ufrag:ETEn\r\n" + "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n" + "m=audio 9 UDP/TLS/RTP/SAVPF 111\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp-mux\r\n" + "a=sendonly\r\n" + "a=mid:0\r\n" + "a=rtpmap:111 opus/48000/2\r\n" + "a=extmap:3 " + "http://www.ietf.org/id/" + "draft-holmer-rmcat-transport-wide-cc-extensions-01\r\n" + "m=video 9 UDP/TLS/RTP/SAVPF 112\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp-mux\r\n" + "a=sendonly\r\n" + "a=mid:1\r\n" + "a=rtpmap:112 VP8/90000\r\n" + "a=extmap:4 " + "http://www.ietf.org/id/" + "draft-holmer-rmcat-transport-wide-cc-extensions-01\r\n"; + auto desc = CreateSessionDescription(SdpType::kOffer, sdp); + ASSERT_NE(desc, nullptr); + RTCError error; + pc->SetRemoteDescription(std::move(desc), &error); + EXPECT_TRUE(error.ok()); + EXPECT_METRIC_EQ(1, + webrtc::metrics::NumEvents( + "WebRTC.PeerConnection.ValidBundledExtensionIds", true)); +} + +TEST_F(SdpOfferAnswerTest, LargeMidsAreRejected) { + auto pc = CreatePeerConnection(); + std::string sdp = + "v=0\r\n" + "o=- 0 3 IN IP4 127.0.0.1\r\n" + "s=-\r\n" + "t=0 0\r\n" + "a=fingerprint:sha-1 " + "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n" + "a=setup:actpass\r\n" + "a=ice-ufrag:ETEn\r\n" + "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n" + "m=video 9 UDP/TLS/RTP/SAVPF 111\r\n" + "c=IN IP4 0.0.0.0\r\n" + "a=rtcp-mux\r\n" + "a=sendonly\r\n" + "a=rtpmap:111 VP8/90000\r\n" + "a=mid:01234567890123456\r\n"; + auto desc = CreateSessionDescription(SdpType::kOffer, sdp); + ASSERT_NE(desc, nullptr); + RTCError error; + pc->SetRemoteDescription(std::move(desc), &error); + EXPECT_FALSE(error.ok()); + EXPECT_EQ(error.type(), RTCErrorType::INVALID_PARAMETER); +} + +TEST_F(SdpOfferAnswerTest, RollbackPreservesAddTrackMid) { + std::string sdp = + "v=0\r\n" + "o=- 4131505339648218884 3 IN IP4 **-----**\r\n" + "s=-\r\n" + "t=0 0\r\n" + "a=ice-lite\r\n" + "a=msid-semantic: WMS 100030878598094:4Qs1PjbLM32RK5u3\r\n" + "a=ice-ufrag:zGWFZ+fVXDeN6UoI/136\r\n" + "a=ice-pwd:9AUNgUqRNI5LSIrC1qFD2iTR\r\n" + "a=fingerprint:sha-256 " + "AD:52:52:E0:B1:37:34:21:0E:15:8E:B7:56:56:7B:B4:39:0E:6D:1C:F5:84:A7:EE:" + "B5:27:3E:30:B1:7D:69:42\r\n" + "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\n" + "a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\n" + "a=group:BUNDLE 0 1\r\n" + "m=audio 40005 UDP/TLS/RTP/SAVPF 111\r\n" + "a=rtpmap:111 opus/48000/2\r\n" + "a=fmtp:111 " + "maxaveragebitrate=20000;maxplaybackrate=16000;minptime=10;usedtx=1;" + "useinbandfec=1;stereo=0\r\n" + "a=rtcp-fb:111 nack\r\n" + "a=setup:passive\r\n" + "a=mid:0\r\n" + "a=msid:- 75156ebd-e705-4da1-920e-2dac39794dfd\r\n" + "a=ptime:60\r\n" + "a=recvonly\r\n" + "a=rtcp-mux\r\n" + "m=audio 40005 UDP/TLS/RTP/SAVPF 111\r\n" + "a=rtpmap:111 opus/48000/2\r\n" + "a=fmtp:111 " + "maxaveragebitrate=20000;maxplaybackrate=16000;minptime=10;usedtx=1;" + "useinbandfec=1;stereo=0\r\n" + "a=rtcp-fb:111 nack\r\n" + "a=setup:passive\r\n" + "a=mid:1\r\n" + "a=msid:100030878598094:4Qs1PjbLM32RK5u3 9695447562408476674\r\n" + "a=ptime:60\r\n" + "a=sendonly\r\n" + "a=ssrc:2565730539 cname:100030878598094:4Qs1PjbLM32RK5u3\r\n" + "a=rtcp-mux\r\n"; + auto pc = CreatePeerConnection(); + auto audio_track = pc->AddAudioTrack("audio_track", {}); + auto first_transceiver = pc->pc()->GetTransceivers()[0]; + EXPECT_FALSE(first_transceiver->mid().has_value()); + auto desc = CreateSessionDescription(SdpType::kOffer, sdp); + ASSERT_NE(desc, nullptr); + RTCError error; + ASSERT_TRUE(pc->SetRemoteDescription(std::move(desc))); + pc->CreateAnswerAndSetAsLocal(); + auto saved_mid = first_transceiver->mid(); + EXPECT_TRUE(saved_mid.has_value()); + auto offer_before_rollback = pc->CreateOfferAndSetAsLocal(); + EXPECT_EQ(saved_mid, first_transceiver->mid()); + auto rollback = pc->CreateRollback(); + ASSERT_NE(rollback, nullptr); + ASSERT_TRUE(pc->SetLocalDescription(std::move(rollback))); + EXPECT_EQ(saved_mid, first_transceiver->mid()); + auto offer2 = pc->CreateOfferAndSetAsLocal(); + ASSERT_NE(offer2, nullptr); + EXPECT_EQ(saved_mid, first_transceiver->mid()); +} + +} // namespace webrtc |