blob: e79ee3d2e563a45146cb5aea1723085d33ea877f [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
Mirko Bonadei317a1f02019-09-17 17:06:18 +020014#include <memory>
Steve Anton8d3444d2017-10-20 15:30:51 -070015#include <tuple>
16
17#include "api/audio_codecs/builtin_audio_decoder_factory.h"
18#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Mirko Bonadei2ff3f492018-11-22 09:00:13 +010019#include "api/create_peerconnection_factory.h"
Steve Anton10542f22019-01-11 09:11:00 -080020#include "api/peer_connection_proxy.h"
Anders Carlsson67537952018-05-03 11:28:29 +020021#include "api/video_codecs/builtin_video_decoder_factory.h"
22#include "api/video_codecs/builtin_video_encoder_factory.h"
Steve Anton10542f22019-01-11 09:11:00 -080023#include "pc/peer_connection.h"
24#include "pc/peer_connection_wrapper.h"
25#include "pc/sdp_utils.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070026#ifdef WEBRTC_ANDROID
Steve Anton10542f22019-01-11 09:11:00 -080027#include "pc/test/android_test_initializer.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070028#endif
Steve Anton10542f22019-01-11 09:11:00 -080029#include "pc/test/fake_audio_capture_module.h"
30#include "pc/test/fake_rtc_certificate_generator.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070031#include "rtc_base/gunit.h"
Steve Anton10542f22019-01-11 09:11:00 -080032#include "rtc_base/virtual_socket_server.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070033#include "test/gmock.h"
34
35namespace webrtc {
36
37using SignalingState = PeerConnectionInterface::SignalingState;
38using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
39using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
40using ::testing::Bool;
41using ::testing::Combine;
42using ::testing::Values;
43
Henrik Boströma3728d32019-10-28 12:09:49 +010044namespace {
45const int64_t kWaitTimeout = 10000;
46} // namespace
47
Steve Anton8d3444d2017-10-20 15:30:51 -070048class PeerConnectionWrapperForSignalingTest : public PeerConnectionWrapper {
49 public:
50 using PeerConnectionWrapper::PeerConnectionWrapper;
51
52 bool initial_offerer() {
53 return GetInternalPeerConnection()->initial_offerer();
54 }
55
56 PeerConnection* GetInternalPeerConnection() {
Mirko Bonadeie97de912017-12-13 11:29:34 +010057 auto* pci =
58 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
59 pc());
60 return static_cast<PeerConnection*>(pci->internal());
Steve Anton8d3444d2017-10-20 15:30:51 -070061 }
62};
63
Henrik Boströma3728d32019-10-28 12:09:49 +010064class ExecuteFunctionOnCreateSessionDescriptionObserver
65 : public CreateSessionDescriptionObserver {
66 public:
67 ExecuteFunctionOnCreateSessionDescriptionObserver(
68 std::function<void(SessionDescriptionInterface*)> function)
69 : function_(std::move(function)) {}
70 ~ExecuteFunctionOnCreateSessionDescriptionObserver() override {
71 RTC_DCHECK(was_called_);
72 }
73
74 bool was_called() const { return was_called_; }
75
76 void OnSuccess(SessionDescriptionInterface* desc) override {
77 RTC_DCHECK(!was_called_);
78 was_called_ = true;
79 function_(desc);
80 }
81
82 void OnFailure(RTCError error) override { RTC_NOTREACHED(); }
83
84 private:
85 bool was_called_ = false;
86 std::function<void(SessionDescriptionInterface*)> function_;
87};
88
Steve Anton8acdd1a2018-02-07 17:27:36 -080089class PeerConnectionSignalingBaseTest : public ::testing::Test {
Steve Anton8d3444d2017-10-20 15:30:51 -070090 protected:
91 typedef std::unique_ptr<PeerConnectionWrapperForSignalingTest> WrapperPtr;
92
Steve Anton8acdd1a2018-02-07 17:27:36 -080093 explicit PeerConnectionSignalingBaseTest(SdpSemantics sdp_semantics)
94 : vss_(new rtc::VirtualSocketServer()),
95 main_(vss_.get()),
96 sdp_semantics_(sdp_semantics) {
Steve Anton8d3444d2017-10-20 15:30:51 -070097#ifdef WEBRTC_ANDROID
98 InitializeAndroidObjects();
99#endif
100 pc_factory_ = CreatePeerConnectionFactory(
101 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
Anders Carlsson67537952018-05-03 11:28:29 +0200102 rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
103 CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
104 CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
105 nullptr /* audio_mixer */, nullptr /* audio_processing */);
Steve Anton8d3444d2017-10-20 15:30:51 -0700106 }
107
108 WrapperPtr CreatePeerConnection() {
109 return CreatePeerConnection(RTCConfiguration());
110 }
111
112 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200113 auto observer = std::make_unique<MockPeerConnectionObserver>();
Steve Anton8acdd1a2018-02-07 17:27:36 -0800114 RTCConfiguration modified_config = config;
115 modified_config.sdp_semantics = sdp_semantics_;
116 auto pc = pc_factory_->CreatePeerConnection(modified_config, nullptr,
117 nullptr, observer.get());
Steve Anton8d3444d2017-10-20 15:30:51 -0700118 if (!pc) {
119 return nullptr;
120 }
121
Yves Gerey4e933292018-10-31 15:36:05 +0100122 observer->SetPeerConnectionInterface(pc.get());
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200123 return std::make_unique<PeerConnectionWrapperForSignalingTest>(
Steve Anton8d3444d2017-10-20 15:30:51 -0700124 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>
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
Harald Alvestrand4a7b3ac2019-01-17 10:39:40 +0100140 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
158 bool HasDtlsTransport(const WrapperPtr& pc_wrapper) {
159 return NumberOfDtlsTransports(pc_wrapper) > 0;
160 }
161
Steve Anton8d3444d2017-10-20 15:30:51 -0700162 std::unique_ptr<rtc::VirtualSocketServer> vss_;
163 rtc::AutoSocketServerThread main_;
164 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
Steve Anton8acdd1a2018-02-07 17:27:36 -0800165 const SdpSemantics sdp_semantics_;
Steve Anton8d3444d2017-10-20 15:30:51 -0700166};
167
Steve Anton8acdd1a2018-02-07 17:27:36 -0800168class PeerConnectionSignalingTest
169 : public PeerConnectionSignalingBaseTest,
170 public ::testing::WithParamInterface<SdpSemantics> {
171 protected:
172 PeerConnectionSignalingTest() : PeerConnectionSignalingBaseTest(GetParam()) {}
173};
174
175TEST_P(PeerConnectionSignalingTest, SetLocalOfferTwiceWorks) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700176 auto caller = CreatePeerConnection();
177
178 EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
179 EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
180}
181
Steve Anton8acdd1a2018-02-07 17:27:36 -0800182TEST_P(PeerConnectionSignalingTest, SetRemoteOfferTwiceWorks) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700183 auto caller = CreatePeerConnection();
184 auto callee = CreatePeerConnection();
185
186 EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
187 EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
188}
189
Steve Anton8acdd1a2018-02-07 17:27:36 -0800190TEST_P(PeerConnectionSignalingTest, FailToSetNullLocalDescription) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700191 auto caller = CreatePeerConnection();
192 std::string error;
193 ASSERT_FALSE(caller->SetLocalDescription(nullptr, &error));
194 EXPECT_EQ("SessionDescription is NULL.", error);
195}
196
Steve Anton8acdd1a2018-02-07 17:27:36 -0800197TEST_P(PeerConnectionSignalingTest, FailToSetNullRemoteDescription) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700198 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
212class PeerConnectionSignalingStateTest
Steve Anton8acdd1a2018-02-07 17:27:36 -0800213 : public PeerConnectionSignalingBaseTest,
214 public ::testing::WithParamInterface<
215 std::tuple<SdpSemantics, SignalingState, bool>> {
Steve Anton8d3444d2017-10-20 15:30:51 -0700216 protected:
Steve Anton8acdd1a2018-02-07 17:27:36 -0800217 PeerConnectionSignalingStateTest()
218 : PeerConnectionSignalingBaseTest(std::get<0>(GetParam())),
219 state_under_test_(std::make_tuple(std::get<1>(GetParam()),
220 std::get<2>(GetParam()))) {}
221
Steve Anton8d3444d2017-10-20 15:30:51 -0700222 RTCConfiguration GetConfig() {
223 RTCConfiguration config;
224 config.certificates.push_back(
225 FakeRTCCertificateGenerator::GenerateCertificate());
226 return config;
227 }
228
Steve Anton8acdd1a2018-02-07 17:27:36 -0800229 WrapperPtr CreatePeerConnectionUnderTest() {
230 return CreatePeerConnectionInState(state_under_test_);
231 }
232
Steve Anton8d3444d2017-10-20 15:30:51 -0700233 WrapperPtr CreatePeerConnectionInState(SignalingState state) {
234 return CreatePeerConnectionInState(std::make_tuple(state, false));
235 }
236
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();
Steve Antona3a92c22017-12-07 10:27:41 -0800255 wrapper->SetLocalDescription(
256 CloneSessionDescriptionAsType(answer.get(), SdpType::kPrAnswer));
Steve Anton8d3444d2017-10-20 15:30:51 -0700257 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();
Steve Antona3a92c22017-12-07 10:27:41 -0800268 wrapper->SetRemoteDescription(
269 CloneSessionDescriptionAsType(answer.get(), SdpType::kPrAnswer));
Steve Anton8d3444d2017-10-20 15:30:51 -0700270 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 }
Steve Anton8acdd1a2018-02-07 17:27:36 -0800288
289 std::tuple<SignalingState, bool> state_under_test_;
Steve Anton8d3444d2017-10-20 15:30:51 -0700290};
291
Steve Anton8d3444d2017-10-20 15:30:51 -0700292TEST_P(PeerConnectionSignalingStateTest, CreateOffer) {
Steve Anton8acdd1a2018-02-07 17:27:36 -0800293 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700294 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
304TEST_P(PeerConnectionSignalingStateTest, CreateAnswer) {
Steve Anton8acdd1a2018-02-07 17:27:36 -0800305 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700306 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));
Steve Antondffead82018-02-06 10:31:29 -0800312 EXPECT_EQ(error,
313 "PeerConnection cannot create an answer in a state other than "
314 "have-remote-offer or have-local-pranswer.");
Steve Anton8d3444d2017-10-20 15:30:51 -0700315 }
316}
317
318TEST_P(PeerConnectionSignalingStateTest, SetLocalOffer) {
Steve Anton8acdd1a2018-02-07 17:27:36 -0800319 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700320 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
341TEST_P(PeerConnectionSignalingStateTest, SetLocalPrAnswer) {
342 auto wrapper_for_pranswer =
343 CreatePeerConnectionInState(SignalingState::kHaveLocalPrAnswer);
344 auto pranswer =
345 CloneSessionDescription(wrapper_for_pranswer->pc()->local_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::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
360TEST_P(PeerConnectionSignalingStateTest, SetLocalAnswer) {
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::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
378TEST_P(PeerConnectionSignalingStateTest, SetRemoteOffer) {
379 auto wrapper_for_offer =
380 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
381 auto offer =
382 CloneSessionDescription(wrapper_for_offer->pc()->remote_description());
383
Steve Anton8acdd1a2018-02-07 17:27:36 -0800384 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700385 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
397TEST_P(PeerConnectionSignalingStateTest, SetRemotePrAnswer) {
398 auto wrapper_for_pranswer =
399 CreatePeerConnectionInState(SignalingState::kHaveRemotePrAnswer);
400 auto pranswer =
401 CloneSessionDescription(wrapper_for_pranswer->pc()->remote_description());
402
Steve Anton8acdd1a2018-02-07 17:27:36 -0800403 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700404 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
416TEST_P(PeerConnectionSignalingStateTest, SetRemoteAnswer) {
417 auto wrapper_for_answer =
418 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
419 auto answer = wrapper_for_answer->CreateAnswer();
420
Steve Anton8acdd1a2018-02-07 17:27:36 -0800421 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700422 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
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100434INSTANTIATE_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()));
Steve Anton8d3444d2017-10-20 15:30:51 -0700444
Steve Antondffead82018-02-06 10:31:29 -0800445// Test that CreateAnswer fails if a round of offer/answer has been done and
446// the PeerConnection is in the stable state.
Steve Anton8acdd1a2018-02-07 17:27:36 -0800447TEST_P(PeerConnectionSignalingTest, CreateAnswerFailsIfStable) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700448 auto caller = CreatePeerConnection();
449 auto callee = CreatePeerConnection();
450
Steve Antondffead82018-02-06 10:31:29 -0800451 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Oleh Prypinc22d6a82018-02-02 08:42:18 +0000452
453 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
Steve Antondffead82018-02-06 10:31:29 -0800454 EXPECT_FALSE(caller->CreateAnswer());
455
456 ASSERT_EQ(SignalingState::kStable, callee->signaling_state());
457 EXPECT_FALSE(callee->CreateAnswer());
Steve Anton8d3444d2017-10-20 15:30:51 -0700458}
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.
Steve Anton8acdd1a2018-02-07 17:27:36 -0800464TEST_P(PeerConnectionSignalingTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700465 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}
Steve Anton8acdd1a2018-02-07 17:27:36 -0800485TEST_P(PeerConnectionSignalingTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700486 SessionVersionIncrementedInSubsequentDifferentAnswer) {
487 auto caller = CreatePeerConnection();
488 auto callee = CreatePeerConnection();
489
490 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
491
Steve Antondffead82018-02-06 10:31:29 -0800492 auto original_answer = callee->CreateAnswer();
Steve Anton8d3444d2017-10-20 15:30:51 -0700493 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
Steve Anton8acdd1a2018-02-07 17:27:36 -0800506TEST_P(PeerConnectionSignalingTest, InitiatorFlagSetOnCallerAndNotOnCallee) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700507 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
Steve Anton8acdd1a2018-02-07 17:27:36 -0800529TEST_P(PeerConnectionSignalingTest, CreateOffersAndShutdown) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700530 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
Henrik Boströma3728d32019-10-28 12:09:49 +0100554// 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.
558TEST_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
568TEST_P(PeerConnectionSignalingTest, SetRemoteDescriptionExecutesImmediately) {
569 auto caller = CreatePeerConnectionWithAudioVideo();
570 auto callee = CreatePeerConnection();
571
572 // This offer will cause receivers to be created.
573 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
574
575 // By not waiting for the observer's callback we can verify that the operation
576 // executed immediately.
577 callee->pc()->SetRemoteDescription(std::move(offer),
578 new MockSetRemoteDescriptionObserver());
579 EXPECT_EQ(2u, callee->pc()->GetReceivers().size());
580}
581
582TEST_P(PeerConnectionSignalingTest, CreateOfferBlocksSetRemoteDescription) {
583 auto caller = CreatePeerConnectionWithAudioVideo();
584 auto callee = CreatePeerConnection();
585
586 // This offer will cause receivers to be created.
587 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
588
589 EXPECT_EQ(0u, callee->pc()->GetReceivers().size());
590 rtc::scoped_refptr<MockCreateSessionDescriptionObserver> offer_observer(
591 new rtc::RefCountedObject<MockCreateSessionDescriptionObserver>());
592 // Synchronously invoke CreateOffer() and SetRemoteDescription(). The
593 // SetRemoteDescription() operation should be chained to be executed
594 // asynchronously, when CreateOffer() completes.
595 callee->pc()->CreateOffer(offer_observer, RTCOfferAnswerOptions());
596 callee->pc()->SetRemoteDescription(std::move(offer),
597 new MockSetRemoteDescriptionObserver());
598 // CreateOffer() is asynchronous; without message processing this operation
599 // should not have completed.
600 EXPECT_FALSE(offer_observer->called());
601 // Due to chaining, the receivers should not have been created by the offer
602 // yet.
603 EXPECT_EQ(0u, callee->pc()->GetReceivers().size());
604 // EXPECT_TRUE_WAIT causes messages to be processed...
605 EXPECT_TRUE_WAIT(offer_observer->called(), kWaitTimeout);
606 // Now that the offer has been completed, SetRemoteDescription() will have
607 // been executed next in the chain.
608 EXPECT_EQ(2u, callee->pc()->GetReceivers().size());
609}
610
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100611INSTANTIATE_TEST_SUITE_P(PeerConnectionSignalingTest,
612 PeerConnectionSignalingTest,
613 Values(SdpSemantics::kPlanB,
614 SdpSemantics::kUnifiedPlan));
Steve Anton8acdd1a2018-02-07 17:27:36 -0800615
Harald Alvestrand4a7b3ac2019-01-17 10:39:40 +0100616class PeerConnectionSignalingUnifiedPlanTest
617 : public PeerConnectionSignalingBaseTest {
618 protected:
619 PeerConnectionSignalingUnifiedPlanTest()
620 : PeerConnectionSignalingBaseTest(SdpSemantics::kUnifiedPlan) {}
621};
622
Henrik Boströma3728d32019-10-28 12:09:49 +0100623// We verify that SetLocalDescription() executed immediately by verifying that
624// the transceiver mid values got assigned. SLD executing immeditately is not
625// unique to Unified Plan, but the transceivers used to verify this are only
626// available in Unified Plan.
627TEST_F(PeerConnectionSignalingUnifiedPlanTest,
628 SetLocalDescriptionExecutesImmediately) {
629 auto caller = CreatePeerConnectionWithAudioVideo();
630
631 // This offer will cause transceiver mids to get assigned.
632 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
633
634 // By not waiting for the observer's callback we can verify that the operation
635 // executed immediately.
636 RTC_DCHECK(!caller->pc()->GetTransceivers()[0]->mid().has_value());
637 caller->pc()->SetLocalDescription(
638 new rtc::RefCountedObject<MockSetSessionDescriptionObserver>(),
639 offer.release());
640 EXPECT_TRUE(caller->pc()->GetTransceivers()[0]->mid().has_value());
641}
642
643TEST_F(PeerConnectionSignalingUnifiedPlanTest,
644 SetLocalDescriptionExecutesImmediatelyInsideCreateOfferCallback) {
645 auto caller = CreatePeerConnectionWithAudioVideo();
646
647 // This offer will cause transceiver mids to get assigned.
648 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
649
650 rtc::scoped_refptr<ExecuteFunctionOnCreateSessionDescriptionObserver>
651 offer_observer(new rtc::RefCountedObject<
652 ExecuteFunctionOnCreateSessionDescriptionObserver>(
653 [pc = caller->pc()](SessionDescriptionInterface* desc) {
654 // By not waiting for the observer's callback we can verify that the
655 // operation executed immediately.
656 RTC_DCHECK(!pc->GetTransceivers()[0]->mid().has_value());
657 pc->SetLocalDescription(
658 new rtc::RefCountedObject<MockSetSessionDescriptionObserver>(),
659 desc);
660 EXPECT_TRUE(pc->GetTransceivers()[0]->mid().has_value());
661 }));
662 caller->pc()->CreateOffer(offer_observer, RTCOfferAnswerOptions());
663 EXPECT_TRUE_WAIT(offer_observer->was_called(), kWaitTimeout);
664}
665
Harald Alvestrand4a7b3ac2019-01-17 10:39:40 +0100666// Test that transports are shown in the sender/receiver API after offer/answer.
667// This only works in Unified Plan.
668TEST_F(PeerConnectionSignalingUnifiedPlanTest,
669 DtlsTransportsInstantiateInOfferAnswer) {
670 auto caller = CreatePeerConnectionWithAudioVideo();
671 auto callee = CreatePeerConnection();
672
673 EXPECT_FALSE(HasDtlsTransport(caller));
674 EXPECT_FALSE(HasDtlsTransport(callee));
675 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
676 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
677 EXPECT_TRUE(HasDtlsTransport(caller));
678 callee->SetRemoteDescription(std::move(offer));
679 EXPECT_FALSE(HasDtlsTransport(callee));
680 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
681 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
682 EXPECT_TRUE(HasDtlsTransport(callee));
683 caller->SetRemoteDescription(std::move(answer));
684 EXPECT_TRUE(HasDtlsTransport(caller));
685
686 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
687}
688
689TEST_F(PeerConnectionSignalingUnifiedPlanTest, DtlsTransportsMergeWhenBundled) {
690 auto caller = CreatePeerConnectionWithAudioVideo();
691 auto callee = CreatePeerConnection();
692
693 EXPECT_FALSE(HasDtlsTransport(caller));
694 EXPECT_FALSE(HasDtlsTransport(callee));
695 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
696 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
697 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
698 callee->SetRemoteDescription(std::move(offer));
699 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
700 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
701 caller->SetRemoteDescription(std::move(answer));
702 EXPECT_EQ(1, NumberOfDtlsTransports(caller));
703
704 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
705}
706
707TEST_F(PeerConnectionSignalingUnifiedPlanTest,
708 DtlsTransportsAreSeparateeWhenUnbundled) {
709 auto caller = CreatePeerConnectionWithAudioVideo();
710 auto callee = CreatePeerConnection();
711
712 EXPECT_FALSE(HasDtlsTransport(caller));
713 EXPECT_FALSE(HasDtlsTransport(callee));
714 RTCOfferAnswerOptions unbundle_options;
715 unbundle_options.use_rtp_mux = false;
716 auto offer = caller->CreateOffer(unbundle_options);
717 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
718 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
719 callee->SetRemoteDescription(std::move(offer));
720 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
721 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
722 EXPECT_EQ(2, NumberOfDtlsTransports(callee));
723 caller->SetRemoteDescription(std::move(answer));
724 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
725
726 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
727}
728
Steve Anton8d3444d2017-10-20 15:30:51 -0700729} // namespace webrtc