xref: /aosp_15_r20/external/webrtc/pc/sdp_offer_answer_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 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 <memory>
12 #include <utility>
13 #include <vector>
14 
15 #include "api/audio/audio_mixer.h"
16 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
17 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
18 #include "api/create_peerconnection_factory.h"
19 #include "api/media_types.h"
20 #include "api/peer_connection_interface.h"
21 #include "api/rtp_transceiver_interface.h"
22 #include "api/scoped_refptr.h"
23 #include "api/video_codecs/builtin_video_decoder_factory.h"
24 #include "api/video_codecs/builtin_video_encoder_factory.h"
25 #include "modules/audio_device/include/audio_device.h"
26 #include "modules/audio_processing/include/audio_processing.h"
27 #include "p2p/base/port_allocator.h"
28 #include "pc/peer_connection_wrapper.h"
29 #include "pc/test/fake_audio_capture_module.h"
30 #include "pc/test/mock_peer_connection_observers.h"
31 #include "rtc_base/rtc_certificate_generator.h"
32 #include "rtc_base/thread.h"
33 #include "system_wrappers/include/metrics.h"
34 #include "test/gtest.h"
35 
36 // This file contains unit tests that relate to the behavior of the
37 // SdpOfferAnswer module.
38 // Tests are writen as integration tests with PeerConnection, since the
39 // behaviors are still linked so closely that it is hard to test them in
40 // isolation.
41 
42 namespace webrtc {
43 
44 using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
45 
46 namespace {
47 
CreateAndStartThread()48 std::unique_ptr<rtc::Thread> CreateAndStartThread() {
49   auto thread = rtc::Thread::Create();
50   thread->Start();
51   return thread;
52 }
53 
54 }  // namespace
55 
56 class SdpOfferAnswerTest : public ::testing::Test {
57  public:
SdpOfferAnswerTest()58   SdpOfferAnswerTest()
59       // Note: We use a PeerConnectionFactory with a distinct
60       // signaling thread, so that thread handling can be tested.
61       : signaling_thread_(CreateAndStartThread()),
62         pc_factory_(
63             CreatePeerConnectionFactory(nullptr,
64                                         nullptr,
65                                         signaling_thread_.get(),
66                                         FakeAudioCaptureModule::Create(),
67                                         CreateBuiltinAudioEncoderFactory(),
68                                         CreateBuiltinAudioDecoderFactory(),
69                                         CreateBuiltinVideoEncoderFactory(),
70                                         CreateBuiltinVideoDecoderFactory(),
71                                         nullptr /* audio_mixer */,
72                                         nullptr /* audio_processing */)) {
73     webrtc::metrics::Reset();
74   }
75 
CreatePeerConnection()76   std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection() {
77     RTCConfiguration config;
78     config.sdp_semantics = SdpSemantics::kUnifiedPlan;
79     return CreatePeerConnection(config);
80   }
81 
CreatePeerConnection(const RTCConfiguration & config)82   std::unique_ptr<PeerConnectionWrapper> CreatePeerConnection(
83       const RTCConfiguration& config) {
84     auto observer = std::make_unique<MockPeerConnectionObserver>();
85     auto result = pc_factory_->CreatePeerConnectionOrError(
86         config, PeerConnectionDependencies(observer.get()));
87     EXPECT_TRUE(result.ok());
88     observer->SetPeerConnectionInterface(result.value().get());
89     return std::make_unique<PeerConnectionWrapper>(
90         pc_factory_, result.MoveValue(), std::move(observer));
91   }
92 
93  protected:
94   std::unique_ptr<rtc::Thread> signaling_thread_;
95   rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
96 
97  private:
98   rtc::AutoThread main_thread_;
99 };
100 
TEST_F(SdpOfferAnswerTest,OnTrackReturnsProxiedObject)101 TEST_F(SdpOfferAnswerTest, OnTrackReturnsProxiedObject) {
102   auto caller = CreatePeerConnection();
103   auto callee = CreatePeerConnection();
104 
105   auto audio_transceiver = caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO);
106 
107   ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
108   // Verify that caller->observer->OnTrack() has been called with a
109   // proxied transceiver object.
110   ASSERT_EQ(callee->observer()->on_track_transceivers_.size(), 1u);
111   auto transceiver = callee->observer()->on_track_transceivers_[0];
112   // Since the signaling thread is not the current thread,
113   // this will DCHECK if the transceiver is not proxied.
114   transceiver->stopped();
115 }
116 
TEST_F(SdpOfferAnswerTest,BundleRejectsCodecCollisionsAudioVideo)117 TEST_F(SdpOfferAnswerTest, BundleRejectsCodecCollisionsAudioVideo) {
118   auto pc = CreatePeerConnection();
119   std::string sdp =
120       "v=0\r\n"
121       "o=- 0 3 IN IP4 127.0.0.1\r\n"
122       "s=-\r\n"
123       "t=0 0\r\n"
124       "a=group:BUNDLE 0 1\r\n"
125       "a=fingerprint:sha-1 "
126       "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
127       "a=setup:actpass\r\n"
128       "a=ice-ufrag:ETEn\r\n"
129       "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n"
130       "m=audio 9 UDP/TLS/RTP/SAVPF 111\r\n"
131       "c=IN IP4 0.0.0.0\r\n"
132       "a=rtcp-mux\r\n"
133       "a=sendonly\r\n"
134       "a=mid:0\r\n"
135       "a=rtpmap:111 opus/48000/2\r\n"
136       "m=video 9 UDP/TLS/RTP/SAVPF 111\r\n"
137       "c=IN IP4 0.0.0.0\r\n"
138       "a=rtcp-mux\r\n"
139       "a=sendonly\r\n"
140       "a=mid:1\r\n"
141       "a=rtpmap:111 H264/90000\r\n"
142       "a=fmtp:111 "
143       "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id="
144       "42e01f\r\n";
145 
146   auto desc = CreateSessionDescription(SdpType::kOffer, sdp);
147   ASSERT_NE(desc, nullptr);
148   RTCError error;
149   pc->SetRemoteDescription(std::move(desc), &error);
150   EXPECT_TRUE(error.ok());
151   EXPECT_METRIC_EQ(
152       1, webrtc::metrics::NumEvents(
153              "WebRTC.PeerConnection.ValidBundledPayloadTypes", false));
154 }
155 
TEST_F(SdpOfferAnswerTest,BundleRejectsCodecCollisionsVideoFmtp)156 TEST_F(SdpOfferAnswerTest, BundleRejectsCodecCollisionsVideoFmtp) {
157   auto pc = CreatePeerConnection();
158   std::string sdp =
159       "v=0\r\n"
160       "o=- 0 3 IN IP4 127.0.0.1\r\n"
161       "s=-\r\n"
162       "t=0 0\r\n"
163       "a=group:BUNDLE 0 1\r\n"
164       "a=fingerprint:sha-1 "
165       "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
166       "a=setup:actpass\r\n"
167       "a=ice-ufrag:ETEn\r\n"
168       "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n"
169       "m=video 9 UDP/TLS/RTP/SAVPF 111\r\n"
170       "c=IN IP4 0.0.0.0\r\n"
171       "a=rtcp-mux\r\n"
172       "a=sendonly\r\n"
173       "a=mid:0\r\n"
174       "a=rtpmap:111 H264/90000\r\n"
175       "a=fmtp:111 "
176       "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id="
177       "42e01f\r\n"
178       "m=video 9 UDP/TLS/RTP/SAVPF 111\r\n"
179       "c=IN IP4 0.0.0.0\r\n"
180       "a=rtcp-mux\r\n"
181       "a=sendonly\r\n"
182       "a=mid:1\r\n"
183       "a=rtpmap:111 H264/90000\r\n"
184       "a=fmtp:111 "
185       "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id="
186       "42e01f\r\n";
187 
188   auto desc = CreateSessionDescription(SdpType::kOffer, sdp);
189   ASSERT_NE(desc, nullptr);
190   RTCError error;
191   pc->SetRemoteDescription(std::move(desc), &error);
192   EXPECT_TRUE(error.ok());
193   EXPECT_METRIC_EQ(
194       1, webrtc::metrics::NumEvents(
195              "WebRTC.PeerConnection.ValidBundledPayloadTypes", false));
196 }
197 
TEST_F(SdpOfferAnswerTest,BundleCodecCollisionInDifferentBundlesAllowed)198 TEST_F(SdpOfferAnswerTest, BundleCodecCollisionInDifferentBundlesAllowed) {
199   auto pc = CreatePeerConnection();
200   std::string sdp =
201       "v=0\r\n"
202       "o=- 0 3 IN IP4 127.0.0.1\r\n"
203       "s=-\r\n"
204       "t=0 0\r\n"
205       "a=group:BUNDLE 0\r\n"
206       "a=group:BUNDLE 1\r\n"
207       "a=fingerprint:sha-1 "
208       "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB\r\n"
209       "a=setup:actpass\r\n"
210       "a=ice-ufrag:ETEn\r\n"
211       "a=ice-pwd:OtSK0WpNtpUjkY4+86js7Z/l\r\n"
212       "m=video 9 UDP/TLS/RTP/SAVPF 111\r\n"
213       "c=IN IP4 0.0.0.0\r\n"
214       "a=rtcp-mux\r\n"
215       "a=sendonly\r\n"
216       "a=mid:0\r\n"
217       "a=rtpmap:111 H264/90000\r\n"
218       "a=fmtp:111 "
219       "level-asymmetry-allowed=1;packetization-mode=0;profile-level-id="
220       "42e01f\r\n"
221       "m=video 9 UDP/TLS/RTP/SAVPF 111\r\n"
222       "c=IN IP4 0.0.0.0\r\n"
223       "a=rtcp-mux\r\n"
224       "a=sendonly\r\n"
225       "a=mid:1\r\n"
226       "a=rtpmap:111 H264/90000\r\n"
227       "a=fmtp:111 "
228       "level-asymmetry-allowed=1;packetization-mode=1;profile-level-id="
229       "42e01f\r\n";
230 
231   auto desc = CreateSessionDescription(SdpType::kOffer, sdp);
232   ASSERT_NE(desc, nullptr);
233   RTCError error;
234   pc->SetRemoteDescription(std::move(desc), &error);
235   EXPECT_TRUE(error.ok());
236   EXPECT_METRIC_EQ(
237       0, webrtc::metrics::NumEvents(
238              "WebRTC.PeerConnection.ValidBundledPayloadTypes", false));
239 }
240 
241 }  // namespace webrtc
242