blob: 250efc8dc5a2fd581ca249702a4a9111fe2d8b39 [file] [log] [blame]
Steve Anton8d3444d2017-10-20 15:30:51 -07001/*
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// This file contains tests that check the PeerConnection's signaling state
12// machine, as well as tests that check basic, media-agnostic aspects of SDP.
13
Philipp Hancke64a79c72021-05-10 17:28:37 +020014#include <algorithm>
Mirko Bonadei317a1f02019-09-17 17:06:18 +020015#include <memory>
Steve Anton8d3444d2017-10-20 15:30:51 -070016#include <tuple>
17
18#include "api/audio_codecs/builtin_audio_decoder_factory.h"
19#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Mirko Bonadei2ff3f492018-11-22 09:00:13 +010020#include "api/create_peerconnection_factory.h"
Philipp Hancke4e8c1152020-10-13 12:43:15 +020021#include "api/jsep_session_description.h"
Anders Carlsson67537952018-05-03 11:28:29 +020022#include "api/video_codecs/builtin_video_decoder_factory.h"
23#include "api/video_codecs/builtin_video_encoder_factory.h"
Steve Anton10542f22019-01-11 09:11:00 -080024#include "pc/peer_connection.h"
Markus Handella1b82012021-05-26 18:56:30 +020025#include "pc/peer_connection_proxy.h"
Steve Anton10542f22019-01-11 09:11:00 -080026#include "pc/peer_connection_wrapper.h"
27#include "pc/sdp_utils.h"
Philipp Hancke4e8c1152020-10-13 12:43:15 +020028#include "pc/webrtc_sdp.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070029#ifdef WEBRTC_ANDROID
Steve Anton10542f22019-01-11 09:11:00 -080030#include "pc/test/android_test_initializer.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070031#endif
Steve Anton10542f22019-01-11 09:11:00 -080032#include "pc/test/fake_audio_capture_module.h"
33#include "pc/test/fake_rtc_certificate_generator.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070034#include "rtc_base/gunit.h"
Steve Anton10542f22019-01-11 09:11:00 -080035#include "rtc_base/virtual_socket_server.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070036#include "test/gmock.h"
37
38namespace webrtc {
39
40using SignalingState = PeerConnectionInterface::SignalingState;
41using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
42using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
43using ::testing::Bool;
44using ::testing::Combine;
45using ::testing::Values;
46
Henrik Boströma3728d32019-10-28 12:09:49 +010047namespace {
48const int64_t kWaitTimeout = 10000;
49} // namespace
50
Steve Anton8d3444d2017-10-20 15:30:51 -070051class PeerConnectionWrapperForSignalingTest : public PeerConnectionWrapper {
52 public:
53 using PeerConnectionWrapper::PeerConnectionWrapper;
54
55 bool initial_offerer() {
56 return GetInternalPeerConnection()->initial_offerer();
57 }
58
59 PeerConnection* GetInternalPeerConnection() {
Mirko Bonadeie97de912017-12-13 11:29:34 +010060 auto* pci =
61 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
62 pc());
63 return static_cast<PeerConnection*>(pci->internal());
Steve Anton8d3444d2017-10-20 15:30:51 -070064 }
65};
66
Henrik Boströma3728d32019-10-28 12:09:49 +010067class ExecuteFunctionOnCreateSessionDescriptionObserver
68 : public CreateSessionDescriptionObserver {
69 public:
70 ExecuteFunctionOnCreateSessionDescriptionObserver(
71 std::function<void(SessionDescriptionInterface*)> function)
72 : function_(std::move(function)) {}
73 ~ExecuteFunctionOnCreateSessionDescriptionObserver() override {
74 RTC_DCHECK(was_called_);
75 }
76
77 bool was_called() const { return was_called_; }
78
79 void OnSuccess(SessionDescriptionInterface* desc) override {
80 RTC_DCHECK(!was_called_);
81 was_called_ = true;
82 function_(desc);
83 }
84
Artem Titovd3251962021-11-15 16:57:07 +010085 void OnFailure(RTCError error) override { RTC_DCHECK_NOTREACHED(); }
Henrik Boströma3728d32019-10-28 12:09:49 +010086
87 private:
88 bool was_called_ = false;
89 std::function<void(SessionDescriptionInterface*)> function_;
90};
91
Steve Anton8acdd1a2018-02-07 17:27:36 -080092class PeerConnectionSignalingBaseTest : public ::testing::Test {
Steve Anton8d3444d2017-10-20 15:30:51 -070093 protected:
94 typedef std::unique_ptr<PeerConnectionWrapperForSignalingTest> WrapperPtr;
95
Steve Anton8acdd1a2018-02-07 17:27:36 -080096 explicit PeerConnectionSignalingBaseTest(SdpSemantics sdp_semantics)
97 : vss_(new rtc::VirtualSocketServer()),
98 main_(vss_.get()),
99 sdp_semantics_(sdp_semantics) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700100#ifdef WEBRTC_ANDROID
101 InitializeAndroidObjects();
102#endif
103 pc_factory_ = CreatePeerConnectionFactory(
104 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
Anders Carlsson67537952018-05-03 11:28:29 +0200105 rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
106 CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
107 CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
108 nullptr /* audio_mixer */, nullptr /* audio_processing */);
Steve Anton8d3444d2017-10-20 15:30:51 -0700109 }
110
111 WrapperPtr CreatePeerConnection() {
112 return CreatePeerConnection(RTCConfiguration());
113 }
114
115 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200116 auto observer = std::make_unique<MockPeerConnectionObserver>();
Steve Anton8acdd1a2018-02-07 17:27:36 -0800117 RTCConfiguration modified_config = config;
118 modified_config.sdp_semantics = sdp_semantics_;
119 auto pc = pc_factory_->CreatePeerConnection(modified_config, nullptr,
120 nullptr, observer.get());
Steve Anton8d3444d2017-10-20 15:30:51 -0700121 if (!pc) {
122 return nullptr;
123 }
124
Yves Gerey4e933292018-10-31 15:36:05 +0100125 observer->SetPeerConnectionInterface(pc.get());
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200126 return std::make_unique<PeerConnectionWrapperForSignalingTest>(
Steve Anton8d3444d2017-10-20 15:30:51 -0700127 pc_factory_, pc, std::move(observer));
128 }
129
130 // Accepts the same arguments as CreatePeerConnection and adds default audio
131 // and video tracks.
132 template <typename... Args>
133 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
134 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
135 if (!wrapper) {
136 return nullptr;
137 }
138 wrapper->AddAudioTrack("a");
139 wrapper->AddVideoTrack("v");
140 return wrapper;
141 }
142
Harald Alvestrand4a7b3ac2019-01-17 10:39:40 +0100143 int NumberOfDtlsTransports(const WrapperPtr& pc_wrapper) {
144 std::set<DtlsTransportInterface*> transports;
145 auto transceivers = pc_wrapper->pc()->GetTransceivers();
146
147 for (auto& transceiver : transceivers) {
148 if (transceiver->sender()->dtls_transport()) {
149 EXPECT_TRUE(transceiver->receiver()->dtls_transport());
150 EXPECT_EQ(transceiver->sender()->dtls_transport().get(),
151 transceiver->receiver()->dtls_transport().get());
152 transports.insert(transceiver->sender()->dtls_transport().get());
153 } else {
154 // If one transceiver is missing, they all should be.
155 EXPECT_EQ(0UL, transports.size());
156 }
157 }
158 return transports.size();
159 }
160
161 bool HasDtlsTransport(const WrapperPtr& pc_wrapper) {
162 return NumberOfDtlsTransports(pc_wrapper) > 0;
163 }
164
Steve Anton8d3444d2017-10-20 15:30:51 -0700165 std::unique_ptr<rtc::VirtualSocketServer> vss_;
166 rtc::AutoSocketServerThread main_;
167 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
Steve Anton8acdd1a2018-02-07 17:27:36 -0800168 const SdpSemantics sdp_semantics_;
Steve Anton8d3444d2017-10-20 15:30:51 -0700169};
170
Steve Anton8acdd1a2018-02-07 17:27:36 -0800171class PeerConnectionSignalingTest
172 : public PeerConnectionSignalingBaseTest,
173 public ::testing::WithParamInterface<SdpSemantics> {
174 protected:
175 PeerConnectionSignalingTest() : PeerConnectionSignalingBaseTest(GetParam()) {}
176};
177
178TEST_P(PeerConnectionSignalingTest, SetLocalOfferTwiceWorks) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700179 auto caller = CreatePeerConnection();
180
181 EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
182 EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
183}
184
Steve Anton8acdd1a2018-02-07 17:27:36 -0800185TEST_P(PeerConnectionSignalingTest, SetRemoteOfferTwiceWorks) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700186 auto caller = CreatePeerConnection();
187 auto callee = CreatePeerConnection();
188
189 EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
190 EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
191}
192
Steve Anton8acdd1a2018-02-07 17:27:36 -0800193TEST_P(PeerConnectionSignalingTest, FailToSetNullLocalDescription) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700194 auto caller = CreatePeerConnection();
195 std::string error;
196 ASSERT_FALSE(caller->SetLocalDescription(nullptr, &error));
197 EXPECT_EQ("SessionDescription is NULL.", error);
198}
199
Steve Anton8acdd1a2018-02-07 17:27:36 -0800200TEST_P(PeerConnectionSignalingTest, FailToSetNullRemoteDescription) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700201 auto caller = CreatePeerConnection();
202 std::string error;
203 ASSERT_FALSE(caller->SetRemoteDescription(nullptr, &error));
204 EXPECT_EQ("SessionDescription is NULL.", error);
205}
206
207// The following parameterized test verifies that calls to various signaling
208// methods on PeerConnection will succeed/fail depending on what is the
209// PeerConnection's signaling state. Note that the test tries many different
210// forms of SignalingState::kClosed by arriving at a valid state then calling
Artem Titov880fa812021-07-30 22:30:23 +0200211// `Close()`. This is intended to catch cases where the PeerConnection signaling
Steve Anton8d3444d2017-10-20 15:30:51 -0700212// method ignores the closed flag but may work/not work because of the single
213// state the PeerConnection was created in before it was closed.
214
215class PeerConnectionSignalingStateTest
Steve Anton8acdd1a2018-02-07 17:27:36 -0800216 : public PeerConnectionSignalingBaseTest,
217 public ::testing::WithParamInterface<
218 std::tuple<SdpSemantics, SignalingState, bool>> {
Steve Anton8d3444d2017-10-20 15:30:51 -0700219 protected:
Steve Anton8acdd1a2018-02-07 17:27:36 -0800220 PeerConnectionSignalingStateTest()
221 : PeerConnectionSignalingBaseTest(std::get<0>(GetParam())),
222 state_under_test_(std::make_tuple(std::get<1>(GetParam()),
223 std::get<2>(GetParam()))) {}
224
Steve Anton8d3444d2017-10-20 15:30:51 -0700225 RTCConfiguration GetConfig() {
226 RTCConfiguration config;
227 config.certificates.push_back(
228 FakeRTCCertificateGenerator::GenerateCertificate());
229 return config;
230 }
231
Steve Anton8acdd1a2018-02-07 17:27:36 -0800232 WrapperPtr CreatePeerConnectionUnderTest() {
233 return CreatePeerConnectionInState(state_under_test_);
234 }
235
Steve Anton8d3444d2017-10-20 15:30:51 -0700236 WrapperPtr CreatePeerConnectionInState(SignalingState state) {
237 return CreatePeerConnectionInState(std::make_tuple(state, false));
238 }
239
240 WrapperPtr CreatePeerConnectionInState(
241 std::tuple<SignalingState, bool> state_tuple) {
242 SignalingState state = std::get<0>(state_tuple);
243 bool closed = std::get<1>(state_tuple);
244
245 auto wrapper = CreatePeerConnectionWithAudioVideo(GetConfig());
246 switch (state) {
247 case SignalingState::kStable: {
248 break;
249 }
250 case SignalingState::kHaveLocalOffer: {
251 wrapper->SetLocalDescription(wrapper->CreateOffer());
252 break;
253 }
254 case SignalingState::kHaveLocalPrAnswer: {
255 auto caller = CreatePeerConnectionWithAudioVideo(GetConfig());
256 wrapper->SetRemoteDescription(caller->CreateOffer());
257 auto answer = wrapper->CreateAnswer();
Steve Antona3a92c22017-12-07 10:27:41 -0800258 wrapper->SetLocalDescription(
259 CloneSessionDescriptionAsType(answer.get(), SdpType::kPrAnswer));
Steve Anton8d3444d2017-10-20 15:30:51 -0700260 break;
261 }
262 case SignalingState::kHaveRemoteOffer: {
263 auto caller = CreatePeerConnectionWithAudioVideo(GetConfig());
264 wrapper->SetRemoteDescription(caller->CreateOffer());
265 break;
266 }
267 case SignalingState::kHaveRemotePrAnswer: {
268 auto callee = CreatePeerConnectionWithAudioVideo(GetConfig());
269 callee->SetRemoteDescription(wrapper->CreateOfferAndSetAsLocal());
270 auto answer = callee->CreateAnswer();
Steve Antona3a92c22017-12-07 10:27:41 -0800271 wrapper->SetRemoteDescription(
272 CloneSessionDescriptionAsType(answer.get(), SdpType::kPrAnswer));
Steve Anton8d3444d2017-10-20 15:30:51 -0700273 break;
274 }
275 case SignalingState::kClosed: {
Artem Titovd3251962021-11-15 16:57:07 +0100276 RTC_DCHECK_NOTREACHED()
277 << "Set the second member of the tuple to true to "
278 "achieve a closed state from an existing, valid "
279 "state.";
Steve Anton8d3444d2017-10-20 15:30:51 -0700280 }
281 }
282
283 RTC_DCHECK_EQ(state, wrapper->pc()->signaling_state());
284
285 if (closed) {
286 wrapper->pc()->Close();
287 RTC_DCHECK_EQ(SignalingState::kClosed, wrapper->signaling_state());
288 }
289
290 return wrapper;
291 }
Steve Anton8acdd1a2018-02-07 17:27:36 -0800292
293 std::tuple<SignalingState, bool> state_under_test_;
Steve Anton8d3444d2017-10-20 15:30:51 -0700294};
295
Steve Anton8d3444d2017-10-20 15:30:51 -0700296TEST_P(PeerConnectionSignalingStateTest, CreateOffer) {
Steve Anton8acdd1a2018-02-07 17:27:36 -0800297 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700298 if (wrapper->signaling_state() != SignalingState::kClosed) {
299 EXPECT_TRUE(wrapper->CreateOffer());
300 } else {
301 std::string error;
302 ASSERT_FALSE(wrapper->CreateOffer(RTCOfferAnswerOptions(), &error));
303 EXPECT_PRED_FORMAT2(AssertStartsWith, error,
304 "CreateOffer called when PeerConnection is closed.");
305 }
306}
307
308TEST_P(PeerConnectionSignalingStateTest, CreateAnswer) {
Steve Anton8acdd1a2018-02-07 17:27:36 -0800309 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700310 if (wrapper->signaling_state() == SignalingState::kHaveLocalPrAnswer ||
311 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
312 EXPECT_TRUE(wrapper->CreateAnswer());
313 } else {
314 std::string error;
315 ASSERT_FALSE(wrapper->CreateAnswer(RTCOfferAnswerOptions(), &error));
Steve Antondffead82018-02-06 10:31:29 -0800316 EXPECT_EQ(error,
317 "PeerConnection cannot create an answer in a state other than "
318 "have-remote-offer or have-local-pranswer.");
Steve Anton8d3444d2017-10-20 15:30:51 -0700319 }
320}
321
322TEST_P(PeerConnectionSignalingStateTest, SetLocalOffer) {
Steve Anton8acdd1a2018-02-07 17:27:36 -0800323 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700324 if (wrapper->signaling_state() == SignalingState::kStable ||
325 wrapper->signaling_state() == SignalingState::kHaveLocalOffer) {
326 // Need to call CreateOffer on the PeerConnection under test, otherwise when
327 // setting the local offer it will want to verify the DTLS fingerprint
328 // against the locally generated certificate, but without a call to
329 // CreateOffer the certificate will never be generated.
330 EXPECT_TRUE(wrapper->SetLocalDescription(wrapper->CreateOffer()));
331 } else {
332 auto wrapper_for_offer =
333 CreatePeerConnectionInState(SignalingState::kHaveLocalOffer);
334 auto offer =
335 CloneSessionDescription(wrapper_for_offer->pc()->local_description());
336
337 std::string error;
338 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(offer), &error));
339 EXPECT_PRED_FORMAT2(
340 AssertStartsWith, error,
341 "Failed to set local offer sdp: Called in wrong state:");
342 }
343}
344
345TEST_P(PeerConnectionSignalingStateTest, SetLocalPrAnswer) {
346 auto wrapper_for_pranswer =
347 CreatePeerConnectionInState(SignalingState::kHaveLocalPrAnswer);
348 auto pranswer =
349 CloneSessionDescription(wrapper_for_pranswer->pc()->local_description());
350
Steve Anton8acdd1a2018-02-07 17:27:36 -0800351 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700352 if (wrapper->signaling_state() == SignalingState::kHaveLocalPrAnswer ||
353 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
354 EXPECT_TRUE(wrapper->SetLocalDescription(std::move(pranswer)));
355 } else {
356 std::string error;
357 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(pranswer), &error));
358 EXPECT_PRED_FORMAT2(
359 AssertStartsWith, error,
360 "Failed to set local pranswer sdp: Called in wrong state:");
361 }
362}
363
364TEST_P(PeerConnectionSignalingStateTest, SetLocalAnswer) {
365 auto wrapper_for_answer =
366 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
367 auto answer = wrapper_for_answer->CreateAnswer();
368
Steve Anton8acdd1a2018-02-07 17:27:36 -0800369 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700370 if (wrapper->signaling_state() == SignalingState::kHaveLocalPrAnswer ||
371 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
372 EXPECT_TRUE(wrapper->SetLocalDescription(std::move(answer)));
373 } else {
374 std::string error;
375 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(answer), &error));
376 EXPECT_PRED_FORMAT2(
377 AssertStartsWith, error,
378 "Failed to set local answer sdp: Called in wrong state:");
379 }
380}
381
382TEST_P(PeerConnectionSignalingStateTest, SetRemoteOffer) {
383 auto wrapper_for_offer =
384 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
385 auto offer =
386 CloneSessionDescription(wrapper_for_offer->pc()->remote_description());
387
Steve Anton8acdd1a2018-02-07 17:27:36 -0800388 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700389 if (wrapper->signaling_state() == SignalingState::kStable ||
390 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
391 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(offer)));
392 } else {
393 std::string error;
394 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(offer), &error));
395 EXPECT_PRED_FORMAT2(
396 AssertStartsWith, error,
397 "Failed to set remote offer sdp: Called in wrong state:");
398 }
399}
400
401TEST_P(PeerConnectionSignalingStateTest, SetRemotePrAnswer) {
402 auto wrapper_for_pranswer =
403 CreatePeerConnectionInState(SignalingState::kHaveRemotePrAnswer);
404 auto pranswer =
405 CloneSessionDescription(wrapper_for_pranswer->pc()->remote_description());
406
Steve Anton8acdd1a2018-02-07 17:27:36 -0800407 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700408 if (wrapper->signaling_state() == SignalingState::kHaveLocalOffer ||
409 wrapper->signaling_state() == SignalingState::kHaveRemotePrAnswer) {
410 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(pranswer)));
411 } else {
412 std::string error;
413 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(pranswer), &error));
414 EXPECT_PRED_FORMAT2(
415 AssertStartsWith, error,
416 "Failed to set remote pranswer sdp: Called in wrong state:");
417 }
418}
419
420TEST_P(PeerConnectionSignalingStateTest, SetRemoteAnswer) {
421 auto wrapper_for_answer =
422 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
423 auto answer = wrapper_for_answer->CreateAnswer();
424
Steve Anton8acdd1a2018-02-07 17:27:36 -0800425 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700426 if (wrapper->signaling_state() == SignalingState::kHaveLocalOffer ||
427 wrapper->signaling_state() == SignalingState::kHaveRemotePrAnswer) {
428 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(answer)));
429 } else {
430 std::string error;
431 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(answer), &error));
432 EXPECT_PRED_FORMAT2(
433 AssertStartsWith, error,
434 "Failed to set remote answer sdp: Called in wrong state:");
435 }
436}
437
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100438INSTANTIATE_TEST_SUITE_P(PeerConnectionSignalingTest,
439 PeerConnectionSignalingStateTest,
440 Combine(Values(SdpSemantics::kPlanB,
441 SdpSemantics::kUnifiedPlan),
442 Values(SignalingState::kStable,
443 SignalingState::kHaveLocalOffer,
444 SignalingState::kHaveLocalPrAnswer,
445 SignalingState::kHaveRemoteOffer,
446 SignalingState::kHaveRemotePrAnswer),
447 Bool()));
Steve Anton8d3444d2017-10-20 15:30:51 -0700448
Steve Antondffead82018-02-06 10:31:29 -0800449// Test that CreateAnswer fails if a round of offer/answer has been done and
450// the PeerConnection is in the stable state.
Steve Anton8acdd1a2018-02-07 17:27:36 -0800451TEST_P(PeerConnectionSignalingTest, CreateAnswerFailsIfStable) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700452 auto caller = CreatePeerConnection();
453 auto callee = CreatePeerConnection();
454
Steve Antondffead82018-02-06 10:31:29 -0800455 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Oleh Prypinc22d6a82018-02-02 08:42:18 +0000456
457 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
Steve Antondffead82018-02-06 10:31:29 -0800458 EXPECT_FALSE(caller->CreateAnswer());
459
460 ASSERT_EQ(SignalingState::kStable, callee->signaling_state());
461 EXPECT_FALSE(callee->CreateAnswer());
Steve Anton8d3444d2017-10-20 15:30:51 -0700462}
463
464// According to https://tools.ietf.org/html/rfc3264#section-8, the session id
465// stays the same but the version must be incremented if a later, different
466// session description is generated. These two tests verify that is the case for
467// both offers and answers.
Steve Anton8acdd1a2018-02-07 17:27:36 -0800468TEST_P(PeerConnectionSignalingTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700469 SessionVersionIncrementedInSubsequentDifferentOffer) {
470 auto caller = CreatePeerConnection();
471 auto callee = CreatePeerConnection();
472
473 auto original_offer = caller->CreateOfferAndSetAsLocal();
474 const std::string original_id = original_offer->session_id();
475 const std::string original_version = original_offer->session_version();
476
477 ASSERT_TRUE(callee->SetRemoteDescription(std::move(original_offer)));
478 ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateAnswer()));
479
480 // Add track to get a different offer.
481 caller->AddAudioTrack("a");
482
483 auto later_offer = caller->CreateOffer();
484
485 EXPECT_EQ(original_id, later_offer->session_id());
486 EXPECT_LT(rtc::FromString<uint64_t>(original_version),
487 rtc::FromString<uint64_t>(later_offer->session_version()));
488}
Steve Anton8acdd1a2018-02-07 17:27:36 -0800489TEST_P(PeerConnectionSignalingTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700490 SessionVersionIncrementedInSubsequentDifferentAnswer) {
491 auto caller = CreatePeerConnection();
492 auto callee = CreatePeerConnection();
493
494 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
495
Steve Antondffead82018-02-06 10:31:29 -0800496 auto original_answer = callee->CreateAnswer();
Steve Anton8d3444d2017-10-20 15:30:51 -0700497 const std::string original_id = original_answer->session_id();
498 const std::string original_version = original_answer->session_version();
499
500 // Add track to get a different answer.
501 callee->AddAudioTrack("a");
502
503 auto later_answer = callee->CreateAnswer();
504
505 EXPECT_EQ(original_id, later_answer->session_id());
506 EXPECT_LT(rtc::FromString<uint64_t>(original_version),
507 rtc::FromString<uint64_t>(later_answer->session_version()));
508}
509
Steve Anton8acdd1a2018-02-07 17:27:36 -0800510TEST_P(PeerConnectionSignalingTest, InitiatorFlagSetOnCallerAndNotOnCallee) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700511 auto caller = CreatePeerConnectionWithAudioVideo();
512 auto callee = CreatePeerConnectionWithAudioVideo();
513
514 EXPECT_FALSE(caller->initial_offerer());
515 EXPECT_FALSE(callee->initial_offerer());
516
517 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
518
519 EXPECT_TRUE(caller->initial_offerer());
520 EXPECT_FALSE(callee->initial_offerer());
521
522 ASSERT_TRUE(
523 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
524
525 EXPECT_TRUE(caller->initial_offerer());
526 EXPECT_FALSE(callee->initial_offerer());
527}
528
529// Test creating a PeerConnection, request multiple offers, destroy the
530// PeerConnection and make sure we get success/failure callbacks for all of the
531// requests.
532// Background: crbug.com/507307
Steve Anton8acdd1a2018-02-07 17:27:36 -0800533TEST_P(PeerConnectionSignalingTest, CreateOffersAndShutdown) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700534 auto caller = CreatePeerConnection();
535
536 RTCOfferAnswerOptions options;
537 options.offer_to_receive_audio =
538 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
539
540 rtc::scoped_refptr<MockCreateSessionDescriptionObserver> observers[100];
541 for (auto& observer : observers) {
Tommi87f70902021-04-27 14:43:08 +0200542 observer = rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
Steve Anton8d3444d2017-10-20 15:30:51 -0700543 caller->pc()->CreateOffer(observer, options);
544 }
545
546 // Destroy the PeerConnection.
547 caller.reset(nullptr);
548
549 for (auto& observer : observers) {
550 // We expect to have received a notification now even if the PeerConnection
551 // was terminated. The offer creation may or may not have succeeded, but we
552 // must have received a notification.
553 EXPECT_TRUE(observer->called());
554 }
555}
556
Henrik Boströma3728d32019-10-28 12:09:49 +0100557// Similar to the above test, but by closing the PC first the CreateOffer() will
558// fail "early", which triggers a codepath where the PeerConnection is
559// reponsible for invoking the observer, instead of the normal codepath where
560// the WebRtcSessionDescriptionFactory is responsible for it.
561TEST_P(PeerConnectionSignalingTest, CloseCreateOfferAndShutdown) {
562 auto caller = CreatePeerConnection();
Tommi87f70902021-04-27 14:43:08 +0200563 auto observer = rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
Henrik Boströma3728d32019-10-28 12:09:49 +0100564 caller->pc()->Close();
565 caller->pc()->CreateOffer(observer, RTCOfferAnswerOptions());
566 caller.reset(nullptr);
567 EXPECT_TRUE(observer->called());
568}
569
Henrik Boström831ae4e2020-07-29 12:04:00 +0200570TEST_P(PeerConnectionSignalingTest,
571 ImplicitCreateOfferAndShutdownWithOldObserver) {
Henrik Boströmd4089ca2020-07-28 10:39:36 +0200572 auto caller = CreatePeerConnection();
Henrik Boström4c9c75a2020-07-29 09:46:40 +0000573 auto observer = MockSetSessionDescriptionObserver::Create();
Henrik Boström831ae4e2020-07-29 12:04:00 +0200574 caller->pc()->SetLocalDescription(observer.get());
575 caller.reset(nullptr);
576 // The old observer does not get invoked because posted messages are lost.
577 EXPECT_FALSE(observer->called());
578}
579
580TEST_P(PeerConnectionSignalingTest, ImplicitCreateOfferAndShutdown) {
581 auto caller = CreatePeerConnection();
582 rtc::scoped_refptr<FakeSetLocalDescriptionObserver> observer(
583 new FakeSetLocalDescriptionObserver());
Henrik Boström4e196702019-10-30 10:35:50 +0100584 caller->pc()->SetLocalDescription(observer);
585 caller.reset(nullptr);
Henrik Boström831ae4e2020-07-29 12:04:00 +0200586 // The new observer gets invoked because it is called immediately.
587 EXPECT_TRUE(observer->called());
588 EXPECT_FALSE(observer->error().ok());
589}
590
591TEST_P(PeerConnectionSignalingTest,
592 CloseBeforeImplicitCreateOfferAndShutdownWithOldObserver) {
593 auto caller = CreatePeerConnection();
594 auto observer = MockSetSessionDescriptionObserver::Create();
595 caller->pc()->Close();
596 caller->pc()->SetLocalDescription(observer.get());
597 caller.reset(nullptr);
598 // The old observer does not get invoked because posted messages are lost.
Henrik Boström4e196702019-10-30 10:35:50 +0100599 EXPECT_FALSE(observer->called());
600}
601
602TEST_P(PeerConnectionSignalingTest, CloseBeforeImplicitCreateOfferAndShutdown) {
603 auto caller = CreatePeerConnection();
Henrik Boström831ae4e2020-07-29 12:04:00 +0200604 rtc::scoped_refptr<FakeSetLocalDescriptionObserver> observer(
605 new FakeSetLocalDescriptionObserver());
Henrik Boström4e196702019-10-30 10:35:50 +0100606 caller->pc()->Close();
607 caller->pc()->SetLocalDescription(observer);
608 caller.reset(nullptr);
Henrik Boström831ae4e2020-07-29 12:04:00 +0200609 // The new observer gets invoked because it is called immediately.
610 EXPECT_TRUE(observer->called());
611 EXPECT_FALSE(observer->error().ok());
612}
613
614TEST_P(PeerConnectionSignalingTest,
615 CloseAfterImplicitCreateOfferAndShutdownWithOldObserver) {
616 auto caller = CreatePeerConnection();
617 auto observer = MockSetSessionDescriptionObserver::Create();
618 caller->pc()->SetLocalDescription(observer.get());
619 caller->pc()->Close();
620 caller.reset(nullptr);
621 // The old observer does not get invoked because posted messages are lost.
Henrik Boström4e196702019-10-30 10:35:50 +0100622 EXPECT_FALSE(observer->called());
623}
624
625TEST_P(PeerConnectionSignalingTest, CloseAfterImplicitCreateOfferAndShutdown) {
626 auto caller = CreatePeerConnection();
Henrik Boström831ae4e2020-07-29 12:04:00 +0200627 rtc::scoped_refptr<FakeSetLocalDescriptionObserver> observer(
628 new FakeSetLocalDescriptionObserver());
Henrik Boström4e196702019-10-30 10:35:50 +0100629 caller->pc()->SetLocalDescription(observer);
630 caller->pc()->Close();
631 caller.reset(nullptr);
Henrik Boström831ae4e2020-07-29 12:04:00 +0200632 // The new observer gets invoked because it is called immediately.
633 EXPECT_TRUE(observer->called());
634 EXPECT_FALSE(observer->error().ok());
635}
636
637TEST_P(PeerConnectionSignalingTest,
638 SetLocalDescriptionNewObserverIsInvokedImmediately) {
639 auto caller = CreatePeerConnection();
640 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
641
642 rtc::scoped_refptr<FakeSetLocalDescriptionObserver> observer(
643 new FakeSetLocalDescriptionObserver());
644 caller->pc()->SetLocalDescription(std::move(offer), observer);
645 // The new observer is invoked immediately.
646 EXPECT_TRUE(observer->called());
647 EXPECT_TRUE(observer->error().ok());
648}
649
650TEST_P(PeerConnectionSignalingTest,
651 SetLocalDescriptionOldObserverIsInvokedInAPostedMessage) {
652 auto caller = CreatePeerConnection();
653 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
654
655 auto observer = MockSetSessionDescriptionObserver::Create();
656 caller->pc()->SetLocalDescription(observer, offer.release());
657 // The old observer is not invoked immediately.
Henrik Boström4e196702019-10-30 10:35:50 +0100658 EXPECT_FALSE(observer->called());
Henrik Boström831ae4e2020-07-29 12:04:00 +0200659 // Process all currently pending messages by waiting for a posted task to run.
660 bool checkpoint_reached = false;
661 rtc::Thread::Current()->PostTask(
662 RTC_FROM_HERE, [&checkpoint_reached] { checkpoint_reached = true; });
663 EXPECT_TRUE_WAIT(checkpoint_reached, kWaitTimeout);
664 // If resolving the observer was pending, it must now have been called.
665 EXPECT_TRUE(observer->called());
Henrik Boström4e196702019-10-30 10:35:50 +0100666}
667
Henrik Boströma3728d32019-10-28 12:09:49 +0100668TEST_P(PeerConnectionSignalingTest, SetRemoteDescriptionExecutesImmediately) {
669 auto caller = CreatePeerConnectionWithAudioVideo();
670 auto callee = CreatePeerConnection();
671
672 // This offer will cause receivers to be created.
673 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
674
675 // By not waiting for the observer's callback we can verify that the operation
676 // executed immediately.
677 callee->pc()->SetRemoteDescription(std::move(offer),
Henrik Boström831ae4e2020-07-29 12:04:00 +0200678 new FakeSetRemoteDescriptionObserver());
Henrik Boströma3728d32019-10-28 12:09:49 +0100679 EXPECT_EQ(2u, callee->pc()->GetReceivers().size());
680}
681
682TEST_P(PeerConnectionSignalingTest, CreateOfferBlocksSetRemoteDescription) {
683 auto caller = CreatePeerConnectionWithAudioVideo();
684 auto callee = CreatePeerConnection();
685
686 // This offer will cause receivers to be created.
687 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
688
689 EXPECT_EQ(0u, callee->pc()->GetReceivers().size());
Tommi87f70902021-04-27 14:43:08 +0200690 auto offer_observer =
691 rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
Henrik Boströma3728d32019-10-28 12:09:49 +0100692 // Synchronously invoke CreateOffer() and SetRemoteDescription(). The
693 // SetRemoteDescription() operation should be chained to be executed
694 // asynchronously, when CreateOffer() completes.
695 callee->pc()->CreateOffer(offer_observer, RTCOfferAnswerOptions());
696 callee->pc()->SetRemoteDescription(std::move(offer),
Henrik Boström831ae4e2020-07-29 12:04:00 +0200697 new FakeSetRemoteDescriptionObserver());
Henrik Boströma3728d32019-10-28 12:09:49 +0100698 // CreateOffer() is asynchronous; without message processing this operation
699 // should not have completed.
700 EXPECT_FALSE(offer_observer->called());
701 // Due to chaining, the receivers should not have been created by the offer
702 // yet.
703 EXPECT_EQ(0u, callee->pc()->GetReceivers().size());
704 // EXPECT_TRUE_WAIT causes messages to be processed...
705 EXPECT_TRUE_WAIT(offer_observer->called(), kWaitTimeout);
706 // Now that the offer has been completed, SetRemoteDescription() will have
707 // been executed next in the chain.
708 EXPECT_EQ(2u, callee->pc()->GetReceivers().size());
709}
710
Henrik Boström4e196702019-10-30 10:35:50 +0100711TEST_P(PeerConnectionSignalingTest,
712 ParameterlessSetLocalDescriptionCreatesOffer) {
713 auto caller = CreatePeerConnectionWithAudioVideo();
714
715 auto observer = MockSetSessionDescriptionObserver::Create();
Henrik Boström831ae4e2020-07-29 12:04:00 +0200716 caller->pc()->SetLocalDescription(observer.get());
Henrik Boström4e196702019-10-30 10:35:50 +0100717
718 // The offer is created asynchronously; message processing is needed for it to
719 // complete.
720 EXPECT_FALSE(observer->called());
721 EXPECT_FALSE(caller->pc()->pending_local_description());
722 EXPECT_EQ(PeerConnection::kStable, caller->signaling_state());
723
724 // Wait for messages to be processed.
725 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
726 EXPECT_TRUE(observer->result());
727 EXPECT_TRUE(caller->pc()->pending_local_description());
728 EXPECT_EQ(SdpType::kOffer,
729 caller->pc()->pending_local_description()->GetType());
730 EXPECT_EQ(PeerConnection::kHaveLocalOffer, caller->signaling_state());
731}
732
733TEST_P(PeerConnectionSignalingTest,
734 ParameterlessSetLocalDescriptionCreatesAnswer) {
735 auto caller = CreatePeerConnectionWithAudioVideo();
736 auto callee = CreatePeerConnectionWithAudioVideo();
737
738 callee->SetRemoteDescription(caller->CreateOffer());
739 EXPECT_EQ(PeerConnection::kHaveRemoteOffer, callee->signaling_state());
740
741 auto observer = MockSetSessionDescriptionObserver::Create();
Henrik Boström831ae4e2020-07-29 12:04:00 +0200742 callee->pc()->SetLocalDescription(observer.get());
Henrik Boström4e196702019-10-30 10:35:50 +0100743
744 // The answer is created asynchronously; message processing is needed for it
745 // to complete.
746 EXPECT_FALSE(observer->called());
747 EXPECT_FALSE(callee->pc()->current_local_description());
748
749 // Wait for messages to be processed.
750 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
751 EXPECT_TRUE(observer->result());
752 EXPECT_TRUE(callee->pc()->current_local_description());
753 EXPECT_EQ(SdpType::kAnswer,
754 callee->pc()->current_local_description()->GetType());
755 EXPECT_EQ(PeerConnection::kStable, callee->signaling_state());
756}
757
758TEST_P(PeerConnectionSignalingTest,
759 ParameterlessSetLocalDescriptionFullExchange) {
760 auto caller = CreatePeerConnectionWithAudioVideo();
761 auto callee = CreatePeerConnectionWithAudioVideo();
762
763 // SetLocalDescription(), implicitly creating an offer.
Henrik Boström831ae4e2020-07-29 12:04:00 +0200764 auto caller_set_local_description_observer =
765 MockSetSessionDescriptionObserver::Create();
766 caller->pc()->SetLocalDescription(
767 caller_set_local_description_observer.get());
Henrik Boström4e196702019-10-30 10:35:50 +0100768 EXPECT_TRUE_WAIT(caller_set_local_description_observer->called(),
769 kWaitTimeout);
770 ASSERT_TRUE(caller->pc()->pending_local_description());
771
772 // SetRemoteDescription(offer)
Henrik Boström831ae4e2020-07-29 12:04:00 +0200773 auto callee_set_remote_description_observer =
774 MockSetSessionDescriptionObserver::Create();
Henrik Boström4e196702019-10-30 10:35:50 +0100775 callee->pc()->SetRemoteDescription(
Henrik Boström831ae4e2020-07-29 12:04:00 +0200776 callee_set_remote_description_observer,
Henrik Boström4e196702019-10-30 10:35:50 +0100777 CloneSessionDescription(caller->pc()->pending_local_description())
778 .release());
779
780 // SetLocalDescription(), implicitly creating an answer.
Henrik Boström831ae4e2020-07-29 12:04:00 +0200781 auto callee_set_local_description_observer =
782 MockSetSessionDescriptionObserver::Create();
783 callee->pc()->SetLocalDescription(
784 callee_set_local_description_observer.get());
Henrik Boström4e196702019-10-30 10:35:50 +0100785 EXPECT_TRUE_WAIT(callee_set_local_description_observer->called(),
786 kWaitTimeout);
787 // Chaining guarantees SetRemoteDescription() happened before
788 // SetLocalDescription().
789 EXPECT_TRUE(callee_set_remote_description_observer->called());
790 EXPECT_TRUE(callee->pc()->current_local_description());
791
792 // SetRemoteDescription(answer)
Henrik Boström831ae4e2020-07-29 12:04:00 +0200793 auto caller_set_remote_description_observer =
794 MockSetSessionDescriptionObserver::Create();
Henrik Boström4e196702019-10-30 10:35:50 +0100795 caller->pc()->SetRemoteDescription(
796 caller_set_remote_description_observer,
797 CloneSessionDescription(callee->pc()->current_local_description())
798 .release());
799 EXPECT_TRUE_WAIT(caller_set_remote_description_observer->called(),
800 kWaitTimeout);
801
802 EXPECT_EQ(PeerConnection::kStable, caller->signaling_state());
803 EXPECT_EQ(PeerConnection::kStable, callee->signaling_state());
804}
805
806TEST_P(PeerConnectionSignalingTest,
807 ParameterlessSetLocalDescriptionCloseBeforeCreatingOffer) {
808 auto caller = CreatePeerConnectionWithAudioVideo();
809
810 auto observer = MockSetSessionDescriptionObserver::Create();
811 caller->pc()->Close();
Henrik Boström831ae4e2020-07-29 12:04:00 +0200812 caller->pc()->SetLocalDescription(observer.get());
Henrik Boström4e196702019-10-30 10:35:50 +0100813
814 // The operation should fail asynchronously.
815 EXPECT_FALSE(observer->called());
816 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
817 EXPECT_FALSE(observer->result());
818 // This did not affect the signaling state.
819 EXPECT_EQ(PeerConnection::kClosed, caller->pc()->signaling_state());
820 EXPECT_EQ(
821 "SetLocalDescription failed to create session description - "
822 "SetLocalDescription called when PeerConnection is closed.",
823 observer->error());
824}
825
826TEST_P(PeerConnectionSignalingTest,
827 ParameterlessSetLocalDescriptionCloseWhileCreatingOffer) {
828 auto caller = CreatePeerConnectionWithAudioVideo();
829
830 auto observer = MockSetSessionDescriptionObserver::Create();
Henrik Boström831ae4e2020-07-29 12:04:00 +0200831 caller->pc()->SetLocalDescription(observer.get());
Henrik Boström4e196702019-10-30 10:35:50 +0100832 caller->pc()->Close();
833
834 // The operation should fail asynchronously.
835 EXPECT_FALSE(observer->called());
836 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
837 EXPECT_FALSE(observer->result());
838 // This did not affect the signaling state.
839 EXPECT_EQ(PeerConnection::kClosed, caller->pc()->signaling_state());
840 EXPECT_EQ(
841 "SetLocalDescription failed to create session description - "
842 "CreateOffer failed because the session was shut down",
843 observer->error());
844}
845
Philipp Hancke4e8c1152020-10-13 12:43:15 +0200846TEST_P(PeerConnectionSignalingTest, UnsupportedContentType) {
847 auto caller = CreatePeerConnection();
848
849 // Call setRemoteDescription with a m= line we don't understand.
850 std::string sdp =
851 "v=0\r\n"
852 "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
853 "s=-\r\n"
854 "t=0 0\r\n"
855 "m=bogus 9 FOO 0 8\r\n"
856 "c=IN IP4 0.0.0.0\r\n"
857 "a=mid:bogusmid\r\n";
858 std::unique_ptr<webrtc::SessionDescriptionInterface> remote_description =
859 webrtc::CreateSessionDescription(SdpType::kOffer, sdp, nullptr);
860
861 EXPECT_TRUE(caller->SetRemoteDescription(std::move(remote_description)));
862
863 // Assert we respond back with something meaningful.
864 auto answer = caller->CreateAnswer();
865 ASSERT_EQ(answer->description()->contents().size(), 1u);
866 EXPECT_NE(answer->description()
867 ->contents()[0]
868 .media_description()
869 ->as_unsupported(),
870 nullptr);
871 EXPECT_EQ(answer->description()
872 ->contents()[0]
873 .media_description()
874 ->as_unsupported()
875 ->media_type(),
876 "bogus");
877 EXPECT_TRUE(answer->description()->contents()[0].rejected);
878 EXPECT_EQ(answer->description()->contents()[0].mid(), "bogusmid");
879 EXPECT_EQ(
880 answer->description()->contents()[0].media_description()->protocol(),
881 "FOO");
882 EXPECT_FALSE(
883 answer->description()->contents()[0].media_description()->has_codecs());
884
885 EXPECT_TRUE(caller->SetLocalDescription(std::move(answer)));
886
887 // Assert we keep this in susequent offers.
888 auto offer = caller->CreateOffer();
889 EXPECT_EQ(offer->description()
890 ->contents()[0]
891 .media_description()
892 ->as_unsupported()
893 ->media_type(),
894 "bogus");
895 EXPECT_TRUE(offer->description()->contents()[0].rejected);
896 EXPECT_EQ(offer->description()->contents()[0].media_description()->protocol(),
897 "FOO");
898 EXPECT_EQ(offer->description()->contents()[0].mid(), "bogusmid");
899 EXPECT_FALSE(
900 offer->description()->contents()[0].media_description()->has_codecs());
901 EXPECT_TRUE(caller->SetLocalDescription(std::move(offer)));
902}
903
Philipp Hanckeb7bc2432021-03-11 15:28:00 +0100904TEST_P(PeerConnectionSignalingTest, ReceiveFlexFec) {
905 auto caller = CreatePeerConnection();
906
907 std::string sdp =
908 "v=0\r\n"
909 "o=- 8403615332048243445 2 IN IP4 127.0.0.1\r\n"
910 "s=-\r\n"
911 "t=0 0\r\n"
912 "a=group:BUNDLE 0\r\n"
913 "m=video 9 UDP/TLS/RTP/SAVPF 102 122\r\n"
914 "c=IN IP4 0.0.0.0\r\n"
915 "a=rtcp:9 IN IP4 0.0.0.0\r\n"
916 "a=ice-ufrag:IZeV\r\n"
917 "a=ice-pwd:uaZhQD4rYM/Tta2qWBT1Bbt4\r\n"
918 "a=ice-options:trickle\r\n"
919 "a=fingerprint:sha-256 "
920 "D8:6C:3D:FA:23:E2:2C:63:11:2D:D0:86:BE:C4:D0:65:F9:42:F7:1C:06:04:27:E6:"
921 "1C:2C:74:01:8D:50:67:23\r\n"
922 "a=setup:actpass\r\n"
923 "a=mid:0\r\n"
924 "a=sendrecv\r\n"
925 "a=msid:stream track\r\n"
926 "a=rtcp-mux\r\n"
927 "a=rtcp-rsize\r\n"
928 "a=rtpmap:102 VP8/90000\r\n"
929 "a=rtcp-fb:102 goog-remb\r\n"
930 "a=rtcp-fb:102 transport-cc\r\n"
931 "a=rtcp-fb:102 ccm fir\r\n"
932 "a=rtcp-fb:102 nack\r\n"
933 "a=rtcp-fb:102 nack pli\r\n"
934 "a=rtpmap:122 flexfec-03/90000\r\n"
935 "a=fmtp:122 repair-window=10000000\r\n"
936 "a=ssrc-group:FEC-FR 1224551896 1953032773\r\n"
937 "a=ssrc:1224551896 cname:/exJcmhSLpyu9FgV\r\n"
938 "a=ssrc:1953032773 cname:/exJcmhSLpyu9FgV\r\n";
939 std::unique_ptr<webrtc::SessionDescriptionInterface> remote_description =
940 webrtc::CreateSessionDescription(SdpType::kOffer, sdp, nullptr);
941
942 EXPECT_TRUE(caller->SetRemoteDescription(std::move(remote_description)));
943
944 auto answer = caller->CreateAnswer();
945 ASSERT_EQ(answer->description()->contents().size(), 1u);
946 ASSERT_NE(
947 answer->description()->contents()[0].media_description()->as_video(),
948 nullptr);
949 auto codecs = answer->description()
950 ->contents()[0]
951 .media_description()
952 ->as_video()
953 ->codecs();
954 ASSERT_EQ(codecs.size(), 2u);
955 EXPECT_EQ(codecs[1].name, "flexfec-03");
956
957 EXPECT_TRUE(caller->SetLocalDescription(std::move(answer)));
958}
959
Philipp Hancke64a79c72021-05-10 17:28:37 +0200960TEST_P(PeerConnectionSignalingTest, ReceiveFlexFecReoffer) {
961 auto caller = CreatePeerConnection();
962
963 std::string sdp =
964 "v=0\r\n"
965 "o=- 8403615332048243445 2 IN IP4 127.0.0.1\r\n"
966 "s=-\r\n"
967 "t=0 0\r\n"
968 "a=group:BUNDLE 0\r\n"
969 "m=video 9 UDP/TLS/RTP/SAVPF 102 35\r\n"
970 "c=IN IP4 0.0.0.0\r\n"
971 "a=rtcp:9 IN IP4 0.0.0.0\r\n"
972 "a=ice-ufrag:IZeV\r\n"
973 "a=ice-pwd:uaZhQD4rYM/Tta2qWBT1Bbt4\r\n"
974 "a=ice-options:trickle\r\n"
975 "a=fingerprint:sha-256 "
976 "D8:6C:3D:FA:23:E2:2C:63:11:2D:D0:86:BE:C4:D0:65:F9:42:F7:1C:06:04:27:E6:"
977 "1C:2C:74:01:8D:50:67:23\r\n"
978 "a=setup:actpass\r\n"
979 "a=mid:0\r\n"
980 "a=sendrecv\r\n"
981 "a=msid:stream track\r\n"
982 "a=rtcp-mux\r\n"
983 "a=rtcp-rsize\r\n"
984 "a=rtpmap:102 VP8/90000\r\n"
985 "a=rtcp-fb:102 goog-remb\r\n"
986 "a=rtcp-fb:102 transport-cc\r\n"
987 "a=rtcp-fb:102 ccm fir\r\n"
988 "a=rtcp-fb:102 nack\r\n"
989 "a=rtcp-fb:102 nack pli\r\n"
990 "a=rtpmap:35 flexfec-03/90000\r\n"
991 "a=fmtp:35 repair-window=10000000\r\n"
992 "a=ssrc-group:FEC-FR 1224551896 1953032773\r\n"
993 "a=ssrc:1224551896 cname:/exJcmhSLpyu9FgV\r\n"
994 "a=ssrc:1953032773 cname:/exJcmhSLpyu9FgV\r\n";
995 std::unique_ptr<webrtc::SessionDescriptionInterface> remote_description =
996 webrtc::CreateSessionDescription(SdpType::kOffer, sdp, nullptr);
997
998 EXPECT_TRUE(caller->SetRemoteDescription(std::move(remote_description)));
999
1000 auto answer = caller->CreateAnswer();
1001 ASSERT_EQ(answer->description()->contents().size(), 1u);
1002 ASSERT_NE(
1003 answer->description()->contents()[0].media_description()->as_video(),
1004 nullptr);
1005 auto codecs = answer->description()
1006 ->contents()[0]
1007 .media_description()
1008 ->as_video()
1009 ->codecs();
1010 ASSERT_EQ(codecs.size(), 2u);
1011 EXPECT_EQ(codecs[1].name, "flexfec-03");
1012 EXPECT_EQ(codecs[1].id, 35);
1013
1014 EXPECT_TRUE(caller->SetLocalDescription(std::move(answer)));
1015
1016 // This generates a collision for AV1 which needs to be remapped.
1017 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1018 auto offer_codecs = offer->description()
1019 ->contents()[0]
1020 .media_description()
1021 ->as_video()
1022 ->codecs();
1023 auto flexfec_it = std::find_if(
1024 offer_codecs.begin(), offer_codecs.end(),
1025 [](const cricket::Codec& codec) { return codec.name == "flexfec-03"; });
1026 ASSERT_EQ(flexfec_it->id, 35);
1027 auto av1_it = std::find_if(
1028 offer_codecs.begin(), offer_codecs.end(),
Sergey Silkin6b19d822021-09-09 15:09:11 +02001029 [](const cricket::Codec& codec) { return codec.name == "AV1"; });
Philipp Hancke64a79c72021-05-10 17:28:37 +02001030 if (av1_it != offer_codecs.end()) {
1031 ASSERT_NE(av1_it->id, 35);
1032 }
1033}
1034
Philipp Hancke187e9d42021-11-08 09:58:15 +01001035TEST_P(PeerConnectionSignalingTest, MidAttributeMaxLength) {
1036 auto caller = CreatePeerConnection();
1037
1038 std::string sdp =
1039 "v=0\r\n"
1040 "o=- 8403615332048243445 2 IN IP4 127.0.0.1\r\n"
1041 "s=-\r\n"
1042 "t=0 0\r\n"
1043 "m=video 9 UDP/TLS/RTP/SAVPF 102\r\n"
1044 "c=IN IP4 0.0.0.0\r\n"
1045 "a=rtcp:9 IN IP4 0.0.0.0\r\n"
1046 "a=ice-ufrag:IZeV\r\n"
1047 "a=ice-pwd:uaZhQD4rYM/Tta2qWBT1Bbt4\r\n"
1048 "a=ice-options:trickle\r\n"
1049 "a=fingerprint:sha-256 "
1050 "D8:6C:3D:FA:23:E2:2C:63:11:2D:D0:86:BE:C4:D0:65:F9:42:F7:1C:06:04:27:E6:"
1051 "1C:2C:74:01:8D:50:67:23\r\n"
1052 "a=setup:actpass\r\n"
1053 // Too long mid attribute.
Philipp Hancke063bb382021-11-29 12:05:38 +01001054 "a=mid:0123456789012345678901234567890123\r\n"
Philipp Hancke187e9d42021-11-08 09:58:15 +01001055 "a=sendrecv\r\n"
1056 "a=msid:stream track\r\n"
1057 "a=rtcp-mux\r\n"
1058 "a=rtcp-rsize\r\n"
1059 "a=rtpmap:102 VP8/90000\r\n"
1060 "a=rtcp-fb:102 goog-remb\r\n"
1061 "a=rtcp-fb:102 transport-cc\r\n"
1062 "a=rtcp-fb:102 ccm fir\r\n"
1063 "a=rtcp-fb:102 nack\r\n"
1064 "a=rtcp-fb:102 nack pli\r\n"
1065 "a=ssrc:1224551896 cname:/exJcmhSLpyu9FgV\r\n";
1066 std::unique_ptr<webrtc::SessionDescriptionInterface> remote_description =
1067 webrtc::CreateSessionDescription(SdpType::kOffer, sdp, nullptr);
1068
1069 EXPECT_FALSE(caller->SetRemoteDescription(std::move(remote_description)));
1070}
1071
Mirko Bonadeic84f6612019-01-31 12:20:57 +01001072INSTANTIATE_TEST_SUITE_P(PeerConnectionSignalingTest,
1073 PeerConnectionSignalingTest,
1074 Values(SdpSemantics::kPlanB,
1075 SdpSemantics::kUnifiedPlan));
Steve Anton8acdd1a2018-02-07 17:27:36 -08001076
Harald Alvestrand4a7b3ac2019-01-17 10:39:40 +01001077class PeerConnectionSignalingUnifiedPlanTest
1078 : public PeerConnectionSignalingBaseTest {
1079 protected:
1080 PeerConnectionSignalingUnifiedPlanTest()
1081 : PeerConnectionSignalingBaseTest(SdpSemantics::kUnifiedPlan) {}
1082};
1083
Henrik Boströma3728d32019-10-28 12:09:49 +01001084// We verify that SetLocalDescription() executed immediately by verifying that
1085// the transceiver mid values got assigned. SLD executing immeditately is not
1086// unique to Unified Plan, but the transceivers used to verify this are only
1087// available in Unified Plan.
1088TEST_F(PeerConnectionSignalingUnifiedPlanTest,
Henrik Boström831ae4e2020-07-29 12:04:00 +02001089 SetLocalDescriptionExecutesImmediatelyUsingOldObserver) {
Henrik Boströma3728d32019-10-28 12:09:49 +01001090 auto caller = CreatePeerConnectionWithAudioVideo();
1091
1092 // This offer will cause transceiver mids to get assigned.
1093 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1094
1095 // By not waiting for the observer's callback we can verify that the operation
Henrik Boström831ae4e2020-07-29 12:04:00 +02001096 // executed immediately. The old observer is invoked in a posted message, so
1097 // waiting for it would not ensure synchronicity.
Henrik Boströma3728d32019-10-28 12:09:49 +01001098 RTC_DCHECK(!caller->pc()->GetTransceivers()[0]->mid().has_value());
1099 caller->pc()->SetLocalDescription(
Tommi87f70902021-04-27 14:43:08 +02001100 rtc::make_ref_counted<MockSetSessionDescriptionObserver>(),
Henrik Boströma3728d32019-10-28 12:09:49 +01001101 offer.release());
1102 EXPECT_TRUE(caller->pc()->GetTransceivers()[0]->mid().has_value());
1103}
1104
1105TEST_F(PeerConnectionSignalingUnifiedPlanTest,
Henrik Boström831ae4e2020-07-29 12:04:00 +02001106 SetLocalDescriptionExecutesImmediatelyUsingNewObserver) {
1107 auto caller = CreatePeerConnectionWithAudioVideo();
1108
1109 // This offer will cause transceiver mids to get assigned.
1110 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1111
1112 // Verify that mids were assigned without waiting for the observer. (However,
1113 // the new observer should also be invoked synchronously - as is ensured by
1114 // other tests.)
1115 RTC_DCHECK(!caller->pc()->GetTransceivers()[0]->mid().has_value());
1116 caller->pc()->SetLocalDescription(std::move(offer),
1117 new FakeSetLocalDescriptionObserver());
1118 EXPECT_TRUE(caller->pc()->GetTransceivers()[0]->mid().has_value());
1119}
1120
1121TEST_F(PeerConnectionSignalingUnifiedPlanTest,
Henrik Boströma3728d32019-10-28 12:09:49 +01001122 SetLocalDescriptionExecutesImmediatelyInsideCreateOfferCallback) {
1123 auto caller = CreatePeerConnectionWithAudioVideo();
1124
1125 // This offer will cause transceiver mids to get assigned.
1126 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1127
Tommi87f70902021-04-27 14:43:08 +02001128 auto offer_observer =
1129 rtc::make_ref_counted<ExecuteFunctionOnCreateSessionDescriptionObserver>(
Henrik Boströma3728d32019-10-28 12:09:49 +01001130 [pc = caller->pc()](SessionDescriptionInterface* desc) {
1131 // By not waiting for the observer's callback we can verify that the
1132 // operation executed immediately.
1133 RTC_DCHECK(!pc->GetTransceivers()[0]->mid().has_value());
1134 pc->SetLocalDescription(
1135 new rtc::RefCountedObject<MockSetSessionDescriptionObserver>(),
1136 desc);
1137 EXPECT_TRUE(pc->GetTransceivers()[0]->mid().has_value());
Tommi87f70902021-04-27 14:43:08 +02001138 });
Henrik Boströma3728d32019-10-28 12:09:49 +01001139 caller->pc()->CreateOffer(offer_observer, RTCOfferAnswerOptions());
1140 EXPECT_TRUE_WAIT(offer_observer->was_called(), kWaitTimeout);
1141}
1142
Harald Alvestrand4a7b3ac2019-01-17 10:39:40 +01001143// Test that transports are shown in the sender/receiver API after offer/answer.
1144// This only works in Unified Plan.
1145TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1146 DtlsTransportsInstantiateInOfferAnswer) {
1147 auto caller = CreatePeerConnectionWithAudioVideo();
1148 auto callee = CreatePeerConnection();
1149
1150 EXPECT_FALSE(HasDtlsTransport(caller));
1151 EXPECT_FALSE(HasDtlsTransport(callee));
1152 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1153 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
1154 EXPECT_TRUE(HasDtlsTransport(caller));
1155 callee->SetRemoteDescription(std::move(offer));
1156 EXPECT_FALSE(HasDtlsTransport(callee));
1157 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
1158 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
1159 EXPECT_TRUE(HasDtlsTransport(callee));
1160 caller->SetRemoteDescription(std::move(answer));
1161 EXPECT_TRUE(HasDtlsTransport(caller));
1162
1163 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
1164}
1165
1166TEST_F(PeerConnectionSignalingUnifiedPlanTest, DtlsTransportsMergeWhenBundled) {
1167 auto caller = CreatePeerConnectionWithAudioVideo();
1168 auto callee = CreatePeerConnection();
1169
1170 EXPECT_FALSE(HasDtlsTransport(caller));
1171 EXPECT_FALSE(HasDtlsTransport(callee));
1172 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1173 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
1174 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
1175 callee->SetRemoteDescription(std::move(offer));
1176 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
1177 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
1178 caller->SetRemoteDescription(std::move(answer));
1179 EXPECT_EQ(1, NumberOfDtlsTransports(caller));
1180
1181 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
1182}
1183
1184TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1185 DtlsTransportsAreSeparateeWhenUnbundled) {
1186 auto caller = CreatePeerConnectionWithAudioVideo();
1187 auto callee = CreatePeerConnection();
1188
1189 EXPECT_FALSE(HasDtlsTransport(caller));
1190 EXPECT_FALSE(HasDtlsTransport(callee));
1191 RTCOfferAnswerOptions unbundle_options;
1192 unbundle_options.use_rtp_mux = false;
1193 auto offer = caller->CreateOffer(unbundle_options);
1194 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
1195 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
1196 callee->SetRemoteDescription(std::move(offer));
1197 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
1198 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
1199 EXPECT_EQ(2, NumberOfDtlsTransports(callee));
1200 caller->SetRemoteDescription(std::move(answer));
1201 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
1202
1203 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
1204}
1205
Henrik Boströme574a312020-08-25 10:20:11 +02001206TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1207 ShouldFireNegotiationNeededWhenNoChangesArePending) {
1208 auto caller = CreatePeerConnection();
1209 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
1210 auto transceiver =
1211 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, RtpTransceiverInit());
1212 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1213 EXPECT_TRUE(caller->pc()->ShouldFireNegotiationNeededEvent(
1214 caller->observer()->latest_negotiation_needed_event()));
1215}
1216
1217TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1218 SuppressNegotiationNeededWhenOperationChainIsNotEmpty) {
1219 auto caller = CreatePeerConnection();
1220 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
1221 auto transceiver =
1222 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, RtpTransceiverInit());
1223 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1224
Tommi87f70902021-04-27 14:43:08 +02001225 auto observer = rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
Henrik Boströme574a312020-08-25 10:20:11 +02001226 caller->pc()->CreateOffer(observer, RTCOfferAnswerOptions());
1227 // For this test to work, the operation has to be pending, i.e. the observer
1228 // has not yet been invoked.
1229 EXPECT_FALSE(observer->called());
1230 // Because the Operations Chain is not empty, the event is now suppressed.
1231 EXPECT_FALSE(caller->pc()->ShouldFireNegotiationNeededEvent(
1232 caller->observer()->latest_negotiation_needed_event()));
1233 caller->observer()->clear_latest_negotiation_needed_event();
1234
1235 // When the Operations Chain becomes empty again, a new negotiation needed
1236 // event will be generated that is not suppressed.
1237 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
1238 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1239 EXPECT_TRUE(caller->pc()->ShouldFireNegotiationNeededEvent(
1240 caller->observer()->latest_negotiation_needed_event()));
1241}
1242
1243TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1244 SuppressNegotiationNeededWhenSignalingStateIsNotStable) {
1245 auto caller = CreatePeerConnection();
1246 auto callee = CreatePeerConnection();
1247 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1248
1249 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
1250 auto transceiver =
1251 callee->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, RtpTransceiverInit());
1252 EXPECT_TRUE(callee->observer()->has_negotiation_needed_event());
1253
1254 // Change signaling state (to "have-remote-offer") by setting a remote offer.
1255 callee->SetRemoteDescription(std::move(offer));
1256 // Because the signaling state is not "stable", the event is now suppressed.
1257 EXPECT_FALSE(callee->pc()->ShouldFireNegotiationNeededEvent(
1258 callee->observer()->latest_negotiation_needed_event()));
1259 callee->observer()->clear_latest_negotiation_needed_event();
1260
1261 // Upon rolling back to "stable", a new negotiation needed event will be
1262 // generated that is not suppressed.
1263 callee->SetLocalDescription(CreateSessionDescription(SdpType::kRollback, ""));
1264 EXPECT_TRUE(callee->observer()->has_negotiation_needed_event());
1265 EXPECT_TRUE(callee->pc()->ShouldFireNegotiationNeededEvent(
1266 callee->observer()->latest_negotiation_needed_event()));
1267}
1268
Steve Anton8d3444d2017-10-20 15:30:51 -07001269} // namespace webrtc