blob: 3059fd2cf0b479ce116062ec3b3eb7bb7ec6623d [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
14#include <tuple>
15
16#include "api/audio_codecs/builtin_audio_decoder_factory.h"
17#include "api/audio_codecs/builtin_audio_encoder_factory.h"
18#include "api/peerconnectionproxy.h"
19#include "pc/peerconnection.h"
20#include "pc/peerconnectionwrapper.h"
21#include "pc/sdputils.h"
22#ifdef WEBRTC_ANDROID
23#include "pc/test/androidtestinitializer.h"
24#endif
25#include "pc/test/fakeaudiocapturemodule.h"
26#include "pc/test/fakertccertificategenerator.h"
27#include "rtc_base/gunit.h"
28#include "rtc_base/ptr_util.h"
29#include "rtc_base/stringutils.h"
30#include "rtc_base/virtualsocketserver.h"
31#include "test/gmock.h"
32
33namespace webrtc {
34
35using SignalingState = PeerConnectionInterface::SignalingState;
36using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
37using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
38using ::testing::Bool;
39using ::testing::Combine;
40using ::testing::Values;
41
42class PeerConnectionWrapperForSignalingTest : public PeerConnectionWrapper {
43 public:
44 using PeerConnectionWrapper::PeerConnectionWrapper;
45
46 bool initial_offerer() {
47 return GetInternalPeerConnection()->initial_offerer();
48 }
49
50 PeerConnection* GetInternalPeerConnection() {
Mirko Bonadeie97de912017-12-13 11:29:34 +010051 auto* pci =
52 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
53 pc());
54 return static_cast<PeerConnection*>(pci->internal());
Steve Anton8d3444d2017-10-20 15:30:51 -070055 }
56};
57
Steve Anton8acdd1a2018-02-07 17:27:36 -080058class PeerConnectionSignalingBaseTest : public ::testing::Test {
Steve Anton8d3444d2017-10-20 15:30:51 -070059 protected:
60 typedef std::unique_ptr<PeerConnectionWrapperForSignalingTest> WrapperPtr;
61
Steve Anton8acdd1a2018-02-07 17:27:36 -080062 explicit PeerConnectionSignalingBaseTest(SdpSemantics sdp_semantics)
63 : vss_(new rtc::VirtualSocketServer()),
64 main_(vss_.get()),
65 sdp_semantics_(sdp_semantics) {
Steve Anton8d3444d2017-10-20 15:30:51 -070066#ifdef WEBRTC_ANDROID
67 InitializeAndroidObjects();
68#endif
69 pc_factory_ = CreatePeerConnectionFactory(
70 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
71 FakeAudioCaptureModule::Create(), CreateBuiltinAudioEncoderFactory(),
72 CreateBuiltinAudioDecoderFactory(), nullptr, nullptr);
73 }
74
75 WrapperPtr CreatePeerConnection() {
76 return CreatePeerConnection(RTCConfiguration());
77 }
78
79 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
80 auto observer = rtc::MakeUnique<MockPeerConnectionObserver>();
Steve Anton8acdd1a2018-02-07 17:27:36 -080081 RTCConfiguration modified_config = config;
82 modified_config.sdp_semantics = sdp_semantics_;
83 auto pc = pc_factory_->CreatePeerConnection(modified_config, nullptr,
84 nullptr, observer.get());
Steve Anton8d3444d2017-10-20 15:30:51 -070085 if (!pc) {
86 return nullptr;
87 }
88
89 return rtc::MakeUnique<PeerConnectionWrapperForSignalingTest>(
90 pc_factory_, pc, std::move(observer));
91 }
92
93 // Accepts the same arguments as CreatePeerConnection and adds default audio
94 // and video tracks.
95 template <typename... Args>
96 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
97 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
98 if (!wrapper) {
99 return nullptr;
100 }
101 wrapper->AddAudioTrack("a");
102 wrapper->AddVideoTrack("v");
103 return wrapper;
104 }
105
106 std::unique_ptr<rtc::VirtualSocketServer> vss_;
107 rtc::AutoSocketServerThread main_;
108 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
Steve Anton8acdd1a2018-02-07 17:27:36 -0800109 const SdpSemantics sdp_semantics_;
Steve Anton8d3444d2017-10-20 15:30:51 -0700110};
111
Steve Anton8acdd1a2018-02-07 17:27:36 -0800112class PeerConnectionSignalingTest
113 : public PeerConnectionSignalingBaseTest,
114 public ::testing::WithParamInterface<SdpSemantics> {
115 protected:
116 PeerConnectionSignalingTest() : PeerConnectionSignalingBaseTest(GetParam()) {}
117};
118
119TEST_P(PeerConnectionSignalingTest, SetLocalOfferTwiceWorks) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700120 auto caller = CreatePeerConnection();
121
122 EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
123 EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
124}
125
Steve Anton8acdd1a2018-02-07 17:27:36 -0800126TEST_P(PeerConnectionSignalingTest, SetRemoteOfferTwiceWorks) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700127 auto caller = CreatePeerConnection();
128 auto callee = CreatePeerConnection();
129
130 EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
131 EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
132}
133
Steve Anton8acdd1a2018-02-07 17:27:36 -0800134TEST_P(PeerConnectionSignalingTest, FailToSetNullLocalDescription) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700135 auto caller = CreatePeerConnection();
136 std::string error;
137 ASSERT_FALSE(caller->SetLocalDescription(nullptr, &error));
138 EXPECT_EQ("SessionDescription is NULL.", error);
139}
140
Steve Anton8acdd1a2018-02-07 17:27:36 -0800141TEST_P(PeerConnectionSignalingTest, FailToSetNullRemoteDescription) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700142 auto caller = CreatePeerConnection();
143 std::string error;
144 ASSERT_FALSE(caller->SetRemoteDescription(nullptr, &error));
145 EXPECT_EQ("SessionDescription is NULL.", error);
146}
147
148// The following parameterized test verifies that calls to various signaling
149// methods on PeerConnection will succeed/fail depending on what is the
150// PeerConnection's signaling state. Note that the test tries many different
151// forms of SignalingState::kClosed by arriving at a valid state then calling
152// |Close()|. This is intended to catch cases where the PeerConnection signaling
153// method ignores the closed flag but may work/not work because of the single
154// state the PeerConnection was created in before it was closed.
155
156class PeerConnectionSignalingStateTest
Steve Anton8acdd1a2018-02-07 17:27:36 -0800157 : public PeerConnectionSignalingBaseTest,
158 public ::testing::WithParamInterface<
159 std::tuple<SdpSemantics, SignalingState, bool>> {
Steve Anton8d3444d2017-10-20 15:30:51 -0700160 protected:
Steve Anton8acdd1a2018-02-07 17:27:36 -0800161 PeerConnectionSignalingStateTest()
162 : PeerConnectionSignalingBaseTest(std::get<0>(GetParam())),
163 state_under_test_(std::make_tuple(std::get<1>(GetParam()),
164 std::get<2>(GetParam()))) {}
165
Steve Anton8d3444d2017-10-20 15:30:51 -0700166 RTCConfiguration GetConfig() {
167 RTCConfiguration config;
168 config.certificates.push_back(
169 FakeRTCCertificateGenerator::GenerateCertificate());
170 return config;
171 }
172
Steve Anton8acdd1a2018-02-07 17:27:36 -0800173 WrapperPtr CreatePeerConnectionUnderTest() {
174 return CreatePeerConnectionInState(state_under_test_);
175 }
176
Steve Anton8d3444d2017-10-20 15:30:51 -0700177 WrapperPtr CreatePeerConnectionInState(SignalingState state) {
178 return CreatePeerConnectionInState(std::make_tuple(state, false));
179 }
180
181 WrapperPtr CreatePeerConnectionInState(
182 std::tuple<SignalingState, bool> state_tuple) {
183 SignalingState state = std::get<0>(state_tuple);
184 bool closed = std::get<1>(state_tuple);
185
186 auto wrapper = CreatePeerConnectionWithAudioVideo(GetConfig());
187 switch (state) {
188 case SignalingState::kStable: {
189 break;
190 }
191 case SignalingState::kHaveLocalOffer: {
192 wrapper->SetLocalDescription(wrapper->CreateOffer());
193 break;
194 }
195 case SignalingState::kHaveLocalPrAnswer: {
196 auto caller = CreatePeerConnectionWithAudioVideo(GetConfig());
197 wrapper->SetRemoteDescription(caller->CreateOffer());
198 auto answer = wrapper->CreateAnswer();
Steve Antona3a92c22017-12-07 10:27:41 -0800199 wrapper->SetLocalDescription(
200 CloneSessionDescriptionAsType(answer.get(), SdpType::kPrAnswer));
Steve Anton8d3444d2017-10-20 15:30:51 -0700201 break;
202 }
203 case SignalingState::kHaveRemoteOffer: {
204 auto caller = CreatePeerConnectionWithAudioVideo(GetConfig());
205 wrapper->SetRemoteDescription(caller->CreateOffer());
206 break;
207 }
208 case SignalingState::kHaveRemotePrAnswer: {
209 auto callee = CreatePeerConnectionWithAudioVideo(GetConfig());
210 callee->SetRemoteDescription(wrapper->CreateOfferAndSetAsLocal());
211 auto answer = callee->CreateAnswer();
Steve Antona3a92c22017-12-07 10:27:41 -0800212 wrapper->SetRemoteDescription(
213 CloneSessionDescriptionAsType(answer.get(), SdpType::kPrAnswer));
Steve Anton8d3444d2017-10-20 15:30:51 -0700214 break;
215 }
216 case SignalingState::kClosed: {
217 RTC_NOTREACHED() << "Set the second member of the tuple to true to "
218 "achieve a closed state from an existing, valid "
219 "state.";
220 }
221 }
222
223 RTC_DCHECK_EQ(state, wrapper->pc()->signaling_state());
224
225 if (closed) {
226 wrapper->pc()->Close();
227 RTC_DCHECK_EQ(SignalingState::kClosed, wrapper->signaling_state());
228 }
229
230 return wrapper;
231 }
Steve Anton8acdd1a2018-02-07 17:27:36 -0800232
233 std::tuple<SignalingState, bool> state_under_test_;
Steve Anton8d3444d2017-10-20 15:30:51 -0700234};
235
Steve Anton8d3444d2017-10-20 15:30:51 -0700236TEST_P(PeerConnectionSignalingStateTest, CreateOffer) {
Steve Anton8acdd1a2018-02-07 17:27:36 -0800237 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700238 if (wrapper->signaling_state() != SignalingState::kClosed) {
239 EXPECT_TRUE(wrapper->CreateOffer());
240 } else {
241 std::string error;
242 ASSERT_FALSE(wrapper->CreateOffer(RTCOfferAnswerOptions(), &error));
243 EXPECT_PRED_FORMAT2(AssertStartsWith, error,
244 "CreateOffer called when PeerConnection is closed.");
245 }
246}
247
248TEST_P(PeerConnectionSignalingStateTest, CreateAnswer) {
Steve Anton8acdd1a2018-02-07 17:27:36 -0800249 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700250 if (wrapper->signaling_state() == SignalingState::kHaveLocalPrAnswer ||
251 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
252 EXPECT_TRUE(wrapper->CreateAnswer());
253 } else {
254 std::string error;
255 ASSERT_FALSE(wrapper->CreateAnswer(RTCOfferAnswerOptions(), &error));
Steve Antondffead82018-02-06 10:31:29 -0800256 EXPECT_EQ(error,
257 "PeerConnection cannot create an answer in a state other than "
258 "have-remote-offer or have-local-pranswer.");
Steve Anton8d3444d2017-10-20 15:30:51 -0700259 }
260}
261
262TEST_P(PeerConnectionSignalingStateTest, SetLocalOffer) {
Steve Anton8acdd1a2018-02-07 17:27:36 -0800263 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700264 if (wrapper->signaling_state() == SignalingState::kStable ||
265 wrapper->signaling_state() == SignalingState::kHaveLocalOffer) {
266 // Need to call CreateOffer on the PeerConnection under test, otherwise when
267 // setting the local offer it will want to verify the DTLS fingerprint
268 // against the locally generated certificate, but without a call to
269 // CreateOffer the certificate will never be generated.
270 EXPECT_TRUE(wrapper->SetLocalDescription(wrapper->CreateOffer()));
271 } else {
272 auto wrapper_for_offer =
273 CreatePeerConnectionInState(SignalingState::kHaveLocalOffer);
274 auto offer =
275 CloneSessionDescription(wrapper_for_offer->pc()->local_description());
276
277 std::string error;
278 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(offer), &error));
279 EXPECT_PRED_FORMAT2(
280 AssertStartsWith, error,
281 "Failed to set local offer sdp: Called in wrong state:");
282 }
283}
284
285TEST_P(PeerConnectionSignalingStateTest, SetLocalPrAnswer) {
286 auto wrapper_for_pranswer =
287 CreatePeerConnectionInState(SignalingState::kHaveLocalPrAnswer);
288 auto pranswer =
289 CloneSessionDescription(wrapper_for_pranswer->pc()->local_description());
290
Steve Anton8acdd1a2018-02-07 17:27:36 -0800291 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700292 if (wrapper->signaling_state() == SignalingState::kHaveLocalPrAnswer ||
293 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
294 EXPECT_TRUE(wrapper->SetLocalDescription(std::move(pranswer)));
295 } else {
296 std::string error;
297 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(pranswer), &error));
298 EXPECT_PRED_FORMAT2(
299 AssertStartsWith, error,
300 "Failed to set local pranswer sdp: Called in wrong state:");
301 }
302}
303
304TEST_P(PeerConnectionSignalingStateTest, SetLocalAnswer) {
305 auto wrapper_for_answer =
306 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
307 auto answer = wrapper_for_answer->CreateAnswer();
308
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->SetLocalDescription(std::move(answer)));
313 } else {
314 std::string error;
315 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(answer), &error));
316 EXPECT_PRED_FORMAT2(
317 AssertStartsWith, error,
318 "Failed to set local answer sdp: Called in wrong state:");
319 }
320}
321
322TEST_P(PeerConnectionSignalingStateTest, SetRemoteOffer) {
323 auto wrapper_for_offer =
324 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
325 auto offer =
326 CloneSessionDescription(wrapper_for_offer->pc()->remote_description());
327
Steve Anton8acdd1a2018-02-07 17:27:36 -0800328 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700329 if (wrapper->signaling_state() == SignalingState::kStable ||
330 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
331 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(offer)));
332 } else {
333 std::string error;
334 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(offer), &error));
335 EXPECT_PRED_FORMAT2(
336 AssertStartsWith, error,
337 "Failed to set remote offer sdp: Called in wrong state:");
338 }
339}
340
341TEST_P(PeerConnectionSignalingStateTest, SetRemotePrAnswer) {
342 auto wrapper_for_pranswer =
343 CreatePeerConnectionInState(SignalingState::kHaveRemotePrAnswer);
344 auto pranswer =
345 CloneSessionDescription(wrapper_for_pranswer->pc()->remote_description());
346
Steve Anton8acdd1a2018-02-07 17:27:36 -0800347 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700348 if (wrapper->signaling_state() == SignalingState::kHaveLocalOffer ||
349 wrapper->signaling_state() == SignalingState::kHaveRemotePrAnswer) {
350 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(pranswer)));
351 } else {
352 std::string error;
353 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(pranswer), &error));
354 EXPECT_PRED_FORMAT2(
355 AssertStartsWith, error,
356 "Failed to set remote pranswer sdp: Called in wrong state:");
357 }
358}
359
360TEST_P(PeerConnectionSignalingStateTest, SetRemoteAnswer) {
361 auto wrapper_for_answer =
362 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
363 auto answer = wrapper_for_answer->CreateAnswer();
364
Steve Anton8acdd1a2018-02-07 17:27:36 -0800365 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700366 if (wrapper->signaling_state() == SignalingState::kHaveLocalOffer ||
367 wrapper->signaling_state() == SignalingState::kHaveRemotePrAnswer) {
368 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(answer)));
369 } else {
370 std::string error;
371 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(answer), &error));
372 EXPECT_PRED_FORMAT2(
373 AssertStartsWith, error,
374 "Failed to set remote answer sdp: Called in wrong state:");
375 }
376}
377
378INSTANTIATE_TEST_CASE_P(PeerConnectionSignalingTest,
379 PeerConnectionSignalingStateTest,
Steve Anton8acdd1a2018-02-07 17:27:36 -0800380 Combine(Values(SdpSemantics::kPlanB,
381 SdpSemantics::kUnifiedPlan),
382 Values(SignalingState::kStable,
Steve Anton8d3444d2017-10-20 15:30:51 -0700383 SignalingState::kHaveLocalOffer,
384 SignalingState::kHaveLocalPrAnswer,
385 SignalingState::kHaveRemoteOffer,
386 SignalingState::kHaveRemotePrAnswer),
387 Bool()));
388
Steve Antondffead82018-02-06 10:31:29 -0800389// Test that CreateAnswer fails if a round of offer/answer has been done and
390// the PeerConnection is in the stable state.
Steve Anton8acdd1a2018-02-07 17:27:36 -0800391TEST_P(PeerConnectionSignalingTest, CreateAnswerFailsIfStable) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700392 auto caller = CreatePeerConnection();
393 auto callee = CreatePeerConnection();
394
Steve Antondffead82018-02-06 10:31:29 -0800395 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Oleh Prypinc22d6a82018-02-02 08:42:18 +0000396
397 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
Steve Antondffead82018-02-06 10:31:29 -0800398 EXPECT_FALSE(caller->CreateAnswer());
399
400 ASSERT_EQ(SignalingState::kStable, callee->signaling_state());
401 EXPECT_FALSE(callee->CreateAnswer());
Steve Anton8d3444d2017-10-20 15:30:51 -0700402}
403
404// According to https://tools.ietf.org/html/rfc3264#section-8, the session id
405// stays the same but the version must be incremented if a later, different
406// session description is generated. These two tests verify that is the case for
407// both offers and answers.
Steve Anton8acdd1a2018-02-07 17:27:36 -0800408TEST_P(PeerConnectionSignalingTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700409 SessionVersionIncrementedInSubsequentDifferentOffer) {
410 auto caller = CreatePeerConnection();
411 auto callee = CreatePeerConnection();
412
413 auto original_offer = caller->CreateOfferAndSetAsLocal();
414 const std::string original_id = original_offer->session_id();
415 const std::string original_version = original_offer->session_version();
416
417 ASSERT_TRUE(callee->SetRemoteDescription(std::move(original_offer)));
418 ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateAnswer()));
419
420 // Add track to get a different offer.
421 caller->AddAudioTrack("a");
422
423 auto later_offer = caller->CreateOffer();
424
425 EXPECT_EQ(original_id, later_offer->session_id());
426 EXPECT_LT(rtc::FromString<uint64_t>(original_version),
427 rtc::FromString<uint64_t>(later_offer->session_version()));
428}
Steve Anton8acdd1a2018-02-07 17:27:36 -0800429TEST_P(PeerConnectionSignalingTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700430 SessionVersionIncrementedInSubsequentDifferentAnswer) {
431 auto caller = CreatePeerConnection();
432 auto callee = CreatePeerConnection();
433
434 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
435
Steve Antondffead82018-02-06 10:31:29 -0800436 auto original_answer = callee->CreateAnswer();
Steve Anton8d3444d2017-10-20 15:30:51 -0700437 const std::string original_id = original_answer->session_id();
438 const std::string original_version = original_answer->session_version();
439
440 // Add track to get a different answer.
441 callee->AddAudioTrack("a");
442
443 auto later_answer = callee->CreateAnswer();
444
445 EXPECT_EQ(original_id, later_answer->session_id());
446 EXPECT_LT(rtc::FromString<uint64_t>(original_version),
447 rtc::FromString<uint64_t>(later_answer->session_version()));
448}
449
Steve Anton8acdd1a2018-02-07 17:27:36 -0800450TEST_P(PeerConnectionSignalingTest, InitiatorFlagSetOnCallerAndNotOnCallee) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700451 auto caller = CreatePeerConnectionWithAudioVideo();
452 auto callee = CreatePeerConnectionWithAudioVideo();
453
454 EXPECT_FALSE(caller->initial_offerer());
455 EXPECT_FALSE(callee->initial_offerer());
456
457 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
458
459 EXPECT_TRUE(caller->initial_offerer());
460 EXPECT_FALSE(callee->initial_offerer());
461
462 ASSERT_TRUE(
463 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
464
465 EXPECT_TRUE(caller->initial_offerer());
466 EXPECT_FALSE(callee->initial_offerer());
467}
468
469// Test creating a PeerConnection, request multiple offers, destroy the
470// PeerConnection and make sure we get success/failure callbacks for all of the
471// requests.
472// Background: crbug.com/507307
Steve Anton8acdd1a2018-02-07 17:27:36 -0800473TEST_P(PeerConnectionSignalingTest, CreateOffersAndShutdown) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700474 auto caller = CreatePeerConnection();
475
476 RTCOfferAnswerOptions options;
477 options.offer_to_receive_audio =
478 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
479
480 rtc::scoped_refptr<MockCreateSessionDescriptionObserver> observers[100];
481 for (auto& observer : observers) {
482 observer =
483 new rtc::RefCountedObject<MockCreateSessionDescriptionObserver>();
484 caller->pc()->CreateOffer(observer, options);
485 }
486
487 // Destroy the PeerConnection.
488 caller.reset(nullptr);
489
490 for (auto& observer : observers) {
491 // We expect to have received a notification now even if the PeerConnection
492 // was terminated. The offer creation may or may not have succeeded, but we
493 // must have received a notification.
494 EXPECT_TRUE(observer->called());
495 }
496}
497
Steve Anton8acdd1a2018-02-07 17:27:36 -0800498INSTANTIATE_TEST_CASE_P(PeerConnectionSignalingTest,
499 PeerConnectionSignalingTest,
500 Values(SdpSemantics::kPlanB,
501 SdpSemantics::kUnifiedPlan));
502
Steve Anton8d3444d2017-10-20 15:30:51 -0700503} // namespace webrtc