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