blob: 54c49af1a89f3214487a63466992b8402ce6903b [file] [log] [blame]
Steve Anton8d3444d2017-10-20 15:30:51 -07001/*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11// This file contains tests that check the PeerConnection's signaling state
12// machine, as well as tests that check basic, media-agnostic aspects of SDP.
13
Philipp Hancke64a79c72021-05-10 17:28:37 +020014#include <algorithm>
Harald Alvestrandc24a2182022-02-23 13:44:59 +000015#include <cstdint>
16#include <functional>
17#include <map>
Mirko Bonadei317a1f02019-09-17 17:06:18 +020018#include <memory>
Harald Alvestrandc24a2182022-02-23 13:44:59 +000019#include <set>
20#include <string>
Steve Anton8d3444d2017-10-20 15:30:51 -070021#include <tuple>
Harald Alvestrandc24a2182022-02-23 13:44:59 +000022#include <type_traits>
23#include <utility>
24#include <vector>
Steve Anton8d3444d2017-10-20 15:30:51 -070025
Harald Alvestrandc24a2182022-02-23 13:44:59 +000026#include "absl/types/optional.h"
27#include "api/audio/audio_mixer.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070028#include "api/audio_codecs/builtin_audio_decoder_factory.h"
29#include "api/audio_codecs/builtin_audio_encoder_factory.h"
Mirko Bonadei2ff3f492018-11-22 09:00:13 +010030#include "api/create_peerconnection_factory.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000031#include "api/dtls_transport_interface.h"
32#include "api/jsep.h"
33#include "api/media_types.h"
34#include "api/peer_connection_interface.h"
35#include "api/rtc_error.h"
36#include "api/rtp_receiver_interface.h"
37#include "api/rtp_sender_interface.h"
38#include "api/rtp_transceiver_interface.h"
39#include "api/scoped_refptr.h"
40#include "api/set_local_description_observer_interface.h"
41#include "api/set_remote_description_observer_interface.h"
Anders Carlsson67537952018-05-03 11:28:29 +020042#include "api/video_codecs/builtin_video_decoder_factory.h"
43#include "api/video_codecs/builtin_video_encoder_factory.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000044#include "media/base/codec.h"
45#include "modules/audio_device/include/audio_device.h"
46#include "modules/audio_processing/include/audio_processing.h"
47#include "p2p/base/port_allocator.h"
Steve Anton10542f22019-01-11 09:11:00 -080048#include "pc/peer_connection.h"
Markus Handella1b82012021-05-26 18:56:30 +020049#include "pc/peer_connection_proxy.h"
Steve Anton10542f22019-01-11 09:11:00 -080050#include "pc/peer_connection_wrapper.h"
51#include "pc/sdp_utils.h"
Harald Alvestrandc24a2182022-02-23 13:44:59 +000052#include "pc/session_description.h"
53#include "pc/test/mock_peer_connection_observers.h"
54#include "rtc_base/checks.h"
55#include "rtc_base/ref_counted_object.h"
56#include "rtc_base/rtc_certificate.h"
57#include "rtc_base/rtc_certificate_generator.h"
58#include "rtc_base/string_encode.h"
59#include "rtc_base/thread.h"
60#include "test/gtest.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070061#ifdef WEBRTC_ANDROID
Steve Anton10542f22019-01-11 09:11:00 -080062#include "pc/test/android_test_initializer.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070063#endif
Steve Anton10542f22019-01-11 09:11:00 -080064#include "pc/test/fake_audio_capture_module.h"
65#include "pc/test/fake_rtc_certificate_generator.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070066#include "rtc_base/gunit.h"
Steve Anton10542f22019-01-11 09:11:00 -080067#include "rtc_base/virtual_socket_server.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070068
69namespace webrtc {
70
71using SignalingState = PeerConnectionInterface::SignalingState;
72using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
73using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
74using ::testing::Bool;
75using ::testing::Combine;
76using ::testing::Values;
77
Henrik Boströma3728d32019-10-28 12:09:49 +010078namespace {
79const int64_t kWaitTimeout = 10000;
80} // namespace
81
Steve Anton8d3444d2017-10-20 15:30:51 -070082class PeerConnectionWrapperForSignalingTest : public PeerConnectionWrapper {
83 public:
84 using PeerConnectionWrapper::PeerConnectionWrapper;
85
86 bool initial_offerer() {
87 return GetInternalPeerConnection()->initial_offerer();
88 }
89
90 PeerConnection* GetInternalPeerConnection() {
Mirko Bonadeie97de912017-12-13 11:29:34 +010091 auto* pci =
92 static_cast<PeerConnectionProxyWithInternal<PeerConnectionInterface>*>(
93 pc());
94 return static_cast<PeerConnection*>(pci->internal());
Steve Anton8d3444d2017-10-20 15:30:51 -070095 }
96};
97
Henrik Boströma3728d32019-10-28 12:09:49 +010098class ExecuteFunctionOnCreateSessionDescriptionObserver
99 : public CreateSessionDescriptionObserver {
100 public:
101 ExecuteFunctionOnCreateSessionDescriptionObserver(
102 std::function<void(SessionDescriptionInterface*)> function)
103 : function_(std::move(function)) {}
104 ~ExecuteFunctionOnCreateSessionDescriptionObserver() override {
105 RTC_DCHECK(was_called_);
106 }
107
108 bool was_called() const { return was_called_; }
109
110 void OnSuccess(SessionDescriptionInterface* desc) override {
111 RTC_DCHECK(!was_called_);
112 was_called_ = true;
113 function_(desc);
114 }
115
Artem Titovd3251962021-11-15 16:57:07 +0100116 void OnFailure(RTCError error) override { RTC_DCHECK_NOTREACHED(); }
Henrik Boströma3728d32019-10-28 12:09:49 +0100117
118 private:
119 bool was_called_ = false;
120 std::function<void(SessionDescriptionInterface*)> function_;
121};
122
Steve Anton8acdd1a2018-02-07 17:27:36 -0800123class PeerConnectionSignalingBaseTest : public ::testing::Test {
Steve Anton8d3444d2017-10-20 15:30:51 -0700124 protected:
125 typedef std::unique_ptr<PeerConnectionWrapperForSignalingTest> WrapperPtr;
126
Steve Anton8acdd1a2018-02-07 17:27:36 -0800127 explicit PeerConnectionSignalingBaseTest(SdpSemantics sdp_semantics)
128 : vss_(new rtc::VirtualSocketServer()),
129 main_(vss_.get()),
130 sdp_semantics_(sdp_semantics) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700131#ifdef WEBRTC_ANDROID
132 InitializeAndroidObjects();
133#endif
134 pc_factory_ = CreatePeerConnectionFactory(
135 rtc::Thread::Current(), rtc::Thread::Current(), rtc::Thread::Current(),
Anders Carlsson67537952018-05-03 11:28:29 +0200136 rtc::scoped_refptr<AudioDeviceModule>(FakeAudioCaptureModule::Create()),
137 CreateBuiltinAudioEncoderFactory(), CreateBuiltinAudioDecoderFactory(),
138 CreateBuiltinVideoEncoderFactory(), CreateBuiltinVideoDecoderFactory(),
139 nullptr /* audio_mixer */, nullptr /* audio_processing */);
Steve Anton8d3444d2017-10-20 15:30:51 -0700140 }
141
142 WrapperPtr CreatePeerConnection() {
143 return CreatePeerConnection(RTCConfiguration());
144 }
145
146 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200147 auto observer = std::make_unique<MockPeerConnectionObserver>();
Steve Anton8acdd1a2018-02-07 17:27:36 -0800148 RTCConfiguration modified_config = config;
149 modified_config.sdp_semantics = sdp_semantics_;
Florent Castelli72424402022-04-06 03:45:10 +0200150 auto result = pc_factory_->CreatePeerConnectionOrError(
151 modified_config, PeerConnectionDependencies(observer.get()));
152 if (!result.ok()) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700153 return nullptr;
154 }
155
Niels Möllerafb246b2022-04-20 14:26:50 +0200156 observer->SetPeerConnectionInterface(result.value().get());
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200157 return std::make_unique<PeerConnectionWrapperForSignalingTest>(
Florent Castelli72424402022-04-06 03:45:10 +0200158 pc_factory_, result.MoveValue(), std::move(observer));
Steve Anton8d3444d2017-10-20 15:30:51 -0700159 }
160
161 // Accepts the same arguments as CreatePeerConnection and adds default audio
162 // and video tracks.
163 template <typename... Args>
164 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
165 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
166 if (!wrapper) {
167 return nullptr;
168 }
169 wrapper->AddAudioTrack("a");
170 wrapper->AddVideoTrack("v");
171 return wrapper;
172 }
173
Harald Alvestrand4a7b3ac2019-01-17 10:39:40 +0100174 int NumberOfDtlsTransports(const WrapperPtr& pc_wrapper) {
175 std::set<DtlsTransportInterface*> transports;
176 auto transceivers = pc_wrapper->pc()->GetTransceivers();
177
178 for (auto& transceiver : transceivers) {
179 if (transceiver->sender()->dtls_transport()) {
180 EXPECT_TRUE(transceiver->receiver()->dtls_transport());
181 EXPECT_EQ(transceiver->sender()->dtls_transport().get(),
182 transceiver->receiver()->dtls_transport().get());
183 transports.insert(transceiver->sender()->dtls_transport().get());
184 } else {
185 // If one transceiver is missing, they all should be.
186 EXPECT_EQ(0UL, transports.size());
187 }
188 }
189 return transports.size();
190 }
191
192 bool HasDtlsTransport(const WrapperPtr& pc_wrapper) {
193 return NumberOfDtlsTransports(pc_wrapper) > 0;
194 }
195
Steve Anton8d3444d2017-10-20 15:30:51 -0700196 std::unique_ptr<rtc::VirtualSocketServer> vss_;
197 rtc::AutoSocketServerThread main_;
198 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
Steve Anton8acdd1a2018-02-07 17:27:36 -0800199 const SdpSemantics sdp_semantics_;
Steve Anton8d3444d2017-10-20 15:30:51 -0700200};
201
Steve Anton8acdd1a2018-02-07 17:27:36 -0800202class PeerConnectionSignalingTest
203 : public PeerConnectionSignalingBaseTest,
204 public ::testing::WithParamInterface<SdpSemantics> {
205 protected:
206 PeerConnectionSignalingTest() : PeerConnectionSignalingBaseTest(GetParam()) {}
207};
208
209TEST_P(PeerConnectionSignalingTest, SetLocalOfferTwiceWorks) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700210 auto caller = CreatePeerConnection();
211
212 EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
213 EXPECT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
214}
215
Steve Anton8acdd1a2018-02-07 17:27:36 -0800216TEST_P(PeerConnectionSignalingTest, SetRemoteOfferTwiceWorks) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700217 auto caller = CreatePeerConnection();
218 auto callee = CreatePeerConnection();
219
220 EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
221 EXPECT_TRUE(callee->SetRemoteDescription(caller->CreateOffer()));
222}
223
Steve Anton8acdd1a2018-02-07 17:27:36 -0800224TEST_P(PeerConnectionSignalingTest, FailToSetNullLocalDescription) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700225 auto caller = CreatePeerConnection();
226 std::string error;
227 ASSERT_FALSE(caller->SetLocalDescription(nullptr, &error));
228 EXPECT_EQ("SessionDescription is NULL.", error);
229}
230
Steve Anton8acdd1a2018-02-07 17:27:36 -0800231TEST_P(PeerConnectionSignalingTest, FailToSetNullRemoteDescription) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700232 auto caller = CreatePeerConnection();
233 std::string error;
234 ASSERT_FALSE(caller->SetRemoteDescription(nullptr, &error));
235 EXPECT_EQ("SessionDescription is NULL.", error);
236}
237
238// The following parameterized test verifies that calls to various signaling
239// methods on PeerConnection will succeed/fail depending on what is the
240// PeerConnection's signaling state. Note that the test tries many different
241// forms of SignalingState::kClosed by arriving at a valid state then calling
Artem Titov880fa812021-07-30 22:30:23 +0200242// `Close()`. This is intended to catch cases where the PeerConnection signaling
Steve Anton8d3444d2017-10-20 15:30:51 -0700243// method ignores the closed flag but may work/not work because of the single
244// state the PeerConnection was created in before it was closed.
245
246class PeerConnectionSignalingStateTest
Steve Anton8acdd1a2018-02-07 17:27:36 -0800247 : public PeerConnectionSignalingBaseTest,
248 public ::testing::WithParamInterface<
249 std::tuple<SdpSemantics, SignalingState, bool>> {
Steve Anton8d3444d2017-10-20 15:30:51 -0700250 protected:
Steve Anton8acdd1a2018-02-07 17:27:36 -0800251 PeerConnectionSignalingStateTest()
252 : PeerConnectionSignalingBaseTest(std::get<0>(GetParam())),
253 state_under_test_(std::make_tuple(std::get<1>(GetParam()),
254 std::get<2>(GetParam()))) {}
255
Steve Anton8d3444d2017-10-20 15:30:51 -0700256 RTCConfiguration GetConfig() {
257 RTCConfiguration config;
258 config.certificates.push_back(
259 FakeRTCCertificateGenerator::GenerateCertificate());
260 return config;
261 }
262
Steve Anton8acdd1a2018-02-07 17:27:36 -0800263 WrapperPtr CreatePeerConnectionUnderTest() {
264 return CreatePeerConnectionInState(state_under_test_);
265 }
266
Steve Anton8d3444d2017-10-20 15:30:51 -0700267 WrapperPtr CreatePeerConnectionInState(SignalingState state) {
268 return CreatePeerConnectionInState(std::make_tuple(state, false));
269 }
270
271 WrapperPtr CreatePeerConnectionInState(
272 std::tuple<SignalingState, bool> state_tuple) {
273 SignalingState state = std::get<0>(state_tuple);
274 bool closed = std::get<1>(state_tuple);
275
276 auto wrapper = CreatePeerConnectionWithAudioVideo(GetConfig());
277 switch (state) {
278 case SignalingState::kStable: {
279 break;
280 }
281 case SignalingState::kHaveLocalOffer: {
282 wrapper->SetLocalDescription(wrapper->CreateOffer());
283 break;
284 }
285 case SignalingState::kHaveLocalPrAnswer: {
286 auto caller = CreatePeerConnectionWithAudioVideo(GetConfig());
287 wrapper->SetRemoteDescription(caller->CreateOffer());
288 auto answer = wrapper->CreateAnswer();
Steve Antona3a92c22017-12-07 10:27:41 -0800289 wrapper->SetLocalDescription(
290 CloneSessionDescriptionAsType(answer.get(), SdpType::kPrAnswer));
Steve Anton8d3444d2017-10-20 15:30:51 -0700291 break;
292 }
293 case SignalingState::kHaveRemoteOffer: {
294 auto caller = CreatePeerConnectionWithAudioVideo(GetConfig());
295 wrapper->SetRemoteDescription(caller->CreateOffer());
296 break;
297 }
298 case SignalingState::kHaveRemotePrAnswer: {
299 auto callee = CreatePeerConnectionWithAudioVideo(GetConfig());
300 callee->SetRemoteDescription(wrapper->CreateOfferAndSetAsLocal());
301 auto answer = callee->CreateAnswer();
Steve Antona3a92c22017-12-07 10:27:41 -0800302 wrapper->SetRemoteDescription(
303 CloneSessionDescriptionAsType(answer.get(), SdpType::kPrAnswer));
Steve Anton8d3444d2017-10-20 15:30:51 -0700304 break;
305 }
306 case SignalingState::kClosed: {
Artem Titovd3251962021-11-15 16:57:07 +0100307 RTC_DCHECK_NOTREACHED()
308 << "Set the second member of the tuple to true to "
309 "achieve a closed state from an existing, valid "
310 "state.";
Steve Anton8d3444d2017-10-20 15:30:51 -0700311 }
312 }
313
314 RTC_DCHECK_EQ(state, wrapper->pc()->signaling_state());
315
316 if (closed) {
317 wrapper->pc()->Close();
318 RTC_DCHECK_EQ(SignalingState::kClosed, wrapper->signaling_state());
319 }
320
321 return wrapper;
322 }
Steve Anton8acdd1a2018-02-07 17:27:36 -0800323
324 std::tuple<SignalingState, bool> state_under_test_;
Steve Anton8d3444d2017-10-20 15:30:51 -0700325};
326
Steve Anton8d3444d2017-10-20 15:30:51 -0700327TEST_P(PeerConnectionSignalingStateTest, CreateOffer) {
Steve Anton8acdd1a2018-02-07 17:27:36 -0800328 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700329 if (wrapper->signaling_state() != SignalingState::kClosed) {
330 EXPECT_TRUE(wrapper->CreateOffer());
331 } else {
332 std::string error;
333 ASSERT_FALSE(wrapper->CreateOffer(RTCOfferAnswerOptions(), &error));
334 EXPECT_PRED_FORMAT2(AssertStartsWith, error,
335 "CreateOffer called when PeerConnection is closed.");
336 }
337}
338
339TEST_P(PeerConnectionSignalingStateTest, CreateAnswer) {
Steve Anton8acdd1a2018-02-07 17:27:36 -0800340 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700341 if (wrapper->signaling_state() == SignalingState::kHaveLocalPrAnswer ||
342 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
343 EXPECT_TRUE(wrapper->CreateAnswer());
344 } else {
345 std::string error;
346 ASSERT_FALSE(wrapper->CreateAnswer(RTCOfferAnswerOptions(), &error));
Steve Antondffead82018-02-06 10:31:29 -0800347 EXPECT_EQ(error,
348 "PeerConnection cannot create an answer in a state other than "
349 "have-remote-offer or have-local-pranswer.");
Steve Anton8d3444d2017-10-20 15:30:51 -0700350 }
351}
352
353TEST_P(PeerConnectionSignalingStateTest, SetLocalOffer) {
Steve Anton8acdd1a2018-02-07 17:27:36 -0800354 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700355 if (wrapper->signaling_state() == SignalingState::kStable ||
356 wrapper->signaling_state() == SignalingState::kHaveLocalOffer) {
357 // Need to call CreateOffer on the PeerConnection under test, otherwise when
358 // setting the local offer it will want to verify the DTLS fingerprint
359 // against the locally generated certificate, but without a call to
360 // CreateOffer the certificate will never be generated.
361 EXPECT_TRUE(wrapper->SetLocalDescription(wrapper->CreateOffer()));
362 } else {
363 auto wrapper_for_offer =
364 CreatePeerConnectionInState(SignalingState::kHaveLocalOffer);
365 auto offer =
366 CloneSessionDescription(wrapper_for_offer->pc()->local_description());
367
368 std::string error;
369 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(offer), &error));
370 EXPECT_PRED_FORMAT2(
371 AssertStartsWith, error,
372 "Failed to set local offer sdp: Called in wrong state:");
373 }
374}
375
376TEST_P(PeerConnectionSignalingStateTest, SetLocalPrAnswer) {
377 auto wrapper_for_pranswer =
378 CreatePeerConnectionInState(SignalingState::kHaveLocalPrAnswer);
379 auto pranswer =
380 CloneSessionDescription(wrapper_for_pranswer->pc()->local_description());
381
Steve Anton8acdd1a2018-02-07 17:27:36 -0800382 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700383 if (wrapper->signaling_state() == SignalingState::kHaveLocalPrAnswer ||
384 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
385 EXPECT_TRUE(wrapper->SetLocalDescription(std::move(pranswer)));
386 } else {
387 std::string error;
388 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(pranswer), &error));
389 EXPECT_PRED_FORMAT2(
390 AssertStartsWith, error,
391 "Failed to set local pranswer sdp: Called in wrong state:");
392 }
393}
394
395TEST_P(PeerConnectionSignalingStateTest, SetLocalAnswer) {
396 auto wrapper_for_answer =
397 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
398 auto answer = wrapper_for_answer->CreateAnswer();
399
Steve Anton8acdd1a2018-02-07 17:27:36 -0800400 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700401 if (wrapper->signaling_state() == SignalingState::kHaveLocalPrAnswer ||
402 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
403 EXPECT_TRUE(wrapper->SetLocalDescription(std::move(answer)));
404 } else {
405 std::string error;
406 ASSERT_FALSE(wrapper->SetLocalDescription(std::move(answer), &error));
407 EXPECT_PRED_FORMAT2(
408 AssertStartsWith, error,
409 "Failed to set local answer sdp: Called in wrong state:");
410 }
411}
412
413TEST_P(PeerConnectionSignalingStateTest, SetRemoteOffer) {
414 auto wrapper_for_offer =
415 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
416 auto offer =
417 CloneSessionDescription(wrapper_for_offer->pc()->remote_description());
418
Steve Anton8acdd1a2018-02-07 17:27:36 -0800419 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700420 if (wrapper->signaling_state() == SignalingState::kStable ||
421 wrapper->signaling_state() == SignalingState::kHaveRemoteOffer) {
422 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(offer)));
423 } else {
424 std::string error;
425 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(offer), &error));
426 EXPECT_PRED_FORMAT2(
427 AssertStartsWith, error,
428 "Failed to set remote offer sdp: Called in wrong state:");
429 }
430}
431
432TEST_P(PeerConnectionSignalingStateTest, SetRemotePrAnswer) {
433 auto wrapper_for_pranswer =
434 CreatePeerConnectionInState(SignalingState::kHaveRemotePrAnswer);
435 auto pranswer =
436 CloneSessionDescription(wrapper_for_pranswer->pc()->remote_description());
437
Steve Anton8acdd1a2018-02-07 17:27:36 -0800438 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700439 if (wrapper->signaling_state() == SignalingState::kHaveLocalOffer ||
440 wrapper->signaling_state() == SignalingState::kHaveRemotePrAnswer) {
441 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(pranswer)));
442 } else {
443 std::string error;
444 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(pranswer), &error));
445 EXPECT_PRED_FORMAT2(
446 AssertStartsWith, error,
447 "Failed to set remote pranswer sdp: Called in wrong state:");
448 }
449}
450
451TEST_P(PeerConnectionSignalingStateTest, SetRemoteAnswer) {
452 auto wrapper_for_answer =
453 CreatePeerConnectionInState(SignalingState::kHaveRemoteOffer);
454 auto answer = wrapper_for_answer->CreateAnswer();
455
Steve Anton8acdd1a2018-02-07 17:27:36 -0800456 auto wrapper = CreatePeerConnectionUnderTest();
Steve Anton8d3444d2017-10-20 15:30:51 -0700457 if (wrapper->signaling_state() == SignalingState::kHaveLocalOffer ||
458 wrapper->signaling_state() == SignalingState::kHaveRemotePrAnswer) {
459 EXPECT_TRUE(wrapper->SetRemoteDescription(std::move(answer)));
460 } else {
461 std::string error;
462 ASSERT_FALSE(wrapper->SetRemoteDescription(std::move(answer), &error));
463 EXPECT_PRED_FORMAT2(
464 AssertStartsWith, error,
465 "Failed to set remote answer sdp: Called in wrong state:");
466 }
467}
468
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100469INSTANTIATE_TEST_SUITE_P(PeerConnectionSignalingTest,
470 PeerConnectionSignalingStateTest,
Florent Castelli15a38de2022-04-06 00:38:21 +0200471 Combine(Values(SdpSemantics::kPlanB_DEPRECATED,
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100472 SdpSemantics::kUnifiedPlan),
473 Values(SignalingState::kStable,
474 SignalingState::kHaveLocalOffer,
475 SignalingState::kHaveLocalPrAnswer,
476 SignalingState::kHaveRemoteOffer,
477 SignalingState::kHaveRemotePrAnswer),
478 Bool()));
Steve Anton8d3444d2017-10-20 15:30:51 -0700479
Steve Antondffead82018-02-06 10:31:29 -0800480// Test that CreateAnswer fails if a round of offer/answer has been done and
481// the PeerConnection is in the stable state.
Steve Anton8acdd1a2018-02-07 17:27:36 -0800482TEST_P(PeerConnectionSignalingTest, CreateAnswerFailsIfStable) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700483 auto caller = CreatePeerConnection();
484 auto callee = CreatePeerConnection();
485
Steve Antondffead82018-02-06 10:31:29 -0800486 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Oleh Prypinc22d6a82018-02-02 08:42:18 +0000487
488 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
Steve Antondffead82018-02-06 10:31:29 -0800489 EXPECT_FALSE(caller->CreateAnswer());
490
491 ASSERT_EQ(SignalingState::kStable, callee->signaling_state());
492 EXPECT_FALSE(callee->CreateAnswer());
Steve Anton8d3444d2017-10-20 15:30:51 -0700493}
494
495// According to https://tools.ietf.org/html/rfc3264#section-8, the session id
496// stays the same but the version must be incremented if a later, different
497// session description is generated. These two tests verify that is the case for
498// both offers and answers.
Steve Anton8acdd1a2018-02-07 17:27:36 -0800499TEST_P(PeerConnectionSignalingTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700500 SessionVersionIncrementedInSubsequentDifferentOffer) {
501 auto caller = CreatePeerConnection();
502 auto callee = CreatePeerConnection();
503
504 auto original_offer = caller->CreateOfferAndSetAsLocal();
505 const std::string original_id = original_offer->session_id();
506 const std::string original_version = original_offer->session_version();
507
508 ASSERT_TRUE(callee->SetRemoteDescription(std::move(original_offer)));
509 ASSERT_TRUE(caller->SetRemoteDescription(callee->CreateAnswer()));
510
511 // Add track to get a different offer.
512 caller->AddAudioTrack("a");
513
514 auto later_offer = caller->CreateOffer();
515
516 EXPECT_EQ(original_id, later_offer->session_id());
517 EXPECT_LT(rtc::FromString<uint64_t>(original_version),
518 rtc::FromString<uint64_t>(later_offer->session_version()));
519}
Steve Anton8acdd1a2018-02-07 17:27:36 -0800520TEST_P(PeerConnectionSignalingTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700521 SessionVersionIncrementedInSubsequentDifferentAnswer) {
522 auto caller = CreatePeerConnection();
523 auto callee = CreatePeerConnection();
524
525 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
526
Steve Antondffead82018-02-06 10:31:29 -0800527 auto original_answer = callee->CreateAnswer();
Steve Anton8d3444d2017-10-20 15:30:51 -0700528 const std::string original_id = original_answer->session_id();
529 const std::string original_version = original_answer->session_version();
530
531 // Add track to get a different answer.
532 callee->AddAudioTrack("a");
533
534 auto later_answer = callee->CreateAnswer();
535
536 EXPECT_EQ(original_id, later_answer->session_id());
537 EXPECT_LT(rtc::FromString<uint64_t>(original_version),
538 rtc::FromString<uint64_t>(later_answer->session_version()));
539}
540
Steve Anton8acdd1a2018-02-07 17:27:36 -0800541TEST_P(PeerConnectionSignalingTest, InitiatorFlagSetOnCallerAndNotOnCallee) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700542 auto caller = CreatePeerConnectionWithAudioVideo();
543 auto callee = CreatePeerConnectionWithAudioVideo();
544
545 EXPECT_FALSE(caller->initial_offerer());
546 EXPECT_FALSE(callee->initial_offerer());
547
548 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
549
550 EXPECT_TRUE(caller->initial_offerer());
551 EXPECT_FALSE(callee->initial_offerer());
552
553 ASSERT_TRUE(
554 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
555
556 EXPECT_TRUE(caller->initial_offerer());
557 EXPECT_FALSE(callee->initial_offerer());
558}
559
560// Test creating a PeerConnection, request multiple offers, destroy the
561// PeerConnection and make sure we get success/failure callbacks for all of the
562// requests.
563// Background: crbug.com/507307
Steve Anton8acdd1a2018-02-07 17:27:36 -0800564TEST_P(PeerConnectionSignalingTest, CreateOffersAndShutdown) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700565 auto caller = CreatePeerConnection();
566
567 RTCOfferAnswerOptions options;
568 options.offer_to_receive_audio =
569 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
570
571 rtc::scoped_refptr<MockCreateSessionDescriptionObserver> observers[100];
572 for (auto& observer : observers) {
Tommi87f70902021-04-27 14:43:08 +0200573 observer = rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
Niels Möllerafb246b2022-04-20 14:26:50 +0200574 caller->pc()->CreateOffer(observer.get(), options);
Steve Anton8d3444d2017-10-20 15:30:51 -0700575 }
576
577 // Destroy the PeerConnection.
578 caller.reset(nullptr);
579
580 for (auto& observer : observers) {
581 // We expect to have received a notification now even if the PeerConnection
582 // was terminated. The offer creation may or may not have succeeded, but we
583 // must have received a notification.
584 EXPECT_TRUE(observer->called());
585 }
586}
587
Henrik Boströma3728d32019-10-28 12:09:49 +0100588// Similar to the above test, but by closing the PC first the CreateOffer() will
589// fail "early", which triggers a codepath where the PeerConnection is
590// reponsible for invoking the observer, instead of the normal codepath where
591// the WebRtcSessionDescriptionFactory is responsible for it.
592TEST_P(PeerConnectionSignalingTest, CloseCreateOfferAndShutdown) {
593 auto caller = CreatePeerConnection();
Tommi87f70902021-04-27 14:43:08 +0200594 auto observer = rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
Henrik Boströma3728d32019-10-28 12:09:49 +0100595 caller->pc()->Close();
Niels Möllerafb246b2022-04-20 14:26:50 +0200596 caller->pc()->CreateOffer(observer.get(), RTCOfferAnswerOptions());
Henrik Boströma3728d32019-10-28 12:09:49 +0100597 caller.reset(nullptr);
598 EXPECT_TRUE(observer->called());
599}
600
Henrik Boström831ae4e2020-07-29 12:04:00 +0200601TEST_P(PeerConnectionSignalingTest,
602 ImplicitCreateOfferAndShutdownWithOldObserver) {
Henrik Boströmd4089ca2020-07-28 10:39:36 +0200603 auto caller = CreatePeerConnection();
Henrik Boström4c9c75a2020-07-29 09:46:40 +0000604 auto observer = MockSetSessionDescriptionObserver::Create();
Henrik Boström831ae4e2020-07-29 12:04:00 +0200605 caller->pc()->SetLocalDescription(observer.get());
606 caller.reset(nullptr);
607 // The old observer does not get invoked because posted messages are lost.
608 EXPECT_FALSE(observer->called());
609}
610
611TEST_P(PeerConnectionSignalingTest, ImplicitCreateOfferAndShutdown) {
612 auto caller = CreatePeerConnection();
Niels Möller9dde1202022-03-21 10:36:32 +0100613 auto observer = rtc::make_ref_counted<FakeSetLocalDescriptionObserver>();
Henrik Boström4e196702019-10-30 10:35:50 +0100614 caller->pc()->SetLocalDescription(observer);
615 caller.reset(nullptr);
Henrik Boström831ae4e2020-07-29 12:04:00 +0200616 // The new observer gets invoked because it is called immediately.
617 EXPECT_TRUE(observer->called());
618 EXPECT_FALSE(observer->error().ok());
619}
620
621TEST_P(PeerConnectionSignalingTest,
622 CloseBeforeImplicitCreateOfferAndShutdownWithOldObserver) {
623 auto caller = CreatePeerConnection();
624 auto observer = MockSetSessionDescriptionObserver::Create();
625 caller->pc()->Close();
626 caller->pc()->SetLocalDescription(observer.get());
627 caller.reset(nullptr);
628 // The old observer does not get invoked because posted messages are lost.
Henrik Boström4e196702019-10-30 10:35:50 +0100629 EXPECT_FALSE(observer->called());
630}
631
632TEST_P(PeerConnectionSignalingTest, CloseBeforeImplicitCreateOfferAndShutdown) {
633 auto caller = CreatePeerConnection();
Niels Möller9dde1202022-03-21 10:36:32 +0100634 auto observer = rtc::make_ref_counted<FakeSetLocalDescriptionObserver>();
Henrik Boström4e196702019-10-30 10:35:50 +0100635 caller->pc()->Close();
636 caller->pc()->SetLocalDescription(observer);
637 caller.reset(nullptr);
Henrik Boström831ae4e2020-07-29 12:04:00 +0200638 // The new observer gets invoked because it is called immediately.
639 EXPECT_TRUE(observer->called());
640 EXPECT_FALSE(observer->error().ok());
641}
642
643TEST_P(PeerConnectionSignalingTest,
644 CloseAfterImplicitCreateOfferAndShutdownWithOldObserver) {
645 auto caller = CreatePeerConnection();
646 auto observer = MockSetSessionDescriptionObserver::Create();
647 caller->pc()->SetLocalDescription(observer.get());
648 caller->pc()->Close();
649 caller.reset(nullptr);
650 // The old observer does not get invoked because posted messages are lost.
Henrik Boström4e196702019-10-30 10:35:50 +0100651 EXPECT_FALSE(observer->called());
652}
653
654TEST_P(PeerConnectionSignalingTest, CloseAfterImplicitCreateOfferAndShutdown) {
655 auto caller = CreatePeerConnection();
Niels Möller9dde1202022-03-21 10:36:32 +0100656 auto observer = rtc::make_ref_counted<FakeSetLocalDescriptionObserver>();
Henrik Boström4e196702019-10-30 10:35:50 +0100657 caller->pc()->SetLocalDescription(observer);
658 caller->pc()->Close();
659 caller.reset(nullptr);
Henrik Boström831ae4e2020-07-29 12:04:00 +0200660 // The new observer gets invoked because it is called immediately.
661 EXPECT_TRUE(observer->called());
662 EXPECT_FALSE(observer->error().ok());
663}
664
665TEST_P(PeerConnectionSignalingTest,
666 SetLocalDescriptionNewObserverIsInvokedImmediately) {
667 auto caller = CreatePeerConnection();
668 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
669
Niels Möller9dde1202022-03-21 10:36:32 +0100670 auto observer = rtc::make_ref_counted<FakeSetLocalDescriptionObserver>();
Henrik Boström831ae4e2020-07-29 12:04:00 +0200671 caller->pc()->SetLocalDescription(std::move(offer), observer);
672 // The new observer is invoked immediately.
673 EXPECT_TRUE(observer->called());
674 EXPECT_TRUE(observer->error().ok());
675}
676
677TEST_P(PeerConnectionSignalingTest,
678 SetLocalDescriptionOldObserverIsInvokedInAPostedMessage) {
679 auto caller = CreatePeerConnection();
680 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
681
682 auto observer = MockSetSessionDescriptionObserver::Create();
Niels Möllerafb246b2022-04-20 14:26:50 +0200683 caller->pc()->SetLocalDescription(observer.get(), offer.release());
Henrik Boström831ae4e2020-07-29 12:04:00 +0200684 // The old observer is not invoked immediately.
Henrik Boström4e196702019-10-30 10:35:50 +0100685 EXPECT_FALSE(observer->called());
Henrik Boström831ae4e2020-07-29 12:04:00 +0200686 // Process all currently pending messages by waiting for a posted task to run.
687 bool checkpoint_reached = false;
688 rtc::Thread::Current()->PostTask(
Henrik Boström595f6882022-01-24 09:57:03 +0100689 [&checkpoint_reached] { checkpoint_reached = true; });
Henrik Boström831ae4e2020-07-29 12:04:00 +0200690 EXPECT_TRUE_WAIT(checkpoint_reached, kWaitTimeout);
691 // If resolving the observer was pending, it must now have been called.
692 EXPECT_TRUE(observer->called());
Henrik Boström4e196702019-10-30 10:35:50 +0100693}
694
Henrik Boströma3728d32019-10-28 12:09:49 +0100695TEST_P(PeerConnectionSignalingTest, SetRemoteDescriptionExecutesImmediately) {
696 auto caller = CreatePeerConnectionWithAudioVideo();
697 auto callee = CreatePeerConnection();
698
699 // This offer will cause receivers to be created.
700 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
701
702 // By not waiting for the observer's callback we can verify that the operation
703 // executed immediately.
Niels Möllere7cc8832022-01-04 15:20:03 +0100704 callee->pc()->SetRemoteDescription(
705 std::move(offer),
706 rtc::make_ref_counted<FakeSetRemoteDescriptionObserver>());
Henrik Boströma3728d32019-10-28 12:09:49 +0100707 EXPECT_EQ(2u, callee->pc()->GetReceivers().size());
708}
709
710TEST_P(PeerConnectionSignalingTest, CreateOfferBlocksSetRemoteDescription) {
711 auto caller = CreatePeerConnectionWithAudioVideo();
712 auto callee = CreatePeerConnection();
713
714 // This offer will cause receivers to be created.
715 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
716
717 EXPECT_EQ(0u, callee->pc()->GetReceivers().size());
Tommi87f70902021-04-27 14:43:08 +0200718 auto offer_observer =
719 rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
Henrik Boströma3728d32019-10-28 12:09:49 +0100720 // Synchronously invoke CreateOffer() and SetRemoteDescription(). The
721 // SetRemoteDescription() operation should be chained to be executed
722 // asynchronously, when CreateOffer() completes.
Niels Möllerafb246b2022-04-20 14:26:50 +0200723 callee->pc()->CreateOffer(offer_observer.get(), RTCOfferAnswerOptions());
Niels Möllere7cc8832022-01-04 15:20:03 +0100724 callee->pc()->SetRemoteDescription(
725 std::move(offer),
726 rtc::make_ref_counted<FakeSetRemoteDescriptionObserver>());
Henrik Boströma3728d32019-10-28 12:09:49 +0100727 // CreateOffer() is asynchronous; without message processing this operation
728 // should not have completed.
729 EXPECT_FALSE(offer_observer->called());
730 // Due to chaining, the receivers should not have been created by the offer
731 // yet.
732 EXPECT_EQ(0u, callee->pc()->GetReceivers().size());
733 // EXPECT_TRUE_WAIT causes messages to be processed...
734 EXPECT_TRUE_WAIT(offer_observer->called(), kWaitTimeout);
735 // Now that the offer has been completed, SetRemoteDescription() will have
736 // been executed next in the chain.
737 EXPECT_EQ(2u, callee->pc()->GetReceivers().size());
738}
739
Henrik Boström4e196702019-10-30 10:35:50 +0100740TEST_P(PeerConnectionSignalingTest,
741 ParameterlessSetLocalDescriptionCreatesOffer) {
742 auto caller = CreatePeerConnectionWithAudioVideo();
743
744 auto observer = MockSetSessionDescriptionObserver::Create();
Henrik Boström831ae4e2020-07-29 12:04:00 +0200745 caller->pc()->SetLocalDescription(observer.get());
Henrik Boström4e196702019-10-30 10:35:50 +0100746
747 // The offer is created asynchronously; message processing is needed for it to
748 // complete.
749 EXPECT_FALSE(observer->called());
750 EXPECT_FALSE(caller->pc()->pending_local_description());
751 EXPECT_EQ(PeerConnection::kStable, caller->signaling_state());
752
753 // Wait for messages to be processed.
754 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
755 EXPECT_TRUE(observer->result());
756 EXPECT_TRUE(caller->pc()->pending_local_description());
757 EXPECT_EQ(SdpType::kOffer,
758 caller->pc()->pending_local_description()->GetType());
759 EXPECT_EQ(PeerConnection::kHaveLocalOffer, caller->signaling_state());
760}
761
762TEST_P(PeerConnectionSignalingTest,
763 ParameterlessSetLocalDescriptionCreatesAnswer) {
764 auto caller = CreatePeerConnectionWithAudioVideo();
765 auto callee = CreatePeerConnectionWithAudioVideo();
766
767 callee->SetRemoteDescription(caller->CreateOffer());
768 EXPECT_EQ(PeerConnection::kHaveRemoteOffer, callee->signaling_state());
769
770 auto observer = MockSetSessionDescriptionObserver::Create();
Henrik Boström831ae4e2020-07-29 12:04:00 +0200771 callee->pc()->SetLocalDescription(observer.get());
Henrik Boström4e196702019-10-30 10:35:50 +0100772
773 // The answer is created asynchronously; message processing is needed for it
774 // to complete.
775 EXPECT_FALSE(observer->called());
776 EXPECT_FALSE(callee->pc()->current_local_description());
777
778 // Wait for messages to be processed.
779 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
780 EXPECT_TRUE(observer->result());
781 EXPECT_TRUE(callee->pc()->current_local_description());
782 EXPECT_EQ(SdpType::kAnswer,
783 callee->pc()->current_local_description()->GetType());
784 EXPECT_EQ(PeerConnection::kStable, callee->signaling_state());
785}
786
787TEST_P(PeerConnectionSignalingTest,
788 ParameterlessSetLocalDescriptionFullExchange) {
789 auto caller = CreatePeerConnectionWithAudioVideo();
790 auto callee = CreatePeerConnectionWithAudioVideo();
791
792 // SetLocalDescription(), implicitly creating an offer.
Henrik Boström831ae4e2020-07-29 12:04:00 +0200793 auto caller_set_local_description_observer =
794 MockSetSessionDescriptionObserver::Create();
795 caller->pc()->SetLocalDescription(
796 caller_set_local_description_observer.get());
Henrik Boström4e196702019-10-30 10:35:50 +0100797 EXPECT_TRUE_WAIT(caller_set_local_description_observer->called(),
798 kWaitTimeout);
799 ASSERT_TRUE(caller->pc()->pending_local_description());
800
801 // SetRemoteDescription(offer)
Henrik Boström831ae4e2020-07-29 12:04:00 +0200802 auto callee_set_remote_description_observer =
803 MockSetSessionDescriptionObserver::Create();
Henrik Boström4e196702019-10-30 10:35:50 +0100804 callee->pc()->SetRemoteDescription(
Niels Möllerafb246b2022-04-20 14:26:50 +0200805 callee_set_remote_description_observer.get(),
Henrik Boström4e196702019-10-30 10:35:50 +0100806 CloneSessionDescription(caller->pc()->pending_local_description())
807 .release());
808
809 // SetLocalDescription(), implicitly creating an answer.
Henrik Boström831ae4e2020-07-29 12:04:00 +0200810 auto callee_set_local_description_observer =
811 MockSetSessionDescriptionObserver::Create();
812 callee->pc()->SetLocalDescription(
813 callee_set_local_description_observer.get());
Henrik Boström4e196702019-10-30 10:35:50 +0100814 EXPECT_TRUE_WAIT(callee_set_local_description_observer->called(),
815 kWaitTimeout);
816 // Chaining guarantees SetRemoteDescription() happened before
817 // SetLocalDescription().
818 EXPECT_TRUE(callee_set_remote_description_observer->called());
819 EXPECT_TRUE(callee->pc()->current_local_description());
820
821 // SetRemoteDescription(answer)
Henrik Boström831ae4e2020-07-29 12:04:00 +0200822 auto caller_set_remote_description_observer =
823 MockSetSessionDescriptionObserver::Create();
Henrik Boström4e196702019-10-30 10:35:50 +0100824 caller->pc()->SetRemoteDescription(
Niels Möllerafb246b2022-04-20 14:26:50 +0200825 caller_set_remote_description_observer.get(),
Henrik Boström4e196702019-10-30 10:35:50 +0100826 CloneSessionDescription(callee->pc()->current_local_description())
827 .release());
828 EXPECT_TRUE_WAIT(caller_set_remote_description_observer->called(),
829 kWaitTimeout);
830
831 EXPECT_EQ(PeerConnection::kStable, caller->signaling_state());
832 EXPECT_EQ(PeerConnection::kStable, callee->signaling_state());
833}
834
835TEST_P(PeerConnectionSignalingTest,
836 ParameterlessSetLocalDescriptionCloseBeforeCreatingOffer) {
837 auto caller = CreatePeerConnectionWithAudioVideo();
838
839 auto observer = MockSetSessionDescriptionObserver::Create();
840 caller->pc()->Close();
Henrik Boström831ae4e2020-07-29 12:04:00 +0200841 caller->pc()->SetLocalDescription(observer.get());
Henrik Boström4e196702019-10-30 10:35:50 +0100842
843 // The operation should fail asynchronously.
844 EXPECT_FALSE(observer->called());
845 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
846 EXPECT_FALSE(observer->result());
847 // This did not affect the signaling state.
848 EXPECT_EQ(PeerConnection::kClosed, caller->pc()->signaling_state());
849 EXPECT_EQ(
850 "SetLocalDescription failed to create session description - "
851 "SetLocalDescription called when PeerConnection is closed.",
852 observer->error());
853}
854
855TEST_P(PeerConnectionSignalingTest,
856 ParameterlessSetLocalDescriptionCloseWhileCreatingOffer) {
857 auto caller = CreatePeerConnectionWithAudioVideo();
858
859 auto observer = MockSetSessionDescriptionObserver::Create();
Henrik Boström831ae4e2020-07-29 12:04:00 +0200860 caller->pc()->SetLocalDescription(observer.get());
Henrik Boström4e196702019-10-30 10:35:50 +0100861 caller->pc()->Close();
862
863 // The operation should fail asynchronously.
864 EXPECT_FALSE(observer->called());
865 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
866 EXPECT_FALSE(observer->result());
867 // This did not affect the signaling state.
868 EXPECT_EQ(PeerConnection::kClosed, caller->pc()->signaling_state());
869 EXPECT_EQ(
870 "SetLocalDescription failed to create session description - "
871 "CreateOffer failed because the session was shut down",
872 observer->error());
873}
874
Philipp Hancke4e8c1152020-10-13 12:43:15 +0200875TEST_P(PeerConnectionSignalingTest, UnsupportedContentType) {
876 auto caller = CreatePeerConnection();
877
878 // Call setRemoteDescription with a m= line we don't understand.
879 std::string sdp =
880 "v=0\r\n"
881 "o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1\r\n"
882 "s=-\r\n"
883 "t=0 0\r\n"
884 "m=bogus 9 FOO 0 8\r\n"
885 "c=IN IP4 0.0.0.0\r\n"
886 "a=mid:bogusmid\r\n";
887 std::unique_ptr<webrtc::SessionDescriptionInterface> remote_description =
888 webrtc::CreateSessionDescription(SdpType::kOffer, sdp, nullptr);
889
890 EXPECT_TRUE(caller->SetRemoteDescription(std::move(remote_description)));
891
892 // Assert we respond back with something meaningful.
893 auto answer = caller->CreateAnswer();
894 ASSERT_EQ(answer->description()->contents().size(), 1u);
895 EXPECT_NE(answer->description()
896 ->contents()[0]
897 .media_description()
898 ->as_unsupported(),
899 nullptr);
900 EXPECT_EQ(answer->description()
901 ->contents()[0]
902 .media_description()
903 ->as_unsupported()
904 ->media_type(),
905 "bogus");
906 EXPECT_TRUE(answer->description()->contents()[0].rejected);
907 EXPECT_EQ(answer->description()->contents()[0].mid(), "bogusmid");
908 EXPECT_EQ(
909 answer->description()->contents()[0].media_description()->protocol(),
910 "FOO");
911 EXPECT_FALSE(
912 answer->description()->contents()[0].media_description()->has_codecs());
913
914 EXPECT_TRUE(caller->SetLocalDescription(std::move(answer)));
915
916 // Assert we keep this in susequent offers.
917 auto offer = caller->CreateOffer();
918 EXPECT_EQ(offer->description()
919 ->contents()[0]
920 .media_description()
921 ->as_unsupported()
922 ->media_type(),
923 "bogus");
924 EXPECT_TRUE(offer->description()->contents()[0].rejected);
925 EXPECT_EQ(offer->description()->contents()[0].media_description()->protocol(),
926 "FOO");
927 EXPECT_EQ(offer->description()->contents()[0].mid(), "bogusmid");
928 EXPECT_FALSE(
929 offer->description()->contents()[0].media_description()->has_codecs());
930 EXPECT_TRUE(caller->SetLocalDescription(std::move(offer)));
931}
932
Philipp Hanckeb7bc2432021-03-11 15:28:00 +0100933TEST_P(PeerConnectionSignalingTest, ReceiveFlexFec) {
934 auto caller = CreatePeerConnection();
935
936 std::string sdp =
937 "v=0\r\n"
938 "o=- 8403615332048243445 2 IN IP4 127.0.0.1\r\n"
939 "s=-\r\n"
940 "t=0 0\r\n"
941 "a=group:BUNDLE 0\r\n"
942 "m=video 9 UDP/TLS/RTP/SAVPF 102 122\r\n"
943 "c=IN IP4 0.0.0.0\r\n"
944 "a=rtcp:9 IN IP4 0.0.0.0\r\n"
945 "a=ice-ufrag:IZeV\r\n"
946 "a=ice-pwd:uaZhQD4rYM/Tta2qWBT1Bbt4\r\n"
947 "a=ice-options:trickle\r\n"
948 "a=fingerprint:sha-256 "
949 "D8:6C:3D:FA:23:E2:2C:63:11:2D:D0:86:BE:C4:D0:65:F9:42:F7:1C:06:04:27:E6:"
950 "1C:2C:74:01:8D:50:67:23\r\n"
951 "a=setup:actpass\r\n"
952 "a=mid:0\r\n"
953 "a=sendrecv\r\n"
954 "a=msid:stream track\r\n"
955 "a=rtcp-mux\r\n"
956 "a=rtcp-rsize\r\n"
957 "a=rtpmap:102 VP8/90000\r\n"
958 "a=rtcp-fb:102 goog-remb\r\n"
959 "a=rtcp-fb:102 transport-cc\r\n"
960 "a=rtcp-fb:102 ccm fir\r\n"
961 "a=rtcp-fb:102 nack\r\n"
962 "a=rtcp-fb:102 nack pli\r\n"
963 "a=rtpmap:122 flexfec-03/90000\r\n"
964 "a=fmtp:122 repair-window=10000000\r\n"
965 "a=ssrc-group:FEC-FR 1224551896 1953032773\r\n"
966 "a=ssrc:1224551896 cname:/exJcmhSLpyu9FgV\r\n"
967 "a=ssrc:1953032773 cname:/exJcmhSLpyu9FgV\r\n";
968 std::unique_ptr<webrtc::SessionDescriptionInterface> remote_description =
969 webrtc::CreateSessionDescription(SdpType::kOffer, sdp, nullptr);
970
971 EXPECT_TRUE(caller->SetRemoteDescription(std::move(remote_description)));
972
973 auto answer = caller->CreateAnswer();
974 ASSERT_EQ(answer->description()->contents().size(), 1u);
975 ASSERT_NE(
976 answer->description()->contents()[0].media_description()->as_video(),
977 nullptr);
978 auto codecs = answer->description()
979 ->contents()[0]
980 .media_description()
981 ->as_video()
982 ->codecs();
983 ASSERT_EQ(codecs.size(), 2u);
984 EXPECT_EQ(codecs[1].name, "flexfec-03");
985
986 EXPECT_TRUE(caller->SetLocalDescription(std::move(answer)));
987}
988
Philipp Hancke64a79c72021-05-10 17:28:37 +0200989TEST_P(PeerConnectionSignalingTest, ReceiveFlexFecReoffer) {
990 auto caller = CreatePeerConnection();
991
992 std::string sdp =
993 "v=0\r\n"
994 "o=- 8403615332048243445 2 IN IP4 127.0.0.1\r\n"
995 "s=-\r\n"
996 "t=0 0\r\n"
997 "a=group:BUNDLE 0\r\n"
998 "m=video 9 UDP/TLS/RTP/SAVPF 102 35\r\n"
999 "c=IN IP4 0.0.0.0\r\n"
1000 "a=rtcp:9 IN IP4 0.0.0.0\r\n"
1001 "a=ice-ufrag:IZeV\r\n"
1002 "a=ice-pwd:uaZhQD4rYM/Tta2qWBT1Bbt4\r\n"
1003 "a=ice-options:trickle\r\n"
1004 "a=fingerprint:sha-256 "
1005 "D8:6C:3D:FA:23:E2:2C:63:11:2D:D0:86:BE:C4:D0:65:F9:42:F7:1C:06:04:27:E6:"
1006 "1C:2C:74:01:8D:50:67:23\r\n"
1007 "a=setup:actpass\r\n"
1008 "a=mid:0\r\n"
1009 "a=sendrecv\r\n"
1010 "a=msid:stream track\r\n"
1011 "a=rtcp-mux\r\n"
1012 "a=rtcp-rsize\r\n"
1013 "a=rtpmap:102 VP8/90000\r\n"
1014 "a=rtcp-fb:102 goog-remb\r\n"
1015 "a=rtcp-fb:102 transport-cc\r\n"
1016 "a=rtcp-fb:102 ccm fir\r\n"
1017 "a=rtcp-fb:102 nack\r\n"
1018 "a=rtcp-fb:102 nack pli\r\n"
1019 "a=rtpmap:35 flexfec-03/90000\r\n"
1020 "a=fmtp:35 repair-window=10000000\r\n"
1021 "a=ssrc-group:FEC-FR 1224551896 1953032773\r\n"
1022 "a=ssrc:1224551896 cname:/exJcmhSLpyu9FgV\r\n"
1023 "a=ssrc:1953032773 cname:/exJcmhSLpyu9FgV\r\n";
1024 std::unique_ptr<webrtc::SessionDescriptionInterface> remote_description =
1025 webrtc::CreateSessionDescription(SdpType::kOffer, sdp, nullptr);
1026
1027 EXPECT_TRUE(caller->SetRemoteDescription(std::move(remote_description)));
1028
1029 auto answer = caller->CreateAnswer();
1030 ASSERT_EQ(answer->description()->contents().size(), 1u);
1031 ASSERT_NE(
1032 answer->description()->contents()[0].media_description()->as_video(),
1033 nullptr);
1034 auto codecs = answer->description()
1035 ->contents()[0]
1036 .media_description()
1037 ->as_video()
1038 ->codecs();
1039 ASSERT_EQ(codecs.size(), 2u);
1040 EXPECT_EQ(codecs[1].name, "flexfec-03");
1041 EXPECT_EQ(codecs[1].id, 35);
1042
1043 EXPECT_TRUE(caller->SetLocalDescription(std::move(answer)));
1044
1045 // This generates a collision for AV1 which needs to be remapped.
1046 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1047 auto offer_codecs = offer->description()
1048 ->contents()[0]
1049 .media_description()
1050 ->as_video()
1051 ->codecs();
1052 auto flexfec_it = std::find_if(
1053 offer_codecs.begin(), offer_codecs.end(),
1054 [](const cricket::Codec& codec) { return codec.name == "flexfec-03"; });
1055 ASSERT_EQ(flexfec_it->id, 35);
1056 auto av1_it = std::find_if(
1057 offer_codecs.begin(), offer_codecs.end(),
Sergey Silkin6b19d822021-09-09 15:09:11 +02001058 [](const cricket::Codec& codec) { return codec.name == "AV1"; });
Philipp Hancke64a79c72021-05-10 17:28:37 +02001059 if (av1_it != offer_codecs.end()) {
1060 ASSERT_NE(av1_it->id, 35);
1061 }
1062}
1063
Philipp Hancke187e9d42021-11-08 09:58:15 +01001064TEST_P(PeerConnectionSignalingTest, MidAttributeMaxLength) {
1065 auto caller = CreatePeerConnection();
1066
1067 std::string sdp =
1068 "v=0\r\n"
1069 "o=- 8403615332048243445 2 IN IP4 127.0.0.1\r\n"
1070 "s=-\r\n"
1071 "t=0 0\r\n"
1072 "m=video 9 UDP/TLS/RTP/SAVPF 102\r\n"
1073 "c=IN IP4 0.0.0.0\r\n"
1074 "a=rtcp:9 IN IP4 0.0.0.0\r\n"
1075 "a=ice-ufrag:IZeV\r\n"
1076 "a=ice-pwd:uaZhQD4rYM/Tta2qWBT1Bbt4\r\n"
1077 "a=ice-options:trickle\r\n"
1078 "a=fingerprint:sha-256 "
1079 "D8:6C:3D:FA:23:E2:2C:63:11:2D:D0:86:BE:C4:D0:65:F9:42:F7:1C:06:04:27:E6:"
1080 "1C:2C:74:01:8D:50:67:23\r\n"
1081 "a=setup:actpass\r\n"
1082 // Too long mid attribute.
Philipp Hancke063bb382021-11-29 12:05:38 +01001083 "a=mid:0123456789012345678901234567890123\r\n"
Philipp Hancke187e9d42021-11-08 09:58:15 +01001084 "a=sendrecv\r\n"
1085 "a=msid:stream track\r\n"
1086 "a=rtcp-mux\r\n"
1087 "a=rtcp-rsize\r\n"
1088 "a=rtpmap:102 VP8/90000\r\n"
1089 "a=rtcp-fb:102 goog-remb\r\n"
1090 "a=rtcp-fb:102 transport-cc\r\n"
1091 "a=rtcp-fb:102 ccm fir\r\n"
1092 "a=rtcp-fb:102 nack\r\n"
1093 "a=rtcp-fb:102 nack pli\r\n"
1094 "a=ssrc:1224551896 cname:/exJcmhSLpyu9FgV\r\n";
1095 std::unique_ptr<webrtc::SessionDescriptionInterface> remote_description =
1096 webrtc::CreateSessionDescription(SdpType::kOffer, sdp, nullptr);
1097
1098 EXPECT_FALSE(caller->SetRemoteDescription(std::move(remote_description)));
1099}
1100
Mirko Bonadeic84f6612019-01-31 12:20:57 +01001101INSTANTIATE_TEST_SUITE_P(PeerConnectionSignalingTest,
1102 PeerConnectionSignalingTest,
Florent Castelli15a38de2022-04-06 00:38:21 +02001103 Values(SdpSemantics::kPlanB_DEPRECATED,
Mirko Bonadeic84f6612019-01-31 12:20:57 +01001104 SdpSemantics::kUnifiedPlan));
Steve Anton8acdd1a2018-02-07 17:27:36 -08001105
Harald Alvestrand4a7b3ac2019-01-17 10:39:40 +01001106class PeerConnectionSignalingUnifiedPlanTest
1107 : public PeerConnectionSignalingBaseTest {
1108 protected:
1109 PeerConnectionSignalingUnifiedPlanTest()
1110 : PeerConnectionSignalingBaseTest(SdpSemantics::kUnifiedPlan) {}
1111};
1112
Henrik Boströma3728d32019-10-28 12:09:49 +01001113// We verify that SetLocalDescription() executed immediately by verifying that
1114// the transceiver mid values got assigned. SLD executing immeditately is not
1115// unique to Unified Plan, but the transceivers used to verify this are only
1116// available in Unified Plan.
1117TEST_F(PeerConnectionSignalingUnifiedPlanTest,
Henrik Boström831ae4e2020-07-29 12:04:00 +02001118 SetLocalDescriptionExecutesImmediatelyUsingOldObserver) {
Henrik Boströma3728d32019-10-28 12:09:49 +01001119 auto caller = CreatePeerConnectionWithAudioVideo();
1120
1121 // This offer will cause transceiver mids to get assigned.
1122 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1123
1124 // By not waiting for the observer's callback we can verify that the operation
Henrik Boström831ae4e2020-07-29 12:04:00 +02001125 // executed immediately. The old observer is invoked in a posted message, so
1126 // waiting for it would not ensure synchronicity.
Henrik Boströma3728d32019-10-28 12:09:49 +01001127 RTC_DCHECK(!caller->pc()->GetTransceivers()[0]->mid().has_value());
1128 caller->pc()->SetLocalDescription(
Niels Möllerafb246b2022-04-20 14:26:50 +02001129 rtc::make_ref_counted<MockSetSessionDescriptionObserver>().get(),
Henrik Boströma3728d32019-10-28 12:09:49 +01001130 offer.release());
1131 EXPECT_TRUE(caller->pc()->GetTransceivers()[0]->mid().has_value());
1132}
1133
1134TEST_F(PeerConnectionSignalingUnifiedPlanTest,
Henrik Boström831ae4e2020-07-29 12:04:00 +02001135 SetLocalDescriptionExecutesImmediatelyUsingNewObserver) {
1136 auto caller = CreatePeerConnectionWithAudioVideo();
1137
1138 // This offer will cause transceiver mids to get assigned.
1139 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1140
1141 // Verify that mids were assigned without waiting for the observer. (However,
1142 // the new observer should also be invoked synchronously - as is ensured by
1143 // other tests.)
1144 RTC_DCHECK(!caller->pc()->GetTransceivers()[0]->mid().has_value());
Niels Möllere7cc8832022-01-04 15:20:03 +01001145 caller->pc()->SetLocalDescription(
1146 std::move(offer),
1147 rtc::make_ref_counted<FakeSetLocalDescriptionObserver>());
Henrik Boström831ae4e2020-07-29 12:04:00 +02001148 EXPECT_TRUE(caller->pc()->GetTransceivers()[0]->mid().has_value());
1149}
1150
1151TEST_F(PeerConnectionSignalingUnifiedPlanTest,
Henrik Boströma3728d32019-10-28 12:09:49 +01001152 SetLocalDescriptionExecutesImmediatelyInsideCreateOfferCallback) {
1153 auto caller = CreatePeerConnectionWithAudioVideo();
1154
1155 // This offer will cause transceiver mids to get assigned.
1156 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1157
Tommi87f70902021-04-27 14:43:08 +02001158 auto offer_observer =
1159 rtc::make_ref_counted<ExecuteFunctionOnCreateSessionDescriptionObserver>(
Henrik Boströma3728d32019-10-28 12:09:49 +01001160 [pc = caller->pc()](SessionDescriptionInterface* desc) {
1161 // By not waiting for the observer's callback we can verify that the
1162 // operation executed immediately.
1163 RTC_DCHECK(!pc->GetTransceivers()[0]->mid().has_value());
1164 pc->SetLocalDescription(
Niels Möllerafb246b2022-04-20 14:26:50 +02001165 rtc::make_ref_counted<MockSetSessionDescriptionObserver>()
1166 .get(),
Henrik Boströma3728d32019-10-28 12:09:49 +01001167 desc);
1168 EXPECT_TRUE(pc->GetTransceivers()[0]->mid().has_value());
Tommi87f70902021-04-27 14:43:08 +02001169 });
Niels Möllerafb246b2022-04-20 14:26:50 +02001170 caller->pc()->CreateOffer(offer_observer.get(), RTCOfferAnswerOptions());
Henrik Boströma3728d32019-10-28 12:09:49 +01001171 EXPECT_TRUE_WAIT(offer_observer->was_called(), kWaitTimeout);
1172}
1173
Harald Alvestrand4a7b3ac2019-01-17 10:39:40 +01001174// Test that transports are shown in the sender/receiver API after offer/answer.
1175// This only works in Unified Plan.
1176TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1177 DtlsTransportsInstantiateInOfferAnswer) {
1178 auto caller = CreatePeerConnectionWithAudioVideo();
1179 auto callee = CreatePeerConnection();
1180
1181 EXPECT_FALSE(HasDtlsTransport(caller));
1182 EXPECT_FALSE(HasDtlsTransport(callee));
1183 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1184 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
1185 EXPECT_TRUE(HasDtlsTransport(caller));
1186 callee->SetRemoteDescription(std::move(offer));
1187 EXPECT_FALSE(HasDtlsTransport(callee));
1188 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
1189 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
1190 EXPECT_TRUE(HasDtlsTransport(callee));
1191 caller->SetRemoteDescription(std::move(answer));
1192 EXPECT_TRUE(HasDtlsTransport(caller));
1193
1194 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
1195}
1196
1197TEST_F(PeerConnectionSignalingUnifiedPlanTest, DtlsTransportsMergeWhenBundled) {
1198 auto caller = CreatePeerConnectionWithAudioVideo();
1199 auto callee = CreatePeerConnection();
1200
1201 EXPECT_FALSE(HasDtlsTransport(caller));
1202 EXPECT_FALSE(HasDtlsTransport(callee));
1203 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1204 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
1205 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
1206 callee->SetRemoteDescription(std::move(offer));
1207 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
1208 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
1209 caller->SetRemoteDescription(std::move(answer));
1210 EXPECT_EQ(1, NumberOfDtlsTransports(caller));
1211
1212 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
1213}
1214
1215TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1216 DtlsTransportsAreSeparateeWhenUnbundled) {
1217 auto caller = CreatePeerConnectionWithAudioVideo();
1218 auto callee = CreatePeerConnection();
1219
1220 EXPECT_FALSE(HasDtlsTransport(caller));
1221 EXPECT_FALSE(HasDtlsTransport(callee));
1222 RTCOfferAnswerOptions unbundle_options;
1223 unbundle_options.use_rtp_mux = false;
1224 auto offer = caller->CreateOffer(unbundle_options);
1225 caller->SetLocalDescription(CloneSessionDescription(offer.get()));
1226 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
1227 callee->SetRemoteDescription(std::move(offer));
1228 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
1229 callee->SetLocalDescription(CloneSessionDescription(answer.get()));
1230 EXPECT_EQ(2, NumberOfDtlsTransports(callee));
1231 caller->SetRemoteDescription(std::move(answer));
1232 EXPECT_EQ(2, NumberOfDtlsTransports(caller));
1233
1234 ASSERT_EQ(SignalingState::kStable, caller->signaling_state());
1235}
1236
Henrik Boströme574a312020-08-25 10:20:11 +02001237TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1238 ShouldFireNegotiationNeededWhenNoChangesArePending) {
1239 auto caller = CreatePeerConnection();
1240 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
1241 auto transceiver =
1242 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, RtpTransceiverInit());
1243 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1244 EXPECT_TRUE(caller->pc()->ShouldFireNegotiationNeededEvent(
1245 caller->observer()->latest_negotiation_needed_event()));
1246}
1247
1248TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1249 SuppressNegotiationNeededWhenOperationChainIsNotEmpty) {
1250 auto caller = CreatePeerConnection();
1251 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
1252 auto transceiver =
1253 caller->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, RtpTransceiverInit());
1254 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1255
Tommi87f70902021-04-27 14:43:08 +02001256 auto observer = rtc::make_ref_counted<MockCreateSessionDescriptionObserver>();
Niels Möllerafb246b2022-04-20 14:26:50 +02001257 caller->pc()->CreateOffer(observer.get(), RTCOfferAnswerOptions());
Henrik Boströme574a312020-08-25 10:20:11 +02001258 // For this test to work, the operation has to be pending, i.e. the observer
1259 // has not yet been invoked.
1260 EXPECT_FALSE(observer->called());
1261 // Because the Operations Chain is not empty, the event is now suppressed.
1262 EXPECT_FALSE(caller->pc()->ShouldFireNegotiationNeededEvent(
1263 caller->observer()->latest_negotiation_needed_event()));
1264 caller->observer()->clear_latest_negotiation_needed_event();
1265
1266 // When the Operations Chain becomes empty again, a new negotiation needed
1267 // event will be generated that is not suppressed.
1268 EXPECT_TRUE_WAIT(observer->called(), kWaitTimeout);
1269 EXPECT_TRUE(caller->observer()->has_negotiation_needed_event());
1270 EXPECT_TRUE(caller->pc()->ShouldFireNegotiationNeededEvent(
1271 caller->observer()->latest_negotiation_needed_event()));
1272}
1273
1274TEST_F(PeerConnectionSignalingUnifiedPlanTest,
1275 SuppressNegotiationNeededWhenSignalingStateIsNotStable) {
1276 auto caller = CreatePeerConnection();
1277 auto callee = CreatePeerConnection();
1278 auto offer = caller->CreateOffer(RTCOfferAnswerOptions());
1279
1280 EXPECT_FALSE(caller->observer()->has_negotiation_needed_event());
1281 auto transceiver =
1282 callee->AddTransceiver(cricket::MEDIA_TYPE_AUDIO, RtpTransceiverInit());
1283 EXPECT_TRUE(callee->observer()->has_negotiation_needed_event());
1284
1285 // Change signaling state (to "have-remote-offer") by setting a remote offer.
1286 callee->SetRemoteDescription(std::move(offer));
1287 // Because the signaling state is not "stable", the event is now suppressed.
1288 EXPECT_FALSE(callee->pc()->ShouldFireNegotiationNeededEvent(
1289 callee->observer()->latest_negotiation_needed_event()));
1290 callee->observer()->clear_latest_negotiation_needed_event();
1291
1292 // Upon rolling back to "stable", a new negotiation needed event will be
1293 // generated that is not suppressed.
1294 callee->SetLocalDescription(CreateSessionDescription(SdpType::kRollback, ""));
1295 EXPECT_TRUE(callee->observer()->has_negotiation_needed_event());
1296 EXPECT_TRUE(callee->pc()->ShouldFireNegotiationNeededEvent(
1297 callee->observer()->latest_negotiation_needed_event()));
1298}
1299
Philipp Hancke16dae202021-11-18 18:27:12 +01001300TEST_F(PeerConnectionSignalingUnifiedPlanTest, RtxReofferApt) {
1301 auto callee = CreatePeerConnection();
1302
1303 std::string sdp =
1304 "v=0\r\n"
1305 "o=- 8403615332048243445 2 IN IP4 127.0.0.1\r\n"
1306 "s=-\r\n"
1307 "t=0 0\r\n"
1308 "m=video 9 UDP/TLS/RTP/SAVPF 102\r\n"
1309 "c=IN IP4 0.0.0.0\r\n"
1310 "a=rtcp:9 IN IP4 0.0.0.0\r\n"
1311 "a=ice-ufrag:IZeV\r\n"
1312 "a=ice-pwd:uaZhQD4rYM/Tta2qWBT1Bbt4\r\n"
1313 "a=ice-options:trickle\r\n"
1314 "a=fingerprint:sha-256 "
1315 "D8:6C:3D:FA:23:E2:2C:63:11:2D:D0:86:BE:C4:D0:65:F9:42:F7:1C:06:04:27:E6:"
1316 "1C:2C:74:01:8D:50:67:23\r\n"
1317 "a=setup:actpass\r\n"
1318 "a=mid:0\r\n"
1319 "a=sendrecv\r\n"
1320 "a=msid:stream track\r\n"
1321 "a=rtcp-mux\r\n"
1322 "a=rtcp-rsize\r\n"
1323 "a=rtpmap:102 VP8/90000\r\n"
1324 "a=rtcp-fb:102 goog-remb\r\n"
1325 "a=rtcp-fb:102 transport-cc\r\n"
1326 "a=rtcp-fb:102 ccm fir\r\n"
1327 "a=rtcp-fb:102 nack\r\n"
1328 "a=rtcp-fb:102 nack pli\r\n"
1329 "a=ssrc:1224551896 cname:/exJcmhSLpyu9FgV\r\n";
1330 std::unique_ptr<webrtc::SessionDescriptionInterface> remote_description =
1331 webrtc::CreateSessionDescription(SdpType::kOffer, sdp, nullptr);
1332
1333 EXPECT_TRUE(callee->SetRemoteDescription(std::move(remote_description)));
1334
1335 auto answer = callee->CreateAnswer(RTCOfferAnswerOptions());
1336 EXPECT_TRUE(
1337 callee->SetLocalDescription(CloneSessionDescription(answer.get())));
1338
Florent Castelli72424402022-04-06 03:45:10 +02001339 callee->pc()->GetTransceivers()[0]->StopStandard();
Philipp Hancke16dae202021-11-18 18:27:12 +01001340 auto reoffer = callee->CreateOffer(RTCOfferAnswerOptions());
1341 auto codecs = reoffer->description()
1342 ->contents()[0]
1343 .media_description()
1344 ->as_video()
1345 ->codecs();
1346 ASSERT_GT(codecs.size(), 2u);
1347 EXPECT_EQ(codecs[0].name, "VP8");
1348 EXPECT_EQ(codecs[1].name, "rtx");
1349 auto apt_it = codecs[1].params.find("apt");
1350 ASSERT_NE(apt_it, codecs[1].params.end());
1351 // The apt should match the id from the remote offer.
1352 EXPECT_EQ(apt_it->second, rtc::ToString(codecs[0].id));
1353 EXPECT_EQ(apt_it->second, "102");
1354}
1355
Steve Anton8d3444d2017-10-20 15:30:51 -07001356} // namespace webrtc