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 // 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
14 #include <memory>
15 #include <tuple>
16
17 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
18 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
19 #include "api/create_peerconnection_factory.h"
20 #include "api/peer_connection_proxy.h"
21 #include "api/video_codecs/builtin_video_decoder_factory.h"
22 #include "api/video_codecs/builtin_video_encoder_factory.h"
23 #include "pc/peer_connection.h"
24 #include "pc/peer_connection_wrapper.h"
25 #include "pc/sdp_utils.h"
26 #ifdef WEBRTC_ANDROID
27 #include "pc/test/android_test_initializer.h"
28 #endif
29 #include "pc/test/fake_audio_capture_module.h"
30 #include "pc/test/fake_rtc_certificate_generator.h"
31 #include "rtc_base/gunit.h"
32 #include "rtc_base/virtual_socket_server.h"
33 #include "test/gmock.h"
34
35 namespace webrtc {
36
37 using SignalingState = PeerConnectionInterface::SignalingState;
38 using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
39 using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
40 using ::testing::Bool;
41 using ::testing::Combine;
42 using ::testing::Values;
43
44 namespace {
45 const int64_t kWaitTimeout = 10000;
46 } // namespace
47
48 class PeerConnectionWrapperForSignalingTest : public PeerConnectionWrapper {
49 public:
50 using PeerConnectionWrapper::PeerConnectionWrapper;
51
initial_offerer()52 bool initial_offerer() {
53 return GetInternalPeerConnection()->initial_offerer();
54 }
55
GetInternalPeerConnection()56 PeerConnection* GetInternalPeerConnection() {
57 auto* pci =
58 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
59 pc());
60 return static_cast<PeerConnection*>(pci->internal());
61 }
62 };
63
64 class ExecuteFunctionOnCreateSessionDescriptionObserver
65 : public CreateSessionDescriptionObserver {
66 public:
ExecuteFunctionOnCreateSessionDescriptionObserver(std::function<void (SessionDescriptionInterface *)> function)67 ExecuteFunctionOnCreateSessionDescriptionObserver(
68 std::function<void(SessionDescriptionInterface*)> function)
69 : function_(std::move(function)) {}
~ExecuteFunctionOnCreateSessionDescriptionObserver()70 ~ExecuteFunctionOnCreateSessionDescriptionObserver() override {
71 RTC_DCHECK(was_called_);
72 }
73
was_called() const74 bool was_called() const { return was_called_; }
75
OnSuccess(SessionDescriptionInterface * desc)76 void OnSuccess(SessionDescriptionInterface* desc) override {
77 RTC_DCHECK(!was_called_);
78 was_called_ = true;
79 function_(desc);
80 }
81
OnFailure(RTCError error)82 void OnFailure(RTCError error) override { RTC_NOTREACHED(); }
83
84 private:
85 bool was_called_ = false;
86 std::function<void(SessionDescriptionInterface*)> function_;
87 };
88
89 class PeerConnectionSignalingBaseTest : public ::testing::Test {
90 protected:
91 typedef std::unique_ptr<PeerConnectionWrapperForSignalingTest> WrapperPtr;
92
PeerConnectionSignalingBaseTest(SdpSemantics sdp_semantics)93 explicit PeerConnectionSignalingBaseTest(SdpSemantics sdp_semantics)
94 : vss_(new rtc::VirtualSocketServer()),
95 main_(vss_.get()),
96 sdp_semantics_(sdp_semantics) {
97 #ifdef WEBRTC_ANDROID
98 InitializeAndroidObjects();
99 #endif
100 pc_factory_ = CreatePeerConnectionFactory(
101 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
102 rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
103 CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
104 CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
105 nullptr /* audio_mixer */, nullptr /* audio_processing */);
106 }
107
CreatePeerConnection()108 WrapperPtr CreatePeerConnection() {
109 return CreatePeerConnection(RTCConfiguration());
110 }
111
CreatePeerConnection(const RTCConfiguration & config)112 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
113 auto observer = std::make_unique<MockPeerConnectionObserver>();
114 RTCConfiguration modified_config = config;
115 modified_config.sdp_semantics = sdp_semantics_;
116 auto pc = pc_factory_->CreatePeerConnection(modified_config, nullptr,
117 nullptr, observer.get());
118 if (!pc) {
119 return nullptr;
120 }
121
122 observer->SetPeerConnectionInterface(pc.get());
123 return std::make_unique<PeerConnectionWrapperForSignalingTest>(
124 pc_factory_, pc, std::move(observer));
125 }
126
127 // Accepts the same arguments as CreatePeerConnection and adds default audio
128 // and video tracks.
129 template <typename... Args>
CreatePeerConnectionWithAudioVideo(Args &&...args)130 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
131 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
132 if (!wrapper) {
133 return nullptr;
134 }
135 wrapper->AddAudioTrack("a");
136 wrapper->AddVideoTrack("v");
137 return wrapper;
138 }
139
NumberOfDtlsTransports(const WrapperPtr & pc_wrapper)140 int NumberOfDtlsTransports(const WrapperPtr& pc_wrapper) {
141 std::set<DtlsTransportInterface*> transports;
142 auto transceivers = pc_wrapper->pc()->GetTransceivers();
143
144 for (auto& transceiver : transceivers) {
145 if (transceiver->sender()->dtls_transport()) {
146 EXPECT_TRUE(transceiver->receiver()->dtls_transport());
147 EXPECT_EQ(transceiver->sender()->dtls_transport().get(),
148 transceiver->receiver()->dtls_transport().get());
149 transports.insert(transceiver->sender()->dtls_transport().get());
150 } else {
151 // If one transceiver is missing, they all should be.
152 EXPECT_EQ(0UL, transports.size());
153 }
154 }
155 return transports.size();
156 }
157
HasDtlsTransport(const WrapperPtr & pc_wrapper)158 bool HasDtlsTransport(const WrapperPtr& pc_wrapper) {
159 return NumberOfDtlsTransports(pc_wrapper) > 0;
160 }
161
162 std::unique_ptr<rtc::VirtualSocketServer> vss_;
163 rtc::AutoSocketServerThread main_;
164 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
165 const SdpSemantics sdp_semantics_;
166 };
167
168 class PeerConnectionSignalingTest
169 : public PeerConnectionSignalingBaseTest,
170 public ::testing::WithParamInterface<SdpSemantics> {
171 protected:
PeerConnectionSignalingTest()172 PeerConnectionSignalingTest() : PeerConnectionSignalingBaseTest(GetParam()) {}
173 };
174
TEST_P(PeerConnectionSignalingTest,SetLocalOfferTwiceWorks)175 TEST_P(PeerConnectionSignalingTest, SetLocalOfferTwiceWorks) {
176 auto caller = CreatePeerConnection();
177
178 EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
179 EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
180 }
181
TEST_P(PeerConnectionSignalingTest,SetRemoteOfferTwiceWorks)182 TEST_P(PeerConnectionSignalingTest, SetRemoteOfferTwiceWorks) {
183 auto caller = CreatePeerConnection();
184 auto callee = CreatePeerConnection();
185
186 EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
187 EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
188 }
189
TEST_P(PeerConnectionSignalingTest,FailToSetNullLocalDescription)190 TEST_P(PeerConnectionSignalingTest, FailToSetNullLocalDescription) {
191 auto caller = CreatePeerConnection();
192 std::string error;
193 ASSERT_FALSE(caller->SetLocalDescription(nullptr, &error));
194 EXPECT_EQ("SessionDescription is NULL.", error);
195 }
196
TEST_P(PeerConnectionSignalingTest,FailToSetNullRemoteDescription)197 TEST_P(PeerConnectionSignalingTest, FailToSetNullRemoteDescription) {
198 auto caller = CreatePeerConnection();
199 std::string error;
200 ASSERT_FALSE(caller->SetRemoteDescription(nullptr, &error));
201 EXPECT_EQ("SessionDescription is NULL.", error);
202 }
203
204 // The following parameterized test verifies that calls to various signaling
205 // methods on PeerConnection will succeed/fail depending on what is the
206 // PeerConnection's signaling state. Note that the test tries many different
207 // forms of SignalingState::kClosed by arriving at a valid state then calling
208 // |Close()|. This is intended to catch cases where the PeerConnection signaling
209 // method ignores the closed flag but may work/not work because of the single
210 // state the PeerConnection was created in before it was closed.
211
212 class PeerConnectionSignalingStateTest
213 : public PeerConnectionSignalingBaseTest,
214 public ::testing::WithParamInterface<
215 std::tuple<SdpSemantics, SignalingState, bool>> {
216 protected:
PeerConnectionSignalingStateTest()217 PeerConnectionSignalingStateTest()
218 : PeerConnectionSignalingBaseTest(std::get<0>(GetParam())),
219 state_under_test_(std::make_tuple(std::get<1>(GetParam()),
220 std::get<2>(GetParam()))) {}
221
GetConfig()222 RTCConfiguration GetConfig() {
223 RTCConfiguration config;
224 config.certificates.push_back(
225 FakeRTCCertificateGenerator::GenerateCertificate());
226 return config;
227 }
228
CreatePeerConnectionUnderTest()229 WrapperPtr CreatePeerConnectionUnderTest() {
230 return CreatePeerConnectionInState(state_under_test_);
231 }
232
CreatePeerConnectionInState(SignalingState state)233 WrapperPtr CreatePeerConnectionInState(SignalingState state) {
234 return CreatePeerConnectionInState(std::make_tuple(state, false));
235 }
236
CreatePeerConnectionInState(std::tuple<SignalingState,bool> state_tuple)237 WrapperPtr CreatePeerConnectionInState(
238 std::tuple<SignalingState, bool> state_tuple) {
239 SignalingState state = std::get<0>(state_tuple);
240 bool closed = std::get<1>(state_tuple);
241
242 auto wrapper = CreatePeerConnectionWithAudioVideo(GetConfig());
243 switch (state) {
244 case SignalingState::kStable: {
245 break;
246 }
247 case SignalingState::kHaveLocalOffer: {
248 wrapper->SetLocalDescription(wrapper->CreateOffer());
249 break;
250 }
251 case SignalingState::kHaveLocalPrAnswer: {
252 auto caller = CreatePeerConnectionWithAudioVideo(GetConfig());
253 wrapper->SetRemoteDescription(caller->CreateOffer());
254 auto answer = wrapper->CreateAnswer();
255 wrapper->SetLocalDescription(
256 CloneSessionDescriptionAsType(answer.get(), SdpType::kPrAnswer));
257 break;
258 }
259 case SignalingState::kHaveRemoteOffer: {
260 auto caller = CreatePeerConnectionWithAudioVideo(GetConfig());
261 wrapper->SetRemoteDescription(caller->CreateOffer());
262 break;
263 }
264 case SignalingState::kHaveRemotePrAnswer: {
265 auto callee = CreatePeerConnectionWithAudioVideo(GetConfig());
266 callee->SetRemoteDescription(wrapper->CreateOfferAndSetAsLocal());
267 auto answer = callee->CreateAnswer();
268 wrapper->SetRemoteDescription(
269 CloneSessionDescriptionAsType(answer.get(), SdpType::kPrAnswer));
270 break;
271 }
272 case SignalingState::kClosed: {
273 RTC_NOTREACHED() << "Set the second member of the tuple to true to "
274 "achieve a closed state from an existing, valid "
275 "state.";
276 }
277 }
278
279 RTC_DCHECK_EQ(state, wrapper->pc()->signaling_state());
280
281 if (closed) {
282 wrapper->pc()->Close();
283 RTC_DCHECK_EQ(SignalingState::kClosed, wrapper->signaling_state());
284 }
285
286 return wrapper;
287 }
288
289 std::tuple<SignalingState, bool> state_under_test_;
290 };
291
TEST_P(PeerConnectionSignalingStateTest,CreateOffer)292 TEST_P(PeerConnectionSignalingStateTest, CreateOffer) {
293 auto wrapper = CreatePeerConnectionUnderTest();
294 if (wrapper->signaling_state() != SignalingState::kClosed) {
295 EXPECT_TRUE(wrapper->CreateOffer());
296 } else {
297 std::string error;
298 ASSERT_FALSE(wrapper->CreateOffer(RTCOfferAnswerOptions(), &error));
299 EXPECT_PRED_FORMAT2(AssertStartsWith, error,
300 "CreateOffer called when PeerConnection is closed.");
301 }
302 }
303
TEST_P(PeerConnectionSignalingStateTest,CreateAnswer)304 TEST_P(PeerConnectionSignalingStateTest, CreateAnswer) {
305 auto wrapper = CreatePeerConnectionUnderTest();
306 if (wrapper->signaling_state() == SignalingState::kHaveLocalPrAnswer ||
307 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
308 EXPECT_TRUE(wrapper->CreateAnswer());
309 } else {
310 std::string error;
311 ASSERT_FALSE(wrapper->CreateAnswer(RTCOfferAnswerOptions(), &error));
312 EXPECT_EQ(error,
313 "PeerConnection cannot create an answer in a state other than "
314 "have-remote-offer or have-local-pranswer.");
315 }
316 }
317
TEST_P(PeerConnectionSignalingStateTest,SetLocalOffer)318 TEST_P(PeerConnectionSignalingStateTest, SetLocalOffer) {
319 auto wrapper = CreatePeerConnectionUnderTest();
320 if (wrapper->signaling_state() == SignalingState::kStable ||
321 wrapper->signaling_state() == SignalingState::kHaveLocalOffer) {
322 // Need to call CreateOffer on the PeerConnection under test, otherwise when
323 // setting the local offer it will want to verify the DTLS fingerprint
324 // against the locally generated certificate, but without a call to
325 // CreateOffer the certificate will never be generated.
326 EXPECT_TRUE(wrapper->SetLocalDescription(wrapper->CreateOffer()));
327 } else {
328 auto wrapper_for_offer =
329 CreatePeerConnectionInState(SignalingState::kHaveLocalOffer);
330 auto offer =
331 CloneSessionDescription(wrapper_for_offer->pc()->local_description());
332
333 std::string error;
334 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(offer), &error));
335 EXPECT_PRED_FORMAT2(
336 AssertStartsWith, error,
337 "Failed to set local offer sdp: Called in wrong state:");
338 }
339 }
340
TEST_P(PeerConnectionSignalingStateTest,SetLocalPrAnswer)341 TEST_P(PeerConnectionSignalingStateTest, SetLocalPrAnswer) {
342 auto wrapper_for_pranswer =
343 CreatePeerConnectionInState(SignalingState::kHaveLocalPrAnswer);
344 auto pranswer =
345 CloneSessionDescription(wrapper_for_pranswer->pc()->local_description());
346
347 auto wrapper = CreatePeerConnectionUnderTest();
348 if (wrapper->signaling_state() == SignalingState::kHaveLocalPrAnswer ||
349 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
350 EXPECT_TRUE(wrapper->SetLocalDescription(std::move(pranswer)));
351 } else {
352 std::string error;
353 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(pranswer), &error));
354 EXPECT_PRED_FORMAT2(
355 AssertStartsWith, error,
356 "Failed to set local pranswer sdp: Called in wrong state:");
357 }
358 }
359
TEST_P(PeerConnectionSignalingStateTest,SetLocalAnswer)360 TEST_P(PeerConnectionSignalingStateTest, SetLocalAnswer) {
361 auto wrapper_for_answer =
362 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
363 auto answer = wrapper_for_answer->CreateAnswer();
364
365 auto wrapper = CreatePeerConnectionUnderTest();
366 if (wrapper->signaling_state() == SignalingState::kHaveLocalPrAnswer ||
367 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
368 EXPECT_TRUE(wrapper->SetLocalDescription(std::move(answer)));
369 } else {
370 std::string error;
371 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(answer), &error));
372 EXPECT_PRED_FORMAT2(
373 AssertStartsWith, error,
374 "Failed to set local answer sdp: Called in wrong state:");
375 }
376 }
377
TEST_P(PeerConnectionSignalingStateTest,SetRemoteOffer)378 TEST_P(PeerConnectionSignalingStateTest, SetRemoteOffer) {
379 auto wrapper_for_offer =
380 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
381 auto offer =
382 CloneSessionDescription(wrapper_for_offer->pc()->remote_description());
383
384 auto wrapper = CreatePeerConnectionUnderTest();
385 if (wrapper->signaling_state() == SignalingState::kStable ||
386 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
387 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(offer)));
388 } else {
389 std::string error;
390 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(offer), &error));
391 EXPECT_PRED_FORMAT2(
392 AssertStartsWith, error,
393 "Failed to set remote offer sdp: Called in wrong state:");
394 }
395 }
396
TEST_P(PeerConnectionSignalingStateTest,SetRemotePrAnswer)397 TEST_P(PeerConnectionSignalingStateTest, SetRemotePrAnswer) {
398 auto wrapper_for_pranswer =
399 CreatePeerConnectionInState(SignalingState::kHaveRemotePrAnswer);
400 auto pranswer =
401 CloneSessionDescription(wrapper_for_pranswer->pc()->remote_description());
402
403 auto wrapper = CreatePeerConnectionUnderTest();
404 if (wrapper->signaling_state() == SignalingState::kHaveLocalOffer ||
405 wrapper->signaling_state() == SignalingState::kHaveRemotePrAnswer) {
406 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(pranswer)));
407 } else {
408 std::string error;
409 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(pranswer), &error));
410 EXPECT_PRED_FORMAT2(
411 AssertStartsWith, error,
412 "Failed to set remote pranswer sdp: Called in wrong state:");
413 }
414 }
415
TEST_P(PeerConnectionSignalingStateTest,SetRemoteAnswer)416 TEST_P(PeerConnectionSignalingStateTest, SetRemoteAnswer) {
417 auto wrapper_for_answer =
418 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
419 auto answer = wrapper_for_answer->CreateAnswer();
420
421 auto wrapper = CreatePeerConnectionUnderTest();
422 if (wrapper->signaling_state() == SignalingState::kHaveLocalOffer ||
423 wrapper->signaling_state() == SignalingState::kHaveRemotePrAnswer) {
424 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(answer)));
425 } else {
426 std::string error;
427 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(answer), &error));
428 EXPECT_PRED_FORMAT2(
429 AssertStartsWith, error,
430 "Failed to set remote answer sdp: Called in wrong state:");
431 }
432 }
433
434 INSTANTIATE_TEST_SUITE_P(PeerConnectionSignalingTest,
435 PeerConnectionSignalingStateTest,
436 Combine(Values(SdpSemantics::kPlanB,
437 SdpSemantics::kUnifiedPlan),
438 Values(SignalingState::kStable,
439 SignalingState::kHaveLocalOffer,
440 SignalingState::kHaveLocalPrAnswer,
441 SignalingState::kHaveRemoteOffer,
442 SignalingState::kHaveRemotePrAnswer),
443 Bool()));
444
445 // Test that CreateAnswer fails if a round of offer/answer has been done and
446 // the PeerConnection is in the stable state.
TEST_P(PeerConnectionSignalingTest,CreateAnswerFailsIfStable)447 TEST_P(PeerConnectionSignalingTest, CreateAnswerFailsIfStable) {
448 auto caller = CreatePeerConnection();
449 auto callee = CreatePeerConnection();
450
451 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
452
453 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
454 EXPECT_FALSE(caller->CreateAnswer());
455
456 ASSERT_EQ(SignalingState::kStable, callee->signaling_state());
457 EXPECT_FALSE(callee->CreateAnswer());
458 }
459
460 // According to https://tools.ietf.org/html/rfc3264#section-8, the session id
461 // stays the same but the version must be incremented if a later, different
462 // session description is generated. These two tests verify that is the case for
463 // both offers and answers.
TEST_P(PeerConnectionSignalingTest,SessionVersionIncrementedInSubsequentDifferentOffer)464 TEST_P(PeerConnectionSignalingTest,
465 SessionVersionIncrementedInSubsequentDifferentOffer) {
466 auto caller = CreatePeerConnection();
467 auto callee = CreatePeerConnection();
468
469 auto original_offer = caller->CreateOfferAndSetAsLocal();
470 const std::string original_id = original_offer->session_id();
471 const std::string original_version = original_offer->session_version();
472
473 ASSERT_TRUE(callee->SetRemoteDescription(std::move(original_offer)));
474 ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateAnswer()));
475
476 // Add track to get a different offer.
477 caller->AddAudioTrack("a");
478
479 auto later_offer = caller->CreateOffer();
480
481 EXPECT_EQ(original_id, later_offer->session_id());
482 EXPECT_LT(rtc::FromString<uint64_t>(original_version),
483 rtc::FromString<uint64_t>(later_offer->session_version()));
484 }
TEST_P(PeerConnectionSignalingTest,SessionVersionIncrementedInSubsequentDifferentAnswer)485 TEST_P(PeerConnectionSignalingTest,
486 SessionVersionIncrementedInSubsequentDifferentAnswer) {
487 auto caller = CreatePeerConnection();
488 auto callee = CreatePeerConnection();
489
490 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
491
492 auto original_answer = callee->CreateAnswer();
493 const std::string original_id = original_answer->session_id();
494 const std::string original_version = original_answer->session_version();
495
496 // Add track to get a different answer.
497 callee->AddAudioTrack("a");
498
499 auto later_answer = callee->CreateAnswer();
500
501 EXPECT_EQ(original_id, later_answer->session_id());
502 EXPECT_LT(rtc::FromString<uint64_t>(original_version),
503 rtc::FromString<uint64_t>(later_answer->session_version()));
504 }
505
TEST_P(PeerConnectionSignalingTest,InitiatorFlagSetOnCallerAndNotOnCallee)506 TEST_P(PeerConnectionSignalingTest, InitiatorFlagSetOnCallerAndNotOnCallee) {
507 auto caller = CreatePeerConnectionWithAudioVideo();
508 auto callee = CreatePeerConnectionWithAudioVideo();
509
510 EXPECT_FALSE(caller->initial_offerer());
511 EXPECT_FALSE(callee->initial_offerer());
512
513 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
514
515 EXPECT_TRUE(caller->initial_offerer());
516 EXPECT_FALSE(callee->initial_offerer());
517
518 ASSERT_TRUE(
519 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
520
521 EXPECT_TRUE(caller->initial_offerer());
522 EXPECT_FALSE(callee->initial_offerer());
523 }
524
525 // Test creating a PeerConnection, request multiple offers, destroy the
526 // PeerConnection and make sure we get success/failure callbacks for all of the
527 // requests.
528 // Background: crbug.com/507307
TEST_P(PeerConnectionSignalingTest,CreateOffersAndShutdown)529 TEST_P(PeerConnectionSignalingTest, CreateOffersAndShutdown) {
530 auto caller = CreatePeerConnection();
531
532 RTCOfferAnswerOptions options;
533 options.offer_to_receive_audio =
534 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
535
536 rtc::scoped_refptr<MockCreateSessionDescriptionObserver> observers[100];
537 for (auto& observer : observers) {
538 observer =
539 new rtc::RefCountedObject<MockCreateSessionDescriptionObserver>();
540 caller->pc()->CreateOffer(observer, options);
541 }
542
543 // Destroy the PeerConnection.
544 caller.reset(nullptr);
545
546 for (auto& observer : observers) {
547 // We expect to have received a notification now even if the PeerConnection
548 // was terminated. The offer creation may or may not have succeeded, but we
549 // must have received a notification.
550 EXPECT_TRUE(observer->called());
551 }
552 }
553
554 // Similar to the above test, but by closing the PC first the CreateOffer() will
555 // fail "early", which triggers a codepath where the PeerConnection is
556 // reponsible for invoking the observer, instead of the normal codepath where
557 // the WebRtcSessionDescriptionFactory is responsible for it.
TEST_P(PeerConnectionSignalingTest,CloseCreateOfferAndShutdown)558 TEST_P(PeerConnectionSignalingTest, CloseCreateOfferAndShutdown) {
559 auto caller = CreatePeerConnection();
560 rtc::scoped_refptr<MockCreateSessionDescriptionObserver> observer =
561 new rtc::RefCountedObject<MockCreateSessionDescriptionObserver>();
562 caller->pc()->Close();
563 caller->pc()->CreateOffer(observer, RTCOfferAnswerOptions());
564 caller.reset(nullptr);
565 EXPECT_TRUE(observer->called());
566 }
567
TEST_P(PeerConnectionSignalingTest,ImplicitCreateOfferAndShutdown)568 TEST_P(PeerConnectionSignalingTest, ImplicitCreateOfferAndShutdown) {
569 auto caller = CreatePeerConnection();
570 auto observer = MockSetSessionDescriptionObserver::Create();
571 caller->pc()->SetLocalDescription(observer);
572 caller.reset(nullptr);
573 EXPECT_FALSE(observer->called());
574 }
575
TEST_P(PeerConnectionSignalingTest,CloseBeforeImplicitCreateOfferAndShutdown)576 TEST_P(PeerConnectionSignalingTest, CloseBeforeImplicitCreateOfferAndShutdown) {
577 auto caller = CreatePeerConnection();
578 auto observer = MockSetSessionDescriptionObserver::Create();
579 caller->pc()->Close();
580 caller->pc()->SetLocalDescription(observer);
581 caller.reset(nullptr);
582 EXPECT_FALSE(observer->called());
583 }
584
TEST_P(PeerConnectionSignalingTest,CloseAfterImplicitCreateOfferAndShutdown)585 TEST_P(PeerConnectionSignalingTest, CloseAfterImplicitCreateOfferAndShutdown) {
586 auto caller = CreatePeerConnection();
587 auto observer = MockSetSessionDescriptionObserver::Create();
588 caller->pc()->SetLocalDescription(observer);
589 caller->pc()->Close();
590 caller.reset(nullptr);
591 EXPECT_FALSE(observer->called());
592 }
593
TEST_P(PeerConnectionSignalingTest,SetRemoteDescriptionExecutesImmediately)594 TEST_P(PeerConnectionSignalingTest, SetRemoteDescriptionExecutesImmediately) {
595 auto caller = CreatePeerConnectionWithAudioVideo();
596 auto callee = CreatePeerConnection();
597
598 // This offer will cause receivers to be created.
599 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
600
601 // By not waiting for the observer's callback we can verify that the operation
602 // executed immediately.
603 callee->pc()->SetRemoteDescription(std::move(offer),
604 new MockSetRemoteDescriptionObserver());
605 EXPECT_EQ(2u, callee->pc()->GetReceivers().size());
606 }
607
TEST_P(PeerConnectionSignalingTest,CreateOfferBlocksSetRemoteDescription)608 TEST_P(PeerConnectionSignalingTest, CreateOfferBlocksSetRemoteDescription) {
609 auto caller = CreatePeerConnectionWithAudioVideo();
610 auto callee = CreatePeerConnection();
611
612 // This offer will cause receivers to be created.
613 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
614
615 EXPECT_EQ(0u, callee->pc()->GetReceivers().size());
616 rtc::scoped_refptr<MockCreateSessionDescriptionObserver> offer_observer(
617 new rtc::RefCountedObject<MockCreateSessionDescriptionObserver>());
618 // Synchronously invoke CreateOffer() and SetRemoteDescription(). The
619 // SetRemoteDescription() operation should be chained to be executed
620 // asynchronously, when CreateOffer() completes.
621 callee->pc()->CreateOffer(offer_observer, RTCOfferAnswerOptions());
622 callee->pc()->SetRemoteDescription(std::move(offer),
623 new MockSetRemoteDescriptionObserver());
624 // CreateOffer() is asynchronous; without message processing this operation
625 // should not have completed.
626 EXPECT_FALSE(offer_observer->called());
627 // Due to chaining, the receivers should not have been created by the offer
628 // yet.
629 EXPECT_EQ(0u, callee->pc()->GetReceivers().size());
630 // EXPECT_TRUE_WAIT causes messages to be processed...
631 EXPECT_TRUE_WAIT(offer_observer->called(), kWaitTimeout);
632 // Now that the offer has been completed, SetRemoteDescription() will have
633 // been executed next in the chain.
634 EXPECT_EQ(2u, callee->pc()->GetReceivers().size());
635 }
636
TEST_P(PeerConnectionSignalingTest,ParameterlessSetLocalDescriptionCreatesOffer)637 TEST_P(PeerConnectionSignalingTest,
638 ParameterlessSetLocalDescriptionCreatesOffer) {
639 auto caller = CreatePeerConnectionWithAudioVideo();
640
641 auto observer = MockSetSessionDescriptionObserver::Create();
642 caller->pc()->SetLocalDescription(observer);
643
644 // The offer is created asynchronously; message processing is needed for it to
645 // complete.
646 EXPECT_FALSE(observer->called());
647 EXPECT_FALSE(caller->pc()->pending_local_description());
648 EXPECT_EQ(PeerConnection::kStable, caller->signaling_state());
649
650 // Wait for messages to be processed.
651 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
652 EXPECT_TRUE(observer->result());
653 EXPECT_TRUE(caller->pc()->pending_local_description());
654 EXPECT_EQ(SdpType::kOffer,
655 caller->pc()->pending_local_description()->GetType());
656 EXPECT_EQ(PeerConnection::kHaveLocalOffer, caller->signaling_state());
657 }
658
TEST_P(PeerConnectionSignalingTest,ParameterlessSetLocalDescriptionCreatesAnswer)659 TEST_P(PeerConnectionSignalingTest,
660 ParameterlessSetLocalDescriptionCreatesAnswer) {
661 auto caller = CreatePeerConnectionWithAudioVideo();
662 auto callee = CreatePeerConnectionWithAudioVideo();
663
664 callee->SetRemoteDescription(caller->CreateOffer());
665 EXPECT_EQ(PeerConnection::kHaveRemoteOffer, callee->signaling_state());
666
667 auto observer = MockSetSessionDescriptionObserver::Create();
668 callee->pc()->SetLocalDescription(observer);
669
670 // The answer is created asynchronously; message processing is needed for it
671 // to complete.
672 EXPECT_FALSE(observer->called());
673 EXPECT_FALSE(callee->pc()->current_local_description());
674
675 // Wait for messages to be processed.
676 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
677 EXPECT_TRUE(observer->result());
678 EXPECT_TRUE(callee->pc()->current_local_description());
679 EXPECT_EQ(SdpType::kAnswer,
680 callee->pc()->current_local_description()->GetType());
681 EXPECT_EQ(PeerConnection::kStable, callee->signaling_state());
682 }
683
TEST_P(PeerConnectionSignalingTest,ParameterlessSetLocalDescriptionFullExchange)684 TEST_P(PeerConnectionSignalingTest,
685 ParameterlessSetLocalDescriptionFullExchange) {
686 auto caller = CreatePeerConnectionWithAudioVideo();
687 auto callee = CreatePeerConnectionWithAudioVideo();
688
689 // SetLocalDescription(), implicitly creating an offer.
690 rtc::scoped_refptr<MockSetSessionDescriptionObserver>
691 caller_set_local_description_observer(
692 new rtc::RefCountedObject<MockSetSessionDescriptionObserver>());
693 caller->pc()->SetLocalDescription(caller_set_local_description_observer);
694 EXPECT_TRUE_WAIT(caller_set_local_description_observer->called(),
695 kWaitTimeout);
696 ASSERT_TRUE(caller->pc()->pending_local_description());
697
698 // SetRemoteDescription(offer)
699 rtc::scoped_refptr<MockSetSessionDescriptionObserver>
700 callee_set_remote_description_observer(
701 new rtc::RefCountedObject<MockSetSessionDescriptionObserver>());
702 callee->pc()->SetRemoteDescription(
703 callee_set_remote_description_observer.get(),
704 CloneSessionDescription(caller->pc()->pending_local_description())
705 .release());
706
707 // SetLocalDescription(), implicitly creating an answer.
708 rtc::scoped_refptr<MockSetSessionDescriptionObserver>
709 callee_set_local_description_observer(
710 new rtc::RefCountedObject<MockSetSessionDescriptionObserver>());
711 callee->pc()->SetLocalDescription(callee_set_local_description_observer);
712 EXPECT_TRUE_WAIT(callee_set_local_description_observer->called(),
713 kWaitTimeout);
714 // Chaining guarantees SetRemoteDescription() happened before
715 // SetLocalDescription().
716 EXPECT_TRUE(callee_set_remote_description_observer->called());
717 EXPECT_TRUE(callee->pc()->current_local_description());
718
719 // SetRemoteDescription(answer)
720 rtc::scoped_refptr<MockSetSessionDescriptionObserver>
721 caller_set_remote_description_observer(
722 new rtc::RefCountedObject<MockSetSessionDescriptionObserver>());
723 caller->pc()->SetRemoteDescription(
724 caller_set_remote_description_observer,
725 CloneSessionDescription(callee->pc()->current_local_description())
726 .release());
727 EXPECT_TRUE_WAIT(caller_set_remote_description_observer->called(),
728 kWaitTimeout);
729
730 EXPECT_EQ(PeerConnection::kStable, caller->signaling_state());
731 EXPECT_EQ(PeerConnection::kStable, callee->signaling_state());
732 }
733
TEST_P(PeerConnectionSignalingTest,ParameterlessSetLocalDescriptionCloseBeforeCreatingOffer)734 TEST_P(PeerConnectionSignalingTest,
735 ParameterlessSetLocalDescriptionCloseBeforeCreatingOffer) {
736 auto caller = CreatePeerConnectionWithAudioVideo();
737
738 auto observer = MockSetSessionDescriptionObserver::Create();
739 caller->pc()->Close();
740 caller->pc()->SetLocalDescription(observer);
741
742 // The operation should fail asynchronously.
743 EXPECT_FALSE(observer->called());
744 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
745 EXPECT_FALSE(observer->result());
746 // This did not affect the signaling state.
747 EXPECT_EQ(PeerConnection::kClosed, caller->pc()->signaling_state());
748 EXPECT_EQ(
749 "SetLocalDescription failed to create session description - "
750 "SetLocalDescription called when PeerConnection is closed.",
751 observer->error());
752 }
753
TEST_P(PeerConnectionSignalingTest,ParameterlessSetLocalDescriptionCloseWhileCreatingOffer)754 TEST_P(PeerConnectionSignalingTest,
755 ParameterlessSetLocalDescriptionCloseWhileCreatingOffer) {
756 auto caller = CreatePeerConnectionWithAudioVideo();
757
758 auto observer = MockSetSessionDescriptionObserver::Create();
759 caller->pc()->SetLocalDescription(observer);
760 caller->pc()->Close();
761
762 // The operation should fail asynchronously.
763 EXPECT_FALSE(observer->called());
764 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
765 EXPECT_FALSE(observer->result());
766 // This did not affect the signaling state.
767 EXPECT_EQ(PeerConnection::kClosed, caller->pc()->signaling_state());
768 EXPECT_EQ(
769 "SetLocalDescription failed to create session description - "
770 "CreateOffer failed because the session was shut down",
771 observer->error());
772 }
773
774 INSTANTIATE_TEST_SUITE_P(PeerConnectionSignalingTest,
775 PeerConnectionSignalingTest,
776 Values(SdpSemantics::kPlanB,
777 SdpSemantics::kUnifiedPlan));
778
779 class PeerConnectionSignalingUnifiedPlanTest
780 : public PeerConnectionSignalingBaseTest {
781 protected:
PeerConnectionSignalingUnifiedPlanTest()782 PeerConnectionSignalingUnifiedPlanTest()
783 : PeerConnectionSignalingBaseTest(SdpSemantics::kUnifiedPlan) {}
784 };
785
786 // We verify that SetLocalDescription() executed immediately by verifying that
787 // the transceiver mid values got assigned. SLD executing immeditately is not
788 // unique to Unified Plan, but the transceivers used to verify this are only
789 // available in Unified Plan.
TEST_F(PeerConnectionSignalingUnifiedPlanTest,SetLocalDescriptionExecutesImmediately)790 TEST_F(PeerConnectionSignalingUnifiedPlanTest,
791 SetLocalDescriptionExecutesImmediately) {
792 auto caller = CreatePeerConnectionWithAudioVideo();
793
794 // This offer will cause transceiver mids to get assigned.
795 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
796
797 // By not waiting for the observer's callback we can verify that the operation
798 // executed immediately.
799 RTC_DCHECK(!caller->pc()->GetTransceivers()[0]->mid().has_value());
800 caller->pc()->SetLocalDescription(
801 new rtc::RefCountedObject<MockSetSessionDescriptionObserver>(),
802 offer.release());
803 EXPECT_TRUE(caller->pc()->GetTransceivers()[0]->mid().has_value());
804 }
805
TEST_F(PeerConnectionSignalingUnifiedPlanTest,SetLocalDescriptionExecutesImmediatelyInsideCreateOfferCallback)806 TEST_F(PeerConnectionSignalingUnifiedPlanTest,
807 SetLocalDescriptionExecutesImmediatelyInsideCreateOfferCallback) {
808 auto caller = CreatePeerConnectionWithAudioVideo();
809
810 // This offer will cause transceiver mids to get assigned.
811 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
812
813 rtc::scoped_refptr<ExecuteFunctionOnCreateSessionDescriptionObserver>
814 offer_observer(new rtc::RefCountedObject<
815 ExecuteFunctionOnCreateSessionDescriptionObserver>(
816 [pc = caller->pc()](SessionDescriptionInterface* desc) {
817 // By not waiting for the observer's callback we can verify that the
818 // operation executed immediately.
819 RTC_DCHECK(!pc->GetTransceivers()[0]->mid().has_value());
820 pc->SetLocalDescription(
821 new rtc::RefCountedObject<MockSetSessionDescriptionObserver>(),
822 desc);
823 EXPECT_TRUE(pc->GetTransceivers()[0]->mid().has_value());
824 }));
825 caller->pc()->CreateOffer(offer_observer, RTCOfferAnswerOptions());
826 EXPECT_TRUE_WAIT(offer_observer->was_called(), kWaitTimeout);
827 }
828
829 // Test that transports are shown in the sender/receiver API after offer/answer.
830 // This only works in Unified Plan.
TEST_F(PeerConnectionSignalingUnifiedPlanTest,DtlsTransportsInstantiateInOfferAnswer)831 TEST_F(PeerConnectionSignalingUnifiedPlanTest,
832 DtlsTransportsInstantiateInOfferAnswer) {
833 auto caller = CreatePeerConnectionWithAudioVideo();
834 auto callee = CreatePeerConnection();
835
836 EXPECT_FALSE(HasDtlsTransport(caller));
837 EXPECT_FALSE(HasDtlsTransport(callee));
838 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
839 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
840 EXPECT_TRUE(HasDtlsTransport(caller));
841 callee->SetRemoteDescription(std::move(offer));
842 EXPECT_FALSE(HasDtlsTransport(callee));
843 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
844 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
845 EXPECT_TRUE(HasDtlsTransport(callee));
846 caller->SetRemoteDescription(std::move(answer));
847 EXPECT_TRUE(HasDtlsTransport(caller));
848
849 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
850 }
851
TEST_F(PeerConnectionSignalingUnifiedPlanTest,DtlsTransportsMergeWhenBundled)852 TEST_F(PeerConnectionSignalingUnifiedPlanTest, DtlsTransportsMergeWhenBundled) {
853 auto caller = CreatePeerConnectionWithAudioVideo();
854 auto callee = CreatePeerConnection();
855
856 EXPECT_FALSE(HasDtlsTransport(caller));
857 EXPECT_FALSE(HasDtlsTransport(callee));
858 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
859 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
860 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
861 callee->SetRemoteDescription(std::move(offer));
862 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
863 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
864 caller->SetRemoteDescription(std::move(answer));
865 EXPECT_EQ(1, NumberOfDtlsTransports(caller));
866
867 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
868 }
869
TEST_F(PeerConnectionSignalingUnifiedPlanTest,DtlsTransportsAreSeparateeWhenUnbundled)870 TEST_F(PeerConnectionSignalingUnifiedPlanTest,
871 DtlsTransportsAreSeparateeWhenUnbundled) {
872 auto caller = CreatePeerConnectionWithAudioVideo();
873 auto callee = CreatePeerConnection();
874
875 EXPECT_FALSE(HasDtlsTransport(caller));
876 EXPECT_FALSE(HasDtlsTransport(callee));
877 RTCOfferAnswerOptions unbundle_options;
878 unbundle_options.use_rtp_mux = false;
879 auto offer = caller->CreateOffer(unbundle_options);
880 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
881 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
882 callee->SetRemoteDescription(std::move(offer));
883 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
884 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
885 EXPECT_EQ(2, NumberOfDtlsTransports(callee));
886 caller->SetRemoteDescription(std::move(answer));
887 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
888
889 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
890 }
891
892 } // namespace webrtc
893